diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index 6da6f08c65e6ecf72b6c0237070ae3a235e6efe1..752a383a33014ba2a3480908fd19930ca2a4f4b4 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -144,6 +144,42 @@ unsigned AccessDeclarationAST::lastToken() const return access_specifier_token + 1; } +unsigned QtObjectTagAST::firstToken() const +{ + return q_object_token; +} + +unsigned QtObjectTagAST::lastToken() const +{ + return q_object_token + 1; +} + +unsigned QtPrivateSlotAST::firstToken() const +{ + return q_private_slot_token; +} + +unsigned QtPrivateSlotAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + else if (declarator) + return declarator->lastToken(); + else if (type_specifiers) + type_specifiers->lastToken(); + else if (comma_token) + return comma_token + 1; + else if (dptr_rparen_token) + return dptr_rparen_token + 1; + else if (dptr_lparen_token) + return dptr_lparen_token + 1; + else if (dptr_token) + return dptr_token + 1; + else if (lparen_token) + return lparen_token + 1; + return q_private_slot_token + 1; +} + unsigned QtPropertyDeclarationItemAST::firstToken() const { return item_name_token; diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index f9f13a0b7ad10d02fe96957b0d6557be58fbc0cf..85040258e268300ce2a08bacfbd66859c63d8a57 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -101,7 +101,7 @@ public: return lastValue; } - + _Tp value; List *next; }; @@ -260,6 +260,8 @@ public: virtual QtInterfacesDeclarationAST *asQtInterfacesDeclaration() { return 0; } virtual QtMemberDeclarationAST *asQtMemberDeclaration() { return 0; } virtual QtMethodAST *asQtMethod() { return 0; } + virtual QtObjectTagAST *asQtObjectTag() { return 0; } + virtual QtPrivateSlotAST *asQtPrivateSlot() { return 0; } virtual QtPropertyDeclarationAST *asQtPropertyDeclaration() { return 0; } virtual QtPropertyDeclarationItemAST *asQtPropertyDeclarationItem() { return 0; } virtual QualifiedNameAST *asQualifiedName() { return 0; } @@ -578,6 +580,50 @@ protected: virtual bool match0(AST *, ASTMatcher *); }; +class CPLUSPLUS_EXPORT QtObjectTagAST: public DeclarationAST +{ +public: + unsigned q_object_token; + +public: + virtual QtObjectTagAST *asQtObjectTag() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual QtObjectTagAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class CPLUSPLUS_EXPORT QtPrivateSlotAST: public DeclarationAST +{ +public: + unsigned q_private_slot_token; + unsigned lparen_token; + unsigned dptr_token; + unsigned dptr_lparen_token; + unsigned dptr_rparen_token; + unsigned comma_token; + SpecifierListAST *type_specifiers; + DeclaratorAST *declarator; + unsigned rparen_token; + +public: + virtual QtPrivateSlotAST *asQtPrivateSlot() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual QtPrivateSlotAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + class QtPropertyDeclarationItemAST: public AST { public: diff --git a/src/shared/cplusplus/ASTClone.cpp b/src/shared/cplusplus/ASTClone.cpp index 1e58c3f692e6bc58da79f086cbbf6be2889439a8..7920644c43db556a40e09e1ff51c0285afe99e92 100644 --- a/src/shared/cplusplus/ASTClone.cpp +++ b/src/shared/cplusplus/ASTClone.cpp @@ -155,6 +155,31 @@ AccessDeclarationAST *AccessDeclarationAST::clone(MemoryPool *pool) const return ast; } +QtObjectTagAST *QtObjectTagAST::clone(MemoryPool *pool) const +{ + QtObjectTagAST *ast = new (pool) QtObjectTagAST; + ast->q_object_token = q_object_token; + return ast; +} + +QtPrivateSlotAST *QtPrivateSlotAST::clone(MemoryPool *pool) const +{ + QtPrivateSlotAST *ast = new (pool) QtPrivateSlotAST; + ast->q_private_slot_token = q_private_slot_token; + ast->lparen_token = lparen_token; + ast->dptr_token = dptr_token; + ast->dptr_lparen_token = dptr_lparen_token; + ast->dptr_rparen_token = dptr_rparen_token; + ast->comma_token = comma_token; + for (SpecifierListAST *iter = type_specifiers, **ast_iter = &ast->type_specifiers; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0); + if (declarator) + ast->declarator = declarator->clone(pool); + ast->rparen_token = rparen_token; + return ast; +} + QtPropertyDeclarationItemAST *QtPropertyDeclarationItemAST::clone(MemoryPool *pool) const { QtPropertyDeclarationItemAST *ast = new (pool) QtPropertyDeclarationItemAST; diff --git a/src/shared/cplusplus/ASTMatch0.cpp b/src/shared/cplusplus/ASTMatch0.cpp index d594b441d2a332e12969e07656243f5b66f445f0..0b97e9c7fa2b27aeeb13e3ddab1678d548bc83a2 100644 --- a/src/shared/cplusplus/ASTMatch0.cpp +++ b/src/shared/cplusplus/ASTMatch0.cpp @@ -121,6 +121,22 @@ bool AccessDeclarationAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +bool QtObjectTagAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (QtObjectTagAST *_other = pattern->asQtObjectTag()) + return matcher->match(this, _other); + + return false; +} + +bool QtPrivateSlotAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (QtPrivateSlotAST *_other = pattern->asQtPrivateSlot()) + return matcher->match(this, _other); + + return false; +} + bool QtPropertyDeclarationItemAST::match0(AST *pattern, ASTMatcher *matcher) { if (QtPropertyDeclarationItemAST *_other = pattern->asQtPropertyDeclarationItem()) diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp index 044f7b1f060c9be5175d8b22ce2ea121f9cda5fb..e9734c661fe418b73064fc69fa4b332aaf6b3405 100644 --- a/src/shared/cplusplus/ASTMatcher.cpp +++ b/src/shared/cplusplus/ASTMatcher.cpp @@ -231,6 +231,48 @@ bool ASTMatcher::match(AccessDeclarationAST *node, AccessDeclarationAST *pattern return true; } +bool ASTMatcher::match(QtObjectTagAST *node, QtObjectTagAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->q_object_token = node->q_object_token; + + return true; +} + +bool ASTMatcher::match(QtPrivateSlotAST *node, QtPrivateSlotAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->q_private_slot_token = node->q_private_slot_token; + + pattern->lparen_token = node->lparen_token; + + pattern->dptr_token = node->dptr_token; + + pattern->dptr_lparen_token = node->dptr_lparen_token; + + pattern->dptr_rparen_token = node->dptr_rparen_token; + + pattern->comma_token = node->comma_token; + + if (! pattern->type_specifiers) + pattern->type_specifiers = node->type_specifiers; + else if (! AST::match(node->type_specifiers, pattern->type_specifiers, this)) + return false; + + if (! pattern->declarator) + pattern->declarator = node->declarator; + else if (! AST::match(node->declarator, pattern->declarator, this)) + return false; + + pattern->rparen_token = node->rparen_token; + + return true; +} + bool ASTMatcher::match(QtPropertyDeclarationItemAST *node, QtPropertyDeclarationItemAST *pattern) { (void) node; diff --git a/src/shared/cplusplus/ASTMatcher.h b/src/shared/cplusplus/ASTMatcher.h index 3de5b736a86233a877b2874c071d79c6a205c259..baae1ce874f43e0bcb765933fa54032813a0097e 100644 --- a/src/shared/cplusplus/ASTMatcher.h +++ b/src/shared/cplusplus/ASTMatcher.h @@ -40,6 +40,8 @@ public: virtual ~ASTMatcher(); virtual bool match(AccessDeclarationAST *node, AccessDeclarationAST *pattern); + virtual bool match(QtObjectTagAST *node, QtObjectTagAST *pattern); + virtual bool match(QtPrivateSlotAST *node, QtPrivateSlotAST *pattern); virtual bool match(QtPropertyDeclarationAST *node, QtPropertyDeclarationAST *pattern); virtual bool match(QtEnumDeclarationAST *node, QtEnumDeclarationAST *pattern); virtual bool match(QtFlagsDeclarationAST *node, QtFlagsDeclarationAST *pattern); diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp index 0e9575240d3d7fdaa5eab4c69a8b9c7d29325457..f58974f0168e228cb49c3711e5ba1472d10d60a4 100644 --- a/src/shared/cplusplus/ASTVisit.cpp +++ b/src/shared/cplusplus/ASTVisit.cpp @@ -123,6 +123,22 @@ void AccessDeclarationAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void QtObjectTagAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } + visitor->endVisit(this); +} + +void QtPrivateSlotAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(type_specifiers, visitor); + accept(declarator, visitor); + } + visitor->endVisit(this); +} + void QtPropertyDeclarationItemAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h index 25a9aa27419c1c5385c7bf91ca4d2119337d8e0b..4490f11faab5787bbe83c062691d7e22f569870f 100644 --- a/src/shared/cplusplus/ASTVisitor.h +++ b/src/shared/cplusplus/ASTVisitor.h @@ -103,6 +103,8 @@ public: virtual void postVisit(AST *) {} virtual bool visit(AccessDeclarationAST *) { return true; } + virtual bool visit(QtObjectTagAST *) { return true; } + virtual bool visit(QtPrivateSlotAST *) { return true; } virtual bool visit(QtPropertyDeclarationAST *) { return true; } virtual bool visit(QtEnumDeclarationAST *) { return true; } virtual bool visit(QtFlagsDeclarationAST *) { return true; } @@ -235,6 +237,8 @@ public: virtual bool visit(ObjCSynchronizedStatementAST *) { return true; } virtual void endVisit(AccessDeclarationAST *) { } + virtual void endVisit(QtObjectTagAST *) {} + virtual void endVisit(QtPrivateSlotAST *) {} virtual void endVisit(QtPropertyDeclarationAST *) { } virtual void endVisit(QtEnumDeclarationAST *) { } virtual void endVisit(QtFlagsDeclarationAST *) { } diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h index d068f1203624031876c527bdf41e070ff7da9d13..f8f129acb49fc244954ad76a4c10f2f3e5b6fb8d 100644 --- a/src/shared/cplusplus/ASTfwd.h +++ b/src/shared/cplusplus/ASTfwd.h @@ -167,6 +167,8 @@ class QtInterfaceNameAST; class QtInterfacesDeclarationAST; class QtMemberDeclarationAST; class QtMethodAST; +class QtObjectTagAST; +class QtPrivateSlotAST; class QtPropertyDeclarationAST; class QtPropertyDeclarationItemAST; class QualifiedNameAST; diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp index 7ce723e3cc9d1b51a0084a0ac15ad193f64c1589..0e6beaf06f4a8fa9153f9f9598f1160ee8c9c528 100644 --- a/src/shared/cplusplus/Keywords.cpp +++ b/src/shared/cplusplus/Keywords.cpp @@ -912,7 +912,33 @@ static inline int classify8(const char *s, bool q) { } else if (q && s[0] == 'Q') { if (s[1] == '_') { - if (s[2] == 'S') { + if (s[2] == 'G') { + if (s[3] == 'A') { + if (s[4] == 'D') { + if (s[5] == 'G') { + if (s[6] == 'E') { + if (s[7] == 'T') { + return T_Q_GADGET; + } + } + } + } + } + } + else if (s[2] == 'O') { + if (s[3] == 'B') { + if (s[4] == 'J') { + if (s[5] == 'E') { + if (s[6] == 'C') { + if (s[7] == 'T') { + return T_Q_OBJECT; + } + } + } + } + } + } + else if (s[2] == 'S') { if (s[3] == 'I') { if (s[4] == 'G') { if (s[5] == 'N') { @@ -1103,7 +1129,24 @@ static inline int classify10(const char *s, bool q) { } else if (q && s[0] == 'Q') { if (s[1] == '_') { - if (s[2] == 'P') { + if (s[2] == 'O') { + if (s[3] == 'V') { + if (s[4] == 'E') { + if (s[5] == 'R') { + if (s[6] == 'R') { + if (s[7] == 'I') { + if (s[8] == 'D') { + if (s[9] == 'E') { + return T_Q_PROPERTY; // Q_OVERRIDE is just an alias for Q_PROPERTY + } + } + } + } + } + } + } + } + else if (s[2] == 'P') { if (s[3] == 'R') { if (s[4] == 'O') { if (s[5] == 'P') { @@ -1345,6 +1388,83 @@ static inline int classify16(const char *s, bool) { return T_IDENTIFIER; } +static inline int classify14(const char *s, bool q) { + if (q && s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'P') { + if (s[3] == 'R') { + if (s[4] == 'I') { + if (s[5] == 'V') { + if (s[6] == 'A') { + if (s[7] == 'T') { + if (s[8] == 'E') { + if (s[9] == '_') { + if (s[10] == 'S') { + if (s[11] == 'L') { + if (s[12] == 'O') { + if (s[13] == 'T') { + return T_Q_PRIVATE_SLOT; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_IDENTIFIER; +} + +static inline int classify19(const char *s, bool q) { + if (q && s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'D') { + if (s[3] == 'E') { + if (s[4] == 'C') { + if (s[5] == 'L') { + if (s[6] == 'A') { + if (s[7] == 'R') { + if (s[8] == 'E') { + if (s[9] == '_') { + if (s[10] == 'I') { + if (s[11] == 'N') { + if (s[12] == 'T') { + if (s[13] == 'E') { + if (s[14] == 'R') { + if (s[15] == 'F') { + if (s[16] == 'A') { + if (s[17] == 'C') { + if (s[18] == 'E') { + return T_Q_DECLARE_INTERFACE; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_IDENTIFIER; +} + + int Lexer::classify(const char *s, int n, bool q) { switch (n) { case 2: return classify2(s, q); @@ -1359,7 +1479,9 @@ int Lexer::classify(const char *s, int n, bool q) { case 11: return classify11(s, q); case 12: return classify12(s, q); case 13: return classify13(s, q); + case 14: return classify14(s, q); case 16: return classify16(s, q); + case 19: return classify19(s, q); default: return T_IDENTIFIER; } // switch } diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 95372cbad5befd6e110ea3c45324bcf65fd3ee3c..ce5afdd5faa377280d21ab376d5ba986935e6a89 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -609,6 +609,21 @@ bool Parser::parseDeclaration(DeclarationAST *&node) case T_AT_IMPLEMENTATION: return parseObjCImplementation(node); + case T_Q_DECLARE_INTERFACE: + { + consumeToken(); + unsigned lparen_token = 0; + match(T_LPAREN, &lparen_token); + NameAST *name = 0; + parseName(name); + unsigned comma_token = 0; + match(T_COMMA, &comma_token); + unsigned string_literal = 0; + match(T_STRING_LITERAL, &string_literal); + unsigned rparen_token = 0; + match(T_RPAREN, &rparen_token); + } return true; + case T_AT_END: // TODO: should this be done here, or higher-up? _translationUnit->error(cursor(), "skip stray token `%s'", tok().spell()); @@ -2019,6 +2034,32 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node) { DEBUG_THIS_RULE(); switch (LA()) { + case T_Q_OBJECT: + case T_Q_GADGET: + { + QtObjectTagAST *ast = new (_pool) QtObjectTagAST; + ast->q_object_token = consumeToken(); + node = ast; + return true; + } + + case T_Q_PRIVATE_SLOT: + { + QtPrivateSlotAST *ast = new (_pool) QtPrivateSlotAST; + ast->q_private_slot_token = consumeToken(); + match(T_LPAREN, &ast->lparen_token); + match(T_IDENTIFIER, &ast->dptr_token); + if (LA() == T_LPAREN) { + ast->dptr_lparen_token = consumeToken(); + match(T_RPAREN, &ast->dptr_rparen_token); + } + match(T_COMMA, &ast->comma_token); + parseTypeSpecifier(ast->type_specifiers); + parseDeclarator(ast->declarator); + match(T_RPAREN, &ast->rparen_token); + node = ast; + } return true; + case T_SEMICOLON: return parseEmptyDeclaration(node); diff --git a/src/shared/cplusplus/Token.cpp b/src/shared/cplusplus/Token.cpp index cafce02eacb047eab4e0d9f9d7c75675c9e2e1a3..2bb8763e66fa3265fb95f25aecd2cf48be154913 100644 --- a/src/shared/cplusplus/Token.cpp +++ b/src/shared/cplusplus/Token.cpp @@ -91,9 +91,12 @@ static const char *token_names[] = { ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"), ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"), + // Qt keywords ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"), ("Q_FOREACH"), ("Q_D"), ("Q_Q"), - ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_INTERFACES"), ("Q_ENUMS"), ("Q_FLAGS") + ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_INTERFACES"), ("Q_ENUMS"), ("Q_FLAGS"), + ("Q_PRIVATE_SLOT"), ("Q_DECLARE_INTERFACE"), ("Q_OBJECT"), ("Q_GADGET"), + }; Token::Token() : diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h index e71d25bf62a3c66c1e42c8ec1cb3598b6e251f48..2c858551549441087099c3b8f4f96328a9ba6d2b 100644 --- a/src/shared/cplusplus/Token.h +++ b/src/shared/cplusplus/Token.h @@ -243,7 +243,11 @@ enum Kind { T_Q_INTERFACES, T_Q_ENUMS, T_Q_FLAGS, - T_LAST_KEYWORD = T_Q_FLAGS, + T_Q_PRIVATE_SLOT, + T_Q_DECLARE_INTERFACE, + T_Q_OBJECT, + T_Q_GADGET, + T_LAST_KEYWORD = T_Q_GADGET, // aliases T_OR = T_PIPE_PIPE,