diff options
author | Owen Avery <powerboat9.gamer@gmail.com> | 2023-06-03 17:40:18 -0400 |
---|---|---|
committer | CohenArthur <arthur.cohen@embecosm.com> | 2023-06-30 08:01:24 +0000 |
commit | 40b4f94e9597627fa57d77a87fd8ac0a187f4a7d (patch) | |
tree | 3b833bb32b48b85a273b086af22694ece30ae8e6 /gcc | |
parent | 7af86eaaffec8cab5ad80e242480fe9f6c1ffaa6 (diff) | |
download | gcc-40b4f94e9597627fa57d77a87fd8ac0a187f4a7d.zip gcc-40b4f94e9597627fa57d77a87fd8ac0a187f4a7d.tar.gz gcc-40b4f94e9597627fa57d77a87fd8ac0a187f4a7d.tar.bz2 |
Improve macro repetition handling
gcc/rust/ChangeLog:
* expand/rust-macro-expand.cc
(MacroExpander::match_matcher): Remove append_fragment inside repetitions.
(MacroExpander::match_n_matches): Use sub_stack push/pop to handle repetitions.
(MatchedFragmentContainer::add_fragment): Add MatchedFragmentContainer accepting version.
* expand/rust-macro-expand.h
(MatchedFragmentContainer::add_fragment): Likewise.
(MatchedFragmentContainerRepetition::add_fragment): Likewise.
(SubstititionScope::append_fragment): Likewise.
gcc/testsuite/ChangeLog:
* rust/compile/macro56.rs: New test.
Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 36 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.h | 34 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/macro56.rs | 9 |
3 files changed, 63 insertions, 16 deletions
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 7cacb39..e313e1a 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -501,14 +501,9 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser, // matched fragment get the offset in the token stream size_t offs_end = source.get_offs (); - if (in_repetition) - sub_stack.append_fragment ( - MatchedFragment (fragment->get_ident ().as_string (), - offs_begin, offs_end)); - else - sub_stack.insert_metavar ( - MatchedFragment (fragment->get_ident ().as_string (), - offs_begin, offs_end)); + sub_stack.insert_metavar ( + MatchedFragment (fragment->get_ident ().as_string (), offs_begin, + offs_end)); } break; @@ -598,6 +593,7 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser, if (!match_token (parser, *rep.get_sep ())) break; + sub_stack.push (); bool valid_current_match = false; for (auto &match : matches) { @@ -612,13 +608,7 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser, // matched fragment get the offset in the token stream size_t offs_end = source.get_offs (); - // The main difference with match_matcher happens here: Instead - // of inserting a new fragment, we append to one. If that - // fragment does not exist, then the operation is similar to - // `insert_fragment` with the difference that we are not - // creating a metavariable, but a repetition of one, which is - // really different. - sub_stack.append_fragment ( + sub_stack.insert_metavar ( MatchedFragment (fragment->get_ident ().as_string (), offs_begin, offs_end)); } @@ -645,6 +635,12 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser, break; } } + auto old_stack = sub_stack.pop (); + + // nest metavars into repetitions + for (auto &ent : old_stack) + sub_stack.append_fragment (ent.first, std::move (ent.second)); + // If we've encountered an error once, stop trying to match more // repetitions if (!valid_current_match) @@ -1201,6 +1197,16 @@ MatchedFragmentContainer::add_fragment (MatchedFragment fragment) .add_fragment (fragment); } +void +MatchedFragmentContainer::add_fragment ( + std::unique_ptr<MatchedFragmentContainer> fragment) +{ + rust_assert (!is_single_fragment ()); + + return static_cast<MatchedFragmentContainerRepetition &> (*this) + .add_fragment (std::move (fragment)); +} + std::unique_ptr<MatchedFragmentContainer> MatchedFragmentContainer::zero () { diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index 19e71f7..e566d5d 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -111,6 +111,11 @@ public: */ void add_fragment (MatchedFragment fragment); + /** + * Add a matched fragment to the container + */ + void add_fragment (std::unique_ptr<MatchedFragmentContainer> fragment); + // const std::string &get_fragment_name () const { return fragment_name; } bool is_single_fragment () const { return get_kind () == Kind::MetaVar; } @@ -155,7 +160,15 @@ public: */ void add_fragment (MatchedFragment fragment) { - fragments.emplace_back (metavar (fragment)); + add_fragment (metavar (fragment)); + } + + /** + * Add a matched fragment to the container + */ + void add_fragment (std::unique_ptr<MatchedFragmentContainer> fragment) + { + fragments.emplace_back (std::move (fragment)); } virtual Kind get_kind () const { return Kind::Repetition; } @@ -227,6 +240,25 @@ public: it->second->add_fragment (fragment); } + /** + * Append a new matched fragment to a repetition into the current substitution + * map + */ + void append_fragment (std::string ident, + std::unique_ptr<MatchedFragmentContainer> fragment) + { + auto ¤t_map = stack.back (); + auto it = current_map.find (ident); + + if (it == current_map.end ()) + it = current_map + .emplace (ident, std::unique_ptr<MatchedFragmentContainer> ( + new MatchedFragmentContainerRepetition ())) + .first; + + it->second->add_fragment (std::move (fragment)); + } + void insert_matches (std::string key, std::unique_ptr<MatchedFragmentContainer> matches) { diff --git a/gcc/testsuite/rust/compile/macro56.rs b/gcc/testsuite/rust/compile/macro56.rs new file mode 100644 index 0000000..bf42a64 --- /dev/null +++ b/gcc/testsuite/rust/compile/macro56.rs @@ -0,0 +1,9 @@ +macro_rules! check { + (a, b, c ; x, y, z; e, r; a) => {} +} + +macro_rules! foo { + ($($($i:ident),*);*) => {check!($($($i),*);*);} +} + +foo!(a, b, c ; x, y, z; e, r; a); |