mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Solidity parser, can not parse much yet.
This commit is contained in:
parent
ef59373871
commit
56e9cc8db7
23
AST.cpp
Normal file
23
AST.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
This file is part of cpp-ethereum.
|
||||
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
cpp-ethereum is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @author Christian <c@ethdev.com>
|
||||
* @date 2014
|
||||
* Solidity abstract syntax tree.
|
||||
*/
|
||||
|
||||
#include <libsolidity/AST.h>
|
287
AST.h
Normal file
287
AST.h
Normal file
@ -0,0 +1,287 @@
|
||||
/*
|
||||
This file is part of cpp-ethereum.
|
||||
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
cpp-ethereum is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @author Christian <c@ethdev.com>
|
||||
* @date 2014
|
||||
* Solidity abstract syntax tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include <libsolidity/BaseTypes.h>
|
||||
#include <libsolidity/Token.h>
|
||||
|
||||
namespace dev {
|
||||
namespace solidity {
|
||||
|
||||
template <class T>
|
||||
using ptr = std::shared_ptr<T>;
|
||||
template <class T>
|
||||
using vecptr = std::vector<ptr<T>>;
|
||||
|
||||
class VariableDeclaration;
|
||||
class StructDefinition;
|
||||
class FunctionDefinition;
|
||||
class TypeName;
|
||||
class Block;
|
||||
class Expression;
|
||||
|
||||
class ASTNode
|
||||
{
|
||||
public:
|
||||
explicit ASTNode(const Location& _location)
|
||||
: m_location(_location)
|
||||
{}
|
||||
private:
|
||||
Location m_location;
|
||||
};
|
||||
|
||||
class ContractDefinition : public ASTNode
|
||||
{
|
||||
public:
|
||||
ContractDefinition(const Location& _location,
|
||||
const std::string& _name,
|
||||
const vecptr<StructDefinition>& _definedStructs,
|
||||
const vecptr<VariableDeclaration>& _stateVariables,
|
||||
const vecptr<FunctionDefinition>& _definedFunctions)
|
||||
: ASTNode(_location),
|
||||
m_name(_name),
|
||||
m_definedStructs(_definedStructs),
|
||||
m_stateVariables(_stateVariables),
|
||||
m_definedFunctions(_definedFunctions)
|
||||
{}
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
vecptr<StructDefinition> m_definedStructs;
|
||||
vecptr<VariableDeclaration> m_stateVariables;
|
||||
vecptr<FunctionDefinition> m_definedFunctions;
|
||||
};
|
||||
|
||||
class StructDefinition : public ASTNode
|
||||
{
|
||||
private:
|
||||
std::string m_name;
|
||||
vecptr<VariableDeclaration> m_members;
|
||||
};
|
||||
|
||||
class FunctionDefinition : public ASTNode
|
||||
{
|
||||
private:
|
||||
std::string m_name;
|
||||
vecptr<VariableDeclaration> m_arguments;
|
||||
bool m_isDeclaredConst;
|
||||
vecptr<VariableDeclaration> m_returns;
|
||||
ptr<Block> m_body;
|
||||
};
|
||||
|
||||
class VariableDeclaration : public ASTNode
|
||||
{
|
||||
public:
|
||||
VariableDeclaration(const Location& _location,
|
||||
const ptr<TypeName>& _type,
|
||||
const std::string& _name)
|
||||
: ASTNode(_location),
|
||||
m_type(_type),
|
||||
m_name(_name)
|
||||
{}
|
||||
private:
|
||||
ptr<TypeName> m_type; ///<s can be empty ("var")
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
/// types
|
||||
/// @{
|
||||
|
||||
class TypeName : public ASTNode
|
||||
{
|
||||
public:
|
||||
explicit TypeName(const Location& _location)
|
||||
: ASTNode(_location)
|
||||
{}
|
||||
};
|
||||
|
||||
/// any pre-defined type that is not a mapping
|
||||
class ElementaryTypeName : public TypeName
|
||||
{
|
||||
public:
|
||||
explicit ElementaryTypeName(const Location& _location, Token::Value _type)
|
||||
: TypeName(_location), m_type(_type)
|
||||
{}
|
||||
private:
|
||||
Token::Value m_type;
|
||||
};
|
||||
|
||||
class UserDefinedTypeName : public TypeName
|
||||
{
|
||||
public:
|
||||
UserDefinedTypeName(const Location& _location, const std::string& _name)
|
||||
: TypeName(_location), m_name(_name)
|
||||
{}
|
||||
private:
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
class MappingTypeName : public TypeName
|
||||
{
|
||||
public:
|
||||
explicit MappingTypeName(const Location& _location)
|
||||
: TypeName(_location)
|
||||
{}
|
||||
private:
|
||||
ptr<ElementaryTypeName> m_keyType;
|
||||
ptr<TypeName> m_valueType;
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
/// Statements
|
||||
/// @{
|
||||
|
||||
class Statement : public ASTNode
|
||||
{
|
||||
};
|
||||
|
||||
class Block : public Statement
|
||||
{
|
||||
private:
|
||||
vecptr<Statement> m_statements;
|
||||
};
|
||||
|
||||
class IfStatement : public Statement
|
||||
{
|
||||
|
||||
private:
|
||||
ptr<Expression> m_condition;
|
||||
ptr<Statement> m_trueBody;
|
||||
ptr<Statement> m_falseBody;
|
||||
};
|
||||
|
||||
class BreakableStatement : public Statement
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class WhileStatement : public BreakableStatement
|
||||
{
|
||||
private:
|
||||
ptr<Expression> m_condition;
|
||||
ptr<Statement> m_body;
|
||||
};
|
||||
|
||||
class Continue : public Statement
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class Break : public Statement
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class Return : public Statement
|
||||
{
|
||||
private:
|
||||
ptr<Expression> m_expression;
|
||||
};
|
||||
|
||||
class VariableAssignment : public Statement
|
||||
{
|
||||
private:
|
||||
ptr<VariableDeclaration> m_variable;
|
||||
Token::Value m_assigmentOperator;
|
||||
ptr<Expression> m_rightHandSide; ///< can be missing
|
||||
};
|
||||
|
||||
class Expression : public Statement
|
||||
{
|
||||
private:
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
/// Expressions
|
||||
/// @{
|
||||
|
||||
class Assignment : public Expression
|
||||
{
|
||||
private:
|
||||
ptr<Expression> m_leftHandSide;
|
||||
Token::Value m_assigmentOperator;
|
||||
ptr<Expression> m_rightHandSide;
|
||||
};
|
||||
|
||||
class UnaryOperation : public Expression
|
||||
{
|
||||
private:
|
||||
Token::Value m_operator;
|
||||
ptr<Expression> m_subExpression;
|
||||
bool isPrefix;
|
||||
};
|
||||
|
||||
class BinaryOperation : public Expression
|
||||
{
|
||||
private:
|
||||
ptr<Expression> m_left;
|
||||
ptr<Expression> m_right;
|
||||
Token::Value m_operator;
|
||||
};
|
||||
|
||||
class FunctionCall : public Expression
|
||||
{
|
||||
private:
|
||||
std::string m_functionName; // TODO only calls to fixed, named functions for now
|
||||
vecptr<Expression> m_arguments;
|
||||
};
|
||||
|
||||
class MemberAccess : public Expression
|
||||
{
|
||||
private:
|
||||
ptr<Expression> m_expression;
|
||||
std::string m_memberName;
|
||||
};
|
||||
|
||||
class IndexAccess : public Expression
|
||||
{
|
||||
ptr<Expression> m_base;
|
||||
ptr<Expression> m_index;
|
||||
};
|
||||
|
||||
class PrimaryExpression : public Expression
|
||||
{
|
||||
};
|
||||
|
||||
class Identifier : public PrimaryExpression
|
||||
{
|
||||
private:
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
class Literal : public PrimaryExpression
|
||||
{
|
||||
private:
|
||||
std::string m_value;
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
} }
|
22
BaseTypes.h
Normal file
22
BaseTypes.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace dev {
|
||||
namespace solidity {
|
||||
|
||||
// Representation of an interval of source positions.
|
||||
struct Location {
|
||||
Location(int b, int e) : beg_pos(b), end_pos(e) { }
|
||||
Location() : beg_pos(0), end_pos(0) { }
|
||||
|
||||
bool IsValid() const {
|
||||
return beg_pos >= 0 && end_pos >= beg_pos;
|
||||
}
|
||||
|
||||
static Location invalid() { return Location(-1, -1); }
|
||||
|
||||
int beg_pos;
|
||||
int end_pos;
|
||||
};
|
||||
|
||||
} }
|
180
Parser.cpp
Normal file
180
Parser.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
This file is part of cpp-ethereum.
|
||||
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
cpp-ethereum is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @author Christian <c@ethdev.com>
|
||||
* @date 2014
|
||||
* Solidity parser.
|
||||
*/
|
||||
|
||||
#include "libsolidity/BaseTypes.h"
|
||||
#include "libsolidity/Parser.h"
|
||||
#include "libsolidity/Scanner.h"
|
||||
|
||||
namespace dev {
|
||||
namespace solidity {
|
||||
|
||||
ptr<ASTNode> Parser::parse(Scanner& _scanner)
|
||||
{
|
||||
m_scanner = &_scanner;
|
||||
|
||||
return parseContractDefinition();
|
||||
}
|
||||
|
||||
|
||||
/// AST node factory that also tracks the begin and end position of an AST node
|
||||
/// while it is being parsed
|
||||
class Parser::ASTNodeFactory
|
||||
{
|
||||
public:
|
||||
ASTNodeFactory(const Parser& _parser)
|
||||
: m_parser(_parser),
|
||||
m_location(_parser.getPosition(), -1)
|
||||
{}
|
||||
|
||||
void markEndPosition()
|
||||
{
|
||||
m_location.end_pos = m_parser.getEndPosition();
|
||||
}
|
||||
|
||||
/// @todo: check that this actually uses perfect forwarding
|
||||
template <class NodeType, typename... Args>
|
||||
ptr<NodeType> createNode(Args&&... _args)
|
||||
{
|
||||
if (m_location.end_pos < 0) markEndPosition();
|
||||
return std::make_shared<NodeType>(m_location, std::forward<Args>(_args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
const Parser& m_parser;
|
||||
Location m_location;
|
||||
};
|
||||
|
||||
int Parser::getPosition() const
|
||||
{
|
||||
return m_scanner->getCurrentLocation().beg_pos;
|
||||
}
|
||||
|
||||
int Parser::getEndPosition() const
|
||||
{
|
||||
return m_scanner->getCurrentLocation().end_pos;
|
||||
}
|
||||
|
||||
|
||||
ptr<ContractDefinition> Parser::parseContractDefinition()
|
||||
{
|
||||
ASTNodeFactory nodeFactory(*this);
|
||||
|
||||
expectToken(Token::CONTRACT);
|
||||
std::string name = expectIdentifier();
|
||||
expectToken(Token::LBRACE);
|
||||
|
||||
vecptr<StructDefinition> structs;
|
||||
vecptr<VariableDeclaration> stateVariables;
|
||||
vecptr<FunctionDefinition> functions;
|
||||
bool visibilityIsPublic = true;
|
||||
while (true) {
|
||||
Token::Value currentToken = m_scanner->getCurrentToken();
|
||||
if (currentToken == Token::RBRACE) {
|
||||
break;
|
||||
} else if (currentToken == Token::PUBLIC || currentToken == Token::PRIVATE) {
|
||||
visibilityIsPublic = (m_scanner->getCurrentToken() == Token::PUBLIC);
|
||||
m_scanner->next();
|
||||
expectToken(Token::COLON);
|
||||
} else if (currentToken == Token::FUNCTION) {
|
||||
functions.push_back(parseFunctionDefinition(visibilityIsPublic));
|
||||
} else if (currentToken == Token::STRUCT) {
|
||||
structs.push_back(parseStructDefinition());
|
||||
expectToken(Token::SEMICOLON);
|
||||
} else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING ||
|
||||
Token::IsElementaryTypeName(currentToken)) {
|
||||
stateVariables.push_back(parseVariableDeclaration());
|
||||
expectToken(Token::SEMICOLON);
|
||||
} else {
|
||||
throwExpectationError("Function, variable or struct declaration expected.");
|
||||
}
|
||||
}
|
||||
nodeFactory.markEndPosition();
|
||||
|
||||
m_scanner->next();
|
||||
expectToken(Token::EOS);
|
||||
|
||||
return nodeFactory.createNode<ContractDefinition>(name, structs, stateVariables, functions);
|
||||
}
|
||||
|
||||
ptr<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic)
|
||||
{
|
||||
(void) _isPublic;
|
||||
throwExpectationError("Function parsing is not yet implemented.");
|
||||
}
|
||||
|
||||
ptr<StructDefinition> Parser::parseStructDefinition()
|
||||
{
|
||||
throwExpectationError("Struct definition parsing is not yet implemented.");
|
||||
}
|
||||
|
||||
ptr<VariableDeclaration> Parser::parseVariableDeclaration()
|
||||
{
|
||||
ASTNodeFactory nodeFactory(*this);
|
||||
|
||||
ptr<TypeName> type;
|
||||
Token::Value token = m_scanner->getCurrentToken();
|
||||
if (Token::IsElementaryTypeName(token)) {
|
||||
type = ASTNodeFactory(*this).createNode<ElementaryTypeName>(token);
|
||||
m_scanner->next();
|
||||
} else if (token == Token::VAR) {
|
||||
type = ASTNodeFactory(*this).createNode<TypeName>();
|
||||
m_scanner->next();
|
||||
} else if (token == Token::MAPPING) {
|
||||
// TODO
|
||||
throwExpectationError("mappings are not yet implemented");
|
||||
} else if (token == Token::IDENTIFIER) {
|
||||
type = ASTNodeFactory(*this).createNode<UserDefinedTypeName>(m_scanner->getCurrentLiteral());
|
||||
m_scanner->next();
|
||||
} else {
|
||||
throwExpectationError("Expected variable declaration");
|
||||
}
|
||||
nodeFactory.markEndPosition();
|
||||
std::string name = expectIdentifier();
|
||||
return nodeFactory.createNode<VariableDeclaration>(type, name);
|
||||
}
|
||||
|
||||
void Parser::expectToken(Token::Value _value)
|
||||
{
|
||||
if (m_scanner->getCurrentToken() != _value)
|
||||
throwExpectationError(std::string("Expected token ") + std::string(Token::Name(_value)));
|
||||
m_scanner->next();
|
||||
}
|
||||
|
||||
std::string Parser::expectIdentifier()
|
||||
{
|
||||
if (m_scanner->getCurrentToken() != Token::IDENTIFIER)
|
||||
throwExpectationError("Expected identifier");
|
||||
|
||||
std::string literal = m_scanner->getCurrentLiteral();
|
||||
m_scanner->next();
|
||||
return literal;
|
||||
}
|
||||
|
||||
void Parser::throwExpectationError(const std::string& _description)
|
||||
{
|
||||
(void) _description;
|
||||
/// @todo make a proper exception hierarchy
|
||||
throw std::exception();//_description);
|
||||
}
|
||||
|
||||
|
||||
} }
|
64
Parser.h
Normal file
64
Parser.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
This file is part of cpp-ethereum.
|
||||
|
||||
cpp-ethereum is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
cpp-ethereum is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @author Christian <c@ethdev.com>
|
||||
* @date 2014
|
||||
* Solidity parser.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "libsolidity/AST.h"
|
||||
|
||||
namespace dev {
|
||||
namespace solidity {
|
||||
|
||||
class Scanner;
|
||||
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
ptr<ASTNode> parse(Scanner& _scanner);
|
||||
|
||||
private:
|
||||
class ASTNodeFactory;
|
||||
|
||||
/// Start position of the current token
|
||||
int getPosition() const;
|
||||
/// End position of the current token
|
||||
int getEndPosition() const;
|
||||
|
||||
/// Parsing functions for the AST nodes
|
||||
/// @{
|
||||
ptr<ContractDefinition> parseContractDefinition();
|
||||
ptr<FunctionDefinition> parseFunctionDefinition(bool _isPublic);
|
||||
ptr<StructDefinition> parseStructDefinition();
|
||||
ptr<VariableDeclaration> parseVariableDeclaration();
|
||||
/// @}
|
||||
|
||||
/// Helper functions
|
||||
/// @{
|
||||
/// If current token value is not _value, throw exception otherwise advance token.
|
||||
void expectToken(Token::Value _value);
|
||||
std::string expectIdentifier();
|
||||
void throwExpectationError(const std::string& _description);
|
||||
/// @}
|
||||
|
||||
Scanner* m_scanner;
|
||||
};
|
||||
|
||||
} }
|
42
Scanner.cpp
42
Scanner.cpp
@ -82,16 +82,10 @@ void Scanner::reset(const CharStream& _source)
|
||||
{
|
||||
m_source = _source;
|
||||
|
||||
// Initialize current_ to not refer to a literal.
|
||||
m_current_token.token = Token::ILLEGAL;
|
||||
m_current_token.literal.clear();
|
||||
|
||||
m_hasLineTerminatorBeforeNext = true;
|
||||
m_hasMultilineCommentBeforeNext = false;
|
||||
|
||||
m_char = m_source.get();
|
||||
skipWhitespace();
|
||||
scanToken();
|
||||
next();
|
||||
}
|
||||
|
||||
|
||||
@ -466,7 +460,7 @@ Token::Value Scanner::scanString()
|
||||
literal.Complete();
|
||||
|
||||
advance(); // consume quote
|
||||
return Token::STRING;
|
||||
return Token::STRING_LITERAL;
|
||||
}
|
||||
|
||||
|
||||
@ -551,13 +545,17 @@ Token::Value Scanner::scanNumber(bool _periodSeen)
|
||||
// Keyword Matcher
|
||||
|
||||
#define KEYWORDS(KEYWORD_GROUP, KEYWORD) \
|
||||
KEYWORD_GROUP('a') \
|
||||
KEYWORD("address", Token::BREAK) \
|
||||
KEYWORD_GROUP('b') \
|
||||
KEYWORD("break", Token::BREAK) \
|
||||
KEYWORD("bool", Token::BOOL) \
|
||||
KEYWORD_GROUP('c') \
|
||||
KEYWORD("case", Token::CASE) \
|
||||
KEYWORD("catch", Token::CATCH) \
|
||||
KEYWORD("const", Token::CONST) \
|
||||
KEYWORD("continue", Token::CONTINUE) \
|
||||
KEYWORD("contract", Token::CONTRACT) \
|
||||
KEYWORD_GROUP('d') \
|
||||
KEYWORD("debugger", Token::DEBUGGER) \
|
||||
KEYWORD("default", Token::DEFAULT) \
|
||||
@ -571,31 +569,55 @@ Token::Value Scanner::scanNumber(bool _periodSeen)
|
||||
KEYWORD("finally", Token::FINALLY) \
|
||||
KEYWORD("for", Token::FOR) \
|
||||
KEYWORD("function", Token::FUNCTION) \
|
||||
KEYWORD_GROUP('h') \
|
||||
KEYWORD("hash", Token::HASH) \
|
||||
KEYWORD("hash32", Token::HASH32) \
|
||||
KEYWORD("hash64", Token::HASH64) \
|
||||
KEYWORD("hash128", Token::HASH128) \
|
||||
KEYWORD("hash256", Token::HASH256) \
|
||||
KEYWORD_GROUP('i') \
|
||||
KEYWORD("if", Token::IF) \
|
||||
KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \
|
||||
KEYWORD("in", Token::IN) \
|
||||
KEYWORD("instanceof", Token::INSTANCEOF) \
|
||||
KEYWORD("int", Token::INT) \
|
||||
KEYWORD("int32", Token::INT32) \
|
||||
KEYWORD("int64", Token::INT64) \
|
||||
KEYWORD("int128", Token::INT128) \
|
||||
KEYWORD("int256", Token::INT256) \
|
||||
KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD) \
|
||||
KEYWORD_GROUP('l') \
|
||||
KEYWORD_GROUP('m') \
|
||||
KEYWORD_GROUP('n') \
|
||||
KEYWORD("mapping", Token::MAPPING) \
|
||||
KEYWORD("new", Token::NEW) \
|
||||
KEYWORD("null", Token::NULL_LITERAL) \
|
||||
KEYWORD_GROUP('p') \
|
||||
KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD) \
|
||||
KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD) \
|
||||
KEYWORD("private", Token::PRIVATE) \
|
||||
KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD) \
|
||||
KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD) \
|
||||
KEYWORD("public", Token::PUBLIC) \
|
||||
KEYWORD_GROUP('r') \
|
||||
KEYWORD("real", Token::REAL) \
|
||||
KEYWORD("return", Token::RETURN) \
|
||||
KEYWORD_GROUP('s') \
|
||||
KEYWORD("string", Token::STRING_TYPE) \
|
||||
KEYWORD("struct", Token::STRUCT) \
|
||||
KEYWORD("switch", Token::SWITCH) \
|
||||
KEYWORD_GROUP('t') \
|
||||
KEYWORD("text", Token::TEXT) \
|
||||
KEYWORD("this", Token::THIS) \
|
||||
KEYWORD("throw", Token::THROW) \
|
||||
KEYWORD("true", Token::TRUE_LITERAL) \
|
||||
KEYWORD("try", Token::TRY) \
|
||||
KEYWORD("typeof", Token::TYPEOF) \
|
||||
KEYWORD_GROUP('u') \
|
||||
KEYWORD("uint", Token::UINT) \
|
||||
KEYWORD("uint32", Token::UINT32) \
|
||||
KEYWORD("uint64", Token::UINT64) \
|
||||
KEYWORD("uint128", Token::UINT128) \
|
||||
KEYWORD("uint256", Token::UINT256) \
|
||||
KEYWORD("ureal", Token::UREAL) \
|
||||
KEYWORD_GROUP('v') \
|
||||
KEYWORD("var", Token::VAR) \
|
||||
KEYWORD("void", Token::VOID) \
|
||||
|
18
Scanner.h
18
Scanner.h
@ -47,6 +47,7 @@
|
||||
#include <libdevcore/Common.h>
|
||||
#include <libdevcore/Log.h>
|
||||
#include <libdevcore/CommonData.h>
|
||||
#include <libsolidity/BaseTypes.h>
|
||||
#include <libsolidity/Token.h>
|
||||
|
||||
namespace dev {
|
||||
@ -111,21 +112,6 @@ public:
|
||||
bool complete_;
|
||||
};
|
||||
|
||||
// Representation of an interval of source positions.
|
||||
struct Location {
|
||||
Location(int b, int e) : beg_pos(b), end_pos(e) { }
|
||||
Location() : beg_pos(0), end_pos(0) { }
|
||||
|
||||
bool IsValid() const {
|
||||
return beg_pos >= 0 && end_pos >= beg_pos;
|
||||
}
|
||||
|
||||
static Location invalid() { return Location(-1, -1); }
|
||||
|
||||
int beg_pos;
|
||||
int end_pos;
|
||||
};
|
||||
|
||||
explicit Scanner(const CharStream& _source);
|
||||
|
||||
// Resets the scanner as if newly constructed with _input as input.
|
||||
@ -163,8 +149,6 @@ private:
|
||||
std::string literal;
|
||||
};
|
||||
|
||||
static const int kCharacterLookaheadBufferSize = 1;
|
||||
|
||||
// Literal buffer support
|
||||
inline void startNewLiteral() {
|
||||
m_next_token.literal.clear();
|
||||
|
35
Token.h
35
Token.h
@ -152,6 +152,7 @@ namespace solidity {
|
||||
K(CASE, "case", 0) \
|
||||
K(CATCH, "catch", 0) \
|
||||
K(CONTINUE, "continue", 0) \
|
||||
K(CONTRACT, "contract", 0) \
|
||||
K(DEBUGGER, "debugger", 0) \
|
||||
K(DEFAULT, "default", 0) \
|
||||
/* DELETE */ \
|
||||
@ -163,8 +164,12 @@ namespace solidity {
|
||||
K(IF, "if", 0) \
|
||||
/* IN */ \
|
||||
/* INSTANCEOF */ \
|
||||
K(MAPPING, "mapping", 0) \
|
||||
K(NEW, "new", 0) \
|
||||
K(PUBLIC, "public", 0) \
|
||||
K(PRIVATE, "private", 0) \
|
||||
K(RETURN, "return", 0) \
|
||||
K(STRUCT, "struct", 0) \
|
||||
K(SWITCH, "switch", 0) \
|
||||
K(THIS, "this", 0) \
|
||||
K(THROW, "throw", 0) \
|
||||
@ -175,12 +180,36 @@ namespace solidity {
|
||||
K(WHILE, "while", 0) \
|
||||
K(WITH, "with", 0) \
|
||||
\
|
||||
/* type keywords, keep them in this order, keep int as first keyword TODO more to be added */ \
|
||||
K(INT, "int", 0) \
|
||||
K(INT32, "int32", 0) \
|
||||
K(INT64, "int64", 0) \
|
||||
K(INT128, "int128", 0) \
|
||||
K(INT256, "int256", 0) \
|
||||
K(UINT, "uint", 0) \
|
||||
K(UINT32, "uint32", 0) \
|
||||
K(UINT64, "uint64", 0) \
|
||||
K(UINT128, "uint128", 0) \
|
||||
K(UINT256, "uint256", 0) \
|
||||
K(HASH, "hash", 0) \
|
||||
K(HASH32, "hash32", 0) \
|
||||
K(HASH64, "hash64", 0) \
|
||||
K(HASH128, "hash128", 0) \
|
||||
K(HASH256, "hash256", 0) \
|
||||
K(ADDRESS, "address", 0) \
|
||||
K(BOOL, "bool", 0) \
|
||||
K(STRING_TYPE, "string", 0) \
|
||||
K(TEXT, "text", 0) \
|
||||
K(REAL, "real", 0) \
|
||||
K(UREAL, "ureal", 0) \
|
||||
T(TYPES_END, NULL, 0) /* used as type enum end marker */ \
|
||||
\
|
||||
/* Literals (ECMA-262, section 7.8, page 16). */ \
|
||||
K(NULL_LITERAL, "null", 0) \
|
||||
K(TRUE_LITERAL, "true", 0) \
|
||||
K(FALSE_LITERAL, "false", 0) \
|
||||
T(NUMBER, NULL, 0) \
|
||||
T(STRING, NULL, 0) \
|
||||
T(STRING_LITERAL, NULL, 0) \
|
||||
\
|
||||
/* Identifiers (not keywords or future reserved words). */ \
|
||||
T(IDENTIFIER, NULL, 0) \
|
||||
@ -231,6 +260,10 @@ class Token {
|
||||
return tok == IDENTIFIER;
|
||||
}
|
||||
|
||||
static bool IsElementaryTypeName(Value tok) {
|
||||
return INT <= tok && tok < TYPES_END;
|
||||
}
|
||||
|
||||
static bool IsAssignmentOp(Value tok) {
|
||||
return INIT_VAR <= tok && tok <= ASSIGN_MOD;
|
||||
}
|
||||
|
32
grammar.txt
Normal file
32
grammar.txt
Normal file
@ -0,0 +1,32 @@
|
||||
ContractDefinition = 'contract' Identifier '{' ContractPart* '}'
|
||||
ContractPart = VariableDeclaration ';' | StructDefinition ';' |
|
||||
FunctionDefinition ';' | 'public:' | 'private:'
|
||||
|
||||
StructDefinition = 'struct' Identifier '{'
|
||||
( VariableDeclaration (';' VariableDeclaration)* )? '}
|
||||
|
||||
FunctionDefinition = 'function' Identifier ArgumentList 'const'?
|
||||
'returns' ArgumentList Block
|
||||
ArgumentList = '(' ( VariableDeclaration (',' VariableDeclaration)* )? ')'
|
||||
// semantic restriction: mappings and structs (recursively) containing mappings
|
||||
// are not allowed in argument lists
|
||||
VariableDeclaration = TypeName Identifier
|
||||
TypeName = PredefinedType | Identifier | MappingType
|
||||
MappingType = 'mapping' '(' SimplePredefinedType '=>' TypeName ')'
|
||||
|
||||
Block = '{' Statement* '}'
|
||||
Statement = IfStatement | WhileStatement | Continue | Break | Return | VariableAssignment | Expression ';' | Block
|
||||
|
||||
IfStatement = 'if' '(' Expression ')' Statement ( 'else' Statement )?
|
||||
WhileStatement = 'while' '(' Expression ')' Statement
|
||||
Continue = 'continue' ';'
|
||||
Break = 'break' ';'
|
||||
Return = 'return' Expression? ';'
|
||||
VariableAssignment = VariableDeclaration ( AssignmentOp Expression )? ';'
|
||||
|
||||
Expression = Assignment | UnaryOperation | BinaryOperation | FunctionCall | IndexAccess | MemberAccess | PrimaryExpression
|
||||
Assignment = Expression (AssignmentOp Expression)
|
||||
FunctionCall = Identifier '(' ( Expression ( ',' Expression )* ) ')'
|
||||
MemberAccess = Expression '.' Identifier
|
||||
IndexAccess = Expression '[' Expresison ']'
|
||||
PrimaryExpression = Identifier | NumberLiteral | StringLiteral | '(' Expression ')'
|
Loading…
Reference in New Issue
Block a user