From fe2c9cc16dc35c0f55bea45046d64d0170a0bbc0 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 19 Oct 2009 17:47:49 +0200 Subject: Improved parsing of ambiguous statements. Done with Erik Verbruggen --- src/shared/cplusplus/Parser.cpp | 105 +++++++++++++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 12 deletions(-) (limited to 'src/shared/cplusplus/Parser.cpp') diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index d754b234f4..e60751305a 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -56,7 +56,7 @@ #include #include #include -#include + CPLUSPLUS_BEGIN_NAMESPACE Parser::Parser(TranslationUnit *unit) @@ -2041,10 +2041,68 @@ bool Parser::maybeSimpleExpression(SimpleDeclarationAST *simpleDecl) const { if (! simpleDecl->declarators) { SpecifierAST *spec = simpleDecl->decl_specifier_seq; - if (spec && ! spec->next && spec->asNamedTypeSpecifier()) { + + if (spec && ! spec->next && spec->asNamedTypeSpecifier()) return true; + } + + return false; +} + +bool Parser::isPointerDeclaration(DeclarationStatementAST *ast) const +{ + if (! ast) + return false; + + if (SimpleDeclarationAST *declaration = ast->declaration->asSimpleDeclaration()) { + if (SpecifierAST *spec = declaration->decl_specifier_seq) { + if (spec->asNamedTypeSpecifier() && ! spec->next) { + if (DeclaratorListAST *declarators = declaration->declarators) { + if (DeclaratorAST *declarator = declarators->declarator) { + if (declarator->ptr_operators && declarator->equals_token && declarator->initializer) { + return true; + } + } + } + } } } + + return false; +} + +bool Parser::maybeAmbiguousStatement(DeclarationStatementAST *ast) const +{ + if (! ast) + return false; + + if (SimpleDeclarationAST *declaration = ast->declaration->asSimpleDeclaration()) { + if (SpecifierAST *spec = declaration->decl_specifier_seq) { + if (spec->asNamedTypeSpecifier() && ! spec->next) { + if (DeclaratorListAST *declarators = declaration->declarators) { + if (DeclaratorAST *declarator = declarators->declarator) { + if (declarator->core_declarator && + declarator->core_declarator->asNestedDeclarator()) { + // recognized name(id-expression) + return true; + } + } + } + } + + } else if (DeclaratorListAST *declarators = declaration->declarators) { + // no decl_specifiers... + if (DeclaratorAST *declarator = declarators->declarator) { + if (declarator->postfix_declarators && declarator->postfix_declarators->asFunctionDeclarator() + && ! declarator->initializer) { + return false; + } + } + + return true; + } + } + return false; } @@ -2055,31 +2113,35 @@ bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node) unsigned start = cursor(); bool blocked = blockErrors(true); + if (parseDeclarationStatement(node)) { DeclarationStatementAST *stmt = static_cast(node); - SimpleDeclarationAST *simpleDecl = 0; - if (stmt->declaration) - simpleDecl = stmt->declaration->asSimpleDeclaration(); - if (simpleDecl && simpleDecl->decl_specifier_seq && - ! maybeFunctionCall(simpleDecl) && ! maybeSimpleExpression(simpleDecl)) { + if (isPointerDeclaration(stmt)) { + blockErrors(blocked); + return true; + } + + if (! maybeAmbiguousStatement(stmt)) { unsigned end_of_declaration_statement = cursor(); rewind(start); + StatementAST *expression = 0; - if (! parseExpressionStatement(expression) || cursor() != end_of_declaration_statement) { - rewind(end_of_declaration_statement); - } else { - ExpressionOrDeclarationStatementAST *ast = - new (_pool) ExpressionOrDeclarationStatementAST; + if (parseExpressionStatement(expression) && cursor() == end_of_declaration_statement) { + // it's an ambiguous expression-or-declaration statement. + ExpressionOrDeclarationStatementAST *ast = new (_pool) ExpressionOrDeclarationStatementAST; ast->declaration = node; ast->expression = expression; node = ast; } + + rewind(end_of_declaration_statement); blockErrors(blocked); return true; } } + // it's not a declaration statement. blockErrors(blocked); rewind(start); return parseExpressionStatement(node); @@ -2653,6 +2715,12 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, return false; } + // if there is no valid declarator + // and it doesn't look like a fwd or a class declaration + // then it's not a declarations + if (! declarator && ! maybeForwardOrClassDeclaration(decl_specifier_seq)) + return false; + DeclaratorAST *firstDeclarator = declarator; if (declarator) { @@ -2709,6 +2777,19 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, return false; } +bool Parser::maybeForwardOrClassDeclaration(SpecifierAST *decl_specifier_seq) const +{ + // look at the decl_specifier for possible fwd or class declarations. + if (SpecifierAST *spec = decl_specifier_seq) { + if (! spec->next && (spec->asElaboratedTypeSpecifier() || + spec->asEnumSpecifier() || + spec->asClassSpecifier())) + return true; + } + + return false; +} + bool Parser::parseFunctionBody(StatementAST *&node) { if (_translationUnit->skipFunctionBody()) { -- cgit v1.2.1