diff options
author | Raiki Tamura <tamaron1203@gmail.com> | 2022-12-19 01:48:54 +0900 |
---|---|---|
committer | Raiki Tamura <tamaron1203@gmail.com> | 2023-01-10 00:38:52 +0900 |
commit | 9e5769cf45cfc703e807e51b3ad301e123b05b55 (patch) | |
tree | d97961c7c3a95c95bf02dc9b8bc4271eb2a72967 /gcc/rust/parse | |
parent | 0152926ab36ba52153f3f457f6f3bb02bb274073 (diff) | |
download | gcc-9e5769cf45cfc703e807e51b3ad301e123b05b55.zip gcc-9e5769cf45cfc703e807e51b3ad301e123b05b55.tar.gz gcc-9e5769cf45cfc703e807e51b3ad301e123b05b55.tar.bz2 |
Implement declarative macro 2.0 parser
Signed-off-by: Raiki Tamura <tamaron1203@gmail.com>
Diffstat (limited to 'gcc/rust/parse')
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 229 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse.h | 3 |
2 files changed, 177 insertions, 55 deletions
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 864fb86..5f0ee02 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -1023,11 +1023,6 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement) // parse outer attributes for item AST::AttrVec outer_attrs = parse_outer_attributes (); - - // TODO: decide how to deal with VisItem vs MacroItem dichotomy - /* best current solution: catch all keywords that would imply a VisItem in a - * switch and have MacroItem as a last resort */ - const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) @@ -1055,6 +1050,7 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement) case STATIC_TOK: case TRAIT: case IMPL: + case MACRO: /* TODO: implement union keyword but not really because of * context-dependence crappy hack way to parse a union written below to * separate it from the good code. */ @@ -1069,7 +1065,7 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement) case CRATE: case DOLLAR_SIGN: // almost certainly macro invocation semi - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_invocation_semi (std::move (outer_attrs)); break; // crappy hack to do union "keyword" case IDENTIFIER: @@ -1083,19 +1079,18 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement) else if (t->get_str () == "macro_rules") { // macro_rules! macro item - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_rules_def (std::move (outer_attrs)); } else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION || lexer.peek_token (1)->get_id () == EXCLAM) { /* path (probably) or macro invocation, so probably a macro invocation * semi */ - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_invocation_semi (std::move (outer_attrs)); } gcc_fallthrough (); default: // otherwise unrecognised - // return parse_macro_item(std::move(outer_attrs)); add_error (Error (t->get_locus (), "unrecognised token %qs for start of %s", t->get_token_description (), @@ -1326,6 +1321,8 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs) lexer.skip_token (1); // TODO: is this right thing to do? return nullptr; } + case MACRO: + return parse_decl_macro_def (std::move (vis), std::move (outer_attrs)); default: // otherwise vis item clearly doesn't exist, which is not an error // has a catch-all post-switch return to allow other breaks to occur @@ -1334,42 +1331,6 @@ Parser<ManagedTokenSource>::parse_vis_item (AST::AttrVec outer_attrs) return nullptr; } -// Parses a MacroItem (either a MacroInvocationSemi or MacroRulesDefinition). -template <typename ManagedTokenSource> -std::unique_ptr<AST::MacroItem> -Parser<ManagedTokenSource>::parse_macro_item (AST::AttrVec outer_attrs) -{ - const_TokenPtr t = lexer.peek_token (); - - /* dodgy way of detecting macro due to weird context-dependence thing. - * probably can be improved */ - // TODO: ensure that string compare works properly - if (t->get_id () == IDENTIFIER && t->get_str () == "macro_rules") - { - return parse_macro_rules_def (std::move (outer_attrs)); - } - else - { - // DEBUG: TODO: remove - rust_debug ( - "DEBUG - parse_macro_item called and token is not macro_rules"); - if (t->get_id () == IDENTIFIER) - { - rust_debug ("just add to last error: token is not macro_rules and is " - "instead '%s'", - t->get_str ().c_str ()); - } - else - { - rust_debug ("just add to last error: token is not macro_rules and is " - "not an identifier either - it is '%s'", - t->get_token_description ()); - } - - return parse_macro_invocation_semi (std::move (outer_attrs)); - } -} - // Parses a macro rules definition syntax extension whatever thing. template <typename ManagedTokenSource> std::unique_ptr<AST::MacroRulesDefinition> @@ -1503,16 +1464,16 @@ Parser<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs) { // as this is the end, allow recovery (probably) - may change return std::unique_ptr<AST::MacroRulesDefinition> ( - new AST::MacroRulesDefinition ( + AST::MacroRulesDefinition::mbe ( std::move (rule_name), delim_type, std::move (macro_rules), std::move (outer_attrs), macro_locus)); } } return std::unique_ptr<AST::MacroRulesDefinition> ( - new AST::MacroRulesDefinition (std::move (rule_name), delim_type, - std::move (macro_rules), - std::move (outer_attrs), macro_locus)); + AST::MacroRulesDefinition::mbe (std::move (rule_name), delim_type, + std::move (macro_rules), + std::move (outer_attrs), macro_locus)); } else { @@ -1532,6 +1493,165 @@ Parser<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs) } } +// Parses a declarative macro 2.0 definition. +template <typename ManagedTokenSource> +std::unique_ptr<AST::MacroRulesDefinition> +Parser<ManagedTokenSource>::parse_decl_macro_def (AST::Visibility vis, + AST::AttrVec outer_attrs) +{ + // ensure that first token is identifier saying "macro" + const_TokenPtr t = lexer.peek_token (); + if (t->get_id () != MACRO) + { + Error error ( + t->get_locus (), + "declarative macro definition does not start with %<macro%>"); + add_error (std::move (error)); + + // skip after somewhere? + return nullptr; + } + lexer.skip_token (); + Location macro_locus = t->get_locus (); + + // parse macro name + const_TokenPtr ident_tok = expect_token (IDENTIFIER); + if (ident_tok == nullptr) + { + return nullptr; + } + Identifier rule_name = ident_tok->get_str (); + + t = lexer.peek_token (); + if (t->get_id () == LEFT_PAREN) + { + // single definiton of macro rule + // e.g. `macro foo($e:expr) {}` + + // parse macro matcher + Location locus = lexer.peek_token ()->get_locus (); + AST::MacroMatcher matcher = parse_macro_matcher (); + if (matcher.is_error ()) + return nullptr; + + // check delimiter of macro matcher + if (matcher.get_delim_type () != AST::DelimType::PARENS) + { + Error error (locus, "only parenthesis can be used for a macro " + "matcher in declarative macro definition"); + add_error (std::move (error)); + return nullptr; + } + + Location transcriber_loc = lexer.peek_token ()->get_locus (); + AST::DelimTokenTree delim_tok_tree = parse_delim_token_tree (); + AST::MacroTranscriber transcriber (delim_tok_tree, transcriber_loc); + + if (transcriber.get_token_tree ().get_delim_type () + != AST::DelimType::CURLY) + { + Error error (transcriber_loc, + "only braces can be used for a macro transcriber " + "in declarative macro definition"); + add_error (std::move (error)); + return nullptr; + } + + AST::MacroRule macro_rule + = AST::MacroRule (std::move (matcher), std::move (transcriber), locus); + std::vector<AST::MacroRule> macro_rules; + macro_rules.push_back (macro_rule); + + return std::unique_ptr<AST::MacroRulesDefinition> ( + AST::MacroRulesDefinition::decl_macro (std::move (rule_name), + macro_rules, + std::move (outer_attrs), + macro_locus, vis)); + } + else if (t->get_id () == LEFT_CURLY) + { + // multiple definitions of macro rule separated by comma + // e.g. `macro foo { () => {}, ($e:expr) => {}, }` + + // parse left curly + const_TokenPtr left_curly = expect_token (LEFT_CURLY); + if (left_curly == nullptr) + { + return nullptr; + } + + // parse actual macro rules + std::vector<AST::MacroRule> macro_rules; + + // must be at least one macro rule, so parse it + AST::MacroRule initial_rule = parse_macro_rule (); + if (initial_rule.is_error ()) + { + Error error ( + lexer.peek_token ()->get_locus (), + "required first macro rule in declarative macro definition " + "could not be parsed"); + add_error (std::move (error)); + + // skip after somewhere? + return nullptr; + } + macro_rules.push_back (std::move (initial_rule)); + + t = lexer.peek_token (); + // parse macro rules + while (t->get_id () == COMMA) + { + // skip comma + lexer.skip_token (); + + // don't parse if end of macro rules + if (token_id_matches_delims (lexer.peek_token ()->get_id (), + AST::CURLY)) + { + break; + } + + // try to parse next rule + AST::MacroRule rule = parse_macro_rule (); + if (rule.is_error ()) + { + Error error ( + lexer.peek_token ()->get_locus (), + "failed to parse macro rule in declarative macro definition"); + add_error (std::move (error)); + + return nullptr; + } + + macro_rules.push_back (std::move (rule)); + + t = lexer.peek_token (); + } + + // parse right curly + const_TokenPtr right_curly = expect_token (RIGHT_CURLY); + if (right_curly == nullptr) + { + return nullptr; + } + + return std::unique_ptr<AST::MacroRulesDefinition> ( + AST::MacroRulesDefinition::decl_macro (std::move (rule_name), + std::move (macro_rules), + std::move (outer_attrs), + macro_locus, vis)); + } + else + { + add_error (Error (t->get_locus (), + "unexpected token %qs - expecting delimiters " + "(for a declarative macro definiton)", + t->get_token_description ())); + return nullptr; + } +} + // Parses a semi-coloned (except for full block) macro invocation item. template <typename ManagedTokenSource> std::unique_ptr<AST::MacroInvocation> @@ -5995,6 +6115,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions) case STATIC_TOK: case TRAIT: case IMPL: + case MACRO: /* TODO: implement union keyword but not really because of * context-dependence crappy hack way to parse a union written below to * separate it from the good code. */ @@ -6010,7 +6131,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions) case CRATE: case DOLLAR_SIGN: // almost certainly macro invocation semi - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_invocation_semi (std::move (outer_attrs)); break; // crappy hack to do union "keyword" case IDENTIFIER: @@ -6023,7 +6144,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions) else if (t->get_str () == "macro_rules") { // macro_rules! macro item - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_rules_def (std::move (outer_attrs)); } else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION || lexer.peek_token (1)->get_id () == EXCLAM) @@ -6031,7 +6152,7 @@ Parser<ManagedTokenSource>::parse_stmt (ParseRestrictions restrictions) // FIXME: ensure doesn't take any expressions by mistake /* path (probably) or macro invocation, so probably a macro * invocation semi */ - return parse_macro_item (std::move (outer_attrs)); + return parse_macro_invocation_semi (std::move (outer_attrs)); } gcc_fallthrough (); // TODO: find out how to disable gcc "implicit fallthrough" warning @@ -11685,8 +11806,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr_without_block () else if (t->get_str () == "macro_rules") { // macro_rules! macro item - std::unique_ptr<AST::MacroItem> item ( - parse_macro_item (std::move (outer_attrs))); + std::unique_ptr<AST::Item> item ( + parse_macro_rules_def (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } else if (lexer.peek_token (1)->get_id () == SCOPE_RESOLUTION diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 8449181..5c0fcc3 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -197,6 +197,8 @@ private: AST::DelimTokenTree parse_delim_token_tree (); std::unique_ptr<AST::MacroRulesDefinition> parse_macro_rules_def (AST::AttrVec outer_attrs); + std::unique_ptr<AST::MacroRulesDefinition> + parse_decl_macro_def (AST::Visibility vis, AST::AttrVec outer_attrs); std::unique_ptr<AST::MacroInvocation> parse_macro_invocation_semi (AST::AttrVec outer_attrs); std::unique_ptr<AST::MacroInvocation> @@ -209,7 +211,6 @@ private: // Top-level item-related std::unique_ptr<AST::VisItem> parse_vis_item (AST::AttrVec outer_attrs); - std::unique_ptr<AST::MacroItem> parse_macro_item (AST::AttrVec outer_attrs); // VisItem subclass-related std::unique_ptr<AST::Module> parse_module (AST::Visibility vis, |