Commit 3cdd4806 authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Introduced ForeachStatementAST and the bits to parse foreach statements when qtMocRun is enabled.

parent 16286b76
......@@ -1421,6 +1421,8 @@ bool Preprocessor::isQtReservedWord(const QByteArray &macroId) const
const int size = macroId.size();
if (size == 9 && macroId.at(0) == 'Q' && macroId == "Q_SIGNALS")
return true;
else if (size == 9 && macroId.at(0) == 'Q' && macroId == "Q_FOREACH")
return true;
else if (size == 7 && macroId.at(0) == 'Q' && macroId == "Q_SLOTS")
return true;
else if (size == 8 && macroId.at(0) == 'Q' && macroId == "Q_SIGNAL")
......
......@@ -874,6 +874,24 @@ unsigned ExpressionStatementAST::lastToken() const
return 0;
}
unsigned ForeachStatementAST::firstToken() const
{
return foreach_token;
}
unsigned ForeachStatementAST::lastToken() const
{
if (statement)
return statement->lastToken();
else if (rparen_token)
return rparen_token + 1;
else if (expression)
return expression->lastToken();
else if (comma_token)
return comma_token + 1;
return foreach_token + 1;
}
unsigned ForStatementAST::firstToken() const
{
......
......@@ -131,6 +131,7 @@ public:
virtual ExpressionListAST *asExpressionList() { return 0; }
virtual ExpressionOrDeclarationStatementAST *asExpressionOrDeclarationStatement() { return 0; }
virtual ExpressionStatementAST *asExpressionStatement() { return 0; }
virtual ForeachStatementAST *asForeachStatement() { return 0; }
virtual ForStatementAST *asForStatement() { return 0; }
virtual FunctionDeclaratorAST *asFunctionDeclarator() { return 0; }
virtual FunctionDefinitionAST *asFunctionDefinition() { return 0; }
......@@ -1135,6 +1136,37 @@ protected:
virtual void accept0(ASTVisitor *visitor);
};
class CPLUSPLUS_EXPORT ForeachStatementAST: public StatementAST
{
public:
unsigned foreach_token;
unsigned lparen_token;
// declaration
SpecifierAST *type_specifiers;
DeclaratorAST *declarator;
// or an expression
ExpressionAST *initializer;
unsigned comma_token;
ExpressionAST *expression;
unsigned rparen_token;
StatementAST *statement;
public: // annotations
Block *symbol;
public:
virtual ForeachStatementAST *asForeachStatement()
{ return this; }
virtual unsigned firstToken() const;
virtual unsigned lastToken() const;
virtual ForeachStatementAST *clone(MemoryPool *pool) const;
protected:
virtual void accept0(ASTVisitor *visitor);
};
class CPLUSPLUS_EXPORT ForStatementAST: public StatementAST
{
public:
......
......@@ -514,6 +514,23 @@ FunctionDefinitionAST *FunctionDefinitionAST::clone(MemoryPool *pool) const
return ast;
}
ForeachStatementAST *ForeachStatementAST::clone(MemoryPool *pool) const
{
ForeachStatementAST *ast = new (pool) ForeachStatementAST;
// copy StatementAST
// copy ForeachStatementAST
ast->foreach_token = foreach_token;
ast->lparen_token = lparen_token;
if (type_specifiers) ast->type_specifiers = type_specifiers->clone(pool);
if (declarator) ast->declarator = declarator->clone(pool);
if (initializer) ast->initializer = initializer->clone(pool);
ast->comma_token = comma_token;
if (expression) ast->expression = expression->clone(pool);
ast->rparen_token = rparen_token;
if (statement) ast->statement = statement->clone(pool);
return ast;
}
ForStatementAST *ForStatementAST::clone(MemoryPool *pool) const
{
ForStatementAST *ast = new (pool) ForStatementAST;
......
......@@ -474,6 +474,21 @@ void FunctionDefinitionAST::accept0(ASTVisitor *visitor)
visitor->endVisit(this);
}
void ForeachStatementAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
// visit ForeachStatementAST
for (SpecifierAST *it = type_specifiers; it; it = it->next)
accept(it, visitor);
accept(declarator, visitor);
accept(initializer, visitor);
accept(expression, visitor);
accept(statement, visitor);
// visit StatementAST
}
visitor->endVisit(this);
}
void ForStatementAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
......
......@@ -134,6 +134,7 @@ public:
virtual bool visit(ExpressionListAST *) { return true; }
virtual bool visit(ExpressionOrDeclarationStatementAST *) { return true; }
virtual bool visit(ExpressionStatementAST *) { return true; }
virtual bool visit(ForeachStatementAST *) { return true; }
virtual bool visit(ForStatementAST *) { return true; }
virtual bool visit(FunctionDeclaratorAST *) { return true; }
virtual bool visit(FunctionDefinitionAST *) { return true; }
......@@ -242,6 +243,7 @@ public:
virtual void endVisit(ExpressionListAST *) { }
virtual void endVisit(ExpressionOrDeclarationStatementAST *) { }
virtual void endVisit(ExpressionStatementAST *) { }
virtual void endVisit(ForeachStatementAST *) { }
virtual void endVisit(ForStatementAST *) { }
virtual void endVisit(FunctionDeclaratorAST *) { }
virtual void endVisit(FunctionDefinitionAST *) { }
......
......@@ -101,6 +101,7 @@ class ExpressionAST;
class ExpressionListAST;
class ExpressionOrDeclarationStatementAST;
class ExpressionStatementAST;
class ForeachStatementAST;
class ForStatementAST;
class FunctionDeclaratorAST;
class FunctionDefinitionAST;
......
......@@ -251,7 +251,7 @@ bool CheckDeclaration::visit(AccessDeclarationAST *ast)
semantic()->switchVisibility(visibility);
if (ast->slots_token)
semantic()->switchMethodKey(Function::SlotMethod);
else if (accessSpecifier == T_SIGNALS)
else if (accessSpecifier == T_Q_SIGNALS)
semantic()->switchMethodKey(Function::SignalMethod);
else
semantic()->switchMethodKey(Function::NormalMethod);
......
......@@ -141,6 +141,35 @@ bool CheckStatement::visit(ExpressionStatementAST *ast)
return false;
}
bool CheckStatement::visit(ForeachStatementAST *ast)
{
Block *block = control()->newBlock(ast->foreach_token);
block->setStartOffset(tokenAt(ast->firstToken()).offset);
block->setEndOffset(tokenAt(ast->lastToken()).offset);
ast->symbol = block;
_scope->enterSymbol(block);
Scope *previousScope = switchScope(block->members());
if (ast->type_specifiers && ast->declarator) {
FullySpecifiedType ty = semantic()->check(ast->type_specifiers, _scope);
Name *name = 0;
ty = semantic()->check(ast->declarator, ty, _scope, &name);
unsigned location = ast->declarator->firstToken();
if (CoreDeclaratorAST *core_declarator = ast->declarator->core_declarator)
location = core_declarator->firstToken();
Declaration *decl = control()->newDeclaration(location, name);
decl->setType(ty);
_scope->enterSymbol(decl);
} else {
FullySpecifiedType exprTy = semantic()->check(ast->initializer, _scope);
(void) exprTy;
}
FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope);
semantic()->check(ast->statement, _scope);
(void) switchScope(previousScope);
return false;
}
bool CheckStatement::visit(ForStatementAST *ast)
{
Block *block = control()->newBlock(ast->for_token);
......
......@@ -75,6 +75,7 @@ protected:
virtual bool visit(DoStatementAST *ast);
virtual bool visit(ExpressionOrDeclarationStatementAST *ast);
virtual bool visit(ExpressionStatementAST *ast);
virtual bool visit(ForeachStatementAST *ast);
virtual bool visit(ForStatementAST *ast);
virtual bool visit(IfStatementAST *ast);
virtual bool visit(LabeledStatementAST *ast);
......
......@@ -115,7 +115,7 @@ public:
NamedType *namedType(Name *name);
/// Creates a new Declaration symbol.
Declaration *newDeclaration(unsigned sourceLocation, Name *name = 0);
Declaration *newDeclaration(unsigned sourceLocation, Name *name);
/// Creates a new Argument symbol.
Argument *newArgument(unsigned sourceLocation, Name *name = 0);
......
......@@ -297,7 +297,7 @@ static inline int classify5(const char *s, bool q) {
if (s[2] == 'o') {
if (s[3] == 't') {
if (s[4] == 's') {
return T_SLOTS;
return T_Q_SLOTS;
}
}
}
......@@ -627,7 +627,7 @@ static inline int classify7(const char *s, bool q) {
if (s[4] == 'a') {
if (s[5] == 'l') {
if (s[6] == 's') {
return T_SIGNALS;
return T_Q_SIGNALS;
}
}
}
......@@ -687,7 +687,7 @@ static inline int classify7(const char *s, bool q) {
if (s[4] == 'O') {
if (s[5] == 'T') {
if (s[6] == 'S') {
return T_SLOTS;
return T_Q_SLOTS;
}
}
}
......@@ -950,7 +950,21 @@ static inline int classify9(const char *s, bool q) {
if (s[6] == 'A') {
if (s[7] == 'L') {
if (s[8] == 'S') {
return T_SIGNALS;
return T_Q_SIGNALS;
}
}
}
}
}
}
} else if (s[2] == 'F') {
if (s[3] == 'O') {
if (s[4] == 'R') {
if (s[5] == 'E') {
if (s[6] == 'A') {
if (s[7] == 'C') {
if (s[8] == 'H') {
return T_Q_FOREACH;
}
}
}
......
......@@ -1464,11 +1464,11 @@ bool Parser::parseAccessSpecifier(SpecifierAST *&node)
bool Parser::parseAccessDeclaration(DeclarationAST *&node)
{
if (LA() == T_PUBLIC || LA() == T_PROTECTED || LA() == T_PRIVATE || LA() == T_SIGNALS) {
bool isSignals = LA() == T_SIGNALS;
if (LA() == T_PUBLIC || LA() == T_PROTECTED || LA() == T_PRIVATE || LA() == T_Q_SIGNALS) {
bool isSignals = LA() == T_Q_SIGNALS;
AccessDeclarationAST *ast = new (_pool) AccessDeclarationAST;
ast->access_specifier_token = consumeToken();
if (! isSignals && LA() == T_SLOTS)
if (! isSignals && LA() == T_Q_SLOTS)
ast->slots_token = consumeToken();
match(T_COLON, &ast->colon_token);
node = ast;
......@@ -1489,7 +1489,7 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node)
case T_TEMPLATE:
return parseTemplateDeclaration(node);
case T_SIGNALS:
case T_Q_SIGNALS:
case T_PUBLIC:
case T_PROTECTED:
case T_PRIVATE:
......@@ -1861,6 +1861,9 @@ bool Parser::parseStatement(StatementAST *&node)
case T_DO:
return parseDoStatement(node);
case T_Q_FOREACH:
return parseForeachStatement(node);
case T_FOR:
return parseForStatement(node);
......@@ -2108,6 +2111,41 @@ bool Parser::parseDoStatement(StatementAST *&node)
return false;
}
bool Parser::parseForeachStatement(StatementAST *&node)
{
if (LA() == T_Q_FOREACH) {
ForeachStatementAST *ast = new (_pool) ForeachStatementAST;
ast->foreach_token = consumeToken();
match(T_LPAREN, &ast->lparen_token);
unsigned startOfTypeSpecifier = cursor();
bool blocked = blockErrors(true);
if (parseTypeSpecifier(ast->type_specifiers))
parseDeclarator(ast->declarator);
if (! ast->type_specifiers || ! ast->declarator) {
ast->type_specifiers = 0;
ast->declarator = 0;
blockErrors(blocked);
rewind(startOfTypeSpecifier);
parseExpression(ast->expression);
}
blockErrors(blocked);
match(T_COMMA, &ast->comma_token);
parseExpression(ast->expression);
match(T_RPAREN, &ast->rparen_token);
parseStatement(ast->statement);
node = ast;
return true;
}
return false;
}
bool Parser::parseForStatement(StatementAST *&node)
{
if (LA() == T_FOR) {
......
......@@ -121,6 +121,7 @@ public:
bool parseExpressionOrDeclarationStatement(StatementAST *&node);
bool parseExpressionStatement(StatementAST *&node);
bool parseForInitStatement(StatementAST *&node);
bool parseForeachStatement(StatementAST *&node);
bool parseForStatement(StatementAST *&node);
bool parseFunctionBody(StatementAST *&node);
bool parseIfStatement(StatementAST *&node);
......
......@@ -179,7 +179,7 @@ int Semantic::visibilityForAccessSpecifier(int tokenKind) const
return Symbol::Protected;
case T_PRIVATE:
return Symbol::Private;
case T_SIGNALS:
case T_Q_SIGNALS:
return Symbol::Protected;
default:
return Symbol::Public;
......
......@@ -234,10 +234,11 @@ enum Kind {
T_SLOT,
T_Q_SIGNAL,
T_Q_SLOT,
T_SIGNALS,
T_SLOTS,
T_Q_SIGNALS,
T_Q_SLOTS,
T_Q_FOREACH,
T_LAST_KEYWORD = T_SLOTS,
T_LAST_KEYWORD = T_Q_FOREACH,
// aliases
T_OR = T_PIPE_PIPE,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment