Recognize C++0x lambda expressions.

This commit is contained in:
Roberto Raggi
2010-03-24 12:54:25 +01:00
parent 35be3a9f6c
commit 8329d7db94
19 changed files with 850 additions and 37 deletions

View File

@@ -2416,3 +2416,119 @@ unsigned ObjCSynchronizedStatementAST::lastToken() const
if (lparen_token) return lparen_token + 1;
return synchronized_token + 1;
}
unsigned LambdaExpressionAST::firstToken() const
{
if (lambda_introducer)
return lambda_introducer->firstToken();
// assert?
return 0;
}
unsigned LambdaExpressionAST::lastToken() const
{
if (statement)
return statement->lastToken();
else if (lambda_declarator)
return lambda_declarator->lastToken();
return lambda_introducer->lastToken();
}
unsigned LambdaIntroducerAST::firstToken() const
{
return lbracket_token;
}
unsigned LambdaIntroducerAST::lastToken() const
{
if (rbracket_token)
return rbracket_token + 1;
else if (lambda_capture)
return lambda_capture->lastToken();
return lbracket_token + 1;
}
unsigned LambdaCaptureAST::firstToken() const
{
if (default_capture)
return default_capture;
else if (capture_list)
return capture_list->firstToken();
// assert?
return 0;
}
unsigned LambdaCaptureAST::lastToken() const
{
if (capture_list)
return capture_list->lastToken();
else if (default_capture)
return default_capture + 1;
// assert?
return 0;
}
unsigned CaptureAST::firstToken() const
{
// ### implement me
return 0;
}
unsigned CaptureAST::lastToken() const
{
// ### implement me
return 0;
}
unsigned LambdaDeclaratorAST::firstToken() const
{
return lparen_token;
}
unsigned LambdaDeclaratorAST::lastToken() const
{
if (trailing_return_type)
return trailing_return_type->lastToken();
else if (exception_specification)
return exception_specification->lastToken();
else if (mutable_token)
return mutable_token + 1;
else if (attributes)
return attributes->lastToken();
else if (rparen_token)
return rparen_token + 1;
else if (parameter_declaration_clause)
return parameter_declaration_clause->lastToken();
return lparen_token + 1;
}
unsigned TrailingReturnTypeAST::firstToken() const
{
return arrow_token;
}
unsigned TrailingReturnTypeAST::lastToken() const
{
if (declarator)
return declarator->lastToken();
else if (type_specifiers)
return type_specifiers->lastToken();
else if (attributes)
return attributes->lastToken();
return arrow_token + 1;
}

View File

@@ -164,6 +164,7 @@ public:
virtual BoolLiteralAST *asBoolLiteral() { return 0; }
virtual BreakStatementAST *asBreakStatement() { return 0; }
virtual CallAST *asCall() { return 0; }
virtual CaptureAST *asCapture() { return 0; }
virtual CaseStatementAST *asCaseStatement() { return 0; }
virtual CastExpressionAST *asCastExpression() { return 0; }
virtual CatchClauseAST *asCatchClause() { return 0; }
@@ -201,6 +202,10 @@ public:
virtual GotoStatementAST *asGotoStatement() { return 0; }
virtual IfStatementAST *asIfStatement() { return 0; }
virtual LabeledStatementAST *asLabeledStatement() { return 0; }
virtual LambdaCaptureAST *asLambdaCapture() { return 0; }
virtual LambdaDeclaratorAST *asLambdaDeclarator() { return 0; }
virtual LambdaExpressionAST *asLambdaExpression() { return 0; }
virtual LambdaIntroducerAST *asLambdaIntroducer() { return 0; }
virtual LinkageBodyAST *asLinkageBody() { return 0; }
virtual LinkageSpecificationAST *asLinkageSpecification() { return 0; }
virtual MemInitializerAST *asMemInitializer() { return 0; }
@@ -280,6 +285,7 @@ public:
virtual TemplateTypeParameterAST *asTemplateTypeParameter() { return 0; }
virtual ThisExpressionAST *asThisExpression() { return 0; }
virtual ThrowExpressionAST *asThrowExpression() { return 0; }
virtual TrailingReturnTypeAST *asTrailingReturnType() { return 0; }
virtual TranslationUnitAST *asTranslationUnit() { return 0; }
virtual TryBlockStatementAST *asTryBlockStatement() { return 0; }
virtual TypeConstructorCallAST *asTypeConstructorCall() { return 0; }
@@ -4103,7 +4109,157 @@ protected:
virtual bool match0(AST *, ASTMatcher *);
};
class LambdaExpressionAST: public ExpressionAST
{
public:
LambdaIntroducerAST *lambda_introducer;
LambdaDeclaratorAST *lambda_declarator;
StatementAST *statement;
public:
LambdaExpressionAST()
: lambda_introducer(0)
, lambda_declarator(0)
, statement(0)
{}
virtual LambdaExpressionAST *asLambdaExpression() { return this; }
virtual unsigned firstToken() const;
virtual unsigned lastToken() const;
virtual LambdaExpressionAST *clone(MemoryPool *pool) const;
protected:
virtual void accept0(ASTVisitor *visitor);
virtual bool match0(AST *, ASTMatcher *);
};
class LambdaIntroducerAST: public AST
{
public:
unsigned lbracket_token;
LambdaCaptureAST *lambda_capture;
unsigned rbracket_token;
public:
LambdaIntroducerAST()
: lbracket_token(0)
, lambda_capture(0)
, rbracket_token(0)
{}
virtual LambdaIntroducerAST *asLambdaIntroducer() { return this; }
virtual unsigned firstToken() const;
virtual unsigned lastToken() const;
virtual LambdaIntroducerAST *clone(MemoryPool *pool) const;
protected:
virtual void accept0(ASTVisitor *visitor);
virtual bool match0(AST *, ASTMatcher *);
};
class LambdaCaptureAST: public AST
{
public:
unsigned default_capture;
CaptureListAST *capture_list;
public:
LambdaCaptureAST()
: default_capture(0)
, capture_list(0)
{}
virtual LambdaCaptureAST *asLambdaCapture() { return this; }
virtual unsigned firstToken() const;
virtual unsigned lastToken() const;
virtual LambdaCaptureAST *clone(MemoryPool *pool) const;
protected:
virtual void accept0(ASTVisitor *visitor);
virtual bool match0(AST *, ASTMatcher *);
};
class CaptureAST: public AST
{
public:
CaptureAST()
{}
virtual CaptureAST *asCapture() { return this; }
virtual unsigned firstToken() const;
virtual unsigned lastToken() const;
virtual CaptureAST *clone(MemoryPool *pool) const;
protected:
virtual void accept0(ASTVisitor *visitor);
virtual bool match0(AST *, ASTMatcher *);
};
class LambdaDeclaratorAST: public AST
{
public:
unsigned lparen_token;
ParameterDeclarationClauseAST *parameter_declaration_clause;
unsigned rparen_token;
SpecifierListAST *attributes;
unsigned mutable_token;
ExceptionSpecificationAST *exception_specification;
TrailingReturnTypeAST *trailing_return_type;
public:
LambdaDeclaratorAST()
: lparen_token(0)
, parameter_declaration_clause(0)
, rparen_token(0)
, attributes(0)
, mutable_token(0)
, exception_specification(0)
, trailing_return_type(0)
{}
virtual LambdaDeclaratorAST *asLambdaDeclarator() { return this; }
virtual unsigned firstToken() const;
virtual unsigned lastToken() const;
virtual LambdaDeclaratorAST *clone(MemoryPool *pool) const;
protected:
virtual void accept0(ASTVisitor *visitor);
virtual bool match0(AST *, ASTMatcher *);
};
class TrailingReturnTypeAST: public AST
{
public:
unsigned arrow_token;
SpecifierListAST *attributes;
SpecifierListAST *type_specifiers;
DeclaratorAST *declarator;
public:
TrailingReturnTypeAST()
: arrow_token(0)
, attributes(0)
, type_specifiers(0)
, declarator(0)
{}
virtual TrailingReturnTypeAST *asTrailingReturnType() { return this; }
virtual unsigned firstToken() const;
virtual unsigned lastToken() const;
virtual TrailingReturnTypeAST *clone(MemoryPool *pool) const;
protected:
virtual void accept0(ASTVisitor *visitor);
virtual bool match0(AST *, ASTMatcher *);
};
} // end of namespace CPlusPlus
#endif // CPLUSPLUS_AST_H

View File

@@ -1586,3 +1586,73 @@ ObjCSynchronizedStatementAST *ObjCSynchronizedStatementAST::clone(MemoryPool *po
return ast;
}
LambdaExpressionAST *LambdaExpressionAST::clone(MemoryPool *pool) const
{
LambdaExpressionAST *ast = new (pool) LambdaExpressionAST;
if (lambda_introducer)
ast->lambda_introducer = lambda_introducer->clone(pool);
if (lambda_declarator)
ast->lambda_declarator = lambda_declarator->clone(pool);
if (statement)
ast->statement = statement->clone(pool);
return ast;
}
LambdaIntroducerAST *LambdaIntroducerAST::clone(MemoryPool *pool) const
{
LambdaIntroducerAST *ast = new (pool) LambdaIntroducerAST;
ast->lbracket_token = lbracket_token;
if (lambda_capture)
ast->lambda_capture = lambda_capture->clone(pool);
ast->rbracket_token = rbracket_token;
return ast;
}
LambdaCaptureAST *LambdaCaptureAST::clone(MemoryPool *pool) const
{
LambdaCaptureAST *ast = new (pool) LambdaCaptureAST;
for (CaptureListAST *iter = capture_list, **ast_iter = &ast->capture_list;
iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
*ast_iter = new (pool) CaptureListAST((iter->value) ? iter->value->clone(pool) : 0);
return ast;
}
CaptureAST *CaptureAST::clone(MemoryPool *pool) const
{
CaptureAST *ast = new (pool) CaptureAST;
return ast;
}
LambdaDeclaratorAST *LambdaDeclaratorAST::clone(MemoryPool *pool) const
{
LambdaDeclaratorAST *ast = new (pool) LambdaDeclaratorAST;
ast->lparen_token = lparen_token;
if (parameter_declaration_clause)
ast->parameter_declaration_clause = parameter_declaration_clause->clone(pool);
ast->rparen_token = rparen_token;
for (SpecifierListAST *iter = attributes, **ast_iter = &ast->attributes;
iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
*ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
ast->mutable_token = mutable_token;
if (exception_specification)
ast->exception_specification = exception_specification->clone(pool);
if (trailing_return_type)
ast->trailing_return_type = trailing_return_type->clone(pool);
return ast;
}
TrailingReturnTypeAST *TrailingReturnTypeAST::clone(MemoryPool *pool) const
{
TrailingReturnTypeAST *ast = new (pool) TrailingReturnTypeAST;
ast->arrow_token = arrow_token;
for (SpecifierListAST *iter = attributes, **ast_iter = &ast->attributes;
iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
*ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : 0);
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);
return ast;
}

View File

@@ -1089,3 +1089,51 @@ bool ObjCSynchronizedStatementAST::match0(AST *pattern, ASTMatcher *matcher)
return false;
}
bool LambdaExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (LambdaExpressionAST *_other = pattern->asLambdaExpression())
return matcher->match(this, _other);
return false;
}
bool LambdaIntroducerAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (LambdaIntroducerAST *_other = pattern->asLambdaIntroducer())
return matcher->match(this, _other);
return false;
}
bool LambdaCaptureAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (LambdaCaptureAST *_other = pattern->asLambdaCapture())
return matcher->match(this, _other);
return false;
}
bool CaptureAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (CaptureAST *_other = pattern->asCapture())
return matcher->match(this, _other);
return false;
}
bool LambdaDeclaratorAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (LambdaDeclaratorAST *_other = pattern->asLambdaDeclarator())
return matcher->match(this, _other);
return false;
}
bool TrailingReturnTypeAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (TrailingReturnTypeAST *_other = pattern->asTrailingReturnType())
return matcher->match(this, _other);
return false;
}

View File

@@ -2669,3 +2669,123 @@ bool ASTMatcher::match(ObjCSynchronizedStatementAST *node, ObjCSynchronizedState
return true;
}
bool ASTMatcher::match(LambdaExpressionAST *node, LambdaExpressionAST *pattern)
{
(void) node;
(void) pattern;
if (! pattern->lambda_introducer)
pattern->lambda_introducer = node->lambda_introducer;
else if (! AST::match(node->lambda_introducer, pattern->lambda_introducer, this))
return false;
if (! pattern->lambda_declarator)
pattern->lambda_declarator = node->lambda_declarator;
else if (! AST::match(node->lambda_declarator, pattern->lambda_declarator, this))
return false;
if (! pattern->statement)
pattern->statement = node->statement;
else if (! AST::match(node->statement, pattern->statement, this))
return false;
return true;
}
bool ASTMatcher::match(LambdaIntroducerAST *node, LambdaIntroducerAST *pattern)
{
(void) node;
(void) pattern;
pattern->lbracket_token = node->lbracket_token;
if (! pattern->lambda_capture)
pattern->lambda_capture = node->lambda_capture;
else if (! AST::match(node->lambda_capture, pattern->lambda_capture, this))
return false;
pattern->rbracket_token = node->rbracket_token;
return true;
}
bool ASTMatcher::match(LambdaCaptureAST *node, LambdaCaptureAST *pattern)
{
(void) node;
(void) pattern;
if (! pattern->capture_list)
pattern->capture_list = node->capture_list;
else if (! AST::match(node->capture_list, pattern->capture_list, this))
return false;
return true;
}
bool ASTMatcher::match(CaptureAST *node, CaptureAST *pattern)
{
(void) node;
(void) pattern;
return true;
}
bool ASTMatcher::match(LambdaDeclaratorAST *node, LambdaDeclaratorAST *pattern)
{
(void) node;
(void) pattern;
pattern->lparen_token = node->lparen_token;
if (! pattern->parameter_declaration_clause)
pattern->parameter_declaration_clause = node->parameter_declaration_clause;
else if (! AST::match(node->parameter_declaration_clause, pattern->parameter_declaration_clause, this))
return false;
pattern->rparen_token = node->rparen_token;
if (! pattern->attributes)
pattern->attributes = node->attributes;
else if (! AST::match(node->attributes, pattern->attributes, this))
return false;
pattern->mutable_token = node->mutable_token;
if (! pattern->exception_specification)
pattern->exception_specification = node->exception_specification;
else if (! AST::match(node->exception_specification, pattern->exception_specification, this))
return false;
if (! pattern->trailing_return_type)
pattern->trailing_return_type = node->trailing_return_type;
else if (! AST::match(node->trailing_return_type, pattern->trailing_return_type, this))
return false;
return true;
}
bool ASTMatcher::match(TrailingReturnTypeAST *node, TrailingReturnTypeAST *pattern)
{
(void) node;
(void) pattern;
pattern->arrow_token = node->arrow_token;
if (! pattern->attributes)
pattern->attributes = node->attributes;
else if (! AST::match(node->attributes, pattern->attributes, this))
return false;
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;
return true;
}

View File

@@ -170,6 +170,12 @@ public:
virtual bool match(ObjCDynamicPropertiesDeclarationAST *node, ObjCDynamicPropertiesDeclarationAST *pattern);
virtual bool match(ObjCFastEnumerationAST *node, ObjCFastEnumerationAST *pattern);
virtual bool match(ObjCSynchronizedStatementAST *node, ObjCSynchronizedStatementAST *pattern);
virtual bool match(LambdaExpressionAST *node, LambdaExpressionAST *pattern);
virtual bool match(LambdaIntroducerAST *node, LambdaIntroducerAST *pattern);
virtual bool match(LambdaCaptureAST *node, LambdaCaptureAST *pattern);
virtual bool match(LambdaDeclaratorAST *node, LambdaDeclaratorAST *pattern);
virtual bool match(CaptureAST *node, CaptureAST *pattern);
virtual bool match(TrailingReturnTypeAST *node, TrailingReturnTypeAST *pattern);
};
} // end of namespace CPlusPlus

View File

@@ -1159,3 +1159,57 @@ void ObjCSynchronizedStatementAST::accept0(ASTVisitor *visitor)
visitor->endVisit(this);
}
void LambdaExpressionAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
accept(lambda_introducer, visitor);
accept(lambda_declarator, visitor);
accept(statement, visitor);
}
visitor->endVisit(this);
}
void LambdaIntroducerAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
accept(lambda_capture, visitor);
}
visitor->endVisit(this);
}
void LambdaCaptureAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
accept(capture_list, visitor);
}
visitor->endVisit(this);
}
void CaptureAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
}
visitor->endVisit(this);
}
void LambdaDeclaratorAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
accept(parameter_declaration_clause, visitor);
accept(attributes, visitor);
accept(exception_specification, visitor);
accept(trailing_return_type, visitor);
}
visitor->endVisit(this);
}
void TrailingReturnTypeAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
accept(attributes, visitor);
accept(type_specifiers, visitor);
accept(declarator, visitor);
}
visitor->endVisit(this);
}

View File

@@ -209,6 +209,14 @@ public:
virtual bool visit(QtInterfacesDeclarationAST *) { return true; }
virtual bool visit(QtInterfaceNameAST *) { return true; }
// C++0x
virtual bool visit(LambdaExpressionAST *) { return true; }
virtual bool visit(LambdaIntroducerAST *) { return true; }
virtual bool visit(LambdaCaptureAST *) { return true; }
virtual bool visit(LambdaDeclaratorAST *) { return true; }
virtual bool visit(CaptureAST *) { return true; }
virtual bool visit(TrailingReturnTypeAST *) { return true; }
// ObjC++
virtual bool visit(ObjCClassDeclarationAST *) { return true; }
virtual bool visit(ObjCClassForwardDeclarationAST *) { return true; }
@@ -343,6 +351,13 @@ public:
virtual void endVisit(QtInterfacesDeclarationAST *) { }
virtual void endVisit(QtInterfaceNameAST *) { }
virtual void endVisit(LambdaExpressionAST *) { }
virtual void endVisit(LambdaIntroducerAST *) { }
virtual void endVisit(LambdaCaptureAST *) { }
virtual void endVisit(LambdaDeclaratorAST *) { }
virtual void endVisit(CaptureAST *) { }
virtual void endVisit(TrailingReturnTypeAST *) { }
// ObjC++
virtual void endVisit(ObjCClassDeclarationAST *) { }
virtual void endVisit(ObjCClassForwardDeclarationAST *) { }

View File

@@ -71,6 +71,7 @@ class BinaryExpressionAST;
class BoolLiteralAST;
class BreakStatementAST;
class CallAST;
class CaptureAST;
class CaseStatementAST;
class CastExpressionAST;
class CatchClauseAST;
@@ -108,6 +109,10 @@ class FunctionDefinitionAST;
class GotoStatementAST;
class IfStatementAST;
class LabeledStatementAST;
class LambdaCaptureAST;
class LambdaDeclaratorAST;
class LambdaExpressionAST;
class LambdaIntroducerAST;
class LinkageBodyAST;
class LinkageSpecificationAST;
class MemInitializerAST;
@@ -187,6 +192,7 @@ class TemplateIdAST;
class TemplateTypeParameterAST;
class ThisExpressionAST;
class ThrowExpressionAST;
class TrailingReturnTypeAST;
class TranslationUnitAST;
class TryBlockStatementAST;
class TypeConstructorCallAST;
@@ -219,6 +225,8 @@ typedef List<QtPropertyDeclarationItemAST *> QtPropertyDeclarationItemListAST;
typedef List<NameAST *> NameListAST;
typedef List<QtInterfaceNameAST *> QtInterfaceNameListAST;
typedef List<CaptureAST *> CaptureListAST;
typedef List<ObjCMessageArgumentAST *> ObjCMessageArgumentListAST;
typedef List<ObjCSelectorArgumentAST *> ObjCSelectorArgumentListAST;
typedef List<ObjCPropertyAttributeAST *> ObjCPropertyAttributeListAST;

View File

@@ -388,8 +388,19 @@ bool CheckExpression::visit(ObjCEncodeExpressionAST * /*ast*/)
bool CheckExpression::visit(ObjCSelectorExpressionAST *ast)
{
if (_scope->isPrototypeScope())
return false;
(void) semantic()->check(ast->selector, _scope);
return false;
}
bool CheckExpression::visit(LambdaExpressionAST *ast)
{
if (_scope->isPrototypeScope())
return false;
(void) semantic()->check(ast->statement, _scope);
return false;
}

View File

@@ -95,6 +95,7 @@ protected:
virtual bool visit(QtMethodAST *ast);
virtual bool visit(CompoundLiteralAST *ast);
virtual bool visit(CompoundExpressionAST *ast);
virtual bool visit(LambdaExpressionAST *ast);
//names
virtual bool visit(QualifiedNameAST *ast);

View File

@@ -51,7 +51,7 @@
using namespace CPlusPlus;
static inline int classify2(const char *s, bool) {
static inline int classify2(const char *s, bool, bool) {
if (s[0] == 'd') {
if (s[1] == 'o') {
return T_DO;
@@ -65,7 +65,7 @@ static inline int classify2(const char *s, bool) {
return T_IDENTIFIER;
}
static inline int classify3(const char *s, bool q) {
static inline int classify3(const char *s, bool q, bool) {
if (s[0] == 'a') {
if (s[1] == 's') {
if (s[2] == 'm') {
@@ -114,7 +114,7 @@ static inline int classify3(const char *s, bool q) {
return T_IDENTIFIER;
}
static inline int classify4(const char *s, bool q) {
static inline int classify4(const char *s, bool q, bool) {
if (s[0] == 'a') {
if (s[1] == 'u') {
if (s[2] == 't') {
@@ -220,7 +220,7 @@ static inline int classify4(const char *s, bool q) {
return T_IDENTIFIER;
}
static inline int classify5(const char *s, bool q) {
static inline int classify5(const char *s, bool q, bool) {
if (s[0] == '_') {
if (s[1] == '_') {
if (s[2] == 'a') {
@@ -359,7 +359,7 @@ static inline int classify5(const char *s, bool q) {
return T_IDENTIFIER;
}
static inline int classify6(const char *s, bool q) {
static inline int classify6(const char *s, bool q, bool) {
if (s[0] == 'd') {
if (s[1] == 'e') {
if (s[2] == 'l') {
@@ -558,7 +558,7 @@ static inline int classify6(const char *s, bool q) {
return T_IDENTIFIER;
}
static inline int classify7(const char *s, bool q) {
static inline int classify7(const char *s, bool q, bool) {
if (s[0] == '_') {
if (s[1] == '_') {
if (s[2] == 'a') {
@@ -745,7 +745,7 @@ static inline int classify7(const char *s, bool q) {
return T_IDENTIFIER;
}
static inline int classify8(const char *s, bool q) {
static inline int classify8(const char *s, bool q, bool) {
if (s[0] == '_') {
if (s[1] == '_') {
if (s[2] == 'i') {
@@ -956,7 +956,7 @@ static inline int classify8(const char *s, bool q) {
return T_IDENTIFIER;
}
static inline int classify9(const char *s, bool q) {
static inline int classify9(const char *s, bool q, bool) {
if (s[0] == '_') {
if (s[1] == '_') {
if (s[2] == 'c') {
@@ -1050,7 +1050,7 @@ static inline int classify9(const char *s, bool q) {
return T_IDENTIFIER;
}
static inline int classify10(const char *s, bool q) {
static inline int classify10(const char *s, bool q, bool) {
if (s[0] == '_') {
if (s[1] == '_') {
if (s[2] == 'i') {
@@ -1168,7 +1168,7 @@ static inline int classify10(const char *s, bool q) {
return T_IDENTIFIER;
}
static inline int classify11(const char *s, bool q) {
static inline int classify11(const char *s, bool q, bool) {
if (s[0] == '_') {
if (s[1] == '_') {
if (s[2] == 'a') {
@@ -1241,7 +1241,7 @@ static inline int classify11(const char *s, bool q) {
return T_IDENTIFIER;
}
static inline int classify12(const char *s, bool q) {
static inline int classify12(const char *s, bool q, bool) {
if (s[0] == '_') {
if (s[1] == '_') {
if (s[2] == 'v') {
@@ -1320,7 +1320,7 @@ static inline int classify12(const char *s, bool q) {
return T_IDENTIFIER;
}
static inline int classify13(const char *s, bool) {
static inline int classify13(const char *s, bool, bool) {
if (s[0] == '_') {
if (s[1] == '_') {
if (s[2] == 'a') {
@@ -1351,7 +1351,7 @@ static inline int classify13(const char *s, bool) {
return T_IDENTIFIER;
}
static inline int classify16(const char *s, bool) {
static inline int classify16(const char *s, bool, bool) {
if (s[0] == 'r') {
if (s[1] == 'e') {
if (s[2] == 'i') {
@@ -1388,7 +1388,7 @@ static inline int classify16(const char *s, bool) {
return T_IDENTIFIER;
}
static inline int classify14(const char *s, bool q) {
static inline int classify14(const char *s, bool q, bool) {
if (q && s[0] == 'Q') {
if (s[1] == '_') {
if (s[2] == 'P') {
@@ -1421,7 +1421,7 @@ static inline int classify14(const char *s, bool q) {
return T_IDENTIFIER;
}
static inline int classify19(const char *s, bool q) {
static inline int classify19(const char *s, bool q, bool) {
if (q && s[0] == 'Q') {
if (s[1] == '_') {
if (s[2] == 'D') {
@@ -1465,23 +1465,23 @@ static inline int classify19(const char *s, bool q) {
}
int Lexer::classify(const char *s, int n, bool q) {
int Lexer::classify(const char *s, int n, bool q, bool x) {
switch (n) {
case 2: return classify2(s, q);
case 3: return classify3(s, q);
case 4: return classify4(s, q);
case 5: return classify5(s, q);
case 6: return classify6(s, q);
case 7: return classify7(s, q);
case 8: return classify8(s, q);
case 9: return classify9(s, q);
case 10: return classify10(s, 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);
case 2: return classify2(s, q, x);
case 3: return classify3(s, q, x);
case 4: return classify4(s, q, x);
case 5: return classify5(s, q, x);
case 6: return classify6(s, q, x);
case 7: return classify7(s, q, x);
case 8: return classify8(s, q, x);
case 9: return classify9(s, q, x);
case 10: return classify10(s, q, x);
case 11: return classify11(s, q, x);
case 12: return classify12(s, q, x);
case 13: return classify13(s, q, x);
case 14: return classify14(s, q, x);
case 16: return classify16(s, q, x);
case 19: return classify19(s, q, x);
default: return T_IDENTIFIER;
} // switch
}

View File

@@ -119,6 +119,12 @@ bool Lexer::qtMocRunEnabled() const
void Lexer::setQtMocRunEnabled(bool onoff)
{ f._qtMocRunEnabled = onoff; }
bool Lexer::cxx0xEnabled() const
{ return f._cxx0xEnabled; }
void Lexer::setCxxOxEnabled(bool onoff)
{ f._cxx0xEnabled = onoff; }
bool Lexer::objCEnabled() const
{ return f._objCEnabled; }
@@ -680,7 +686,7 @@ void Lexer::scan_helper(Token *tok)
yyinp();
int yylen = _currentChar - yytext;
if (f._scanKeywords)
tok->f.kind = classify(yytext, yylen, f._qtMocRunEnabled);
tok->f.kind = classify(yytext, yylen, f._qtMocRunEnabled, f._cxx0xEnabled);
else
tok->f.kind = T_IDENTIFIER;

View File

@@ -77,6 +77,9 @@ public:
bool qtMocRunEnabled() const;
void setQtMocRunEnabled(bool onoff);
bool cxx0xEnabled() const;
void setCxxOxEnabled(bool onoff);
bool objCEnabled() const;
void setObjCEnabled(bool onoff);
@@ -111,7 +114,7 @@ public:
private:
void scan_helper(Token *tok);
void setSource(const char *firstChar, const char *lastChar);
static int classify(const char *string, int length, bool q);
static int classify(const char *string, int length, bool q, bool cxx0x);
static int classifyObjCAtKeyword(const char *s, int n);
static int classifyOperator(const char *string, int length);
@@ -135,6 +138,7 @@ private:
unsigned _scanKeywords: 1;
unsigned _scanAngleStringLiteralTokens: 1;
unsigned _qtMocRunEnabled: 1;
unsigned _cxx0xEnabled: 1;
unsigned _objCEnabled: 1;
};

View File

@@ -197,7 +197,7 @@ Parser::Parser(TranslationUnit *unit)
_tokenIndex(1),
_templateArguments(0),
_qtMocRunEnabled(false),
_cxx0xEnabled(true), // C++0x is enabled by default
_cxx0xEnabled(false),
_objCEnabled(false),
_inFunctionBody(false),
_inObjCImplementationContext(false),
@@ -2524,7 +2524,8 @@ bool Parser::parseExpressionStatement(StatementAST *&node)
ExpressionAST *expression = 0;
if (parseExpression(expression)) {
ExpressionStatementAST *ast = new (previousPool) ExpressionStatementAST;
ast->expression = expression->clone(previousPool);
if (expression)
ast->expression = expression->clone(previousPool);
match(T_SEMICOLON, &ast->semicolon_token);
node = ast;
parsed = true;
@@ -3646,7 +3647,20 @@ bool Parser::parsePrimaryExpression(ExpressionAST *&node)
case T_SLOT:
return parseQtMethod(node);
case T_LBRACKET:
case T_LBRACKET: {
const unsigned lbracket_token = cursor();
if (_cxx0xEnabled) {
if (parseLambdaExpression(node))
return true;
}
if (_objCEnabled) {
rewind(lbracket_token);
return parseObjCExpression(node);
}
} break;
case T_AT_STRING_LITERAL:
case T_AT_ENCODE:
case T_AT_PROTOCOL:
@@ -5491,3 +5505,164 @@ int Parser::peekAtQtContextKeyword() const
const Identifier *id = tok().identifier;
return classifyQtContextKeyword(id->chars(), id->size());
}
bool Parser::parseLambdaExpression(ExpressionAST *&node)
{
DEBUG_THIS_RULE();
LambdaIntroducerAST *lambda_introducer = 0;
if (parseLambdaIntroducer(lambda_introducer)) {
LambdaExpressionAST *ast = new (_pool) LambdaExpressionAST;
ast->lambda_introducer = lambda_introducer;
parseLambdaDeclarator(ast->lambda_declarator);
parseCompoundStatement(ast->statement);
node = ast;
return true;
}
return false;
}
bool Parser::parseLambdaIntroducer(LambdaIntroducerAST *&node)
{
DEBUG_THIS_RULE();
if (LA() != T_LBRACKET)
return false;
LambdaIntroducerAST *ast = new (_pool) LambdaIntroducerAST;
ast->lbracket_token = consumeToken();
if (LA() != T_RBRACKET)
parseLambdaCapture(ast->lambda_capture);
if (LA() == T_RBRACKET) {
ast->rbracket_token = consumeToken();
if (LA() == T_LPAREN || LA() == T_LBRACE) {
node = ast;
return true;
}
}
return false;
}
bool Parser::parseLambdaCapture(LambdaCaptureAST *&node)
{
DEBUG_THIS_RULE();
bool startsWithDefaultCapture = false;
unsigned default_capture = 0;
CaptureListAST *capture_list = 0;
if (LA() == T_AMPER || LA() == T_EQUAL) {
if (LA(2) == T_COMMA || LA(2) == T_RBRACKET) {
startsWithDefaultCapture = true;
default_capture = consumeToken(); // consume capture-default
}
}
if (startsWithDefaultCapture && LA() == T_COMMA) {
consumeToken(); // consume ','
parseCaptureList(capture_list); // required
} else if (LA() != T_RBRACKET) {
parseCaptureList(capture_list); // optional
}
LambdaCaptureAST *ast = new (_pool) LambdaCaptureAST;
ast->default_capture = default_capture;
ast->capture_list = capture_list;
node = ast;
return true;
}
bool Parser::parseCapture(CaptureAST *&)
{
DEBUG_THIS_RULE();
if (LA() == T_IDENTIFIER) {
consumeToken();
return true;
} else if (LA() == T_AMPER && LA(2) == T_IDENTIFIER) {
consumeToken();
consumeToken();
return true;
} else if (LA() == T_THIS) {
consumeToken();
return true;
}
return false;
}
bool Parser::parseCaptureList(CaptureListAST *&)
{
DEBUG_THIS_RULE();
CaptureAST *capture = 0;
if (parseCapture(capture)) {
while (LA() == T_COMMA) {
consumeToken(); // consume `,'
parseCapture(capture);
}
}
return true;
}
bool Parser::parseLambdaDeclarator(LambdaDeclaratorAST *&node)
{
DEBUG_THIS_RULE();
if (LA() != T_LPAREN)
return false;
LambdaDeclaratorAST *ast = new (_pool) LambdaDeclaratorAST;
ast->lparen_token = consumeToken(); // consume `('
parseParameterDeclarationClause(ast->parameter_declaration_clause);
match(T_RPAREN, &ast->rparen_token);
SpecifierListAST **attr = &ast->attributes;
while (parseAttributeSpecifier(*attr))
attr = &(*attr)->next;
if (LA() == T_MUTABLE)
ast->mutable_token = consumeToken();
parseExceptionSpecification(ast->exception_specification);
parseTrailingReturnType(ast->trailing_return_type);
node = ast;
return true;
}
bool Parser::parseTrailingReturnType(TrailingReturnTypeAST *&node)
{
DEBUG_THIS_RULE();
if (LA() != T_ARROW)
return false;
TrailingReturnTypeAST *ast = new (_pool) TrailingReturnTypeAST;
ast->arrow_token = consumeToken();
SpecifierListAST **attr = &ast->attributes;
while (parseAttributeSpecifier(*attr))
attr = &(*attr)->next;
parseTrailingTypeSpecifierSeq(ast->type_specifiers);
parseAbstractDeclarator(ast->declarator);
return true;
}
bool Parser::parseTrailingTypeSpecifierSeq(SpecifierListAST *&node)
{
DEBUG_THIS_RULE();
return parseSimpleTypeSpecifier(node);
}

View File

@@ -221,6 +221,16 @@ public:
// Qt MOC run
bool parseQtMethod(ExpressionAST *&node);
// C++0x
bool parseLambdaExpression(ExpressionAST *&node);
bool parseLambdaIntroducer(LambdaIntroducerAST *&node);
bool parseLambdaCapture(LambdaCaptureAST *&node);
bool parseLambdaDeclarator(LambdaDeclaratorAST *&node);
bool parseCapture(CaptureAST *&node);
bool parseCaptureList(CaptureListAST *&node);
bool parseTrailingReturnType(TrailingReturnTypeAST *&node);
bool parseTrailingTypeSpecifierSeq(SpecifierListAST *&node);
// ObjC++
bool parseObjCExpression(ExpressionAST *&node);
bool parseObjCClassForwardDeclaration(DeclarationAST *&node);

View File

@@ -87,6 +87,12 @@ bool TranslationUnit::qtMocRunEnabled() const
void TranslationUnit::setQtMocRunEnabled(bool onoff)
{ f._qtMocRunEnabled = onoff; }
bool TranslationUnit::cxx0xEnabled() const
{ return f._cxx0xEnabled; }
void TranslationUnit::setCxxOxEnabled(bool onoff)
{ f._cxx0xEnabled = onoff; }
bool TranslationUnit::objCEnabled() const
{ return f._objCEnabled; }
@@ -173,6 +179,7 @@ void TranslationUnit::tokenize()
Lexer lex(this);
lex.setQtMocRunEnabled(f._qtMocRunEnabled);
lex.setCxxOxEnabled(f._cxx0xEnabled);
lex.setObjCEnabled(f._objCEnabled);
std::stack<unsigned> braces;
@@ -256,6 +263,7 @@ bool TranslationUnit::parse(ParseMode mode)
Parser parser(this);
parser.setQtMocRunEnabled(f._qtMocRunEnabled);
parser.setCxxOxEnabled(f._cxx0xEnabled);
parser.setObjCEnabled(f._objCEnabled);
bool parsed = false;

View File

@@ -98,6 +98,9 @@ public:
bool qtMocRunEnabled() const;
void setQtMocRunEnabled(bool onoff);
bool cxx0xEnabled() const;
void setCxxOxEnabled(bool onoff);
bool objCEnabled() const;
void setObjCEnabled(bool onoff);
@@ -195,6 +198,7 @@ private:
unsigned _blockErrors: 1;
unsigned _skipFunctionBody: 1;
unsigned _qtMocRunEnabled: 1;
unsigned _cxx0xEnabled: 1;
unsigned _objCEnabled: 1;
};
union {