@@ -3905,20 +3905,58 @@ MacroExpander::substitute_metavar (
3905
3905
return expanded;
3906
3906
}
3907
3907
3908
+ std::vector<std::unique_ptr<AST::Token>>
3909
+ MacroExpander::substitute_repetition (
3910
+ std::vector<std::unique_ptr<AST::Token>> &input,
3911
+ std::map<std::string, MatchedFragment> &fragments,
3912
+ std::vector<std::unique_ptr<AST::Token>> &pattern)
3913
+ {
3914
+ // If the repetition is not anything we know (ie no declared metavars, or
3915
+ // metavars which aren't present in the fragment), we can just error out. No
3916
+ // need to paste the tokens as if nothing had happened.
3917
+ for (auto &token : pattern)
3918
+ rust_debug (" [repetition pattern]: %s" , token->as_string ().c_str ());
3919
+
3920
+ return std::vector<std::unique_ptr<AST::Token>> ();
3921
+ }
3922
+
3908
3923
std::pair<std::vector<std::unique_ptr<AST::Token>>, size_t >
3909
3924
MacroExpander::substitute_token (
3925
+ std::vector<std::unique_ptr<AST::Token>> ¯o,
3910
3926
std::vector<std::unique_ptr<AST::Token>> &input,
3911
- std::map<std::string, MatchedFragment> &fragments,
3912
- std::unique_ptr<AST::Token> &token)
3927
+ std::map<std::string, MatchedFragment> &fragments, size_t token_idx)
3913
3928
{
3929
+ auto &token = macro.at (token_idx);
3914
3930
switch (token->get_id ())
3915
3931
{
3916
3932
case IDENTIFIER:
3917
3933
rust_debug (" expanding metavar" );
3918
3934
return {substitute_metavar (input, fragments, token), 1 };
3919
- case LEFT_PAREN:
3920
- rust_debug (" expanding repetition" );
3921
- break ;
3935
+ case LEFT_PAREN: {
3936
+ // We need to parse up until the closing delimiter and expand this
3937
+ // fragment->n times.
3938
+ rust_debug (" expanding repetition" );
3939
+ std::vector<std::unique_ptr<AST::Token>> repetition_pattern;
3940
+ for (size_t rep_idx = token_idx + 1 ;
3941
+ rep_idx < macro.size ()
3942
+ && macro.at (rep_idx)->get_id () != RIGHT_PAREN;
3943
+ rep_idx++)
3944
+ repetition_pattern.emplace_back (macro.at (rep_idx)->clone_token ());
3945
+
3946
+ // FIXME: This skips whitespaces... Is that okay??
3947
+ // FIXME: Is there any existing parsing function that allows us to parse
3948
+ // a macro pattern?
3949
+
3950
+ // FIXME: Add error handling in the case we haven't found a matching
3951
+ // closing delimiter
3952
+
3953
+ // FIXME: We need to parse the repetition token now
3954
+
3955
+ return {
3956
+ substitute_repetition (input, fragments, repetition_pattern),
3957
+ // + 2 for the opening and closing parenthesis which are mandatory
3958
+ repetition_pattern.size () + 2 };
3959
+ }
3922
3960
// TODO: We need to check if the $ was alone. In that case, do
3923
3961
// not error out: Simply act as if there was an empty identifier
3924
3962
// with no associated fragment and paste the dollar sign in the
@@ -3956,10 +3994,9 @@ MacroExpander::substitute_tokens (
3956
3994
auto &tok = macro.at (i);
3957
3995
if (tok->get_id () == DOLLAR_SIGN)
3958
3996
{
3959
- auto &next_tok = macro.at (i + 1 );
3960
3997
// Aaaaah, if only we had C++17 :)
3961
3998
// auto [expanded, tok_to_skip] = ...
3962
- auto p = substitute_token (input, fragments, next_tok );
3999
+ auto p = substitute_token (macro, input, fragments, i + 1 );
3963
4000
auto expanded = std::move (p.first );
3964
4001
auto tok_to_skip = p.second ;
3965
4002
0 commit comments