Adding a ForStatement solidity AST Node.

- Adding ForStatement node
- Implemented Parsing for ForStatement
- A simple parsing test for the ForStatement
- Work in progress
This commit is contained in:
Lefteris Karapetsas 2014-12-15 17:45:18 +01:00
parent 5b802b685e
commit f7029726be
12 changed files with 134 additions and 9 deletions

View File

@ -130,6 +130,13 @@ void WhileStatement::checkTypeRequirements()
m_body->checkTypeRequirements(); m_body->checkTypeRequirements();
} }
void ForStatement::checkTypeRequirements()
{
// LTODO
m_condExpression->expectType(BoolType());
m_body->checkTypeRequirements();
}
void Return::checkTypeRequirements() void Return::checkTypeRequirements()
{ {
if (!m_expression) if (!m_expression)

24
AST.h
View File

@ -509,6 +509,30 @@ private:
ASTPointer<Statement> m_body; ASTPointer<Statement> m_body;
}; };
class ForStatement: public BreakableStatement
{
public:
ForStatement(Location const& _location,
ASTPointer<ASTNode> const& _initExpression,
ASTPointer<Expression> const& _conditionExpression,
ASTPointer<ExpressionStatement> const& _loopExpression,
ASTPointer<Statement> const& _body):
BreakableStatement(_location),
m_initExpression(_initExpression),
m_condExpression(_conditionExpression),
m_loopExpression(_loopExpression),
m_body(_body) {}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
virtual void checkTypeRequirements() override;
private:
ASTPointer<ASTNode> m_initExpression;
ASTPointer<Expression> m_condExpression;
ASTPointer<ExpressionStatement> m_loopExpression;
ASTPointer<Statement> m_body;
};
class Continue: public Statement class Continue: public Statement
{ {
public: public:

View File

@ -52,6 +52,7 @@ class Block;
class IfStatement; class IfStatement;
class BreakableStatement; class BreakableStatement;
class WhileStatement; class WhileStatement;
class ForStatement;
class Continue; class Continue;
class Break; class Break;
class Return; class Return;

View File

@ -150,6 +150,13 @@ bool ASTPrinter::visit(WhileStatement const& _node)
return goDeeper(); return goDeeper();
} }
bool ASTPrinter::visit(ForStatement const& _node)
{
writeLine("ForStatement");
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(Continue const& _node) bool ASTPrinter::visit(Continue const& _node)
{ {
writeLine("Continue"); writeLine("Continue");
@ -360,6 +367,11 @@ void ASTPrinter::endVisit(WhileStatement const&)
m_indentation--; m_indentation--;
} }
void ASTPrinter::endVisit(ForStatement const&)
{
m_indentation--;
}
void ASTPrinter::endVisit(Continue const&) void ASTPrinter::endVisit(Continue const&)
{ {
m_indentation--; m_indentation--;

View File

@ -57,6 +57,7 @@ public:
bool visit(IfStatement const& _node) override; bool visit(IfStatement const& _node) override;
bool visit(BreakableStatement const& _node) override; bool visit(BreakableStatement const& _node) override;
bool visit(WhileStatement const& _node) override; bool visit(WhileStatement const& _node) override;
bool visit(ForStatement const& _node) override;
bool visit(Continue const& _node) override; bool visit(Continue const& _node) override;
bool visit(Break const& _node) override; bool visit(Break const& _node) override;
bool visit(Return const& _node) override; bool visit(Return const& _node) override;
@ -90,6 +91,7 @@ public:
void endVisit(IfStatement const&) override; void endVisit(IfStatement const&) override;
void endVisit(BreakableStatement const&) override; void endVisit(BreakableStatement const&) override;
void endVisit(WhileStatement const&) override; void endVisit(WhileStatement const&) override;
void endVisit(ForStatement const&) override;
void endVisit(Continue const&) override; void endVisit(Continue const&) override;
void endVisit(Break const&) override; void endVisit(Break const&) override;
void endVisit(Return const&) override; void endVisit(Return const&) override;

View File

@ -58,6 +58,7 @@ public:
virtual bool visit(IfStatement&) { return true; } virtual bool visit(IfStatement&) { return true; }
virtual bool visit(BreakableStatement&) { return true; } virtual bool visit(BreakableStatement&) { return true; }
virtual bool visit(WhileStatement&) { return true; } virtual bool visit(WhileStatement&) { return true; }
virtual bool visit(ForStatement&) { return true; }
virtual bool visit(Continue&) { return true; } virtual bool visit(Continue&) { return true; }
virtual bool visit(Break&) { return true; } virtual bool visit(Break&) { return true; }
virtual bool visit(Return&) { return true; } virtual bool visit(Return&) { return true; }
@ -93,6 +94,7 @@ public:
virtual void endVisit(IfStatement&) { } virtual void endVisit(IfStatement&) { }
virtual void endVisit(BreakableStatement&) { } virtual void endVisit(BreakableStatement&) { }
virtual void endVisit(WhileStatement&) { } virtual void endVisit(WhileStatement&) { }
virtual void endVisit(ForStatement&) { }
virtual void endVisit(Continue&) { } virtual void endVisit(Continue&) { }
virtual void endVisit(Break&) { } virtual void endVisit(Break&) { }
virtual void endVisit(Return&) { } virtual void endVisit(Return&) { }
@ -132,6 +134,7 @@ public:
virtual bool visit(IfStatement const&) { return true; } virtual bool visit(IfStatement const&) { return true; }
virtual bool visit(BreakableStatement const&) { return true; } virtual bool visit(BreakableStatement const&) { return true; }
virtual bool visit(WhileStatement const&) { return true; } virtual bool visit(WhileStatement const&) { return true; }
virtual bool visit(ForStatement const&) { return true; }
virtual bool visit(Continue const&) { return true; } virtual bool visit(Continue const&) { return true; }
virtual bool visit(Break const&) { return true; } virtual bool visit(Break const&) { return true; }
virtual bool visit(Return const&) { return true; } virtual bool visit(Return const&) { return true; }
@ -167,6 +170,7 @@ public:
virtual void endVisit(IfStatement const&) { } virtual void endVisit(IfStatement const&) { }
virtual void endVisit(BreakableStatement const&) { } virtual void endVisit(BreakableStatement const&) { }
virtual void endVisit(WhileStatement const&) { } virtual void endVisit(WhileStatement const&) { }
virtual void endVisit(ForStatement const&) { }
virtual void endVisit(Continue const&) { } virtual void endVisit(Continue const&) { }
virtual void endVisit(Break const&) { } virtual void endVisit(Break const&) { }
virtual void endVisit(Return const&) { } virtual void endVisit(Return const&) { }

View File

@ -267,6 +267,30 @@ void WhileStatement::accept(ASTConstVisitor& _visitor) const
_visitor.endVisit(*this); _visitor.endVisit(*this);
} }
void ForStatement::accept(ASTVisitor& _visitor)
{
if (_visitor.visit(*this))
{
m_initExpression->accept(_visitor);
m_condExpression->accept(_visitor);
m_loopExpression->accept(_visitor);
m_body->accept(_visitor);
}
_visitor.endVisit(*this);
}
void ForStatement::accept(ASTConstVisitor& _visitor) const
{
if (_visitor.visit(*this))
{
m_initExpression->accept(_visitor);
m_condExpression->accept(_visitor);
m_loopExpression->accept(_visitor);
m_body->accept(_visitor);
}
_visitor.endVisit(*this);
}
void Continue::accept(ASTVisitor& _visitor) void Continue::accept(ASTVisitor& _visitor)
{ {
_visitor.visit(*this); _visitor.visit(*this);

View File

@ -287,6 +287,13 @@ bool Compiler::visit(WhileStatement const& _whileStatement)
return false; return false;
} }
bool Compiler::visit(ForStatement const& _forStatement)
{
// LTODO
(void) _forStatement;
return false;
}
bool Compiler::visit(Continue const&) bool Compiler::visit(Continue const&)
{ {
if (!m_continueTags.empty()) if (!m_continueTags.empty())

View File

@ -53,6 +53,7 @@ private:
virtual bool visit(FunctionDefinition const& _function) override; virtual bool visit(FunctionDefinition const& _function) override;
virtual bool visit(IfStatement const& _ifStatement) override; virtual bool visit(IfStatement const& _ifStatement) override;
virtual bool visit(WhileStatement const& _whileStatement) override; virtual bool visit(WhileStatement const& _whileStatement) override;
virtual bool visit(ForStatement const& _forStatement) override;
virtual bool visit(Continue const& _continue) override; virtual bool visit(Continue const& _continue) override;
virtual bool visit(Break const& _break) override; virtual bool visit(Break const& _break) override;
virtual bool visit(Return const& _return) override; virtual bool visit(Return const& _return) override;

View File

@ -304,6 +304,8 @@ ASTPointer<Statement> Parser::parseStatement()
return parseIfStatement(); return parseIfStatement();
case Token::WHILE: case Token::WHILE:
return parseWhileStatement(); return parseWhileStatement();
case Token::FOR:
return parseForStatement();
case Token::LBRACE: case Token::LBRACE:
return parseBlock(); return parseBlock();
// starting from here, all statements must be terminated by a semicolon // starting from here, all statements must be terminated by a semicolon
@ -328,15 +330,7 @@ ASTPointer<Statement> Parser::parseStatement()
} }
break; break;
default: default:
// distinguish between variable definition (and potentially assignment) and expression statement if (peekVariableDefinition())
// (which include assignments to other expressions and pre-declared variables)
// We have a variable definition if we get a keyword that specifies a type name, or
// in the case of a user-defined type, we have two identifiers following each other.
if (m_scanner->getCurrentToken() == Token::MAPPING ||
m_scanner->getCurrentToken() == Token::VAR ||
((Token::isElementaryTypeName(m_scanner->getCurrentToken()) ||
m_scanner->getCurrentToken() == Token::IDENTIFIER) &&
m_scanner->peekNextToken() == Token::IDENTIFIER))
statement = parseVariableDefinition(); statement = parseVariableDefinition();
else // "ordinary" expression statement else // "ordinary" expression statement
statement = parseExpressionStatement(); statement = parseExpressionStatement();
@ -377,6 +371,34 @@ ASTPointer<WhileStatement> Parser::parseWhileStatement()
return nodeFactory.createNode<WhileStatement>(condition, body); return nodeFactory.createNode<WhileStatement>(condition, body);
} }
ASTPointer<ForStatement> Parser::parseForStatement()
{
ASTNodeFactory nodeFactory(*this);
expectToken(Token::FOR);
expectToken(Token::LPAREN);
ASTPointer<ASTNode> initExpression = parseVardefOrExprstatement();
expectToken(Token::SEMICOLON);
ASTPointer<Expression> conditionExpression = parseExpression();
expectToken(Token::SEMICOLON);
ASTPointer<ExpressionStatement> loopExpression = parseExpressionStatement();
expectToken(Token::SEMICOLON);
expectToken(Token::RPAREN);
ASTPointer<Statement> body = parseStatement();
nodeFactory.setEndPositionFromNode(body);
return nodeFactory.createNode<ForStatement>(initExpression,
conditionExpression,
loopExpression,
body);
}
ASTPointer<ASTNode> Parser::parseVardefOrExprstatement()
{
if (peekVariableDefinition())
return parseVariableDefinition();
else
return parseExpressionStatement();
}
ASTPointer<VariableDefinition> Parser::parseVariableDefinition() ASTPointer<VariableDefinition> Parser::parseVariableDefinition()
{ {
ASTNodeFactory nodeFactory(*this); ASTNodeFactory nodeFactory(*this);
@ -566,6 +588,20 @@ vector<ASTPointer<Expression>> Parser::parseFunctionCallArguments()
return arguments; return arguments;
} }
// distinguish between variable definition (and potentially assignment) and expression statement
// (which include assignments to other expressions and pre-declared variables)
// We have a variable definition if we get a keyword that specifies a type name, or
// in the case of a user-defined type, we have two identifiers following each other.
bool Parser::peekVariableDefinition()
{
return (m_scanner->getCurrentToken() == Token::MAPPING ||
m_scanner->getCurrentToken() == Token::VAR ||
((Token::isElementaryTypeName(m_scanner->getCurrentToken()) ||
m_scanner->getCurrentToken() == Token::IDENTIFIER) &&
m_scanner->peekNextToken() == Token::IDENTIFIER));
}
void Parser::expectToken(Token::Value _value) void Parser::expectToken(Token::Value _value)
{ {
if (m_scanner->getCurrentToken() != _value) if (m_scanner->getCurrentToken() != _value)

View File

@ -59,6 +59,8 @@ private:
ASTPointer<Statement> parseStatement(); ASTPointer<Statement> parseStatement();
ASTPointer<IfStatement> parseIfStatement(); ASTPointer<IfStatement> parseIfStatement();
ASTPointer<WhileStatement> parseWhileStatement(); ASTPointer<WhileStatement> parseWhileStatement();
ASTPointer<ForStatement> parseForStatement();
ASTPointer<ASTNode> parseVardefOrExprstatement();
ASTPointer<VariableDefinition> parseVariableDefinition(); ASTPointer<VariableDefinition> parseVariableDefinition();
ASTPointer<ExpressionStatement> parseExpressionStatement(); ASTPointer<ExpressionStatement> parseExpressionStatement();
ASTPointer<Expression> parseExpression(); ASTPointer<Expression> parseExpression();
@ -72,6 +74,10 @@ private:
///@{ ///@{
///@name Helper functions ///@name Helper functions
/// Peeks ahead in the scanner to determine if an expression statement
/// could be a variable definition
bool peekVariableDefinition();
/// If current token value is not _value, throw exception otherwise advance token. /// If current token value is not _value, throw exception otherwise advance token.
void expectToken(Token::Value _value); void expectToken(Token::Value _value);
Token::Value expectAssignmentOperator(); Token::Value expectAssignmentOperator();

View File

@ -20,6 +20,7 @@ Statement = IfStatement | WhileStatement | Block |
IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )? IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )?
WhileStatement = 'while' '(' Expression ')' Statement WhileStatement = 'while' '(' Expression ')' Statement
ForStatement = 'for' '(' Expressionstatement Expression Expressionstatement ')' Statement
Continue = 'continue' ';' Continue = 'continue' ';'
Break = 'break' ';' Break = 'break' ';'
Return = 'return' Expression? ';' Return = 'return' Expression? ';'