aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/expand/rust-macro-expand.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/expand/rust-macro-expand.h')
-rw-r--r--gcc/rust/expand/rust-macro-expand.h95
1 files changed, 76 insertions, 19 deletions
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index 88d0e6e..dd48cbd 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -54,32 +54,78 @@ struct MatchedFragment
std::string fragment_ident;
size_t token_offset_begin;
size_t token_offset_end;
- size_t match_amount;
MatchedFragment (std::string identifier, size_t token_offset_begin,
- size_t token_offset_end, size_t match_amount = 1)
+ size_t token_offset_end)
: fragment_ident (identifier), token_offset_begin (token_offset_begin),
- token_offset_end (token_offset_end), match_amount (match_amount)
+ token_offset_end (token_offset_end)
+ {}
+
+ /**
+ * Empty constructor for uninitialized fragments
+ */
+ MatchedFragment () : MatchedFragment ("", 0, 0) {}
+
+ std::string as_string () const
+ {
+ return fragment_ident + "=" + std::to_string (token_offset_begin) + ":"
+ + std::to_string (token_offset_end);
+ }
+};
+
+class MatchedFragmentContainer
+{
+public:
+ MatchedFragmentContainer (std::vector<MatchedFragment> fragments)
+ : fragments (fragments)
{}
/**
* Create a valid fragment matched zero times. This is useful for repetitions
* which allow the absence of a fragment, such as * and ?
*/
- static MatchedFragment zero (std::string identifier)
+ static MatchedFragmentContainer zero ()
{
- // We don't need offsets since there is "no match"
- return MatchedFragment (identifier, 0, 0, 0);
+ return MatchedFragmentContainer ({});
}
- std::string as_string () const
+ /**
+ * Create a valid fragment matched one time
+ */
+ static MatchedFragmentContainer one (MatchedFragment fragment)
{
- return fragment_ident + "=" + std::to_string (token_offset_begin) + ":"
- + std::to_string (token_offset_end) + " (matched "
- + std::to_string (match_amount) + " times)";
+ return MatchedFragmentContainer ({fragment});
}
- void set_match_amount (size_t new_amount) { match_amount = new_amount; }
+ /**
+ * Add a matched fragment to the container
+ */
+ void add_fragment (MatchedFragment fragment)
+ {
+ fragments.emplace_back (fragment);
+ }
+
+ size_t get_match_amount () const { return fragments.size (); }
+ const std::vector<MatchedFragment> &get_fragments () const
+ {
+ return fragments;
+ }
+ // const std::string &get_fragment_name () const { return fragment_name; }
+
+ bool is_single_fragment () const { return get_match_amount () == 1; }
+ const MatchedFragment get_single_fragment () const
+ {
+ rust_assert (get_match_amount () == 1);
+
+ return fragments[0];
+ }
+
+private:
+ /**
+ * Fragments matched `match_amount` times. This can be an empty vector
+ * in case having zero matches is allowed (i.e ? or * operators)
+ */
+ std::vector<MatchedFragment> fragments;
};
class SubstitutionScope
@@ -89,18 +135,21 @@ public:
void push () { stack.push_back ({}); }
- std::map<std::string, std::vector<MatchedFragment>> pop ()
+ std::map<std::string, MatchedFragmentContainer> pop ()
{
auto top = stack.back ();
stack.pop_back ();
return top;
}
- std::map<std::string, std::vector<MatchedFragment>> &peek ()
+ std::map<std::string, MatchedFragmentContainer> &peek ()
{
return stack.back ();
}
+ /**
+ * Insert a new matched fragment into the current substitution map
+ */
void insert_fragment (MatchedFragment fragment)
{
auto &current_map = stack.back ();
@@ -108,19 +157,27 @@ public:
if (it == current_map.end ())
{
- auto new_frags = std::vector<MatchedFragment> ();
- new_frags.emplace_back (fragment);
- current_map.insert ({fragment.fragment_ident, new_frags});
+ current_map.insert (
+ {fragment.fragment_ident, MatchedFragmentContainer::one (fragment)});
}
else
{
auto &frags = it->second;
- frags.emplace_back (fragment);
+ frags.add_fragment (fragment);
}
}
+ void insert_matches (std::string key, MatchedFragmentContainer matches)
+ {
+ auto &current_map = stack.back ();
+ auto it = current_map.find (key);
+ rust_assert (it == current_map.end ());
+
+ current_map.insert ({key, matches});
+ }
+
private:
- std::vector<std::map<std::string, std::vector<MatchedFragment>>> stack;
+ std::vector<std::map<std::string, MatchedFragmentContainer>> stack;
};
// Object used to store shared data (between functions) for macro expansion.
@@ -174,7 +231,7 @@ struct MacroExpander
AST::ASTFragment transcribe_rule (
AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree,
- std::map<std::string, std::vector<MatchedFragment>> &matched_fragments,
+ std::map<std::string, MatchedFragmentContainer> &matched_fragments,
bool semicolon, ContextType ctx);
bool match_fragment (Parser<MacroInvocLexer> &parser,