summaryrefslogtreecommitdiff
path: root/shared/cplusplus
diff options
context:
space:
mode:
Diffstat (limited to 'shared/cplusplus')
-rw-r--r--shared/cplusplus/Lexer.cpp10
-rw-r--r--shared/cplusplus/Lexer.h6
-rw-r--r--shared/cplusplus/Parser.cpp235
-rw-r--r--shared/cplusplus/Parser.h15
-rw-r--r--shared/cplusplus/TranslationUnit.cpp8
-rw-r--r--shared/cplusplus/TranslationUnit.h4
6 files changed, 263 insertions, 15 deletions
diff --git a/shared/cplusplus/Lexer.cpp b/shared/cplusplus/Lexer.cpp
index fcc17313b4..1f4a0f5175 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 84fa410736..b6e361d3da 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 67fed9e011..faa0801250 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 8bde1cccc4..c943664afe 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 c64bbf52c1..caaa9c7d4e 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 9e71b1a8ee..ada079ff48 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;
};
};
};