From 1c544172857a5e1d9f321238d828f864364a005a Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 19 Oct 2023 21:07:43 +0200 Subject: [PATCH] fix: Reduce the amount of backtracing when parsing simple declarations --- src/parser/cxx/parser.cc | 88 +++++++++++++++++++++++----------------- src/parser/cxx/parser.h | 9 ++-- 2 files changed, 54 insertions(+), 43 deletions(-) diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index ab93ae12..c20b598f 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -3793,60 +3793,59 @@ auto Parser::parse_structured_binding(DeclarationAST*& yyast, return true; } -auto Parser::parse_function_definition( +auto Parser::parse_simple_declaration( DeclarationAST*& yyast, List* attributes, List* declSpecifierList, const DeclSpecs& specs, const std::vector& templateDeclarations, BindingContext ctx) -> bool { - LookaheadParser lookahead{this}; - - if (!context_allows_function_definition(ctx)) return false; - DeclaratorAST* declarator = nullptr; Decl decl{specs}; if (!parse_declarator(declarator, decl)) return false; - auto functionDeclarator = getFunctionPrototype(declarator); - if (!functionDeclarator) return false; + auto lookat_function_definition = [&] { + if (!context_allows_function_definition(ctx)) return false; - RequiresClauseAST* requiresClause = nullptr; - (void)parse_requires_clause(requiresClause); + LookaheadParser lookahead{this}; - if (!lookat_function_body()) return false; + auto functionDeclarator = getFunctionPrototype(declarator); + if (!functionDeclarator) return false; - if (ctx == BindingContext::kTemplate) { - mark_maybe_template_name(declarator); - } + RequiresClauseAST* requiresClause = nullptr; + (void)parse_requires_clause(requiresClause); - FunctionBodyAST* functionBody = nullptr; - if (!parse_function_body(functionBody)) parse_error("expected function body"); + if (!lookat_function_body()) return false; - lookahead.commit(); + if (ctx == BindingContext::kTemplate) { + mark_maybe_template_name(declarator); + } - auto ast = new (pool_) FunctionDefinitionAST(); - yyast = ast; + FunctionBodyAST* functionBody = nullptr; + if (!parse_function_body(functionBody)) + parse_error("expected function body"); - ast->attributeList = attributes; - ast->declSpecifierList = declSpecifierList; - ast->declarator = declarator; - ast->requiresClause = requiresClause; - ast->functionBody = functionBody; + lookahead.commit(); - if (classDepth_) pendingFunctionDefinitions_.push_back(ast); + auto ast = new (pool_) FunctionDefinitionAST(); + yyast = ast; - return true; -} + ast->attributeList = attributes; + ast->declSpecifierList = declSpecifierList; + ast->declarator = declarator; + ast->requiresClause = requiresClause; + ast->functionBody = functionBody; + + if (classDepth_) pendingFunctionDefinitions_.push_back(ast); + + return true; + }; + + if (lookat_function_definition()) return true; -auto Parser::parse_simple_declaration( - DeclarationAST*& yyast, List* attributes, - List* declSpecifierList, const DeclSpecs& specs, - const std::vector& templateDeclarations, - BindingContext ctx) -> bool { List* initDeclaratorList = nullptr; auto declIt = &initDeclaratorList; InitDeclaratorAST* initDeclarator = nullptr; - if (!parse_init_declarator(initDeclarator, specs)) return false; + if (!parse_init_declarator(initDeclarator, declarator, specs)) return false; if (ctx == BindingContext::kTemplate) { auto declarator = initDeclarator->declarator; @@ -3893,6 +3892,17 @@ auto Parser::parse_simple_declaration( List* attributes = nullptr; parse_optional_attribute_specifier_seq(attributes); + if (SourceLocation semicolonLoc; + ctx != BindingContext::kTemplate && attributes && + match(TokenKind::T_SEMICOLON, semicolonLoc)) { + auto ast = new (pool_) AttributeDeclarationAST(); + yyast = ast; + + ast->attributeList = attributes; + ast->semicolonLoc = semicolonLoc; + return true; + } + if (parse_template_class_declaration(yyast, attributes, templateDeclarations, ctx)) return true; @@ -3918,11 +3928,9 @@ auto Parser::parse_simple_declaration( if (parse_type_or_forward_declaration(yyast, attributes, declSpecifierList, specs, templateDeclarations, ctx)) return true; - else if (parse_structured_binding(yyast, attributes, declSpecifierList, specs, - ctx)) - return true; - else if (parse_function_definition(yyast, attributes, declSpecifierList, - specs, templateDeclarations, ctx)) + + if (parse_structured_binding(yyast, attributes, declSpecifierList, specs, + ctx)) return true; return parse_simple_declaration(yyast, attributes, declSpecifierList, specs, @@ -4919,6 +4927,12 @@ auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast, Decl decl{specs}; if (!parse_declarator(declarator, decl)) return false; + return parse_init_declarator(yyast, declarator, specs); +} + +auto Parser::parse_init_declarator(InitDeclaratorAST*& yyast, + DeclaratorAST* declarator, + const DeclSpecs& specs) -> bool { RequiresClauseAST* requiresClause = nullptr; ExpressionAST* initializer = nullptr; diff --git a/src/parser/cxx/parser.h b/src/parser/cxx/parser.h index 56c65c10..b15fc544 100644 --- a/src/parser/cxx/parser.h +++ b/src/parser/cxx/parser.h @@ -353,12 +353,6 @@ class Parser final { List* declSpecifierList, const DeclSpecs& specs, BindingContext ctx) -> bool; - [[nodiscard]] auto parse_function_definition( - DeclarationAST*& yyast, List* attributes, - List* declSpecifierList, const DeclSpecs& specs, - const std::vector& templateDeclarations, - BindingContext ctx) -> bool; - [[nodiscard]] auto parse_simple_declaration( DeclarationAST*& yyast, List* attributes, List* declSpecifierList, const DeclSpecs& specs, @@ -425,6 +419,9 @@ class Parser final { DeclSpecs& specs) -> bool; [[nodiscard]] auto parse_init_declarator(InitDeclaratorAST*& yyast, const DeclSpecs& specs) -> bool; + [[nodiscard]] auto parse_init_declarator(InitDeclaratorAST*& yyast, + DeclaratorAST* declarator, + const DeclSpecs& specs) -> bool; [[nodiscard]] auto parse_declarator_initializer( RequiresClauseAST*& requiresClause, ExpressionAST*& yyast) -> bool; void parse_optional_declarator_or_abstract_declarator(DeclaratorAST*& yyast,