diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 9a8d41fe7a8f61d3eae470cd0186ca3c085d2c2c..d112f9ab537ebd4d7c0264ab8dfc79147a207d8d 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -3864,4 +3864,71 @@ unsigned WhileStatementAST::lastToken() const return while_token + 1; } +// ObjC++ +unsigned IdentifierListAST::firstToken() const +{ + return identifier_token; +} + +unsigned IdentifierListAST::lastToken() const +{ + for (const IdentifierListAST *it = this; it; it = it->next) { + if (! it->next && it->identifier_token) { + return it->identifier_token + 1; + } + } + // ### assert? + return 0; +} + +IdentifierListAST *IdentifierListAST::clone(MemoryPool *pool) const +{ + IdentifierListAST *ast = new (pool) IdentifierListAST; + ast->identifier_token = identifier_token; + if (next) + ast->next = next->clone(pool); + return ast; +} + +void IdentifierListAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + +unsigned ObjCClassDeclarationAST::firstToken() const +{ + return class_token; +} + +unsigned ObjCClassDeclarationAST::lastToken() const +{ + if (semicolon_token) + return semicolon_token + 1; + + for (IdentifierListAST *it = identifier_list; it; it = it->next) { + if (! it->next && it->identifier_token) + return it->identifier_token + 1; + } + + return class_token + 1; +} + +ObjCClassDeclarationAST *ObjCClassDeclarationAST::clone(MemoryPool *pool) const +{ + ObjCClassDeclarationAST *ast = new (pool) ObjCClassDeclarationAST; + ast->class_token = class_token; + if (identifier_list) + ast->identifier_list = identifier_list->clone(pool); + ast->semicolon_token = semicolon_token; + return ast; +} + +void ObjCClassDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } +} + + CPLUSPLUS_END_NAMESPACE diff --git a/shared/cplusplus/AST.h b/shared/cplusplus/AST.h index ace137760f1373716a0fc8210a0f6af2454ce3fa..d03cd3ff82c6fc44aac09abbc9979ced259ff7bd 100644 --- a/shared/cplusplus/AST.h +++ b/shared/cplusplus/AST.h @@ -1928,6 +1928,41 @@ protected: virtual void accept0(ASTVisitor *visitor); }; + +// ObjC++ +class CPLUSPLUS_EXPORT IdentifierListAST: public AST +{ +public: + unsigned identifier_token; + IdentifierListAST *next; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual IdentifierListAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT ObjCClassDeclarationAST: public DeclarationAST +{ +public: + unsigned class_token; + IdentifierListAST *identifier_list; + unsigned semicolon_token; + +public: + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual ObjCClassDeclarationAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + CPLUSPLUS_END_NAMESPACE CPLUSPLUS_END_HEADER diff --git a/shared/cplusplus/ASTVisitor.h b/shared/cplusplus/ASTVisitor.h index 4e1ecaefd8fc6fb85a514a311651510403ca53ad..28097c14f704af8151d5a5a76c63f8d3b6458d93 100644 --- a/shared/cplusplus/ASTVisitor.h +++ b/shared/cplusplus/ASTVisitor.h @@ -185,6 +185,10 @@ public: virtual bool visit(WhileStatementAST *) { return true; } virtual bool visit(QtMethodAST *) { return true; } + // ObjC++ + virtual bool visit(IdentifierListAST *) { return true; } + virtual bool visit(ObjCClassDeclarationAST *) { return true; } + private: Control *_control; }; diff --git a/shared/cplusplus/ASTfwd.h b/shared/cplusplus/ASTfwd.h index 14beadfdd0aeca31a483134cae4c7f33fe564dbc..79f794f629ed7c90235ba29911c7d3e57f710418 100644 --- a/shared/cplusplus/ASTfwd.h +++ b/shared/cplusplus/ASTfwd.h @@ -167,6 +167,10 @@ class UsingDirectiveAST; class WhileStatementAST; class QtMethodAST; +// ObjC++ +class IdentifierListAST; +class ObjCClassDeclarationAST; + CPLUSPLUS_END_NAMESPACE CPLUSPLUS_END_HEADER diff --git a/shared/cplusplus/ObjectiveCAtKeywords.cpp b/shared/cplusplus/ObjectiveCAtKeywords.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f8fc7c396fcd5c15879ead5d68af75799b2024f --- /dev/null +++ b/shared/cplusplus/ObjectiveCAtKeywords.cpp @@ -0,0 +1,464 @@ +#include "Lexer.h" +#include "Token.h" + +CPLUSPLUS_BEGIN_NAMESPACE + +static inline int classify3(const char *s) { + if (s[0] == 'e') { + if (s[1] == 'n') { + if (s[2] == 'd') { + return T_AT_END; + } + } + } + else if (s[0] == 't') { + if (s[1] == 'r') { + if (s[2] == 'y') { + return T_AT_TRY; + } + } + } + return T_ERROR; +} + +static inline int classify4(const char *s) { + if (s[0] == 'd') { + if (s[1] == 'e') { + if (s[2] == 'f') { + if (s[3] == 's') { + return T_AT_DEFS; + } + } + } + } + return T_ERROR; +} + +static inline int classify5(const char *s) { + if (s[0] == 'c') { + if (s[1] == 'a') { + if (s[2] == 't') { + if (s[3] == 'c') { + if (s[4] == 'h') { + return T_AT_CATCH; + } + } + } + } + else if (s[1] == 'l') { + if (s[2] == 'a') { + if (s[3] == 's') { + if (s[4] == 's') { + return T_AT_CLASS; + } + } + } + } + } + else if (s[0] == 't') { + if (s[1] == 'h') { + if (s[2] == 'r') { + if (s[3] == 'o') { + if (s[4] == 'w') { + return T_AT_THROW; + } + } + } + } + } + return T_ERROR; +} + +static inline int classify6(const char *s) { + if (s[0] == 'e') { + if (s[1] == 'n') { + if (s[2] == 'c') { + if (s[3] == 'o') { + if (s[4] == 'd') { + if (s[5] == 'e') { + return T_AT_ENCODE; + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'u') { + if (s[2] == 'b') { + if (s[3] == 'l') { + if (s[4] == 'i') { + if (s[5] == 'c') { + return T_AT_PUBLIC; + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify7(const char *s) { + if (s[0] == 'd') { + if (s[1] == 'y') { + if (s[2] == 'n') { + if (s[3] == 'a') { + if (s[4] == 'm') { + if (s[5] == 'i') { + if (s[6] == 'c') { + return T_AT_DYNAMIC; + } + } + } + } + } + } + } + else if (s[0] == 'f') { + if (s[1] == 'i') { + if (s[2] == 'n') { + if (s[3] == 'a') { + if (s[4] == 'l') { + if (s[5] == 'l') { + if (s[6] == 'y') { + return T_AT_FINALLY; + } + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'a') { + if (s[2] == 'c') { + if (s[3] == 'k') { + if (s[4] == 'a') { + if (s[5] == 'g') { + if (s[6] == 'e') { + return T_AT_PACKAGE; + } + } + } + } + } + } + else if (s[1] == 'r') { + if (s[2] == 'i') { + if (s[3] == 'v') { + if (s[4] == 'a') { + if (s[5] == 't') { + if (s[6] == 'e') { + return T_AT_PRIVATE; + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify8(const char *s) { + if (s[0] == 'o') { + if (s[1] == 'p') { + if (s[2] == 't') { + if (s[3] == 'i') { + if (s[4] == 'o') { + if (s[5] == 'n') { + if (s[6] == 'a') { + if (s[7] == 'l') { + return T_AT_OPTIONAL; + } + } + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'r') { + if (s[2] == 'o') { + if (s[3] == 'p') { + if (s[4] == 'e') { + if (s[5] == 'r') { + if (s[6] == 't') { + if (s[7] == 'y') { + return T_AT_PROPERTY; + } + } + } + } + } + else if (s[3] == 't') { + if (s[4] == 'o') { + if (s[5] == 'c') { + if (s[6] == 'o') { + if (s[7] == 'l') { + return T_AT_PROTOCOL; + } + } + } + } + } + } + } + } + else if (s[0] == 'r') { + if (s[1] == 'e') { + if (s[2] == 'q') { + if (s[3] == 'u') { + if (s[4] == 'i') { + if (s[5] == 'r') { + if (s[6] == 'e') { + if (s[7] == 'd') { + return T_AT_REQUIRED; + } + } + } + } + } + } + } + } + else if (s[0] == 's') { + if (s[1] == 'e') { + if (s[2] == 'l') { + if (s[3] == 'e') { + if (s[4] == 'c') { + if (s[5] == 't') { + if (s[6] == 'o') { + if (s[7] == 'r') { + return T_AT_SELECTOR; + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify9(const char *s) { + if (s[0] == 'i') { + if (s[1] == 'n') { + if (s[2] == 't') { + if (s[3] == 'e') { + if (s[4] == 'r') { + if (s[5] == 'f') { + if (s[6] == 'a') { + if (s[7] == 'c') { + if (s[8] == 'e') { + return T_AT_INTERFACE; + } + } + } + } + } + } + } + } + } + else if (s[0] == 'p') { + if (s[1] == 'r') { + if (s[2] == 'o') { + if (s[3] == 't') { + if (s[4] == 'e') { + if (s[5] == 'c') { + if (s[6] == 't') { + if (s[7] == 'e') { + if (s[8] == 'd') { + return T_AT_PROTECTED; + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify10(const char *s) { + if (s[0] == 's') { + if (s[1] == 'y') { + if (s[2] == 'n') { + if (s[3] == 't') { + if (s[4] == 'h') { + if (s[5] == 'e') { + if (s[6] == 's') { + if (s[7] == 'i') { + if (s[8] == 'z') { + if (s[9] == 'e') { + return T_AT_SYNTHESIZE; + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify11(const char *s) { + if (s[0] == 'n') { + if (s[1] == 'o') { + if (s[2] == 't') { + if (s[3] == '_') { + if (s[4] == 'k') { + if (s[5] == 'e') { + if (s[6] == 'y') { + if (s[7] == 'w') { + if (s[8] == 'o') { + if (s[9] == 'r') { + if (s[10] == 'd') { + return T_AT_NOT_KEYWORD; + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify12(const char *s) { + if (s[0] == 's') { + if (s[1] == 'y') { + if (s[2] == 'n') { + if (s[3] == 'c') { + if (s[4] == 'h') { + if (s[5] == 'r') { + if (s[6] == 'o') { + if (s[7] == 'n') { + if (s[8] == 'i') { + if (s[9] == 'z') { + if (s[10] == 'e') { + if (s[11] == 'd') { + return T_AT_SYNCHRONIZED; + } + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify14(const char *s) { + if (s[0] == 'i') { + if (s[1] == 'm') { + if (s[2] == 'p') { + if (s[3] == 'l') { + if (s[4] == 'e') { + if (s[5] == 'm') { + if (s[6] == 'e') { + if (s[7] == 'n') { + if (s[8] == 't') { + if (s[9] == 'a') { + if (s[10] == 't') { + if (s[11] == 'i') { + if (s[12] == 'o') { + if (s[13] == 'n') { + return T_AT_IMPLEMENTATION; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +static inline int classify19(const char *s) { + if (s[0] == 'c') { + if (s[1] == 'o') { + if (s[2] == 'm') { + if (s[3] == 'p') { + if (s[4] == 'a') { + if (s[5] == 't') { + if (s[6] == 'i') { + if (s[7] == 'b') { + if (s[8] == 'i') { + if (s[9] == 'l') { + if (s[10] == 'i') { + if (s[11] == 't') { + if (s[12] == 'y') { + if (s[13] == '_') { + if (s[14] == 'a') { + if (s[15] == 'l') { + if (s[16] == 'i') { + if (s[17] == 'a') { + if (s[18] == 's') { + return T_AT_COMPATIBILITY_ALIAS; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_ERROR; +} + +int Lexer::classifyObjCAtKeyword(const char *s, int n) { + switch (n) { + case 3: return classify3(s); + case 4: return classify4(s); + case 5: return classify5(s); + case 6: return classify6(s); + case 7: return classify7(s); + case 8: return classify8(s); + case 9: return classify9(s); + case 10: return classify10(s); + case 11: return classify11(s); + case 12: return classify12(s); + case 14: return classify14(s); + case 19: return classify19(s); + default: return T_ERROR; + } // switch +} + +CPLUSPLUS_END_NAMESPACE diff --git a/shared/cplusplus/Parser.cpp b/shared/cplusplus/Parser.cpp index 05836e9fca0e8d30fe92cf484c4b97a725d0c886..c1e48f233f4f6cd2dd689d1233fbdf6e89c16c22 100644 --- a/shared/cplusplus/Parser.cpp +++ b/shared/cplusplus/Parser.cpp @@ -395,6 +395,28 @@ bool Parser::parseDeclaration(DeclarationAST *&node) case T_EXPORT: return parseTemplateDeclaration(node); + // objc++ + case T_AT_CLASS: + return parseObjCClassDeclaration(node); + + case T_AT_INTERFACE: + return parseObjCInterfaceDeclaration(node); + + case T_AT_PROTOCOL: + return parseObjCProtocolDeclaration(node); + +// case T_AT_END: +// return parseObjCEndDeclaration(node); + + case T_AT_COMPATIBILITY_ALIAS: + return parseObjCAliasDeclaration(node); + + case T_AT_SYNTHESIZE: + return parseObjCPropertySynthesize(node); + + case T_AT_DYNAMIC: + return parseObjCPropertyDynamic(node); + default: if (LA() == T_EXTERN && LA(2) == T_TEMPLATE) return parseTemplateDeclaration(node); @@ -3261,4 +3283,171 @@ bool Parser::parseThrowExpression(ExpressionAST *&node) return false; } +bool Parser::parseObjCClassDeclaration(DeclarationAST *&node) +{ + if (LA() != T_AT_CLASS) + return false; + + ObjCClassDeclarationAST *ast = new (_pool) ObjCClassDeclarationAST; + ast->class_token = consumeToken(); + parseObjCIdentifierList(ast->identifier_list); + match(T_SEMICOLON, &ast->semicolon_token); + node = ast; + return true; +} + +bool Parser::parseObjCInterfaceDeclaration(DeclarationAST *&node) +{ + if (LA() != T_AT_INTERFACE) + return false; + + unsigned interface_token = consumeToken(); + unsigned interface_name_token = 0; + match(T_IDENTIFIER, &interface_name_token); + if (LA() == T_LPAREN) { + // category interface + unsigned lparen_token = consumeToken(); + unsigned catagory_name_token = 0; + if (LA() == T_IDENTIFIER) + catagory_name_token = consumeToken(); + unsigned rparen_token = 0; + match(T_RPAREN, &rparen_token); + parseObjCProtocolRefs(); + parseObjCClassInstanceVariables(); + parseObjCInterfaceDeclList(); + unsigned end_token = 0; + match(T_AT_END, &end_token); + return true; + } else { + // class interface + unsigned colon_token = 0; + unsigned super_class_token = 0; + if (LA() == T_COLON) { + colon_token = consumeToken(); + match(T_IDENTIFIER, &super_class_token); + } + parseObjCProtocolRefs(); + parseObjCInterfaceDeclList(); + unsigned end_token = 0; + match(T_AT_END, &end_token); + return true; + } + return false; +} + +bool Parser::parseObjCProtocolDeclaration(DeclarationAST *&node) +{ + return false; +} + +bool Parser::parseObjCEndDeclaration(DeclarationAST *&node) +{ + return false; +} + +bool Parser::parseObjCAliasDeclaration(DeclarationAST *&node) +{ + return false; +} + +bool Parser::parseObjCPropertySynthesize(DeclarationAST *&node) +{ + return false; +} + +bool Parser::parseObjCPropertyDynamic(DeclarationAST *&node) +{ + return false; +} + +bool Parser::parseObjCIdentifierList(IdentifierListAST *&node) +{ + if (LA() == T_IDENTIFIER) { + IdentifierListAST **it = &node; + IdentifierListAST *id = new (_pool) IdentifierListAST; + id->identifier_token = consumeToken(); + *it = id; + while (LA() == T_COMMA) { + consumeToken(); + if (LA() == T_IDENTIFIER) { + it = &(*it)->next; + IdentifierListAST *id = new (_pool) IdentifierListAST; + id->identifier_token = consumeToken(); + *it = id; + } + } + return true; + } + return false; +} + +bool Parser::parseObjCProtocolRefs() +{ + return false; +} + +bool Parser::parseObjCClassInstanceVariables() +{ + return false; +} + +bool Parser::parseObjCInterfaceDeclList() +{ + unsigned saved = cursor(); + while (LA() != T_AT_END && parseObjCInterfaceMemberDeclaration()) { + if (saved == cursor()) + consumeToken(); // skip a token + } + return true; +} + +bool Parser::parseObjCInterfaceMemberDeclaration() +{ + switch (LA()) { + case T_SEMICOLON: + consumeToken(); + return true; + + case T_AT_REQUIRED: + case T_AT_OPTIONAL: + consumeToken(); + return true; + + case T_PLUS: + case T_MINUS: + return parseObjCMethodPrototype(); + + default: { + DeclarationAST *declaration = 0; + parseDeclaration(declaration); + } // default + + } // switch + + return true; +} + +bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&ast) +{ + return false; +} + +bool Parser::parseObjCMethodPrototype() +{ + if (LA() != T_PLUS && LA() != T_MINUS) + return false; + + // instance or class method? + unsigned method_type_token = consumeToken(); + + + SpecifierAST *attributes = 0, **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + + return false; +} + + + CPLUSPLUS_END_NAMESPACE diff --git a/shared/cplusplus/Parser.h b/shared/cplusplus/Parser.h index 6059aa683753986fef62d7a58dc7d3d0db2e5f56..1eac8ce765270b1cdb8903c29784431641291f7b 100644 --- a/shared/cplusplus/Parser.h +++ b/shared/cplusplus/Parser.h @@ -203,6 +203,24 @@ public: bool parseUsingDirective(DeclarationAST *&node); bool parseWhileStatement(StatementAST *&node); + // ObjC++ + bool parseObjCClassDeclaration(DeclarationAST *&node); + bool parseObjCInterfaceDeclaration(DeclarationAST *&node); + bool parseObjCProtocolDeclaration(DeclarationAST *&node); + bool parseObjCEndDeclaration(DeclarationAST *&node); + bool parseObjCAliasDeclaration(DeclarationAST *&node); + bool parseObjCPropertySynthesize(DeclarationAST *&node); + bool parseObjCPropertyDynamic(DeclarationAST *&node); + + bool parseObjCIdentifierList(IdentifierListAST *&node); + + bool parseObjCPropertyDeclaration(DeclarationAST *&ast); + bool parseObjCProtocolRefs(); + bool parseObjCClassInstanceVariables(); + bool parseObjCInterfaceMemberDeclaration(); + bool parseObjCInterfaceDeclList(); + bool parseObjCMethodPrototype(); + // Qt MOC run bool parseQtMethod(ExpressionAST *&node); diff --git a/src/libs/cplusplus/SimpleLexer.cpp b/src/libs/cplusplus/SimpleLexer.cpp index 4c2a78303632f481ce2a17cfbf308276010d1292..583f45da3892d8d3121008c88c1741c0380fa0cf 100644 --- a/src/libs/cplusplus/SimpleLexer.cpp +++ b/src/libs/cplusplus/SimpleLexer.cpp @@ -57,7 +57,8 @@ bool SimpleToken::isKeyword() const SimpleLexer::SimpleLexer() : _lastState(0), _skipComments(false), - _qtMocRunEnabled(true) + _qtMocRunEnabled(true), + _objcEnabled(false) { } SimpleLexer::~SimpleLexer() @@ -73,6 +74,17 @@ void SimpleLexer::setQtMocRunEnabled(bool enabled) _qtMocRunEnabled = enabled; } + +bool SimpleLexer::objcEnabled() const +{ + return _objcEnabled; +} + +void SimpleLexer::setObjcEnabled(bool onoff) +{ + _objcEnabled = onoff; +} + bool SimpleLexer::skipComments() const { return _skipComments; @@ -93,6 +105,7 @@ QList<SimpleToken> SimpleLexer::operator()(const QString &text, int state) Lexer lex(firstChar, lastChar); lex.setQtMocRunEnabled(_qtMocRunEnabled); + lex.setObjcEnabled(_objcEnabled); if (! _skipComments) lex.setScanCommentTokens(true); diff --git a/src/libs/cplusplus/SimpleLexer.h b/src/libs/cplusplus/SimpleLexer.h index b4889fc92ea60d1064acd6b4c3db7e07982db8c4..fb64a66c0333b71c07ae88006991e2262378ffe2 100644 --- a/src/libs/cplusplus/SimpleLexer.h +++ b/src/libs/cplusplus/SimpleLexer.h @@ -91,6 +91,9 @@ public: bool qtMocRunEnabled() const; void setQtMocRunEnabled(bool enabled); + bool objcEnabled() const; + void setObjcEnabled(bool onoff); + QList<SimpleToken> operator()(const QString &text, int state = 0); int state() const @@ -100,6 +103,7 @@ private: int _lastState; bool _skipComments: 1; bool _qtMocRunEnabled: 1; + bool _objcEnabled: 1; }; } // end of namespace CPlusPlus