aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/expand/rust-macro-expand.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/expand/rust-macro-expand.cc')
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc158
1 files changed, 123 insertions, 35 deletions
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 3389f20..3bdb8c6 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -786,7 +786,6 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
std::function<AST::SingleASTNode ()> parse_fn)
{
std::vector<AST::SingleASTNode> nodes;
-
while (true)
{
if (parser.peek_current_token ()->get_id () == delimiter)
@@ -815,6 +814,68 @@ transcribe_many_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
}
/**
+ * Transcribe 0 or more external items from a macro invocation
+ *
+ * @param parser Parser to extract items from
+ * @param delimiter Id of the token on which parsing should stop
+ */
+static std::vector<AST::SingleASTNode>
+transcribe_many_ext (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
+{
+ return parse_many (parser, delimiter, [&parser] () {
+ auto item = parser.parse_external_item ();
+ return AST::SingleASTNode (std::move (item));
+ });
+}
+
+/**
+ * Transcribe 0 or more trait items from a macro invocation
+ *
+ * @param parser Parser to extract items from
+ * @param delimiter Id of the token on which parsing should stop
+ */
+static std::vector<AST::SingleASTNode>
+transcribe_many_trait_items (Parser<MacroInvocLexer> &parser,
+ TokenId &delimiter)
+{
+ return parse_many (parser, delimiter, [&parser] () {
+ auto item = parser.parse_trait_item ();
+ return AST::SingleASTNode (std::move (item));
+ });
+}
+
+/**
+ * Transcribe 0 or more impl items from a macro invocation
+ *
+ * @param parser Parser to extract items from
+ * @param delimiter Id of the token on which parsing should stop
+ */
+static std::vector<AST::SingleASTNode>
+transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
+{
+ return parse_many (parser, delimiter, [&parser] () {
+ auto item = parser.parse_inherent_impl_item ();
+ return AST::SingleASTNode (std::move (item));
+ });
+}
+
+/**
+ * Transcribe 0 or more trait impl items from a macro invocation
+ *
+ * @param parser Parser to extract items from
+ * @param delimiter Id of the token on which parsing should stop
+ */
+static std::vector<AST::SingleASTNode>
+transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
+ TokenId &delimiter)
+{
+ return parse_many (parser, delimiter, [&parser] () {
+ auto item = parser.parse_trait_impl_item ();
+ return AST::SingleASTNode (std::move (item));
+ });
+}
+
+/**
* Transcribe 0 or more statements from a macro invocation
*
* @param parser Parser to extract statements from
@@ -845,6 +906,60 @@ transcribe_expression (Parser<MacroInvocLexer> &parser)
return {AST::SingleASTNode (std::move (expr))};
}
+static std::vector<AST::SingleASTNode>
+transcribe_on_delimiter (Parser<MacroInvocLexer> &parser, bool semicolon,
+ AST::DelimType delimiter, TokenId last_token_id)
+{
+ if (semicolon || delimiter == AST::DelimType::CURLY)
+ return transcribe_many_stmts (parser, last_token_id);
+ else
+ return transcribe_expression (parser);
+} // namespace Rust
+
+static std::vector<AST::SingleASTNode>
+transcribe_context (MacroExpander::ContextType ctx,
+ Parser<MacroInvocLexer> &parser, bool semicolon,
+ AST::DelimType delimiter, TokenId last_token_id)
+{
+ // The flow-chart in order to choose a parsing function is as follows:
+ //
+ // [switch special context]
+ // -- Item --> parser.parse_item();
+ // -- Trait --> parser.parse_trait_item();
+ // -- Impl --> parser.parse_impl_item();
+ // -- Extern --> parser.parse_extern_item();
+ // -- None --> [has semicolon?]
+ // -- Yes --> parser.parse_stmt();
+ // -- No --> [switch invocation.delimiter()]
+ // -- { } --> parser.parse_stmt();
+ // -- _ --> parser.parse_expr(); // once!
+
+ // If there is a semicolon OR we are expanding a MacroInvocationSemi, then
+ // we can parse multiple items. Otherwise, parse *one* expression
+
+ switch (ctx)
+ {
+ case MacroExpander::ContextType::ITEM:
+ return transcribe_many_items (parser, last_token_id);
+ break;
+ case MacroExpander::ContextType::TRAIT:
+ return transcribe_many_trait_items (parser, last_token_id);
+ break;
+ case MacroExpander::ContextType::IMPL:
+ return transcribe_many_impl_items (parser, last_token_id);
+ break;
+ case MacroExpander::ContextType::TRAIT_IMPL:
+ return transcribe_many_trait_impl_items (parser, last_token_id);
+ break;
+ case MacroExpander::ContextType::EXTERN:
+ return transcribe_many_ext (parser, last_token_id);
+ break;
+ default:
+ return transcribe_on_delimiter (parser, semicolon, delimiter,
+ last_token_id);
+ }
+}
+
AST::ASTFragment
MacroExpander::transcribe_rule (
AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree,
@@ -864,18 +979,15 @@ MacroExpander::transcribe_rule (
std::vector<std::unique_ptr<AST::Token>> substituted_tokens
= substitute_context.substitute_tokens ();
+ // handy for debugging
+ // for (auto &tok : substituted_tokens)
+ // rust_debug ("[tok] %s", tok->as_string ().c_str ());
+
// parse it to an ASTFragment
MacroInvocLexer lex (std::move (substituted_tokens));
Parser<MacroInvocLexer> parser (std::move (lex));
- // handy for debugging
- // for (auto &tok : substituted_tokens)
- // {
- // rust_debug ("tok: [%s]", tok->as_string ().c_str ());
- // }
-
auto last_token_id = TokenId::RIGHT_CURLY;
- std::vector<AST::SingleASTNode> nodes;
// this is used so we can check that we delimit the stream correctly.
switch (transcribe_tree.get_delim_type ())
@@ -905,33 +1017,9 @@ MacroExpander::transcribe_rule (
// as a statement (either via ExpressionStatement or
// MacroInvocationWithSemi)
- // The flow-chart in order to choose a parsing function is as follows:
- //
- // [is in item context?]
- // -- Yes --> parser.parse_item();
- // -- No --> [has semicolon?]
- // -- Yes --> parser.parse_stmt();
- // -- No --> [switch invocation.delimiter()]
- // -- { } --> parser.parse_stmt();
- // -- _ --> parser.parse_expr();
-
- // If there is a semicolon OR we are expanding a MacroInvocationSemi, then
- // we can parse multiple items. Otherwise, parse *one* expression
-
- if (ctx == ContextType::ITEM)
- nodes = transcribe_many_items (parser, last_token_id);
- else if (semicolon)
- nodes = transcribe_many_stmts (parser, last_token_id);
- else
- switch (invoc_token_tree.get_delim_type ())
- {
- case AST::CURLY:
- nodes = transcribe_many_stmts (parser, last_token_id);
- break;
- default:
- nodes = transcribe_expression (parser);
- break;
- }
+ auto nodes
+ = transcribe_context (ctx, parser, semicolon,
+ invoc_token_tree.get_delim_type (), last_token_id);
// emit any errors
if (parser.has_errors ())