mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Initial implementation of Solidity parser finished, not yet tested much.
This commit is contained in:
parent
c3faa433ef
commit
924f7c62bd
110
AST.h
110
AST.h
@ -54,6 +54,8 @@ public:
|
|||||||
: m_location(_location)
|
: m_location(_location)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
virtual ~ASTNode() {}
|
||||||
|
|
||||||
Location getLocation() const { return m_location; }
|
Location getLocation() const { return m_location; }
|
||||||
private:
|
private:
|
||||||
Location m_location;
|
Location m_location;
|
||||||
@ -146,9 +148,7 @@ private:
|
|||||||
class TypeName : public ASTNode
|
class TypeName : public ASTNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit TypeName(Location const& _location)
|
explicit TypeName(Location const& _location) : ASTNode(_location) {}
|
||||||
: ASTNode(_location)
|
|
||||||
{}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// any pre-defined type that is not a mapping
|
/// any pre-defined type that is not a mapping
|
||||||
@ -192,15 +192,13 @@ private:
|
|||||||
class Statement : public ASTNode
|
class Statement : public ASTNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Statement(Location const& _location)
|
explicit Statement(Location const& _location) : ASTNode(_location) {}
|
||||||
: ASTNode(_location)
|
|
||||||
{}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Block : public Statement
|
class Block : public Statement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Block(Location const& _location, vecptr<Statement> const& _statements)
|
Block(Location const& _location, vecptr<Statement> const& _statements)
|
||||||
: Statement(_location), m_statements(_statements)
|
: Statement(_location), m_statements(_statements)
|
||||||
{}
|
{}
|
||||||
private:
|
private:
|
||||||
@ -209,7 +207,12 @@ private:
|
|||||||
|
|
||||||
class IfStatement : public Statement
|
class IfStatement : public Statement
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
IfStatement(Location const& _location, ptr<Expression> const& _condition,
|
||||||
|
ptr<Statement> const& _trueBody, ptr<Statement> const& _falseBody)
|
||||||
|
: Statement(_location), m_condition(_condition),
|
||||||
|
m_trueBody(_trueBody), m_falseBody(_falseBody)
|
||||||
|
{}
|
||||||
private:
|
private:
|
||||||
ptr<Expression> m_condition;
|
ptr<Expression> m_condition;
|
||||||
ptr<Statement> m_trueBody;
|
ptr<Statement> m_trueBody;
|
||||||
@ -218,11 +221,17 @@ private:
|
|||||||
|
|
||||||
class BreakableStatement : public Statement
|
class BreakableStatement : public Statement
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
BreakableStatement(Location const& _location) : Statement(_location) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class WhileStatement : public BreakableStatement
|
class WhileStatement : public BreakableStatement
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
WhileStatement(Location const& _location, ptr<Expression> const& _condition,
|
||||||
|
ptr<Statement> const& _body)
|
||||||
|
: BreakableStatement(_location), m_condition(_condition), m_body(_body)
|
||||||
|
{}
|
||||||
private:
|
private:
|
||||||
ptr<Expression> m_condition;
|
ptr<Expression> m_condition;
|
||||||
ptr<Statement> m_body;
|
ptr<Statement> m_body;
|
||||||
@ -230,31 +239,42 @@ private:
|
|||||||
|
|
||||||
class Continue : public Statement
|
class Continue : public Statement
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
Continue(Location const& _location) : Statement(_location) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Break : public Statement
|
class Break : public Statement
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
Break(Location const& _location) : Statement(_location) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Return : public Statement
|
class Return : public Statement
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
Return(Location const& _location, ptr<Expression> _expression)
|
||||||
|
: Statement(_location), m_expression(_expression)
|
||||||
|
{}
|
||||||
private:
|
private:
|
||||||
ptr<Expression> m_expression;
|
ptr<Expression> m_expression;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VariableAssignment : public Statement
|
class VariableDefinition : public Statement
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
VariableDefinition(Location const& _location, ptr<VariableDeclaration> _variable,
|
||||||
|
ptr<Expression> _value)
|
||||||
|
: Statement(_location), m_variable(_variable), m_value(_value)
|
||||||
|
{}
|
||||||
private:
|
private:
|
||||||
ptr<VariableDeclaration> m_variable;
|
ptr<VariableDeclaration> m_variable;
|
||||||
Token::Value m_assigmentOperator;
|
ptr<Expression> m_value; ///< can be missing
|
||||||
ptr<Expression> m_rightHandSide; ///< can be missing
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Expression : public Statement
|
class Expression : public Statement
|
||||||
{
|
{
|
||||||
private:
|
public:
|
||||||
|
Expression(Location const& _location) : Statement(_location) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
@ -264,6 +284,12 @@ private:
|
|||||||
|
|
||||||
class Assignment : public Expression
|
class Assignment : public Expression
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
Assignment(Location const& _location, ptr<Expression> const& _leftHandSide,
|
||||||
|
Token::Value _assignmentOperator, ptr<Expression> const& _rightHandSide)
|
||||||
|
: Expression(_location), m_leftHandSide(_leftHandSide),
|
||||||
|
m_assigmentOperator(_assignmentOperator), m_rightHandSide(_rightHandSide)
|
||||||
|
{}
|
||||||
private:
|
private:
|
||||||
ptr<Expression> m_leftHandSide;
|
ptr<Expression> m_leftHandSide;
|
||||||
Token::Value m_assigmentOperator;
|
Token::Value m_assigmentOperator;
|
||||||
@ -272,31 +298,52 @@ private:
|
|||||||
|
|
||||||
class UnaryOperation : public Expression
|
class UnaryOperation : public Expression
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
UnaryOperation(Location const& _location, Token::Value _operator,
|
||||||
|
ptr<Expression> const& _subExpression, bool _isPrefix)
|
||||||
|
: Expression(_location), m_operator(_operator),
|
||||||
|
m_subExpression(_subExpression), m_isPrefix(_isPrefix)
|
||||||
|
{}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Token::Value m_operator;
|
Token::Value m_operator;
|
||||||
ptr<Expression> m_subExpression;
|
ptr<Expression> m_subExpression;
|
||||||
bool isPrefix;
|
bool m_isPrefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BinaryOperation : public Expression
|
class BinaryOperation : public Expression
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
BinaryOperation(Location const& _location, ptr<Expression> const& _left,
|
||||||
|
Token::Value _operator, ptr<Expression> const& _right)
|
||||||
|
: Expression(_location), m_left(_left), m_operator(_operator), m_right(_right)
|
||||||
|
{}
|
||||||
private:
|
private:
|
||||||
ptr<Expression> m_left;
|
ptr<Expression> m_left;
|
||||||
ptr<Expression> m_right;
|
|
||||||
Token::Value m_operator;
|
Token::Value m_operator;
|
||||||
|
ptr<Expression> m_right;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Can be ordinary function call, type cast or struct construction.
|
/// Can be ordinary function call, type cast or struct construction.
|
||||||
class FunctionCall : public Expression
|
class FunctionCall : public Expression
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
FunctionCall(Location const& _location, ptr<Expression> const& _expression,
|
||||||
|
vecptr<Expression> const& _arguments)
|
||||||
|
: Expression(_location), m_expression(_expression), m_arguments(_arguments)
|
||||||
|
{}
|
||||||
private:
|
private:
|
||||||
// if m_functionName is the name of a type, store the token directly
|
ptr<Expression> m_expression;
|
||||||
std::string m_functionName; // "in place" calls of return values are not possible for now
|
|
||||||
vecptr<Expression> m_arguments;
|
vecptr<Expression> m_arguments;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MemberAccess : public Expression
|
class MemberAccess : public Expression
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
MemberAccess(Location const& _location, ptr<Expression> _expression,
|
||||||
|
std::string const& _memberName)
|
||||||
|
: Expression(_location), m_expression(_expression), m_memberName(_memberName)
|
||||||
|
{}
|
||||||
private:
|
private:
|
||||||
ptr<Expression> m_expression;
|
ptr<Expression> m_expression;
|
||||||
std::string m_memberName;
|
std::string m_memberName;
|
||||||
@ -304,23 +351,48 @@ private:
|
|||||||
|
|
||||||
class IndexAccess : public Expression
|
class IndexAccess : public Expression
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
IndexAccess(Location const& _location, ptr<Expression> const& _base,
|
||||||
|
ptr<Expression> const& _index)
|
||||||
|
: Expression(_location), m_base(_base), m_index(_index)
|
||||||
|
{}
|
||||||
|
private:
|
||||||
ptr<Expression> m_base;
|
ptr<Expression> m_base;
|
||||||
ptr<Expression> m_index;
|
ptr<Expression> m_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PrimaryExpression : public Expression
|
class PrimaryExpression : public Expression
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
PrimaryExpression(Location const& _location) : Expression(_location) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Identifier : public PrimaryExpression
|
class Identifier : public PrimaryExpression
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
Identifier(Location const& _location, std::string const& _name)
|
||||||
|
: PrimaryExpression(_location), m_name(_name) {}
|
||||||
private:
|
private:
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ElementaryTypeNameExpression : public PrimaryExpression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ElementaryTypeNameExpression(Location const& _location, Token::Value _type)
|
||||||
|
: PrimaryExpression(_location), m_type(_type) {}
|
||||||
|
private:
|
||||||
|
Token::Value m_type;
|
||||||
|
};
|
||||||
|
|
||||||
class Literal : public PrimaryExpression
|
class Literal : public PrimaryExpression
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
Literal(Location const& _location, Token::Value _token, std::string const& _value)
|
||||||
|
: PrimaryExpression(_location), m_token(_token), m_value(_value)
|
||||||
|
{}
|
||||||
private:
|
private:
|
||||||
|
Token::Value m_token;
|
||||||
std::string m_value;
|
std::string m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
233
Parser.cpp
233
Parser.cpp
@ -231,12 +231,10 @@ ptr<ParameterList> Parser::parseParameterList()
|
|||||||
|
|
||||||
ptr<Block> Parser::parseBlock()
|
ptr<Block> Parser::parseBlock()
|
||||||
{
|
{
|
||||||
|
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
expectToken(Token::LBRACE);
|
expectToken(Token::LBRACE);
|
||||||
vecptr<Statement> statements;
|
vecptr<Statement> statements;
|
||||||
while (m_scanner->getCurrentToken() != Token::RBRACE) {
|
while (m_scanner->getCurrentToken() != Token::RBRACE) {
|
||||||
m_scanner->next();
|
|
||||||
statements.push_back(parseStatement());
|
statements.push_back(parseStatement());
|
||||||
}
|
}
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
@ -246,6 +244,7 @@ ptr<Block> Parser::parseBlock()
|
|||||||
|
|
||||||
ptr<Statement> Parser::parseStatement()
|
ptr<Statement> Parser::parseStatement()
|
||||||
{
|
{
|
||||||
|
ptr<Statement> statement;
|
||||||
|
|
||||||
switch (m_scanner->getCurrentToken()) {
|
switch (m_scanner->getCurrentToken()) {
|
||||||
case Token::IF:
|
case Token::IF:
|
||||||
@ -254,10 +253,227 @@ ptr<Statement> Parser::parseStatement()
|
|||||||
return parseWhileStatement();
|
return parseWhileStatement();
|
||||||
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
|
||||||
case Token::CONTINUE: // all following
|
case Token::CONTINUE:
|
||||||
return
|
statement = ASTNodeFactory(*this).createNode<Continue>();
|
||||||
|
break;
|
||||||
|
case Token::BREAK:
|
||||||
|
statement = ASTNodeFactory(*this).createNode<Break>();
|
||||||
|
break;
|
||||||
|
case Token::RETURN:
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
ptr<Expression> expression;
|
||||||
|
if (m_scanner->next() != Token::SEMICOLON) {
|
||||||
|
expression = parseExpression();
|
||||||
|
nodeFactory.setEndPositionFromNode(expression);
|
||||||
|
}
|
||||||
|
statement = nodeFactory.createNode<Return>(expression);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// distinguish between variable definition (and potentially assignment) and expressions
|
||||||
|
// (which include assignments to other expressions and pre-declared variables)
|
||||||
|
// We have a variable definition if we ge 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->peek() == Token::IDENTIFIER)) {
|
||||||
|
statement = parseVariableDefinition();
|
||||||
|
} else {
|
||||||
|
// "ordinary" expression
|
||||||
|
statement = parseExpression();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
expectToken(Token::SEMICOLON);
|
||||||
|
return statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<IfStatement> Parser::parseIfStatement()
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
expectToken(Token::IF);
|
||||||
|
expectToken(Token::LPAREN);
|
||||||
|
ptr<Expression> condition = parseExpression();
|
||||||
|
expectToken(Token::RPAREN);
|
||||||
|
ptr<Statement> trueBody = parseStatement();
|
||||||
|
ptr<Statement> falseBody;
|
||||||
|
if (m_scanner->getCurrentToken() == Token::ELSE) {
|
||||||
|
m_scanner->next();
|
||||||
|
falseBody = parseStatement();
|
||||||
|
nodeFactory.setEndPositionFromNode(falseBody);
|
||||||
|
} else {
|
||||||
|
nodeFactory.setEndPositionFromNode(trueBody);
|
||||||
|
}
|
||||||
|
return nodeFactory.createNode<IfStatement>(condition, trueBody, falseBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<WhileStatement> Parser::parseWhileStatement()
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
expectToken(Token::WHILE);
|
||||||
|
expectToken(Token::LPAREN);
|
||||||
|
ptr<Expression> condition = parseExpression();
|
||||||
|
expectToken(Token::RPAREN);
|
||||||
|
ptr<Statement> body = parseStatement();
|
||||||
|
nodeFactory.setEndPositionFromNode(body);
|
||||||
|
return nodeFactory.createNode<WhileStatement>(condition, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<VariableDefinition> Parser::parseVariableDefinition()
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
ptr<VariableDeclaration> variable = parseVariableDeclaration();
|
||||||
|
ptr<Expression> value;
|
||||||
|
if (m_scanner->getCurrentToken() == Token::ASSIGN) {
|
||||||
|
m_scanner->next();
|
||||||
|
value = parseExpression();
|
||||||
|
nodeFactory.setEndPositionFromNode(value);
|
||||||
|
} else {
|
||||||
|
nodeFactory.setEndPositionFromNode(variable);
|
||||||
|
}
|
||||||
|
return nodeFactory.createNode<VariableDefinition>(variable, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<Expression> Parser::parseExpression()
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
ptr<Expression> expression = parseBinaryExpression();
|
||||||
|
if (!Token::IsAssignmentOp(m_scanner->getCurrentToken()))
|
||||||
|
return expression;
|
||||||
|
|
||||||
|
Token::Value assignmentOperator = expectAssignmentOperator();
|
||||||
|
ptr<Expression> rightHandSide = parseExpression();
|
||||||
|
nodeFactory.setEndPositionFromNode(rightHandSide);
|
||||||
|
return nodeFactory.createNode<Assignment>(expression, assignmentOperator, rightHandSide);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<Expression> Parser::parseBinaryExpression(int _minPrecedence)
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
ptr<Expression> expression = parseUnaryExpression();
|
||||||
|
int precedence = Token::Precedence(m_scanner->getCurrentToken());
|
||||||
|
for (; precedence >= _minPrecedence; --precedence) {
|
||||||
|
while (Token::Precedence(m_scanner->getCurrentToken()) == precedence) {
|
||||||
|
Token::Value op = m_scanner->getCurrentToken();
|
||||||
|
m_scanner->next();
|
||||||
|
ptr<Expression> right = parseBinaryExpression(precedence + 1);
|
||||||
|
nodeFactory.setEndPositionFromNode(right);
|
||||||
|
expression = nodeFactory.createNode<BinaryOperation>(expression, op, right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<Expression> Parser::parseUnaryExpression()
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
Token::Value token = m_scanner->getCurrentToken();
|
||||||
|
if (Token::IsUnaryOp(token) || Token::IsCountOp(token)) {
|
||||||
|
// prefix expression
|
||||||
|
m_scanner->next();
|
||||||
|
ptr<Expression> subExpression = parseUnaryExpression();
|
||||||
|
nodeFactory.setEndPositionFromNode(subExpression);
|
||||||
|
return nodeFactory.createNode<UnaryOperation>(token, subExpression, true);
|
||||||
|
} else {
|
||||||
|
// potential postfix expression
|
||||||
|
ptr<Expression> subExpression = parseLeftHandSideExpression();
|
||||||
|
token = m_scanner->getCurrentToken();
|
||||||
|
if (!Token::IsCountOp(token))
|
||||||
|
return subExpression;
|
||||||
|
nodeFactory.markEndPosition();
|
||||||
|
m_scanner->next();
|
||||||
|
return nodeFactory.createNode<UnaryOperation>(token, subExpression, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<Expression> Parser::parseLeftHandSideExpression()
|
||||||
|
{
|
||||||
|
ASTNodeFactory nodeFactory(*this);
|
||||||
|
ptr<Expression> expression = parsePrimaryExpression();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
switch (m_scanner->getCurrentToken()) {
|
||||||
|
case Token::LBRACK:
|
||||||
|
{
|
||||||
|
m_scanner->next();
|
||||||
|
ptr<Expression> index = parseExpression();
|
||||||
|
nodeFactory.markEndPosition();
|
||||||
|
expectToken(Token::RBRACK);
|
||||||
|
expression = nodeFactory.createNode<IndexAccess>(expression, index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Token::PERIOD:
|
||||||
|
{
|
||||||
|
m_scanner->next();
|
||||||
|
nodeFactory.markEndPosition();
|
||||||
|
std::string memberName = expectIdentifier();
|
||||||
|
expression = nodeFactory.createNode<MemberAccess>(expression, memberName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Token::LPAREN:
|
||||||
|
{
|
||||||
|
m_scanner->next();
|
||||||
|
vecptr<Expression> arguments = parseFunctionCallArguments();
|
||||||
|
nodeFactory.markEndPosition();
|
||||||
|
expectToken(Token::RPAREN);
|
||||||
|
expression = nodeFactory.createNode<FunctionCall>(expression, arguments);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<Expression> Parser::parsePrimaryExpression()
|
||||||
|
{
|
||||||
|
Token::Value token = m_scanner->getCurrentToken();
|
||||||
|
switch (token) {
|
||||||
|
case Token::TRUE_LITERAL:
|
||||||
|
case Token::FALSE_LITERAL:
|
||||||
|
m_scanner->next();
|
||||||
|
return ASTNodeFactory(*this).createNode<Literal>(token, std::string());
|
||||||
|
case Token::NUMBER:
|
||||||
|
case Token::STRING_LITERAL:
|
||||||
|
m_scanner->next();
|
||||||
|
return ASTNodeFactory(*this).createNode<Literal>(token, m_scanner->getCurrentLiteral());
|
||||||
|
case Token::IDENTIFIER:
|
||||||
|
m_scanner->next();
|
||||||
|
return ASTNodeFactory(*this).createNode<Identifier>(m_scanner->getCurrentLiteral());
|
||||||
|
case Token::LPAREN:
|
||||||
|
{
|
||||||
|
m_scanner->next();
|
||||||
|
ptr<Expression> expression = parseExpression();
|
||||||
|
expectToken(Token::RPAREN);
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if (Token::IsElementaryTypeName(token)) {
|
||||||
|
// used for casts
|
||||||
|
m_scanner->next();
|
||||||
|
return ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(token);
|
||||||
|
} else {
|
||||||
|
throwExpectationError("Expected primary expression.");
|
||||||
|
return ptr<Expression>(); // this is not reached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vecptr<Expression> Parser::parseFunctionCallArguments()
|
||||||
|
{
|
||||||
|
vecptr<Expression> arguments;
|
||||||
|
if (m_scanner->getCurrentToken() != Token::RPAREN) {
|
||||||
|
arguments.push_back(parseExpression());
|
||||||
|
while (m_scanner->getCurrentToken() != Token::RPAREN) {
|
||||||
|
expectToken(Token::COMMA);
|
||||||
|
arguments.push_back(parseExpression());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::expectToken(Token::Value _value)
|
void Parser::expectToken(Token::Value _value)
|
||||||
@ -267,6 +483,15 @@ void Parser::expectToken(Token::Value _value)
|
|||||||
m_scanner->next();
|
m_scanner->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token::Value Parser::expectAssignmentOperator()
|
||||||
|
{
|
||||||
|
Token::Value op = m_scanner->getCurrentToken();
|
||||||
|
if (!Token::IsAssignmentOp(op))
|
||||||
|
throwExpectationError(std::string("Expected assignment operator"));
|
||||||
|
m_scanner->next();
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
std::string Parser::expectIdentifier()
|
std::string Parser::expectIdentifier()
|
||||||
{
|
{
|
||||||
if (m_scanner->getCurrentToken() != Token::IDENTIFIER)
|
if (m_scanner->getCurrentToken() != Token::IDENTIFIER)
|
||||||
|
10
Parser.h
10
Parser.h
@ -53,12 +53,22 @@ private:
|
|||||||
ptr<ParameterList> parseParameterList();
|
ptr<ParameterList> parseParameterList();
|
||||||
ptr<Block> parseBlock();
|
ptr<Block> parseBlock();
|
||||||
ptr<Statement> parseStatement();
|
ptr<Statement> parseStatement();
|
||||||
|
ptr<IfStatement> parseIfStatement();
|
||||||
|
ptr<WhileStatement> parseWhileStatement();
|
||||||
|
ptr<VariableDefinition> parseVariableDefinition();
|
||||||
|
ptr<Expression> parseExpression();
|
||||||
|
ptr<Expression> parseBinaryExpression(int _minPrecedence = 4);
|
||||||
|
ptr<Expression> parseUnaryExpression();
|
||||||
|
ptr<Expression> parseLeftHandSideExpression();
|
||||||
|
ptr<Expression> parsePrimaryExpression();
|
||||||
|
vecptr<Expression> parseFunctionCallArguments();
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
/// Helper functions
|
/// Helper functions
|
||||||
/// @{
|
/// @{
|
||||||
/// 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();
|
||||||
std::string expectIdentifier();
|
std::string expectIdentifier();
|
||||||
void throwExpectationError(const std::string& _description);
|
void throwExpectationError(const std::string& _description);
|
||||||
/// @}
|
/// @}
|
||||||
|
13
grammar.txt
13
grammar.txt
@ -15,18 +15,21 @@ TypeName = ElementaryTypeName | Identifier | Mapping
|
|||||||
Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')'
|
Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')'
|
||||||
|
|
||||||
Block = '{' Statement* '}'
|
Block = '{' Statement* '}'
|
||||||
Statement = IfStatement | WhileStatement | Continue | Break | Return | VariableAssignment | Expression ';' | Block
|
Statement = IfStatement | WhileStatement | Block |
|
||||||
|
( Continue | Break | Return | VariableDefinition | Expression ) ';'
|
||||||
|
|
||||||
IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )?
|
IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )?
|
||||||
WhileStatement = 'while' '(' Expression ')' Statement
|
WhileStatement = 'while' '(' Expression ')' Statement
|
||||||
Continue = 'continue' ';'
|
Continue = 'continue' ';'
|
||||||
Break = 'break' ';'
|
Break = 'break' ';'
|
||||||
Return = 'return' Expression? ';'
|
Return = 'return' Expression? ';'
|
||||||
VariableAssignment = VariableDeclaration ( AssignmentOp Expression )? ';'
|
VariableDefinition = VariableDeclaration ( = Expression )? ';'
|
||||||
|
|
||||||
Expression = Assignment | UnaryOperation | BinaryOperation | FunctionCall | IndexAccess | MemberAccess | PrimaryExpression
|
Expression = Assignment | UnaryOperation | BinaryOperation | FunctionCall | IndexAccess |
|
||||||
|
MemberAccess | PrimaryExpression
|
||||||
|
// The expression syntax is actually much more complicated
|
||||||
Assignment = Expression (AssignmentOp Expression)
|
Assignment = Expression (AssignmentOp Expression)
|
||||||
FunctionCall = Identifier '(' ( Expression ( ',' Expression )* ) ')'
|
FunctionCall = Expression '(' ( Expression ( ',' Expression )* ) ')'
|
||||||
MemberAccess = Expression '.' Identifier
|
MemberAccess = Expression '.' Identifier
|
||||||
IndexAccess = Expression '[' Expresison ']'
|
IndexAccess = Expression '[' Expresison ']'
|
||||||
PrimaryExpression = Identifier | NumberLiteral | StringLiteral | '(' Expression ')'
|
PrimaryExpression = Identifier | NumberLiteral | StringLiteral | ElementaryTypeName | '(' Expression ')'
|
||||||
|
Loading…
Reference in New Issue
Block a user