From b4d72a78dbe365a0b5578e453bb9daaeb0260996 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen <erik.verbruggen@nokia.com> Date: Tue, 16 Mar 2010 17:29:40 +0100 Subject: [PATCH] Added parser support for Q_INTERFACES. --- src/libs/cplusplus/pp-engine.cpp | 2 + src/shared/cplusplus/AST.cpp | 39 ++++++++++++++- src/shared/cplusplus/AST.h | 42 ++++++++++++++++ src/shared/cplusplus/ASTClone.cpp | 23 +++++++++ src/shared/cplusplus/ASTMatch0.cpp | 16 ++++++ src/shared/cplusplus/ASTMatcher.cpp | 37 ++++++++++++++ src/shared/cplusplus/ASTMatcher.h | 2 + src/shared/cplusplus/ASTVisit.cpp | 17 +++++++ src/shared/cplusplus/ASTVisitor.h | 4 ++ src/shared/cplusplus/ASTfwd.h | 3 ++ src/shared/cplusplus/Keywords.cpp | 27 +++++++++- src/shared/cplusplus/Parser.cpp | 76 +++++++++++++++++++++++++++++ src/shared/cplusplus/Parser.h | 1 + src/shared/cplusplus/Token.cpp | 2 +- src/shared/cplusplus/Token.h | 1 + 15 files changed, 289 insertions(+), 3 deletions(-) diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 66d7f908e70..172f50fb4a3 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -1421,6 +1421,8 @@ bool Preprocessor::isQtReservedWord(const QByteArray ¯oId) const return true; else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_FLAGS") return true; + else if (size == 12 && macroId.at(0) == 'Q' && macroId == "Q_INTERFACES") + return true; else if (size == 6 && macroId.at(0) == 'S' && macroId == "SIGNAL") return true; else if (size == 4 && macroId.at(0) == 'S' && macroId == "SLOT") diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index f6aebdb688f..6da6f08c65e 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -197,7 +197,7 @@ unsigned QtEnumDeclarationAST::lastToken() const unsigned QtFlagsDeclarationAST::firstToken() const { - return flags_specifier_token + 1; + return flags_specifier_token; } unsigned QtFlagsDeclarationAST::lastToken() const @@ -212,6 +212,43 @@ unsigned QtFlagsDeclarationAST::lastToken() const return flags_specifier_token + 1; } +unsigned QtInterfaceNameAST::firstToken() const +{ + if (interface_name) + return interface_name->firstToken(); + else if (constraint_list) + return constraint_list->firstToken(); + else + return 0; +} + +unsigned QtInterfaceNameAST::lastToken() const +{ + if (constraint_list) + return constraint_list->lastToken(); + else if (interface_name) + return interface_name->lastToken(); + else + return 0; +} + +unsigned QtInterfacesDeclarationAST::firstToken() const +{ + return interfaces_token; +} + +unsigned QtInterfacesDeclarationAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + else if (interface_name_list) + return interface_name_list->lastToken(); + else if (lparen_token) + return lparen_token + 1; + else + return interfaces_token + 1; +} + unsigned ArrayAccessAST::firstToken() const { return lbracket_token; diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index 40147912bee..f9f13a0b7ad 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -256,6 +256,8 @@ public: virtual PtrOperatorAST *asPtrOperator() { return 0; } virtual QtEnumDeclarationAST *asQtEnumDeclaration() { return 0; } virtual QtFlagsDeclarationAST *asQtFlagsDeclaration() { return 0; } + virtual QtInterfaceNameAST *asQtInterfaceName() { return 0; } + virtual QtInterfacesDeclarationAST *asQtInterfacesDeclaration() { return 0; } virtual QtMemberDeclarationAST *asQtMemberDeclaration() { return 0; } virtual QtMethodAST *asQtMethod() { return 0; } virtual QtPropertyDeclarationAST *asQtPropertyDeclaration() { return 0; } @@ -660,6 +662,46 @@ protected: virtual bool match0(AST *, ASTMatcher *); }; +class CPLUSPLUS_EXPORT QtInterfaceNameAST: public AST +{ +public: + NameAST *interface_name; + NameListAST *constraint_list; + +public: + virtual QtInterfaceNameAST *asQtInterfaceName() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual QtInterfaceNameAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class CPLUSPLUS_EXPORT QtInterfacesDeclarationAST: public DeclarationAST +{ +public: + unsigned interfaces_token; + unsigned lparen_token; + QtInterfaceNameListAST *interface_name_list; + unsigned rparen_token; + +public: + virtual QtInterfacesDeclarationAST *asQtInterfacesDeclaration() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual QtInterfacesDeclarationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + class CPLUSPLUS_EXPORT AsmDefinitionAST: public DeclarationAST { public: diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp index f9d45b6fed7..1e58c3f692e 100644 --- a/src/shared/cplusplus/ASTClone.cpp +++ b/src/shared/cplusplus/ASTClone.cpp @@ -204,6 +204,29 @@ QtFlagsDeclarationAST *QtFlagsDeclarationAST::clone(MemoryPool *pool) const return ast; } +QtInterfaceNameAST *QtInterfaceNameAST::clone(MemoryPool *pool) const +{ + QtInterfaceNameAST *ast = new (pool) QtInterfaceNameAST; + if (interface_name) + ast->interface_name = interface_name->clone(pool); + for (NameListAST *iter = constraint_list, **ast_iter = &ast->constraint_list; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) NameListAST((iter->value) ? iter->value->clone(pool) : 0); + return ast; +} + +QtInterfacesDeclarationAST *QtInterfacesDeclarationAST::clone(MemoryPool *pool) const +{ + QtInterfacesDeclarationAST *ast = new (pool) QtInterfacesDeclarationAST; + ast->interfaces_token = interfaces_token; + ast->lparen_token = lparen_token; + for (QtInterfaceNameListAST *iter = interface_name_list, **ast_iter = &ast->interface_name_list; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) QtInterfaceNameListAST((iter->value) ? iter->value->clone(pool) : 0); + ast->rparen_token = rparen_token; + return ast; +} + AsmDefinitionAST *AsmDefinitionAST::clone(MemoryPool *pool) const { AsmDefinitionAST *ast = new (pool) AsmDefinitionAST; diff --git a/src/shared/cplusplus/ASTMatch0.cpp b/src/shared/cplusplus/ASTMatch0.cpp index 4347c7230b6..d594b441d2a 100644 --- a/src/shared/cplusplus/ASTMatch0.cpp +++ b/src/shared/cplusplus/ASTMatch0.cpp @@ -153,6 +153,22 @@ bool QtFlagsDeclarationAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +bool QtInterfaceNameAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (QtInterfaceNameAST *_other = pattern->asQtInterfaceName()) + return matcher->match(this, _other); + + return false; +} + +bool QtInterfacesDeclarationAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (QtInterfacesDeclarationAST *_other = pattern->asQtInterfacesDeclaration()) + return matcher->match(this, _other); + + return false; +} + bool AsmDefinitionAST::match0(AST *pattern, ASTMatcher *matcher) { if (AsmDefinitionAST *_other = pattern->asAsmDefinition()) diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp index c9980d62e22..044f7b1f060 100644 --- a/src/shared/cplusplus/ASTMatcher.cpp +++ b/src/shared/cplusplus/ASTMatcher.cpp @@ -313,6 +313,43 @@ bool ASTMatcher::match(QtFlagsDeclarationAST *node, QtFlagsDeclarationAST *patte return true; } +bool ASTMatcher::match(QtInterfaceNameAST *node, QtInterfaceNameAST *pattern) +{ + (void) node; + (void) pattern; + + if (! pattern->interface_name) + pattern->interface_name = node->interface_name; + else if (! AST::match(node->interface_name, pattern->interface_name, this)) + return false; + + if (! pattern->constraint_list) + pattern->constraint_list = node->constraint_list; + else if (! AST::match(node->constraint_list, pattern->constraint_list, this)) + return false; + + return true; +} + +bool ASTMatcher::match(QtInterfacesDeclarationAST *node, QtInterfacesDeclarationAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->interfaces_token = node->interfaces_token; + + pattern->lparen_token = node->lparen_token; + + if (! pattern->interface_name_list) + pattern->interface_name_list = node->interface_name_list; + else if (! AST::match(node->interface_name_list, pattern->interface_name_list, this)) + return false; + + pattern->rparen_token = node->rparen_token; + + return true; +} + bool ASTMatcher::match(AsmDefinitionAST *node, AsmDefinitionAST *pattern) { (void) node; diff --git a/src/shared/cplusplus/ASTMatcher.h b/src/shared/cplusplus/ASTMatcher.h index 7dfeec7c16a..3de5b736a86 100644 --- a/src/shared/cplusplus/ASTMatcher.h +++ b/src/shared/cplusplus/ASTMatcher.h @@ -43,6 +43,8 @@ public: virtual bool match(QtPropertyDeclarationAST *node, QtPropertyDeclarationAST *pattern); virtual bool match(QtEnumDeclarationAST *node, QtEnumDeclarationAST *pattern); virtual bool match(QtFlagsDeclarationAST *node, QtFlagsDeclarationAST *pattern); + virtual bool match(QtInterfaceNameAST *node, QtInterfaceNameAST *pattern); + virtual bool match(QtInterfacesDeclarationAST *node, QtInterfacesDeclarationAST *pattern); virtual bool match(ArrayAccessAST *node, ArrayAccessAST *pattern); virtual bool match(ArrayDeclaratorAST *node, ArrayDeclaratorAST *pattern); virtual bool match(ArrayInitializerAST *node, ArrayInitializerAST *pattern); diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp index df08727aec7..0e9575240d3 100644 --- a/src/shared/cplusplus/ASTVisit.cpp +++ b/src/shared/cplusplus/ASTVisit.cpp @@ -157,6 +157,23 @@ void QtFlagsDeclarationAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void QtInterfaceNameAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(interface_name, visitor); + accept(constraint_list, visitor); + } + visitor->endVisit(this); +} + +void QtInterfacesDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(interface_name_list, visitor); + } + visitor->endVisit(this); +} + void AsmDefinitionAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h index bb1bea71092..25a9aa27419 100644 --- a/src/shared/cplusplus/ASTVisitor.h +++ b/src/shared/cplusplus/ASTVisitor.h @@ -204,6 +204,8 @@ public: virtual bool visit(QtMethodAST *) { return true; } virtual bool visit(QtMemberDeclarationAST *) { return true; } virtual bool visit(QtPropertyDeclarationItemAST *) { return true; } + virtual bool visit(QtInterfacesDeclarationAST *) { return true; } + virtual bool visit(QtInterfaceNameAST *) { return true; } // ObjC++ virtual bool visit(ObjCClassDeclarationAST *) { return true; } @@ -334,6 +336,8 @@ public: virtual void endVisit(QtMethodAST *) { } virtual void endVisit(QtMemberDeclarationAST *) { } virtual void endVisit(QtPropertyDeclarationItemAST *) { } + virtual void endVisit(QtInterfacesDeclarationAST *) { } + virtual void endVisit(QtInterfaceNameAST *) { } // ObjC++ virtual void endVisit(ObjCClassDeclarationAST *) { } diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h index 5779bdf0d34..d068f120362 100644 --- a/src/shared/cplusplus/ASTfwd.h +++ b/src/shared/cplusplus/ASTfwd.h @@ -163,6 +163,8 @@ class PostfixExpressionAST; class PtrOperatorAST; class QtEnumDeclarationAST; class QtFlagsDeclarationAST; +class QtInterfaceNameAST; +class QtInterfacesDeclarationAST; class QtMemberDeclarationAST; class QtMethodAST; class QtPropertyDeclarationAST; @@ -213,6 +215,7 @@ typedef List<PtrOperatorAST *> PtrOperatorListAST; typedef List<SpecifierAST *> SpecifierListAST; typedef List<QtPropertyDeclarationItemAST *> QtPropertyDeclarationItemListAST; typedef List<NameAST *> NameListAST; +typedef List<QtInterfaceNameAST *> QtInterfaceNameListAST; typedef List<ObjCMessageArgumentAST *> ObjCMessageArgumentListAST; typedef List<ObjCSelectorArgumentAST *> ObjCSelectorArgumentListAST; diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp index d42ca3795a4..7ce723e3cc9 100644 --- a/src/shared/cplusplus/Keywords.cpp +++ b/src/shared/cplusplus/Keywords.cpp @@ -1198,7 +1198,7 @@ static inline int classify11(const char *s, bool q) { return T_IDENTIFIER; } -static inline int classify12(const char *s, bool) { +static inline int classify12(const char *s, bool q) { if (s[0] == '_') { if (s[1] == '_') { if (s[2] == 'v') { @@ -1224,6 +1224,31 @@ static inline int classify12(const char *s, bool) { } } } + else if (q && s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'I') { + if (s[3] == 'N') { + if (s[4] == 'T') { + if (s[5] == 'E') { + if (s[6] == 'R') { + if (s[7] == 'F') { + if (s[8] == 'A') { + if (s[9] == 'C') { + if (s[10] == 'E') { + if (s[11] == 'S') { + return T_Q_INTERFACES; + } + } + } + } + } + } + } + } + } + } + } + } else if (s[0] == 'd') { if (s[1] == 'y') { if (s[2] == 'n') { diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 93b30251c7c..95372cbad5b 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -293,6 +293,7 @@ void Parser::skipUntilDeclaration() case T_Q_PROPERTY: case T_Q_ENUMS: case T_Q_FLAGS: + case T_Q_INTERFACES: // Qt function specifiers case T_Q_SIGNAL: @@ -1942,6 +1943,78 @@ bool Parser::parseQtFlags(DeclarationAST *&node) return true; } +// class-specifier ::= +// c++-class-specifier +// q-tag +// q-enums-of-flags +// q-class-info +// q-interfaces +// q-private-slot +// +// declaration ::= +// c++-declaration +// q-declare-interface +// q-declare-metatype +// +// q-tag ::= +// Q_OBJECT +// Q_GADGET +// +// q-enums-or-flags ::= +// (Q_ENUMS | Q_FLAGS) LPAREN name+ RPAREN +// +// q-class-info ::= +// Q_CLASS_INFO LPAREN string-literal COMMA STRING_LITERAL RPAREN +// Q_CLASS_INFO LPAREN string-literal COMMA IDENTIFIER LPAREN STRING_LITERAL RPAREN RPAREN + +// q-interfaces ::= +// Q_INTERFACES LPAREN (name q-constraints)* RPAREN +// +// q-constraints ::= +// (COLON name)* +bool Parser::parseQtInterfaces(DeclarationAST *&node) +{ + DEBUG_THIS_RULE(); + if (LA() != T_Q_INTERFACES) + return false; + + QtInterfacesDeclarationAST *ast = new (_pool) QtInterfacesDeclarationAST; + ast->interfaces_token = consumeToken(); + match(T_LPAREN, &ast->lparen_token); + for (QtInterfaceNameListAST **iter = &ast->interface_name_list; LA() && LA() != T_RPAREN; iter = &(*iter)->next) { + NameAST *name_ast = 0; + if (!parseName(name_ast)) + break; + *iter = new (_pool) QtInterfaceNameListAST; + (*iter)->value = new (_pool) QtInterfaceNameAST; + (*iter)->value->interface_name = name_ast; + for (NameListAST **iter2 = &(*iter)->value->constraint_list; LA() && LA() == T_COLON; iter2 = &(*iter2)->next) { + /*unsigned colon_token =*/ consumeToken(); + NameAST *name_ast2 = 0; + if (!parseName(name_ast2)) + break; + *iter2 = new (_pool) NameListAST; + (*iter2)->value = name_ast2; + } + } + + match(T_RPAREN, &ast->rparen_token); + node = ast; + return true; +} + +// q-private-slot ::= +// Q_PRIVATE_SLOT LPAREN IDENTIFIER (LPAREN RPAREN)? COMMA q-function-declaration RPAREN +// +// q-function-declaration ::= +// decl-specifier-list declarator [+ check for the function-declarator] +// +// q-declare-interface ::= +// Q_DECLARE_INTERFACE LPAREN name COMMA (STRING_LITERAL | IDENTIFIER) RPAREN +// +// q-declare-metatype ::= +// Q_DECLARE_METATYPE LPAREN name RPAREN SEMICOLON? [warning] + bool Parser::parseMemberSpecification(DeclarationAST *&node) { DEBUG_THIS_RULE(); @@ -1971,6 +2044,9 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node) case T_Q_FLAGS: return parseQtFlags(node); + case T_Q_INTERFACES: + return parseQtInterfaces(node); + default: return parseSimpleDeclaration(node, /*acceptStructDeclarator=*/true); } // switch diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index e10be3ac81d..1ae857ea81e 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -81,6 +81,7 @@ public: bool parseQtPropertyDeclaration(DeclarationAST *&node); bool parseQtEnumDeclaration(DeclarationAST *&node); bool parseQtFlags(DeclarationAST *&node); + bool parseQtInterfaces(DeclarationAST *&node); bool parseAdditiveExpression(ExpressionAST *&node); bool parseAndExpression(ExpressionAST *&node); bool parseAsmDefinition(DeclarationAST *&node); diff --git a/src/shared/cplusplus/Token.cpp b/src/shared/cplusplus/Token.cpp index 9dfe80b1549..cafce02eacb 100644 --- a/src/shared/cplusplus/Token.cpp +++ b/src/shared/cplusplus/Token.cpp @@ -93,7 +93,7 @@ static const char *token_names[] = { ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"), ("Q_FOREACH"), ("Q_D"), ("Q_Q"), - ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_ENUMS"), ("Q_FLAGS") + ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_INTERFACES"), ("Q_ENUMS"), ("Q_FLAGS") }; Token::Token() : diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h index 7644a31b821..e71d25bf62a 100644 --- a/src/shared/cplusplus/Token.h +++ b/src/shared/cplusplus/Token.h @@ -240,6 +240,7 @@ enum Kind { T_Q_Q, T_Q_INVOKABLE, T_Q_PROPERTY, + T_Q_INTERFACES, T_Q_ENUMS, T_Q_FLAGS, T_LAST_KEYWORD = T_Q_FLAGS, -- GitLab