@@ -54,32 +54,78 @@ struct MatchedFragment
54
54
std::string fragment_ident;
55
55
size_t token_offset_begin;
56
56
size_t token_offset_end;
57
- size_t match_amount;
58
57
59
58
MatchedFragment (std::string identifier, size_t token_offset_begin,
60
- size_t token_offset_end, size_t match_amount = 1 )
59
+ size_t token_offset_end)
61
60
: fragment_ident (identifier), token_offset_begin (token_offset_begin),
62
- token_offset_end (token_offset_end), match_amount (match_amount)
61
+ token_offset_end (token_offset_end)
62
+ {}
63
+
64
+ /* *
65
+ * Empty constructor for uninitialized fragments
66
+ */
67
+ MatchedFragment () : MatchedFragment (" " , 0 , 0 ) {}
68
+
69
+ std::string as_string () const
70
+ {
71
+ return fragment_ident + " =" + std::to_string (token_offset_begin) + " :"
72
+ + std::to_string (token_offset_end);
73
+ }
74
+ };
75
+
76
+ class MatchedFragmentContainer
77
+ {
78
+ public:
79
+ MatchedFragmentContainer (std::vector<MatchedFragment> fragments)
80
+ : fragments (fragments)
63
81
{}
64
82
65
83
/* *
66
84
* Create a valid fragment matched zero times. This is useful for repetitions
67
85
* which allow the absence of a fragment, such as * and ?
68
86
*/
69
- static MatchedFragment zero (std::string identifier )
87
+ static MatchedFragmentContainer zero ()
70
88
{
71
- // We don't need offsets since there is "no match"
72
- return MatchedFragment (identifier, 0 , 0 , 0 );
89
+ return MatchedFragmentContainer ({});
73
90
}
74
91
75
- std::string as_string () const
92
+ /* *
93
+ * Create a valid fragment matched one time
94
+ */
95
+ static MatchedFragmentContainer one (MatchedFragment fragment)
76
96
{
77
- return fragment_ident + " =" + std::to_string (token_offset_begin) + " :"
78
- + std::to_string (token_offset_end) + " (matched "
79
- + std::to_string (match_amount) + " times)" ;
97
+ return MatchedFragmentContainer ({fragment});
80
98
}
81
99
82
- void set_match_amount (size_t new_amount) { match_amount = new_amount; }
100
+ /* *
101
+ * Add a matched fragment to the container
102
+ */
103
+ void add_fragment (MatchedFragment fragment)
104
+ {
105
+ fragments.emplace_back (fragment);
106
+ }
107
+
108
+ size_t get_match_amount () const { return fragments.size (); }
109
+ const std::vector<MatchedFragment> &get_fragments () const
110
+ {
111
+ return fragments;
112
+ }
113
+ // const std::string &get_fragment_name () const { return fragment_name; }
114
+
115
+ bool is_single_fragment () const { return get_match_amount () == 1 ; }
116
+ const MatchedFragment get_single_fragment () const
117
+ {
118
+ rust_assert (get_match_amount () == 1 );
119
+
120
+ return fragments[0 ];
121
+ }
122
+
123
+ private:
124
+ /* *
125
+ * Fragments matched `match_amount` times. This can be an empty vector
126
+ * in case having zero matches is allowed (i.e ? or * operators)
127
+ */
128
+ std::vector<MatchedFragment> fragments;
83
129
};
84
130
85
131
class SubstitutionScope
@@ -89,38 +135,49 @@ class SubstitutionScope
89
135
90
136
void push () { stack.push_back ({}); }
91
137
92
- std::map<std::string, std::vector<MatchedFragment> > pop ()
138
+ std::map<std::string, MatchedFragmentContainer > pop ()
93
139
{
94
140
auto top = stack.back ();
95
141
stack.pop_back ();
96
142
return top;
97
143
}
98
144
99
- std::map<std::string, std::vector<MatchedFragment> > &peek ()
145
+ std::map<std::string, MatchedFragmentContainer > &peek ()
100
146
{
101
147
return stack.back ();
102
148
}
103
149
150
+ /* *
151
+ * Insert a new matched fragment into the current substitution map
152
+ */
104
153
void insert_fragment (MatchedFragment fragment)
105
154
{
106
155
auto ¤t_map = stack.back ();
107
156
auto it = current_map.find (fragment.fragment_ident );
108
157
109
158
if (it == current_map.end ())
110
159
{
111
- auto new_frags = std::vector<MatchedFragment> ();
112
- new_frags.emplace_back (fragment);
113
- current_map.insert ({fragment.fragment_ident , new_frags});
160
+ current_map.insert (
161
+ {fragment.fragment_ident , MatchedFragmentContainer::one (fragment)});
114
162
}
115
163
else
116
164
{
117
165
auto &frags = it->second ;
118
- frags.emplace_back (fragment);
166
+ frags.add_fragment (fragment);
119
167
}
120
168
}
121
169
170
+ void insert_matches (std::string key, MatchedFragmentContainer matches)
171
+ {
172
+ auto ¤t_map = stack.back ();
173
+ auto it = current_map.find (key);
174
+ rust_assert (it == current_map.end ());
175
+
176
+ current_map.insert ({key, matches});
177
+ }
178
+
122
179
private:
123
- std::vector<std::map<std::string, std::vector<MatchedFragment> >> stack;
180
+ std::vector<std::map<std::string, MatchedFragmentContainer >> stack;
124
181
};
125
182
126
183
// Object used to store shared data (between functions) for macro expansion.
@@ -176,7 +233,7 @@ struct MacroExpander
176
233
177
234
AST::ASTFragment transcribe_rule (
178
235
AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree,
179
- std::map<std::string, std::vector<MatchedFragment> > &matched_fragments,
236
+ std::map<std::string, MatchedFragmentContainer > &matched_fragments,
180
237
bool semicolon, ContextType ctx);
181
238
182
239
bool match_fragment (Parser<MacroInvocLexer> &parser,
0 commit comments