diff options
Diffstat (limited to 'gcc/rust/expand/rust-macro-expand.h')
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.h | 95 |
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 ¤t_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 ¤t_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, |