From 33544f79849a5b747d84fea0fc2be25e208e3ab4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 8 Jun 2023 20:14:47 +0100 Subject: gccrs: Parse semicolons in more cases for statement macros gcc/rust/ChangeLog: * ast/rust-ast.h (MacroInvocation::add_semicolon): New method. * ast/rust-macro.h (MacroInvocation::add_semicolon): Add override. * ast/rust-stmt.h (ExprStmt::add_semicolon): Add override. * expand/rust-macro-expand.cc (parse_many): Pass enum by value. (transcribe_many_stmts): Parse statements with semicolons. * parse/rust-parse-impl.h (Parser::parse_let_stmt): Work around lack of NT tokens. (Parser::parse_expr_stmt): Handle statements at end of macro expansions. * parse/rust-parse.h (struct ParseRestrictions): Additional flag. gcc/testsuite/ChangeLog: * rust/compile/macro53.rs: New test. Signed-off-by: Matthew Jasper --- gcc/rust/parse/rust-parse-impl.h | 37 +++++++++++++++++++++++++++++++------ gcc/rust/parse/rust-parse.h | 3 +++ 2 files changed, 34 insertions(+), 6 deletions(-) (limited to 'gcc/rust/parse') diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index d6b045b..c9dbee2 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -6348,8 +6348,16 @@ Parser::parse_let_stmt (AST::AttrVec outer_attrs, } if (restrictions.consume_semi) - if (!skip_token (SEMICOLON)) - return nullptr; + { + // `stmt` macro variables are parsed without a semicolon, but should be + // parsed as a full statement when interpolated. This should be handled + // by having the interpolated statement be distinguishable from normal + // tokens, e.g. by NT tokens. + if (restrictions.allow_close_after_expr_stmt) + maybe_skip_token (SEMICOLON); + else if (!skip_token (SEMICOLON)) + return nullptr; + } return std::unique_ptr ( new AST::LetStmt (std::move (pattern), std::move (expr), std::move (type), @@ -7289,10 +7297,27 @@ Parser::parse_expr_stmt (AST::AttrVec outer_attrs, if (restrictions.consume_semi) { - if (skip_token (SEMICOLON)) - has_semi = true; - else if (expr->is_expr_without_block ()) - return nullptr; + if (maybe_skip_token (SEMICOLON)) + { + has_semi = true; + } + else if (!expr->is_expr_without_block ()) + { + if (restrictions.allow_close_after_expr_stmt) + { + TokenId id = lexer.peek_token ()->get_id (); + if (id != RIGHT_PAREN && id != RIGHT_CURLY && id != RIGHT_SQUARE) + { + expect_token (SEMICOLON); + return nullptr; + } + } + else + { + expect_token (SEMICOLON); + return nullptr; + } + } } return std::unique_ptr ( diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 315d3fc..74313df 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -87,6 +87,9 @@ struct ParseRestrictions bool expr_can_be_null = false; bool expr_can_be_stmt = false; bool consume_semi = true; + /* Macro invocations that are statements can expand without a semicolon after + * the final statement, if it's an expression statement. */ + bool allow_close_after_expr_stmt = false; }; // Parser implementation for gccrs. -- cgit v1.1