diff options
author | Wang Hoi <wanghoi@126.com> | 2014-05-05 22:56:15 +0800 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@digia.com> | 2014-06-17 16:23:23 +0200 |
commit | c56b999ffff249d4cb7dc7e8026a3297b63ff56d (patch) | |
tree | 007d1f5208cd7e03fdc2eceb4cefe3dd4a12ded8 /src/libs/3rdparty | |
parent | d70485180a676c3d97108bb87ec1c32223ee0f2b (diff) | |
download | qt-creator-c56b999ffff249d4cb7dc7e8026a3297b63ff56d.tar.gz |
C: Parser: Support parsing of c99 designated initializers
In case:
int a[6] = { [4] = 29, [2] = 15 };
struct point { int x, y; };
struct point p = { .y = 3, .x = 2 };
Grammar change when c99 language feature is enabled:
old grammar:
braced-init-list :: '{' initializer-list '}'
new grammar:
braced-init-list :: '{' designated-initializer-list '}'
designated-initializer-list :: designated-initializer (',' designated-initializer )*
designated-initializer :: designator* initializer-clause
designator :: '.' identifier
| '[' constant-expression ']'
Task-number: QTCREATORBUG-1902
Change-Id: Ib99d6f553f8d0f50ba3eff86f3a2e86d73372426
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
Diffstat (limited to 'src/libs/3rdparty')
-rw-r--r-- | src/libs/3rdparty/cplusplus/AST.cpp | 66 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/AST.h | 68 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTClone.cpp | 18 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTMatch0.cpp | 16 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTMatcher.cpp | 28 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTMatcher.h | 2 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTPatternBuilder.h | 22 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTVisit.cpp | 16 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTVisitor.h | 4 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/ASTfwd.h | 4 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.cpp | 48 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Parser.h | 5 | ||||
-rw-r--r-- | src/libs/3rdparty/cplusplus/Token.h | 1 |
13 files changed, 296 insertions, 2 deletions
diff --git a/src/libs/3rdparty/cplusplus/AST.cpp b/src/libs/3rdparty/cplusplus/AST.cpp index 5e166b83b2..dd341db6d9 100644 --- a/src/libs/3rdparty/cplusplus/AST.cpp +++ b/src/libs/3rdparty/cplusplus/AST.cpp @@ -4450,3 +4450,69 @@ unsigned AliasDeclarationAST::lastToken() const return 1; } +/** \generated */ +unsigned DesignatedInitializerAST::firstToken() const +{ + if (designator_list) + if (unsigned candidate = designator_list->firstToken()) + return candidate; + if (equal_token) + return equal_token; + if (initializer) + if (unsigned candidate = initializer->firstToken()) + return candidate; + return 0; +} + +/** \generated */ +unsigned DesignatedInitializerAST::lastToken() const +{ + if (initializer) + if (unsigned candidate = initializer->lastToken()) + return candidate; + if (equal_token) + return equal_token + 1; + if (designator_list) + if (unsigned candidate = designator_list->lastToken()) + return candidate; + return 1; +} + +unsigned DesignatorAST::firstToken() const +{ + if (type == DesignatorAST::Dot) { + if (u.dot.dot_token) + return u.dot.dot_token; + if (u.dot.identifier_token) + return u.dot.identifier_token; + } else if (type == DesignatorAST::Bracket) { + if (u.bracket.lbracket_token) + return u.bracket.lbracket_token; + if (u.bracket.expression) + if (unsigned candidate = u.bracket.expression->firstToken()) + return candidate; + if (u.bracket.rbracket_token) + return u.bracket.rbracket_token; + } + return 0; +} + +unsigned DesignatorAST::lastToken() const +{ + if (type == DesignatorAST::Dot) { + if (u.dot.identifier_token) + return u.dot.identifier_token + 1; + if (u.dot.dot_token) + return u.dot.dot_token + 1; + } else if (type == DesignatorAST::Bracket) { + if (u.bracket.rbracket_token) + return u.bracket.rbracket_token + 1; + if (u.bracket.expression) + if (unsigned candidate = u.bracket.expression->lastToken()) + return candidate; + if (u.bracket.lbracket_token) + return u.bracket.lbracket_token + 1; + } + return 1; +} + diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h index 556f898f6d..41c630aea8 100644 --- a/src/libs/3rdparty/cplusplus/AST.h +++ b/src/libs/3rdparty/cplusplus/AST.h @@ -161,6 +161,8 @@ public: virtual DeclaratorIdAST *asDeclaratorId() { return 0; } virtual DecltypeSpecifierAST *asDecltypeSpecifier() { return 0; } virtual DeleteExpressionAST *asDeleteExpression() { return 0; } + virtual DesignatedInitializerAST *asDesignatedInitializer() { return 0; } + virtual DesignatorAST *asDesignator() { return 0; } virtual DestructorNameAST *asDestructorName() { return 0; } virtual DoStatementAST *asDoStatement() { return 0; } virtual DynamicExceptionSpecificationAST *asDynamicExceptionSpecification() { return 0; } @@ -4527,6 +4529,72 @@ protected: virtual bool match0(AST *, ASTMatcher *); }; +class DesignatorAST: public AST +{ +public: + enum Type + { + Invalid, + Dot, + Bracket + }; + Type type; + union Designator + { + struct DotDesignator + { + unsigned dot_token; + unsigned identifier_token; + } dot; + struct BracketDesignator + { + unsigned lbracket_token; + ExpressionAST *expression; + unsigned rbracket_token; + } bracket; + } u; + +public: + DesignatorAST() + : type(Invalid) + {} + + virtual DesignatorAST *asDesignator() { return this; } + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual DesignatorAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class DesignatedInitializerAST: public ExpressionAST +{ +public: + DesignatorListAST *designator_list; + unsigned equal_token; + ExpressionAST *initializer; + +public: + DesignatedInitializerAST() + : designator_list(0) + , equal_token(0) + , initializer(0) + {} + + virtual DesignatedInitializerAST *asDesignatedInitializer() { return this; } + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual DesignatedInitializerAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + } // namespace CPlusPlus #endif // CPLUSPLUS_AST_H diff --git a/src/libs/3rdparty/cplusplus/ASTClone.cpp b/src/libs/3rdparty/cplusplus/ASTClone.cpp index 8ff5d0e9d7..086b12b1c9 100644 --- a/src/libs/3rdparty/cplusplus/ASTClone.cpp +++ b/src/libs/3rdparty/cplusplus/ASTClone.cpp @@ -1762,3 +1762,21 @@ BracedInitializerAST *BracedInitializerAST::clone(MemoryPool *pool) const return ast; } +DesignatorAST *DesignatorAST::clone(MemoryPool *pool) const +{ + DesignatorAST *ast = new (pool) DesignatorAST; + return ast; +} + +DesignatedInitializerAST *DesignatedInitializerAST::clone(MemoryPool *pool) const +{ + DesignatedInitializerAST *ast = new (pool) DesignatedInitializerAST; + for (DesignatorListAST *iter = designator_list, **ast_iter = &ast->designator_list; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) DesignatorListAST((iter->value) ? iter->value->clone(pool) : 0); + ast->equal_token = equal_token; + if (initializer) + ast->initializer = initializer->clone(pool); + return ast; +} + diff --git a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp index 69e3daf615..efeb2c57e0 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp @@ -1192,3 +1192,19 @@ bool BracedInitializerAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +bool DesignatorAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (DesignatorAST *_other = pattern->asDesignator()) + return matcher->match(this, _other); + + return false; +} + +bool DesignatedInitializerAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (DesignatedInitializerAST *_other = pattern->asDesignatedInitializer()) + return matcher->match(this, _other); + + return false; +} + diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp index 105f236070..02cdb9f068 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp @@ -2999,3 +2999,31 @@ bool ASTMatcher::match(BracedInitializerAST *node, BracedInitializerAST *pattern return true; } +bool ASTMatcher::match(DesignatorAST *node, DesignatorAST *pattern) +{ + (void) node; + (void) pattern; + + return true; +} + +bool ASTMatcher::match(DesignatedInitializerAST *node, DesignatedInitializerAST *pattern) +{ + (void) node; + (void) pattern; + + if (! pattern->designator_list) + pattern->designator_list = node->designator_list; + else if (! AST::match(node->designator_list, pattern->designator_list, this)) + return false; + + pattern->equal_token = node->equal_token; + + if (! pattern->initializer) + pattern->initializer = node->initializer; + else if (! AST::match(node->initializer, pattern->initializer, this)) + return false; + + return true; +} + diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.h b/src/libs/3rdparty/cplusplus/ASTMatcher.h index eee507b941..ebb18884e3 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.h +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.h @@ -66,6 +66,8 @@ public: virtual bool match(DeclaratorIdAST *node, DeclaratorIdAST *pattern); virtual bool match(DecltypeSpecifierAST *node, DecltypeSpecifierAST *pattern); virtual bool match(DeleteExpressionAST *node, DeleteExpressionAST *pattern); + virtual bool match(DesignatedInitializerAST *node, DesignatedInitializerAST *pattern); + virtual bool match(DesignatorAST *node, DesignatorAST *pattern); virtual bool match(DestructorNameAST *node, DestructorNameAST *pattern); virtual bool match(DoStatementAST *node, DoStatementAST *pattern); virtual bool match(DynamicExceptionSpecificationAST *node, DynamicExceptionSpecificationAST *pattern); diff --git a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h index b4d413efd8..ce55ccfe81 100644 --- a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h +++ b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h @@ -1147,6 +1147,20 @@ public: return __ast; } + DesignatorAST *Designator() + { + DesignatorAST *__ast = new (&pool) DesignatorAST; + return __ast; + } + + DesignatedInitializerAST *DesignatedInitializer(DesignatorListAST *designator_list = 0, ExpressionAST *initializer = 0) + { + DesignatedInitializerAST *__ast = new (&pool) DesignatedInitializerAST; + __ast->designator_list = designator_list; + __ast->initializer = initializer; + return __ast; + } + AttributeListAST *AttributeList(AttributeAST *value, AttributeListAST *next = 0) { AttributeListAST *__list = new (&pool) AttributeListAST; @@ -1195,6 +1209,14 @@ public: return __list; } + DesignatorListAST *DesignatorList(DesignatorAST *value, DesignatorListAST *next = 0) + { + DesignatorListAST *__list = new (&pool) DesignatorListAST; + __list->next = next; + __list->value = value; + return __list; + } + EnumeratorListAST *EnumeratorList(EnumeratorAST *value, EnumeratorListAST *next = 0) { EnumeratorListAST *__list = new (&pool) EnumeratorListAST; diff --git a/src/libs/3rdparty/cplusplus/ASTVisit.cpp b/src/libs/3rdparty/cplusplus/ASTVisit.cpp index 69ce44c8f1..983f09fc29 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisit.cpp +++ b/src/libs/3rdparty/cplusplus/ASTVisit.cpp @@ -1279,3 +1279,19 @@ void BracedInitializerAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void DesignatorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } + visitor->endVisit(this); +} + +void DesignatedInitializerAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(designator_list, visitor); + accept(initializer, visitor); + } + visitor->endVisit(this); +} + diff --git a/src/libs/3rdparty/cplusplus/ASTVisitor.h b/src/libs/3rdparty/cplusplus/ASTVisitor.h index d9578a4061..66c6c011f4 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisitor.h +++ b/src/libs/3rdparty/cplusplus/ASTVisitor.h @@ -108,6 +108,8 @@ public: virtual bool visit(DeclaratorIdAST *) { return true; } virtual bool visit(DecltypeSpecifierAST *) { return true; } virtual bool visit(DeleteExpressionAST *) { return true; } + virtual bool visit(DesignatedInitializerAST *) { return true; } + virtual bool visit(DesignatorAST *) { return true; } virtual bool visit(DestructorNameAST *) { return true; } virtual bool visit(DoStatementAST *) { return true; } virtual bool visit(DynamicExceptionSpecificationAST *) { return true; } @@ -254,6 +256,8 @@ public: virtual void endVisit(DeclaratorIdAST *) {} virtual void endVisit(DecltypeSpecifierAST *) {} virtual void endVisit(DeleteExpressionAST *) {} + virtual void endVisit(DesignatedInitializerAST *) {} + virtual void endVisit(DesignatorAST *) {} virtual void endVisit(DestructorNameAST *) {} virtual void endVisit(DoStatementAST *) {} virtual void endVisit(DynamicExceptionSpecificationAST *) {} diff --git a/src/libs/3rdparty/cplusplus/ASTfwd.h b/src/libs/3rdparty/cplusplus/ASTfwd.h index 7b79947cb9..a3382c89d6 100644 --- a/src/libs/3rdparty/cplusplus/ASTfwd.h +++ b/src/libs/3rdparty/cplusplus/ASTfwd.h @@ -68,6 +68,8 @@ class DeclaratorAST; class DeclaratorIdAST; class DecltypeSpecifierAST; class DeleteExpressionAST; +class DesignatedInitializerAST; +class DesignatorAST; class DestructorNameAST; class DoStatementAST; class DynamicExceptionSpecificationAST; @@ -215,6 +217,8 @@ typedef List<ObjCPropertyAttributeAST *> ObjCPropertyAttributeListAST; typedef List<ObjCMessageArgumentDeclarationAST *> ObjCMessageArgumentDeclarationListAST; typedef List<ObjCSynthesizedPropertyAST *> ObjCSynthesizedPropertyListAST; +typedef List<DesignatorAST *> DesignatorListAST; + } // namespace CPlusPlus diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index dfd6d1e49a..0163046176 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -2664,7 +2664,7 @@ bool Parser::parseInitializerList0x(ExpressionListAST *&node) ExpressionListAST **expression_list_ptr = &node; ExpressionAST *expression = 0; - if (parseInitializerClause0x(expression)) { + if (parseDesignatedInitializer(expression)) { *expression_list_ptr = new (_pool) ExpressionListAST; (*expression_list_ptr)->value = expression; expression_list_ptr = &(*expression_list_ptr)->next; @@ -2675,7 +2675,7 @@ bool Parser::parseInitializerList0x(ExpressionListAST *&node) while (LA() == T_COMMA && LA(2) != T_RBRACE) { consumeToken(); // consume T_COMMA - if (parseInitializerClause0x(expression)) { + if (parseDesignatedInitializer(expression)) { *expression_list_ptr = new (_pool) ExpressionListAST; (*expression_list_ptr)->value = expression; @@ -5484,6 +5484,50 @@ bool Parser::lookAtObjCSelector() const return false; } +// designated-initializer ::= designator* T_EQUAL initializer-clause +// +bool Parser::parseDesignatedInitializer(ExpressionAST *&node) +{ + DEBUG_THIS_RULE(); + if (!_languageFeatures.c99Enabled || (LA() != T_DOT && LA() != T_LBRACKET)) + return parseInitializerClause0x(node); + + DesignatedInitializerAST *ast = new (_pool) DesignatedInitializerAST; + DesignatorListAST **designator_list_ptr = &ast->designator_list; + DesignatorAST *designator = 0; + while (parseDesignator(designator)) { + *designator_list_ptr = new (_pool) DesignatorListAST; + (*designator_list_ptr)->value = designator; + designator_list_ptr = &(*designator_list_ptr)->next; + } + match(T_EQUAL, &ast->equal_token); + parseInitializerClause0x(ast->initializer); + node = ast; + return true; +} + +// designator ::= T_DOT T_IDENTIFIER +// T_LBRACKET constant-expression T_BRACKET +// +bool Parser::parseDesignator(DesignatorAST *&node) +{ + DesignatorAST *ast = new (_pool) DesignatorAST; + if (LA() == T_DOT) { + ast->type = DesignatorAST::Dot; + ast->u.dot.dot_token = consumeToken(); + match(T_IDENTIFIER, &ast->u.dot.identifier_token); + } else if (LA() == T_LBRACKET) { + ast->type = DesignatorAST::Bracket; + ast->u.bracket.lbracket_token = consumeToken(); + parseConstantExpression(ast->u.bracket.expression); + match(T_RBRACKET, &ast->u.bracket.rbracket_token); + } else { + return false; + } + node = ast; + return true; +} + // objc-class-declaraton ::= T_AT_CLASS (T_IDENTIFIER @ T_COMMA) T_SEMICOLON // bool Parser::parseObjCClassForwardDeclaration(DeclarationAST *&node) diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h index ea49df5e56..c18a079e4e 100644 --- a/src/libs/3rdparty/cplusplus/Parser.h +++ b/src/libs/3rdparty/cplusplus/Parser.h @@ -246,6 +246,11 @@ public: bool lookAtObjCSelector() const; + // c99 + bool parseDesignatedInitializerList(ExpressionListAST *&node); + bool parseDesignatedInitializer(ExpressionAST *&node); + bool parseDesignator(DesignatorAST *&node); + bool skipUntil(int token); void skipUntilDeclaration(); bool skipUntilStatement(); diff --git a/src/libs/3rdparty/cplusplus/Token.h b/src/libs/3rdparty/cplusplus/Token.h index ec10483852..d4a2901c34 100644 --- a/src/libs/3rdparty/cplusplus/Token.h +++ b/src/libs/3rdparty/cplusplus/Token.h @@ -390,6 +390,7 @@ struct LanguageFeatures unsigned int qtKeywordsEnabled : 1; // If Qt is used but QT_NO_KEYWORDS defined unsigned int cxx11Enabled : 1; unsigned int objCEnabled : 1; + unsigned int c99Enabled : 1; }; }; }; |