diff --git a/shared/cplusplus/Lexer.cpp b/shared/cplusplus/Lexer.cpp index fcc17313b4308908b77d49e3ca029f2c4e99f9cc..1f4a0f51751001f0937744391f5632299b824006 100644 --- a/shared/cplusplus/Lexer.cpp +++ b/shared/cplusplus/Lexer.cpp @@ -122,11 +122,11 @@ bool Lexer::qtMocRunEnabled() const void Lexer::setQtMocRunEnabled(bool onoff) { _qtMocRunEnabled = onoff; } -bool Lexer::objcEnabled() const -{ return _objcEnabled; } +bool Lexer::objCEnabled() const +{ return _objCEnabled; } -void Lexer::setObjcEnabled(bool onoff) -{ _objcEnabled = onoff; } +void Lexer::setObjCEnabled(bool onoff) +{ _objCEnabled = onoff; } bool Lexer::isIncremental() const { return _isIncremental; } @@ -554,7 +554,7 @@ void Lexer::scan_helper(Token *tok) break; default: { - if (_objcEnabled) { + if (_objCEnabled) { if (ch == '@' && _yychar >= 'a' && _yychar <= 'z') { const char *yytext = _currentChar; diff --git a/shared/cplusplus/Lexer.h b/shared/cplusplus/Lexer.h index 84fa41073635a03157dad0b92d435f67701e8788..b6e361d3da78f7de2ec1563ad7d1284ac96bf391 100644 --- a/shared/cplusplus/Lexer.h +++ b/shared/cplusplus/Lexer.h @@ -80,8 +80,8 @@ public: bool qtMocRunEnabled() const; void setQtMocRunEnabled(bool onoff); - bool objcEnabled() const; - void setObjcEnabled(bool onoff); + bool objCEnabled() const; + void setObjCEnabled(bool onoff); void scan(Token *tok); @@ -147,7 +147,7 @@ private: unsigned _scanKeywords: 1; unsigned _scanAngleStringLiteralTokens: 1; unsigned _qtMocRunEnabled: 1; - unsigned _objcEnabled: 1; + unsigned _objCEnabled: 1; }; }; unsigned _currentLine; diff --git a/shared/cplusplus/Parser.cpp b/shared/cplusplus/Parser.cpp index 67fed9e011867da2eebe56f22c1d205560153396..faa0801250e9e7610aa541d9dfd6f11164672e09 100644 --- a/shared/cplusplus/Parser.cpp +++ b/shared/cplusplus/Parser.cpp @@ -68,8 +68,9 @@ Parser::Parser(TranslationUnit *unit) _tokenIndex(1), _templateArguments(0), _qtMocRunEnabled(false), - _objcEnabled(false), - _inFunctionBody(false) + _objCEnabled(false), + _inFunctionBody(false), + _inObjCImplementationContext(false) { } Parser::~Parser() @@ -81,6 +82,12 @@ bool Parser::qtMocRunEnabled() const void Parser::setQtMocRunEnabled(bool onoff) { _qtMocRunEnabled = onoff; } +bool Parser::objCEnabled() const +{ return _objCEnabled; } + +void Parser::setObjCEnabled(bool onoff) +{ _objCEnabled = onoff; } + bool Parser::switchTemplateArguments(bool templateArguments) { bool previousTemplateArguments = _templateArguments; @@ -397,6 +404,9 @@ bool Parser::parseDeclaration(DeclarationAST *&node) return parseTemplateDeclaration(node); // objc++ + case T_AT_IMPLEMENTATION: + return parseObjCClassImplementation(node); + case T_AT_CLASS: return parseObjCClassDeclaration(node); @@ -406,8 +416,8 @@ bool Parser::parseDeclaration(DeclarationAST *&node) case T_AT_PROTOCOL: return parseObjCProtocolDeclaration(node); -// case T_AT_END: -// return parseObjCEndDeclaration(node); + case T_AT_END: + return parseObjCEndDeclaration(node); case T_AT_COMPATIBILITY_ALIAS: return parseObjCAliasDeclaration(node); @@ -2540,7 +2550,7 @@ bool Parser::parsePrimaryExpression(ExpressionAST *&node) return parseObjCExpression(node); default: { - if (_objcEnabled && LA() == T_LBRACKET) + if (_objCEnabled && LA() == T_LBRACKET) return parseObjCExpression(node); unsigned startOfName = cursor(); @@ -3293,6 +3303,33 @@ bool Parser::parseThrowExpression(ExpressionAST *&node) return false; } +bool Parser::parseObjCClassImplementation(DeclarationAST *&node) +{ + if (LA() != T_AT_IMPLEMENTATION) + return false; + + unsigned implementation_token = consumeToken(); + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + + if (LA() == T_COLON) { + unsigned colon_token = consumeToken(); + unsigned superclass_name_token = 0; + match(T_IDENTIFIER, &superclass_name_token); + } else if (LA() == T_LPAREN) { + unsigned lparen_token = consumeToken(); + unsigned category_name_token = 0; + if (LA() == T_IDENTIFIER) + category_name_token = consumeToken(); + unsigned rparen_token = 0; + match(T_RPAREN, &rparen_token); + } + + _inObjCImplementationContext = true; + parseObjCMethodDefinitionList(); + return true; +} + bool Parser::parseObjCClassDeclaration(DeclarationAST *&node) { if (LA() != T_AT_CLASS) @@ -3352,7 +3389,18 @@ bool Parser::parseObjCProtocolDeclaration(DeclarationAST *&) bool Parser::parseObjCEndDeclaration(DeclarationAST *&) { - return false; + if (LA() != T_AT_END) + return false; + + unsigned end_token = consumeToken(); + + if (! _inObjCImplementationContext) { + _translationUnit->warning(end_token, + "@end must appear in an @implementation context"); + } + + _inObjCImplementationContext = false; + return true; } bool Parser::parseObjCAliasDeclaration(DeclarationAST *&) @@ -3589,4 +3637,179 @@ bool Parser::parseObjCMessageArguments() return true; } +bool Parser::parseObjCMethodDefinitionList() +{ + bool done = false; + while (! done) { + switch (LA()) { + case T_EOF_SYMBOL: + case T_AT_END: + done = true; + break; + + case T_PLUS: + case T_MINUS: + parseObjCMethodSignature(); + if (LA() == T_SEMICOLON) + consumeToken(); + break; + + case T_AT_PROPERTY: + parseObjCAtProperty(); + break; + + case T_SEMICOLON: + consumeToken(); + break; + + case T_AT_OPTIONAL: + consumeToken(); + break; + + case T_AT_REQUIRED: + consumeToken(); + break; + + case T_TEMPLATE: + case T_NAMESPACE: { + DeclarationAST *declaration = 0; + parseDeclaration(declaration); + } break; + + default: { + unsigned start = cursor(); + DeclarationAST *declaration = 0; + if (LA(1) == T_EXTERN && LA(2) == T_STRING_LITERAL) { + parseLinkageSpecification(declaration); + } else if (parseBlockDeclaration(declaration)) { + // ### accept the declaration. + } else { + if (cursor() == start) { + _translationUnit->error(cursor(), + "stray `%s' between Objective-C++ methods", + tok().spell()); + consumeToken(); + } + } + } break; // default + + } // switch + } + + return true; +} + +bool Parser::parseObjCMethodSignature() +{ + if (LA() != T_PLUS && LA() != T_MINUS) + return false; + + unsigned method_type_token = consumeToken(); + parseObjCTypeName(); + + bool first = true; + + while (lookAtObjCSelector() || LA() == T_COLON) { + if (LA() != T_COLON) + /*selector_name_token = */ consumeToken(); + + SpecifierAST *attributes = 0, **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + + if (first) { + first = false; + + if (LA() != T_COLON) + break; + } + + unsigned colon_token = 0; + match(T_COLON, &colon_token); + + parseObjCTypeName(); + + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + } + + // parse the method tail parameters. + while (LA() == T_COMMA) { + consumeToken(); + + if (LA() == T_DOT_DOT_DOT) { + consumeToken(); + break; + } + + DeclarationAST *parameter_declaration = 0; + parseParameterDeclaration(parameter_declaration); + } + + return true; +} + +bool Parser::parseObjCTypeName() +{ + if (LA() != T_LPAREN) + return false; + + /*unsigned lparen_token = */ consumeToken(); + + parseObjCProtocolQualifiers(); + + ExpressionAST *type_id = 0; + if (LA() != T_RPAREN) + parseTypeId(type_id); + + SpecifierAST *attributes = 0, **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + + unsigned rparen_token = 0; + match(T_RPAREN, &rparen_token); + return true; +} + +bool Parser::parseObjCAtProperty() +{ + if (LA() != T_AT_PROPERTY) + return false; + + /*unsigned property_token = */ consumeToken(); + return true; +} + +bool Parser::parseObjCProtocolQualifiers() +{ + return false; +} + +bool Parser::lookAtObjCSelector() const +{ + switch (LA()) { + case T_IDENTIFIER: + case T_OR: + case T_AND: + case T_NOT: + case T_XOR: + case T_BITOR: + case T_COMPL: + case T_OR_EQ: + case T_AND_EQ: + case T_BITAND: + case T_NOT_EQ: + case T_XOR_EQ: + return true; + + default: + if (tok().isKeyword()) + return true; + } // switch + + return false; +} CPLUSPLUS_END_NAMESPACE diff --git a/shared/cplusplus/Parser.h b/shared/cplusplus/Parser.h index 8bde1cccc46599e1a75c8d0ca7b717b78c856c54..c943664afe1b6428e511bce4e13f52ee146bb7c0 100644 --- a/shared/cplusplus/Parser.h +++ b/shared/cplusplus/Parser.h @@ -70,6 +70,9 @@ public: bool qtMocRunEnabled() const; void setQtMocRunEnabled(bool onoff); + bool objCEnabled() const; + void setObjCEnabled(bool onoff); + bool parseTranslationUnit(TranslationUnitAST *&node); public: @@ -204,6 +207,7 @@ public: bool parseWhileStatement(StatementAST *&node); // ObjC++ + bool parseObjCClassImplementation(DeclarationAST *&node); bool parseObjCClassDeclaration(DeclarationAST *&node); bool parseObjCInterfaceDeclaration(DeclarationAST *&node); bool parseObjCProtocolDeclaration(DeclarationAST *&node); @@ -231,6 +235,14 @@ public: bool parseObjCMessageReceiver(ExpressionAST *&node); bool parseObjCMessageArguments(); + bool parseObjCMethodSignature(); + bool parseObjCMethodDefinitionList(); + bool parseObjCAtProperty(); + bool parseObjCTypeName(); + bool parseObjCProtocolQualifiers(); + + bool lookAtObjCSelector() const; + // Qt MOC run bool parseQtMethod(ExpressionAST *&node); @@ -277,8 +289,9 @@ private: unsigned _tokenIndex; bool _templateArguments: 1; bool _qtMocRunEnabled: 1; - bool _objcEnabled: 1; + bool _objCEnabled: 1; bool _inFunctionBody: 1; + bool _inObjCImplementationContext: 1; private: Parser(const Parser& source); diff --git a/shared/cplusplus/TranslationUnit.cpp b/shared/cplusplus/TranslationUnit.cpp index c64bbf52c15ecf4b7e57aa1b3773ae49b84bde51..caaa9c7d4e709062517f790806e3d73609e21d90 100644 --- a/shared/cplusplus/TranslationUnit.cpp +++ b/shared/cplusplus/TranslationUnit.cpp @@ -92,6 +92,12 @@ bool TranslationUnit::qtMocRunEnabled() const void TranslationUnit::setQtMocRunEnabled(bool onoff) { _qtMocRunEnabled = onoff; } +bool TranslationUnit::objCEnabled() const +{ return _objCEnabled; } + +void TranslationUnit::setObjCEnabled(bool onoff) +{ _objCEnabled = onoff; } + Control *TranslationUnit::control() const { return _control; } @@ -164,6 +170,7 @@ void TranslationUnit::tokenize() Lexer lex(this); lex.setQtMocRunEnabled(_qtMocRunEnabled); + lex.setObjCEnabled(_objCEnabled); std::stack<unsigned> braces; _tokens->push_back(Token()); // the first token needs to be invalid! @@ -228,6 +235,7 @@ bool TranslationUnit::parse(ParseMode mode) Parser parser(this); parser.setQtMocRunEnabled(_qtMocRunEnabled); + parser.setObjCEnabled(_objCEnabled); bool parsed = false; diff --git a/shared/cplusplus/TranslationUnit.h b/shared/cplusplus/TranslationUnit.h index 9e71b1a8ee6d7c66a27352c5d8aad435a6132f42..ada079ff48447b0171bc2e709f838359ef12ceed 100644 --- a/shared/cplusplus/TranslationUnit.h +++ b/shared/cplusplus/TranslationUnit.h @@ -102,6 +102,9 @@ public: bool qtMocRunEnabled() const; void setQtMocRunEnabled(bool onoff); + bool objCEnabled() const; + void setObjCEnabled(bool onoff); + void warning(unsigned index, const char *fmt, ...); void error(unsigned index, const char *fmt, ...); void fatal(unsigned index, const char *fmt, ...); @@ -187,6 +190,7 @@ private: unsigned _blockErrors: 1; unsigned _skipFunctionBody: 1; unsigned _qtMocRunEnabled: 1; + unsigned _objCEnabled: 1; }; }; }; diff --git a/src/libs/cplusplus/SimpleLexer.cpp b/src/libs/cplusplus/SimpleLexer.cpp index 583f45da3892d8d3121008c88c1741c0380fa0cf..440946cdb38256cc9ff99d46d0f46100cf083d82 100644 --- a/src/libs/cplusplus/SimpleLexer.cpp +++ b/src/libs/cplusplus/SimpleLexer.cpp @@ -58,7 +58,7 @@ SimpleLexer::SimpleLexer() : _lastState(0), _skipComments(false), _qtMocRunEnabled(true), - _objcEnabled(false) + _objCEnabled(false) { } SimpleLexer::~SimpleLexer() @@ -74,15 +74,14 @@ void SimpleLexer::setQtMocRunEnabled(bool enabled) _qtMocRunEnabled = enabled; } - -bool SimpleLexer::objcEnabled() const +bool SimpleLexer::objCEnabled() const { - return _objcEnabled; + return _objCEnabled; } -void SimpleLexer::setObjcEnabled(bool onoff) +void SimpleLexer::setObjCEnabled(bool onoff) { - _objcEnabled = onoff; + _objCEnabled = onoff; } bool SimpleLexer::skipComments() const @@ -105,7 +104,7 @@ QList<SimpleToken> SimpleLexer::operator()(const QString &text, int state) Lexer lex(firstChar, lastChar); lex.setQtMocRunEnabled(_qtMocRunEnabled); - lex.setObjcEnabled(_objcEnabled); + lex.setObjCEnabled(_objCEnabled); if (! _skipComments) lex.setScanCommentTokens(true); diff --git a/src/libs/cplusplus/SimpleLexer.h b/src/libs/cplusplus/SimpleLexer.h index fb64a66c0333b71c07ae88006991e2262378ffe2..3f5b736e2dd8d2713e82572c206291ce4df0c733 100644 --- a/src/libs/cplusplus/SimpleLexer.h +++ b/src/libs/cplusplus/SimpleLexer.h @@ -91,8 +91,8 @@ public: bool qtMocRunEnabled() const; void setQtMocRunEnabled(bool enabled); - bool objcEnabled() const; - void setObjcEnabled(bool onoff); + bool objCEnabled() const; + void setObjCEnabled(bool onoff); QList<SimpleToken> operator()(const QString &text, int state = 0); @@ -103,7 +103,7 @@ private: int _lastState; bool _skipComments: 1; bool _qtMocRunEnabled: 1; - bool _objcEnabled: 1; + bool _objCEnabled: 1; }; } // end of namespace CPlusPlus