diff options
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.cpp | 32 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.h | 1 |
2 files changed, 31 insertions, 2 deletions
diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 86eeaa2f2a..11656bd47f 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -66,6 +66,8 @@ public: int DebugRule::depth = 0; +const int declarationsInRowAllowedToFail = 2; + inline bool lookAtAssignmentOperator(int tokenKind) { switch (tokenKind) { @@ -310,6 +312,20 @@ bool Parser::skipUntil(int token) return false; } +void Parser::skipUntilAfterSemicolonOrRightBrace() +{ + while (int tk = LA()) { + switch (tk) { + case T_SEMICOLON: + case T_RBRACE: + consumeToken(); + return; + default: + consumeToken(); + } + } +} + void Parser::skipUntilDeclaration() { for (; ; consumeToken()) { @@ -626,19 +642,25 @@ bool Parser::parseTranslationUnit(TranslationUnitAST *&node) TranslationUnitAST *ast = new (_pool) TranslationUnitAST; DeclarationListAST **decl = &ast->declaration_list; + int declarationsInRowFailedToParse = 0; + while (LA()) { unsigned start_declaration = cursor(); DeclarationAST *declaration = 0; if (parseDeclaration(declaration)) { + declarationsInRowFailedToParse = 0; *decl = new (_pool) DeclarationListAST; (*decl)->value = declaration; decl = &(*decl)->next; } else { error(start_declaration, "expected a declaration"); rewind(start_declaration + 1); - skipUntilDeclaration(); + if (++declarationsInRowFailedToParse == declarationsInRowAllowedToFail) + skipUntilAfterSemicolonOrRightBrace(); + else + skipUntilDeclaration(); } @@ -787,6 +809,8 @@ bool Parser::parseLinkageBody(DeclarationAST *&node) ast->lbrace_token = consumeToken(); DeclarationListAST **declaration_ptr = &ast->declaration_list; + int declarationsInRowFailedToParse = 0; + while (int tk = LA()) { if (tk == T_RBRACE) break; @@ -794,13 +818,17 @@ bool Parser::parseLinkageBody(DeclarationAST *&node) unsigned start_declaration = cursor(); DeclarationAST *declaration = 0; if (parseDeclaration(declaration)) { + declarationsInRowFailedToParse = 0; *declaration_ptr = new (_pool) DeclarationListAST; (*declaration_ptr)->value = declaration; declaration_ptr = &(*declaration_ptr)->next; } else { error(start_declaration, "expected a declaration"); rewind(start_declaration + 1); - skipUntilDeclaration(); + if (++declarationsInRowFailedToParse == declarationsInRowAllowedToFail) + skipUntilAfterSemicolonOrRightBrace(); + else + skipUntilDeclaration(); } _templateArgumentList.clear(); diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h index 4a2a6dfb7e..923b0c4dc8 100644 --- a/src/libs/3rdparty/cplusplus/Parser.h +++ b/src/libs/3rdparty/cplusplus/Parser.h @@ -254,6 +254,7 @@ public: bool parseDesignator(DesignatorAST *&node); bool skipUntil(int token); + void skipUntilAfterSemicolonOrRightBrace(); void skipUntilDeclaration(); bool skipUntilStatement(); bool skip(int l, int r); |