aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/parse/rust-parse-impl.h
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2023-01-09 15:48:12 +0000
committerGitHub <noreply@github.com>2023-01-09 15:48:12 +0000
commit3290293e16fa47cf59f0434343c1bf40497ede90 (patch)
treec98859a1c4cd79baaa13435bb072b4d42836b39e /gcc/rust/parse/rust-parse-impl.h
parent48d32bc9cb05ea02ee0dc9d97d86ff1f559fae4f (diff)
parent9e5769cf45cfc703e807e51b3ad301e123b05b55 (diff)
downloadgcc-3290293e16fa47cf59f0434343c1bf40497ede90.zip
gcc-3290293e16fa47cf59f0434343c1bf40497ede90.tar.gz
gcc-3290293e16fa47cf59f0434343c1bf40497ede90.tar.bz2
Merge #1708
1708: Parse declarative macro (decl_macro 2.0) r=CohenArthur a=tamaroning This PR is currentry wip. Opinions and advices are welcome! Co-authored-by: Raiki Tamura <tamaron1203@gmail.com>
Diffstat (limited to 'gcc/rust/parse/rust-parse-impl.h')
-rw-r--r--gcc/rust/parse/rust-parse-impl.h229
1 files changed, 175 insertions, 54 deletions
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 62c39f6..c19fe9b 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1032,11 +1032,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 ())
@@ -1064,6 +1059,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. */
@@ -1078,7 +1074,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:
@@ -1092,19 +1088,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 (),
@@ -1335,6 +1330,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
@@ -1343,42 +1340,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>
@@ -1512,16 +1473,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
{
@@ -1541,6 +1502,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>
@@ -6004,6 +6124,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. */
@@ -6019,7 +6140,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:
@@ -6032,7 +6153,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)
@@ -6040,7 +6161,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
@@ -11711,8 +11832,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