aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AST.cpp143
-rw-r--r--AST.h37
-rw-r--r--ASTForward.h31
-rw-r--r--ASTPrinter.cpp46
-rw-r--r--ASTPrinter.h34
-rw-r--r--ASTVisitor.h34
-rw-r--r--BaseTypes.h34
-rw-r--r--Exceptions.h31
-rw-r--r--NameAndTypeResolver.cpp44
-rw-r--r--NameAndTypeResolver.h31
-rw-r--r--Parser.cpp288
-rw-r--r--Parser.h31
-rw-r--r--Scanner.cpp911
-rw-r--r--Scanner.h98
-rw-r--r--Scope.cpp33
-rw-r--r--Scope.h31
-rw-r--r--Token.cpp21
-rw-r--r--Token.h194
-rw-r--r--Types.cpp64
-rw-r--r--Types.h58
20 files changed, 1145 insertions, 1049 deletions
diff --git a/AST.cpp b/AST.cpp
index 4fb4c770..355ff1bd 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -26,12 +26,15 @@
#include <libsolidity/ASTVisitor.h>
#include <libsolidity/Exceptions.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
void ContractDefinition::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
listAccept(m_definedStructs, _visitor);
listAccept(m_stateVariables, _visitor);
listAccept(m_definedFunctions, _visitor);
@@ -41,7 +44,8 @@ void ContractDefinition::accept(ASTVisitor& _visitor)
void StructDefinition::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
listAccept(m_members, _visitor);
}
_visitor.endVisit(*this);
@@ -49,7 +53,8 @@ void StructDefinition::accept(ASTVisitor& _visitor)
void ParameterList::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
listAccept(m_parameters, _visitor);
}
_visitor.endVisit(*this);
@@ -57,7 +62,8 @@ void ParameterList::accept(ASTVisitor& _visitor)
void FunctionDefinition::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
m_parameters->accept(_visitor);
if (m_returnParameters)
m_returnParameters->accept(_visitor);
@@ -68,7 +74,8 @@ void FunctionDefinition::accept(ASTVisitor& _visitor)
void VariableDeclaration::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
if (m_typeName)
m_typeName->accept(_visitor);
}
@@ -95,7 +102,8 @@ void UserDefinedTypeName::accept(ASTVisitor& _visitor)
void Mapping::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
m_keyType->accept(_visitor);
m_valueType->accept(_visitor);
}
@@ -110,7 +118,8 @@ void Statement::accept(ASTVisitor& _visitor)
void Block::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
listAccept(m_statements, _visitor);
}
_visitor.endVisit(*this);
@@ -118,7 +127,8 @@ void Block::accept(ASTVisitor& _visitor)
void IfStatement::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
m_condition->accept(_visitor);
m_trueBody->accept(_visitor);
if (m_falseBody)
@@ -135,7 +145,8 @@ void BreakableStatement::accept(ASTVisitor& _visitor)
void WhileStatement::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
m_condition->accept(_visitor);
m_body->accept(_visitor);
}
@@ -156,7 +167,8 @@ void Break::accept(ASTVisitor& _visitor)
void Return::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
if (m_expression)
m_expression->accept(_visitor);
}
@@ -165,7 +177,8 @@ void Return::accept(ASTVisitor& _visitor)
void VariableDefinition::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
m_variable->accept(_visitor);
if (m_value)
m_value->accept(_visitor);
@@ -175,7 +188,8 @@ void VariableDefinition::accept(ASTVisitor& _visitor)
void Assignment::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
m_leftHandSide->accept(_visitor);
m_rightHandSide->accept(_visitor);
}
@@ -184,7 +198,8 @@ void Assignment::accept(ASTVisitor& _visitor)
void UnaryOperation::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
m_subExpression->accept(_visitor);
}
_visitor.endVisit(*this);
@@ -192,7 +207,8 @@ void UnaryOperation::accept(ASTVisitor& _visitor)
void BinaryOperation::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
m_left->accept(_visitor);
m_right->accept(_visitor);
}
@@ -201,7 +217,8 @@ void BinaryOperation::accept(ASTVisitor& _visitor)
void FunctionCall::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
m_expression->accept(_visitor);
listAccept(m_arguments, _visitor);
}
@@ -210,7 +227,8 @@ void FunctionCall::accept(ASTVisitor& _visitor)
void MemberAccess::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
m_expression->accept(_visitor);
}
_visitor.endVisit(*this);
@@ -218,7 +236,8 @@ void MemberAccess::accept(ASTVisitor& _visitor)
void IndexAccess::accept(ASTVisitor& _visitor)
{
- if (_visitor.visit(*this)) {
+ if (_visitor.visit(*this))
+ {
m_base->accept(_visitor);
m_index->accept(_visitor);
}
@@ -253,7 +272,7 @@ void Statement::expectType(Expression& _expression, const Type& _expectedType)
ptr<Type> Block::checkTypeRequirements()
{
- for (ptr<Statement> const& statement : m_statements)
+ for (ptr<Statement> const & statement : m_statements)
statement->checkTypeRequirements();
return ptr<Type>();
}
@@ -292,7 +311,6 @@ ptr<Type> Return::checkTypeRequirements()
"declaration."));
// this could later be changed such that the paramaters type is an anonymous struct type,
// but for now, we only allow one return parameter
-
expectType(*m_expression, *m_returnParameters->getParameters().front()->getType());
return ptr<Type>();
}
@@ -303,10 +321,14 @@ ptr<Type> VariableDefinition::checkTypeRequirements()
// setsthe type.
// Note that assignments before the first declaration are legal because of the special scoping
// rules inherited from JavaScript.
- if (m_value) {
- if (m_variable->getType()) {
+ if (m_value)
+ {
+ if (m_variable->getType())
+ {
expectType(*m_value, *m_variable->getType());
- } else {
+ }
+ else
+ {
// no type declared and no previous assignment, infer the type
m_variable->setType(m_value->checkTypeRequirements());
}
@@ -320,7 +342,8 @@ ptr<Type> Assignment::checkTypeRequirements()
// add a feature to the type system to check that
expectType(*m_rightHandSide, *m_leftHandSide->checkTypeRequirements());
m_type = m_leftHandSide->getType();
- if (m_assigmentOperator != Token::ASSIGN) {
+ if (m_assigmentOperator != Token::ASSIGN)
+ {
// complex assignment
if (!m_type->acceptsBinaryOperator(Token::AssignmentToBinaryOp(m_assigmentOperator)))
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Operator not compatible with type."));
@@ -341,18 +364,19 @@ ptr<Type> BinaryOperation::checkTypeRequirements()
{
m_right->checkTypeRequirements();
m_left->checkTypeRequirements();
-
if (m_right->getType()->isImplicitlyConvertibleTo(*m_left->getType()))
m_commonType = m_left->getType();
else if (m_left->getType()->isImplicitlyConvertibleTo(*m_right->getType()))
m_commonType = m_right->getType();
else
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("No common type found in binary operation."));
-
- if (Token::IsCompareOp(m_operator)) {
+ if (Token::isCompareOp(m_operator))
+ {
m_type = std::make_shared<BoolType>();
- } else {
- BOOST_ASSERT(Token::IsBinaryOp(m_operator));
+ }
+ else
+ {
+ BOOST_ASSERT(Token::isBinaryOp(m_operator));
m_type = m_commonType;
if (!m_commonType->acceptsBinaryOperator(m_operator))
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Operator not compatible with type."));
@@ -363,12 +387,12 @@ ptr<Type> BinaryOperation::checkTypeRequirements()
ptr<Type> FunctionCall::checkTypeRequirements()
{
m_expression->checkTypeRequirements();
- for (ptr<Expression> const& argument : m_arguments)
+ for (ptr<Expression> const & argument : m_arguments)
argument->checkTypeRequirements();
-
ptr<Type> expressionType = m_expression->getType();
Type::Category const category = expressionType->getCategory();
- if (category == Type::Category::TYPE) {
+ if (category == Type::Category::TYPE)
+ {
TypeType* type = dynamic_cast<TypeType*>(expressionType.get());
BOOST_ASSERT(type != nullptr);
//@todo for structs, we have to check the number of arguments to be equal to the
@@ -378,9 +402,11 @@ ptr<Type> FunctionCall::checkTypeRequirements()
"explicit type conersion."));
if (!m_arguments.front()->getType()->isExplicitlyConvertibleTo(*type->getActualType()))
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Explicit type conversion not "
- "allowed."));
+ "allowed."));
m_type = type->getActualType();
- } else if (category == Type::Category::FUNCTION) {
+ }
+ else if (category == Type::Category::FUNCTION)
+ {
//@todo would be nice to create a struct type from the arguments
// and then ask if that is implicitly convertible to the struct represented by the
// function parameters
@@ -390,20 +416,22 @@ ptr<Type> FunctionCall::checkTypeRequirements()
vecptr<VariableDeclaration> const& parameters = fun.getParameters();
if (parameters.size() != m_arguments.size())
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Wrong argument count for "
- "function call."));
- for (size_t i = 0; i < m_arguments.size(); ++i) {
+ "function call."));
+ for (size_t i = 0; i < m_arguments.size(); ++i)
+ {
if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameters[i]->getType()))
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Invalid type for argument in "
"function call."));
}
-
// @todo actually the return type should be an anonymous struct,
// but we change it to the type of the first return value until we have structs
if (fun.getReturnParameterList()->getParameters().empty())
m_type = std::make_shared<VoidType>();
else
m_type = fun.getReturnParameterList()->getParameters().front()->getType();
- } else {
+ }
+ else
+ {
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Type does not support invocation."));
}
return m_type;
@@ -435,7 +463,8 @@ ptr<Type> Identifier::checkTypeRequirements()
// var y = x;
// the type of x is not yet determined.
VariableDeclaration* variable = dynamic_cast<VariableDeclaration*>(m_referencedDeclaration);
- if (variable != nullptr) {
+ if (variable != nullptr)
+ {
if (variable->getType().get() == nullptr)
BOOST_THROW_EXCEPTION(TypeError() << errinfo_comment("Variable referenced before type "
"could be determined."));
@@ -444,13 +473,15 @@ ptr<Type> Identifier::checkTypeRequirements()
}
//@todo can we unify these with TypeName::toType()?
StructDefinition* structDef = dynamic_cast<StructDefinition*>(m_referencedDeclaration);
- if (structDef != nullptr) {
+ if (structDef != nullptr)
+ {
// note that we do not have a struct type here
m_type = std::make_shared<TypeType>(std::make_shared<StructType>(*structDef));
return m_type;
}
FunctionDefinition* functionDef = dynamic_cast<FunctionDefinition*>(m_referencedDeclaration);
- if (functionDef != nullptr) {
+ if (functionDef != nullptr)
+ {
// a function reference is not a TypeType, because calling a TypeType converts to the type.
// Calling a function (e.g. function(12), otherContract.function(34)) does not do a type
// conversion.
@@ -458,7 +489,8 @@ ptr<Type> Identifier::checkTypeRequirements()
return m_type;
}
ContractDefinition* contractDef = dynamic_cast<ContractDefinition*>(m_referencedDeclaration);
- if (contractDef != nullptr) {
+ if (contractDef != nullptr)
+ {
m_type = std::make_shared<TypeType>(std::make_shared<ContractType>(*contractDef));
return m_type;
}
@@ -478,4 +510,5 @@ ptr<Type> Literal::checkTypeRequirements()
return m_type;
}
-} }
+}
+}
diff --git a/AST.h b/AST.h
index c1509b85..a289455c 100644
--- a/AST.h
+++ b/AST.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -33,8 +33,10 @@
#include <libsolidity/Token.h>
#include <libsolidity/Types.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
class ASTVisitor;
@@ -49,8 +51,10 @@ public:
virtual void accept(ASTVisitor& _visitor) = 0;
template <class T>
- static void listAccept(vecptr<T>& _list, ASTVisitor& _visitor) {
- for (ptr<T>& element : _list) element->accept(_visitor);
+ static void listAccept(vecptr<T>& _list, ASTVisitor& _visitor)
+ {
+ for (ptr<T>& element : _list)
+ element->accept(_visitor);
}
Location const& getLocation() const { return m_location; }
@@ -521,4 +525,5 @@ private:
/// @}
-} }
+}
+}
diff --git a/ASTForward.h b/ASTForward.h
index 4963776b..0397cadd 100644
--- a/ASTForward.h
+++ b/ASTForward.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -28,8 +28,10 @@
// Forward-declare all AST node types
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
class ASTNode;
class Declaration;
@@ -74,4 +76,5 @@ using vecptr = std::vector<ptr<T>>;
using ASTString = std::string;
-} }
+}
+}
diff --git a/ASTPrinter.cpp b/ASTPrinter.cpp
index bbaa2e0a..7c48dacb 100644
--- a/ASTPrinter.cpp
+++ b/ASTPrinter.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -23,8 +23,10 @@
#include <libsolidity/ASTPrinter.h>
#include <libsolidity/AST.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
ASTPrinter::ASTPrinter(ptr<ASTNode> _ast, const std::string& _source)
: m_indentation(0), m_source(_source), m_ast(_ast)
@@ -85,7 +87,7 @@ bool ASTPrinter::visit(TypeName& _node)
bool ASTPrinter::visit(ElementaryTypeName& _node)
{
- writeLine(std::string("ElementaryTypeName ") + Token::String(_node.getType()));
+ writeLine(std::string("ElementaryTypeName ") + Token::toString(_node.getType()));
printSourcePart(_node);
return goDeeper();
}
@@ -176,7 +178,7 @@ bool ASTPrinter::visit(Expression& _node)
bool ASTPrinter::visit(Assignment& _node)
{
- writeLine(std::string("Assignment using operator ") + Token::String(_node.getAssignmentOperator()));
+ writeLine(std::string("Assignment using operator ") + Token::toString(_node.getAssignmentOperator()));
printSourcePart(_node);
return goDeeper();
}
@@ -184,14 +186,14 @@ bool ASTPrinter::visit(Assignment& _node)
bool ASTPrinter::visit(UnaryOperation& _node)
{
writeLine(std::string("UnaryOperation (") + (_node.isPrefixOperation() ? "prefix" : "postfix") +
- ") " + Token::String(_node.getOperator()));
+ ") " + Token::toString(_node.getOperator()));
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(BinaryOperation& _node)
{
- writeLine(std::string("BinaryOperation using operator ") + Token::String(_node.getOperator()));
+ writeLine(std::string("BinaryOperation using operator ") + Token::toString(_node.getOperator()));
printSourcePart(_node);
return goDeeper();
}
@@ -233,14 +235,14 @@ bool ASTPrinter::visit(Identifier& _node)
bool ASTPrinter::visit(ElementaryTypeNameExpression& _node)
{
- writeLine(std::string("ElementaryTypeNameExpression ") + Token::String(_node.getTypeToken()));
+ writeLine(std::string("ElementaryTypeNameExpression ") + Token::toString(_node.getTypeToken()));
printSourcePart(_node);
return goDeeper();
}
bool ASTPrinter::visit(Literal& _node)
{
- const char* tokenString = Token::String(_node.getToken());
+ const char* tokenString = Token::toString(_node.getToken());
if (tokenString == nullptr)
tokenString = "----";
writeLine(std::string("Literal, token: ") + tokenString + " value: " + _node.getValue());
@@ -402,7 +404,8 @@ void ASTPrinter::endVisit(Literal&)
void ASTPrinter::printSourcePart(ASTNode const& _node)
{
- if (!m_source.empty()) {
+ if (!m_source.empty())
+ {
Location const& location(_node.getLocation());
*m_ostream << getIndentation() << " Source: |"
<< m_source.substr(location.start, location.end - location.start) << "|\n";
@@ -419,4 +422,5 @@ void ASTPrinter::writeLine(const std::string& _line)
*m_ostream << getIndentation() << _line << '\n';
}
-} }
+}
+}
diff --git a/ASTPrinter.h b/ASTPrinter.h
index 6a864f38..52f34991 100644
--- a/ASTPrinter.h
+++ b/ASTPrinter.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -25,8 +25,10 @@
#include <ostream>
#include <libsolidity/ASTVisitor.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
class ASTPrinter : public ASTVisitor
{
@@ -67,7 +69,7 @@ public:
bool visit(ElementaryTypeNameExpression& _node) override;
bool visit(Literal& _node) override;
- void endVisit(ASTNode & _node) override;
+ void endVisit(ASTNode& _node) override;
void endVisit(ContractDefinition&) override;
void endVisit(StructDefinition&) override;
void endVisit(ParameterList&) override;
@@ -103,10 +105,12 @@ private:
std::string getIndentation() const;
void writeLine(std::string const& _line);
bool goDeeper() { m_indentation++; return true; }
+
int m_indentation;
std::string m_source;
ptr<ASTNode> m_ast;
std::ostream* m_ostream;
};
-} }
+}
+}
diff --git a/ASTVisitor.h b/ASTVisitor.h
index c28d2330..72f28768 100644
--- a/ASTVisitor.h
+++ b/ASTVisitor.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -25,10 +25,13 @@
#include <libsolidity/ASTForward.h>
#include <string>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
-class ASTVisitor {
+class ASTVisitor
+{
public:
/// These functions are called after a call to ASTNode::accept,
/// first visit, then (if visit returns true) recursively for all
@@ -97,4 +100,5 @@ public:
virtual void endVisit(Literal&) { }
};
-} }
+}
+}
diff --git a/BaseTypes.h b/BaseTypes.h
index 6d57b74b..c8926b6a 100644
--- a/BaseTypes.h
+++ b/BaseTypes.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -23,12 +23,15 @@
#pragma once
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
/// Representation of an interval of source positions.
/// The interval includes start and excludes end.
-struct Location {
+struct Location
+{
Location(int _start, int _end) : start(_start), end(_end) { }
Location() : start(-1), end(-1) { }
@@ -38,4 +41,5 @@ struct Location {
int end;
};
-} }
+}
+}
diff --git a/Exceptions.h b/Exceptions.h
index 5e0b1522..c14e0d79 100644
--- a/Exceptions.h
+++ b/Exceptions.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -24,11 +24,14 @@
#include <libdevcore/Exceptions.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
struct ParserError : virtual Exception {};
struct TypeError : virtual Exception {};
struct DeclarationError : virtual Exception {};
-} }
+}
+}
diff --git a/NameAndTypeResolver.cpp b/NameAndTypeResolver.cpp
index 7208d7ac..ada987b0 100644
--- a/NameAndTypeResolver.cpp
+++ b/NameAndTypeResolver.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -26,8 +26,10 @@
#include <libsolidity/Exceptions.h>
#include <boost/assert.hpp>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
NameAndTypeResolver::NameAndTypeResolver()
@@ -38,15 +40,12 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
{
reset();
DeclarationRegistrationHelper registrar(m_scopes, _contract);
-
m_currentScope = &m_scopes[&_contract];
-
//@todo structs
-
- for (ptr<VariableDeclaration> const& variable : _contract.getStateVariables())
+ for (ptr<VariableDeclaration> const & variable : _contract.getStateVariables())
ReferencesResolver resolver(*variable, *this, nullptr);
-
- for (ptr<FunctionDefinition> const& function : _contract.getDefinedFunctions()) {
+ for (ptr<FunctionDefinition> const & function : _contract.getDefinedFunctions())
+ {
m_currentScope = &m_scopes[function.get()];
ReferencesResolver referencesResolver(*function, *this,
function->getReturnParameterList().get());
@@ -54,7 +53,8 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
// First, all function parameter types need to be resolved before we can check
// the types, since it is possible to call functions that are only defined later
// in the source.
- for (ptr<FunctionDefinition> const& function : _contract.getDefinedFunctions()) {
+ for (ptr<FunctionDefinition> const & function : _contract.getDefinedFunctions())
+ {
m_currentScope = &m_scopes[function.get()];
function->getBody().checkTypeRequirements();
}
@@ -141,7 +141,6 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
BOOST_ASSERT(m_currentScope != nullptr);
if (!m_currentScope->registerDeclaration(_declaration))
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_comment("Identifier already declared."));
-
if (_opensScope)
enterNewSubScope(_declaration);
}
@@ -198,4 +197,5 @@ bool ReferencesResolver::visit(Identifier& _identifier)
}
-} }
+}
+}
diff --git a/NameAndTypeResolver.h b/NameAndTypeResolver.h
index f5a3c84e..346c9e64 100644
--- a/NameAndTypeResolver.h
+++ b/NameAndTypeResolver.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -29,8 +29,10 @@
#include <libsolidity/Scope.h>
#include <libsolidity/ASTVisitor.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
class NameAndTypeResolver : private boost::noncopyable
@@ -92,4 +94,5 @@ private:
ParameterList* m_returnParameters;
};
-} }
+}
+}
diff --git a/Parser.cpp b/Parser.cpp
index b2815411..5a329ae7 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -26,13 +26,14 @@
#include <libsolidity/Scanner.h>
#include <libsolidity/Exceptions.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
ptr<ContractDefinition> Parser::parse(std::shared_ptr<Scanner> const& _scanner)
{
m_scanner = _scanner;
-
return parseContractDefinition();
}
@@ -46,9 +47,15 @@ public:
: m_parser(_parser), m_location(_parser.getPosition(), -1)
{}
- void markEndPosition() { m_location.end = m_parser.getEndPosition(); }
+ void markEndPosition()
+ {
+ m_location.end = m_parser.getEndPosition();
+ }
- void setLocationEmpty() { m_location.end = m_location.start; }
+ void setLocationEmpty()
+ {
+ m_location.end = m_location.start;
+ }
/// Set the end position to the one of the given node.
void setEndPositionFromNode(const ptr<ASTNode>& _node)
@@ -58,7 +65,7 @@ public:
/// @todo: check that this actually uses perfect forwarding
template <class NodeType, typename... Args>
- ptr<NodeType> createNode(Args&&... _args)
+ ptr<NodeType> createNode(Args&& ... _args)
{
if (m_location.end < 0)
markEndPosition();
@@ -84,62 +91,73 @@ int Parser::getEndPosition() const
ptr<ContractDefinition> Parser::parseContractDefinition()
{
ASTNodeFactory nodeFactory(*this);
-
expectToken(Token::CONTRACT);
ptr<ASTString> name = expectIdentifierToken();
expectToken(Token::LBRACE);
-
vecptr<StructDefinition> structs;
vecptr<VariableDeclaration> stateVariables;
vecptr<FunctionDefinition> functions;
bool visibilityIsPublic = true;
- while (true) {
+ while (true)
+ {
Token::Value currentToken = m_scanner->getCurrentToken();
- if (currentToken == Token::RBRACE) {
+ if (currentToken == Token::RBRACE)
+ {
break;
- } else if (currentToken == Token::PUBLIC || currentToken == Token::PRIVATE) {
+ }
+ 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) {
+ }
+ else if (currentToken == Token::FUNCTION)
+ {
functions.push_back(parseFunctionDefinition(visibilityIsPublic));
- } else if (currentToken == Token::STRUCT) {
+ }
+ else if (currentToken == Token::STRUCT)
+ {
structs.push_back(parseStructDefinition());
- } else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING ||
- Token::IsElementaryTypeName(currentToken)) {
+ }
+ else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING ||
+ Token::isElementaryTypeName(currentToken))
+ {
bool const allowVar = false;
stateVariables.push_back(parseVariableDeclaration(allowVar));
expectToken(Token::SEMICOLON);
- } else {
+ }
+ else
+ {
throwExpectationError("Function, variable or struct declaration expected.");
}
}
nodeFactory.markEndPosition();
-
expectToken(Token::RBRACE);
expectToken(Token::EOS);
-
return nodeFactory.createNode<ContractDefinition>(name, structs, stateVariables, functions);
}
ptr<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic)
{
ASTNodeFactory nodeFactory(*this);
-
expectToken(Token::FUNCTION);
ptr<ASTString> name(expectIdentifierToken());
ptr<ParameterList> parameters(parseParameterList());
bool isDeclaredConst = false;
- if (m_scanner->getCurrentToken() == Token::CONST) {
+ if (m_scanner->getCurrentToken() == Token::CONST)
+ {
isDeclaredConst = true;
m_scanner->next();
}
ptr<ParameterList> returnParameters;
- if (m_scanner->getCurrentToken() == Token::RETURNS) {
+ if (m_scanner->getCurrentToken() == Token::RETURNS)
+ {
const bool permitEmptyParameterList = false;
m_scanner->next();
returnParameters = parseParameterList(permitEmptyParameterList);
- } else {
+ }
+ else
+ {
// create an empty parameter list at a zero-length location
ASTNodeFactory nodeFactory(*this);
nodeFactory.setLocationEmpty();
@@ -148,32 +166,30 @@ ptr<FunctionDefinition> Parser::parseFunctionDefinition(bool _isPublic)
ptr<Block> block = parseBlock();
nodeFactory.setEndPositionFromNode(block);
return nodeFactory.createNode<FunctionDefinition>(name, _isPublic, parameters,
- isDeclaredConst, returnParameters, block);
+ isDeclaredConst, returnParameters, block);
}
ptr<StructDefinition> Parser::parseStructDefinition()
{
ASTNodeFactory nodeFactory(*this);
-
expectToken(Token::STRUCT);
ptr<ASTString> name = expectIdentifierToken();
vecptr<VariableDeclaration> members;
expectToken(Token::LBRACE);
- while (m_scanner->getCurrentToken() != Token::RBRACE) {
+ while (m_scanner->getCurrentToken() != Token::RBRACE)
+ {
bool const allowVar = false;
members.push_back(parseVariableDeclaration(allowVar));
expectToken(Token::SEMICOLON);
}
nodeFactory.markEndPosition();
expectToken(Token::RBRACE);
-
return nodeFactory.createNode<StructDefinition>(name, members);
}
ptr<VariableDeclaration> Parser::parseVariableDeclaration(bool _allowVar)
{
ASTNodeFactory nodeFactory(*this);
-
ptr<TypeName> type = parseTypeName(_allowVar);
nodeFactory.markEndPosition();
return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken());
@@ -183,58 +199,63 @@ ptr<TypeName> Parser::parseTypeName(bool _allowVar)
{
ptr<TypeName> type;
Token::Value token = m_scanner->getCurrentToken();
- if (Token::IsElementaryTypeName(token)) {
+ if (Token::isElementaryTypeName(token))
+ {
type = ASTNodeFactory(*this).createNode<ElementaryTypeName>(token);
m_scanner->next();
- } else if (token == Token::VAR) {
+ }
+ else if (token == Token::VAR)
+ {
if (!_allowVar)
throwExpectationError("Expected explicit type name.");
m_scanner->next();
- } else if (token == Token::MAPPING) {
+ }
+ else if (token == Token::MAPPING)
+ {
type = parseMapping();
- } else if (token == Token::IDENTIFIER) {
+ }
+ else if (token == Token::IDENTIFIER)
+ {
ASTNodeFactory nodeFactory(*this);
nodeFactory.markEndPosition();
type = nodeFactory.createNode<UserDefinedTypeName>(expectIdentifierToken());
- } else {
+ }
+ else
+ {
throwExpectationError("Expected type name");
}
-
return type;
}
ptr<Mapping> Parser::parseMapping()
{
ASTNodeFactory nodeFactory(*this);
-
expectToken(Token::MAPPING);
expectToken(Token::LPAREN);
-
- if (!Token::IsElementaryTypeName(m_scanner->getCurrentToken()))
+ if (!Token::isElementaryTypeName(m_scanner->getCurrentToken()))
throwExpectationError("Expected elementary type name for mapping key type");
ptr<ElementaryTypeName> keyType;
keyType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(m_scanner->getCurrentToken());
m_scanner->next();
-
expectToken(Token::ARROW);
bool const allowVar = false;
ptr<TypeName> valueType = parseTypeName(allowVar);
nodeFactory.markEndPosition();
expectToken(Token::RPAREN);
-
return nodeFactory.createNode<Mapping>(keyType, valueType);
}
ptr<ParameterList> Parser::parseParameterList(bool _allowEmpty)
{
ASTNodeFactory nodeFactory(*this);
-
vecptr<VariableDeclaration> parameters;
expectToken(Token::LPAREN);
- if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN) {
+ if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN)
+ {
bool const allowVar = false;
parameters.push_back(parseVariableDeclaration(allowVar));
- while (m_scanner->getCurrentToken() != Token::RPAREN) {
+ while (m_scanner->getCurrentToken() != Token::RPAREN)
+ {
expectToken(Token::COMMA);
parameters.push_back(parseVariableDeclaration(allowVar));
}
@@ -249,7 +270,8 @@ ptr<Block> Parser::parseBlock()
ASTNodeFactory nodeFactory(*this);
expectToken(Token::LBRACE);
vecptr<Statement> statements;
- while (m_scanner->getCurrentToken() != Token::RBRACE) {
+ while (m_scanner->getCurrentToken() != Token::RBRACE)
+ {
statements.push_back(parseStatement());
}
nodeFactory.markEndPosition();
@@ -260,16 +282,15 @@ ptr<Block> Parser::parseBlock()
ptr<Statement> Parser::parseStatement()
{
ptr<Statement> statement;
-
- switch (m_scanner->getCurrentToken()) {
+ switch (m_scanner->getCurrentToken())
+ {
case Token::IF:
return parseIfStatement();
case Token::WHILE:
return parseWhileStatement();
case Token::LBRACE:
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:
statement = ASTNodeFactory(*this).createNode<Continue>();
break;
@@ -277,28 +298,32 @@ ptr<Statement> Parser::parseStatement()
statement = ASTNodeFactory(*this).createNode<Break>();
break;
case Token::RETURN:
+ {
+ ASTNodeFactory nodeFactory(*this);
+ ptr<Expression> expression;
+ if (m_scanner->next() != Token::SEMICOLON)
{
- ASTNodeFactory nodeFactory(*this);
- ptr<Expression> expression;
- if (m_scanner->next() != Token::SEMICOLON) {
- expression = parseExpression();
- nodeFactory.setEndPositionFromNode(expression);
- }
- statement = nodeFactory.createNode<Return>(expression);
+ expression = parseExpression();
+ nodeFactory.setEndPositionFromNode(expression);
}
- break;
+ 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)) {
+ m_scanner->getCurrentToken() == Token::VAR ||
+ Token::isElementaryTypeName(m_scanner->getCurrentToken()) ||
+ (m_scanner->getCurrentToken() == Token::IDENTIFIER &&
+ m_scanner->peek() == Token::IDENTIFIER))
+ {
statement = parseVariableDefinition();
- } else {
+ }
+ else
+ {
// "ordinary" expression
statement = parseExpression();
}
@@ -316,11 +341,14 @@ ptr<IfStatement> Parser::parseIfStatement()
expectToken(Token::RPAREN);
ptr<Statement> trueBody = parseStatement();
ptr<Statement> falseBody;
- if (m_scanner->getCurrentToken() == Token::ELSE) {
+ if (m_scanner->getCurrentToken() == Token::ELSE)
+ {
m_scanner->next();
falseBody = parseStatement();
nodeFactory.setEndPositionFromNode(falseBody);
- } else {
+ }
+ else
+ {
nodeFactory.setEndPositionFromNode(trueBody);
}
return nodeFactory.createNode<IfStatement>(condition, trueBody, falseBody);
@@ -344,11 +372,14 @@ ptr<VariableDefinition> Parser::parseVariableDefinition()
bool const allowVar = true;
ptr<VariableDeclaration> variable = parseVariableDeclaration(allowVar);
ptr<Expression> value;
- if (m_scanner->getCurrentToken() == Token::ASSIGN) {
+ if (m_scanner->getCurrentToken() == Token::ASSIGN)
+ {
m_scanner->next();
value = parseExpression();
nodeFactory.setEndPositionFromNode(value);
- } else {
+ }
+ else
+ {
nodeFactory.setEndPositionFromNode(variable);
}
return nodeFactory.createNode<VariableDefinition>(variable, value);
@@ -358,9 +389,8 @@ ptr<Expression> Parser::parseExpression()
{
ASTNodeFactory nodeFactory(*this);
ptr<Expression> expression = parseBinaryExpression();
- if (!Token::IsAssignmentOp(m_scanner->getCurrentToken()))
+ if (!Token::isAssignmentOp(m_scanner->getCurrentToken()))
return expression;
-
Token::Value assignmentOperator = expectAssignmentOperator();
ptr<Expression> rightHandSide = parseExpression();
nodeFactory.setEndPositionFromNode(rightHandSide);
@@ -371,9 +401,11 @@ 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) {
+ 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);
@@ -388,17 +420,20 @@ ptr<Expression> Parser::parseUnaryExpression()
{
ASTNodeFactory nodeFactory(*this);
Token::Value token = m_scanner->getCurrentToken();
- if (Token::IsUnaryOp(token) || Token::IsCountOp(token)) {
+ 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 {
+ }
+ else
+ {
// potential postfix expression
ptr<Expression> subExpression = parseLeftHandSideExpression();
token = m_scanner->getCurrentToken();
- if (!Token::IsCountOp(token))
+ if (!Token::isCountOp(token))
return subExpression;
nodeFactory.markEndPosition();
m_scanner->next();
@@ -410,34 +445,35 @@ ptr<Expression> Parser::parseLeftHandSideExpression()
{
ASTNodeFactory nodeFactory(*this);
ptr<Expression> expression = parsePrimaryExpression();
-
- while (true) {
- switch (m_scanner->getCurrentToken()) {
+ 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;
+ {
+ 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();
- expression = nodeFactory.createNode<MemberAccess>(expression, expectIdentifierToken());
- }
- break;
+ {
+ m_scanner->next();
+ nodeFactory.markEndPosition();
+ expression = nodeFactory.createNode<MemberAccess>(expression, expectIdentifierToken());
+ }
+ break;
case Token::LPAREN:
- {
- m_scanner->next();
- vecptr<Expression> arguments = parseFunctionCallArguments();
- nodeFactory.markEndPosition();
- expectToken(Token::RPAREN);
- expression = nodeFactory.createNode<FunctionCall>(expression, arguments);
- }
- break;
+ {
+ m_scanner->next();
+ vecptr<Expression> arguments = parseFunctionCallArguments();
+ nodeFactory.markEndPosition();
+ expectToken(Token::RPAREN);
+ expression = nodeFactory.createNode<FunctionCall>(expression, arguments);
+ }
+ break;
default:
return expression;
}
@@ -449,8 +485,8 @@ ptr<Expression> Parser::parsePrimaryExpression()
ASTNodeFactory nodeFactory(*this);
Token::Value token = m_scanner->getCurrentToken();
ptr<Expression> expression;
-
- switch (token) {
+ switch (token)
+ {
case Token::TRUE_LITERAL:
case Token::FALSE_LITERAL:
expression = nodeFactory.createNode<Literal>(token, ptr<ASTString>());
@@ -466,18 +502,21 @@ ptr<Expression> Parser::parsePrimaryExpression()
expression = nodeFactory.createNode<Identifier>(getLiteralAndAdvance());
break;
case Token::LPAREN:
- {
- m_scanner->next();
- ptr<Expression> expression = parseExpression();
- expectToken(Token::RPAREN);
- return expression;
- }
+ {
+ m_scanner->next();
+ ptr<Expression> expression = parseExpression();
+ expectToken(Token::RPAREN);
+ return expression;
+ }
default:
- if (Token::IsElementaryTypeName(token)) {
+ if (Token::isElementaryTypeName(token))
+ {
// used for casts
expression = nodeFactory.createNode<ElementaryTypeNameExpression>(token);
m_scanner->next();
- } else {
+ }
+ else
+ {
throwExpectationError("Expected primary expression.");
return ptr<Expression>(); // this is not reached
}
@@ -488,9 +527,11 @@ ptr<Expression> Parser::parsePrimaryExpression()
vecptr<Expression> Parser::parseFunctionCallArguments()
{
vecptr<Expression> arguments;
- if (m_scanner->getCurrentToken() != Token::RPAREN) {
+ if (m_scanner->getCurrentToken() != Token::RPAREN)
+ {
arguments.push_back(parseExpression());
- while (m_scanner->getCurrentToken() != Token::RPAREN) {
+ while (m_scanner->getCurrentToken() != Token::RPAREN)
+ {
expectToken(Token::COMMA);
arguments.push_back(parseExpression());
}
@@ -501,14 +542,14 @@ vecptr<Expression> Parser::parseFunctionCallArguments()
void Parser::expectToken(Token::Value _value)
{
if (m_scanner->getCurrentToken() != _value)
- throwExpectationError(std::string("Expected token ") + std::string(Token::Name(_value)));
+ throwExpectationError(std::string("Expected token ") + std::string(Token::getName(_value)));
m_scanner->next();
}
Token::Value Parser::expectAssignmentOperator()
{
Token::Value op = m_scanner->getCurrentToken();
- if (!Token::IsAssignmentOp(op))
+ if (!Token::isAssignmentOp(op))
throwExpectationError(std::string("Expected assignment operator"));
m_scanner->next();
return op;
@@ -518,7 +559,6 @@ ptr<ASTString> Parser::expectIdentifierToken()
{
if (m_scanner->getCurrentToken() != Token::IDENTIFIER)
throwExpectationError("Expected identifier");
-
return getLiteralAndAdvance();
}
@@ -540,9 +580,9 @@ void Parser::throwExpectationError(const std::string& _description)
<< ", column " << (column + 1) << "\n"
<< m_scanner->getLineAtPosition(getPosition()) << "\n"
<< std::string(column, ' ') << "^";
-
BOOST_THROW_EXCEPTION(ParserError() << errinfo_comment(buf.str()));
}
-} }
+}
+}
diff --git a/Parser.h b/Parser.h
index 84d20cf8..174ed712 100644
--- a/Parser.h
+++ b/Parser.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -24,8 +24,10 @@
#include "libsolidity/AST.h"
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
class Scanner;
@@ -77,4 +79,5 @@ private:
std::shared_ptr<Scanner> m_scanner;
};
-} }
+}
+}
diff --git a/Scanner.cpp b/Scanner.cpp
index 334da8e7..c2875c9c 100644
--- a/Scanner.cpp
+++ b/Scanner.cpp
@@ -45,35 +45,47 @@
#include <libsolidity/Scanner.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
-namespace {
- bool IsDecimalDigit(char c) {
- return '0' <= c && c <= '9';
- }
- bool IsHexDigit(char c) {
- return IsDecimalDigit(c)
- || ('a' <= c && c <= 'f')
- || ('A' <= c && c <= 'F');
- }
- bool IsLineTerminator(char c) { return c == '\n'; }
- bool IsWhiteSpace(char c) {
- return c == ' ' || c == '\n' || c == '\t';
- }
- bool IsIdentifierStart(char c) {
- return c == '_' || c == '$' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
- }
- bool IsIdentifierPart(char c) {
- return IsIdentifierStart(c) || IsDecimalDigit(c);
- }
+namespace
+{
+bool IsDecimalDigit(char c)
+{
+ return '0' <= c && c <= '9';
+}
+bool IsHexDigit(char c)
+{
+ return IsDecimalDigit(c)
+ || ('a' <= c && c <= 'f')
+ || ('A' <= c && c <= 'F');
+}
+bool IsLineTerminator(char c)
+{
+ return c == '\n';
+}
+bool IsWhiteSpace(char c)
+{
+ return c == ' ' || c == '\n' || c == '\t';
+}
+bool IsIdentifierStart(char c)
+{
+ return c == '_' || c == '$' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
+}
+bool IsIdentifierPart(char c)
+{
+ return IsIdentifierStart(c) || IsDecimalDigit(c);
+}
- int HexValue(char c) {
- if (c >= '0' && c <= '9') return c - '0';
- else if (c >= 'a' && c <= 'f') return c - 'a' + 10;
- else if (c >= 'A' && c <= 'F') return c - 'A' + 10;
- else return -1;
- }
+int HexValue(char c)
+{
+ if (c >= '0' && c <= '9') return c - '0';
+ else if (c >= 'a' && c <= 'f') return c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F') return c - 'A' + 10;
+ else return -1;
+}
}
Scanner::Scanner(const CharStream& _source)
@@ -84,7 +96,6 @@ Scanner::Scanner(const CharStream& _source)
void Scanner::reset(const CharStream& _source)
{
m_source = _source;
-
m_char = m_source.get();
skipWhitespace();
scanToken();
@@ -95,18 +106,18 @@ void Scanner::reset(const CharStream& _source)
bool Scanner::scanHexNumber(char& scanned_number, int expected_length)
{
BOOST_ASSERT(expected_length <= 4); // prevent overflow
-
char x = 0;
- for (int i = 0; i < expected_length; i++) {
+ for (int i = 0; i < expected_length; i++)
+ {
int d = HexValue(m_char);
- if (d < 0) {
+ if (d < 0)
+ {
rollback(i);
return false;
}
x = x * 16 + d;
advance();
}
-
scanned_number = x;
return true;
}
@@ -128,16 +139,14 @@ Token::Value Scanner::next()
bool Scanner::skipWhitespace()
{
const int start_position = getSourcePos();
-
- while (true) {
- if (IsLineTerminator(m_char)) {
- m_hasLineTerminatorBeforeNext = true;
- } else if (!IsWhiteSpace(m_char)) {
- break;
- }
- advance();
+ while (true)
+ {
+ if (IsLineTerminator(m_char))
+ m_hasLineTerminatorBeforeNext = true;
+ else if (!IsWhiteSpace(m_char))
+ break;
+ advance();
}
-
// Return whether or not we skipped any characters.
return getSourcePos() != start_position;
}
@@ -145,24 +154,24 @@ bool Scanner::skipWhitespace()
Token::Value Scanner::skipSingleLineComment()
{
- // The line terminator at the end of the line is not considered
- // to be part of the single-line comment; it is recognized
- // separately by the lexical grammar and becomes part of the
- // stream of input elements for the syntactic grammar
- while (advance() && !IsLineTerminator(m_char)) { };
-
- return Token::WHITESPACE;
+ // The line terminator at the end of the line is not considered
+ // to be part of the single-line comment; it is recognized
+ // separately by the lexical grammar and becomes part of the
+ // stream of input elements for the syntactic grammar
+ while (advance() && !IsLineTerminator(m_char)) { };
+ return Token::WHITESPACE;
}
Token::Value Scanner::skipMultiLineComment()
{
BOOST_ASSERT(m_char == '*');
advance();
-
- while (!isSourcePastEndOfInput()) {
+ while (!isSourcePastEndOfInput())
+ {
char ch = m_char;
advance();
- if (IsLineTerminator(ch)) {
+ if (IsLineTerminator(ch))
+ {
// Following ECMA-262, section 7.4, a comment containing
// a newline will make the comment count as a line-terminator.
m_hasMultilineCommentBeforeNext = true;
@@ -170,274 +179,250 @@ Token::Value Scanner::skipMultiLineComment()
// If we have reached the end of the multi-line comment, we
// consume the '/' and insert a whitespace. This way all
// multi-line comments are treated as whitespace.
- if (ch == '*' && m_char == '/') {
+ if (ch == '*' && m_char == '/')
+ {
m_char = ' ';
return Token::WHITESPACE;
}
}
-
// Unterminated multi-line comment.
return Token::ILLEGAL;
}
void Scanner::scanToken()
{
- m_next_token.literal.clear();
- Token::Value token;
- do {
- // Remember the position of the next token
- m_next_token.location.start = getSourcePos();
-
- switch (m_char) {
- case '\n':
- m_hasLineTerminatorBeforeNext = true; // fall-through
- case ' ':
- case '\t':
- token = selectToken(Token::WHITESPACE);
- break;
-
- case '"': case '\'':
- token = scanString();
- break;
-
- case '<':
- // < <= << <<=
- advance();
- if (m_char == '=') {
- token = selectToken(Token::LTE);
- } else if (m_char == '<') {
- token = selectToken('=', Token::ASSIGN_SHL, Token::SHL);
- } else {
- token = Token::LT;
- }
- break;
-
- case '>':
- // > >= >> >>= >>> >>>=
- advance();
- if (m_char == '=') {
- token = selectToken(Token::GTE);
- } else if (m_char == '>') {
- // >> >>= >>> >>>=
- advance();
- if (m_char == '=') {
- token = selectToken(Token::ASSIGN_SAR);
- } else if (m_char == '>') {
- token = selectToken('=', Token::ASSIGN_SHR, Token::SHR);
- } else {
- token = Token::SAR;
- }
- } else {
- token = Token::GT;
- }
- break;
-
- case '=':
- // = == =>
- advance();
- if (m_char == '=') {
- token = selectToken(Token::EQ);
- } else if (m_char == '>') {
- token = selectToken(Token::ARROW);
- } else {
- token = Token::ASSIGN;
- }
- break;
-
- case '!':
- // ! != !==
- advance();
- if (m_char == '=') {
- token = selectToken(Token::NE);
- } else {
- token = Token::NOT;
- }
- break;
-
- case '+':
- // + ++ +=
- advance();
- if (m_char == '+') {
- token = selectToken(Token::INC);
- } else if (m_char == '=') {
- token = selectToken(Token::ASSIGN_ADD);
- } else {
- token = Token::ADD;
- }
- break;
-
- case '-':
- // - -- -=
- advance();
- if (m_char == '-') {
- advance();
- token = Token::DEC;
- } else if (m_char == '=') {
- token = selectToken(Token::ASSIGN_SUB);
- } else {
- token = Token::SUB;
- }
- break;
-
- case '*':
- // * *=
- token = selectToken('=', Token::ASSIGN_MUL, Token::MUL);
- break;
-
- case '%':
- // % %=
- token = selectToken('=', Token::ASSIGN_MOD, Token::MOD);
- break;
-
- case '/':
- // / // /* /=
- advance();
- if (m_char == '/') {
- token = skipSingleLineComment();
- } else if (m_char == '*') {
- token = skipMultiLineComment();
- } else if (m_char == '=') {
- token = selectToken(Token::ASSIGN_DIV);
- } else {
- token = Token::DIV;
- }
- break;
-
- case '&':
- // & && &=
- advance();
- if (m_char == '&') {
- token = selectToken(Token::AND);
- } else if (m_char == '=') {
- token = selectToken(Token::ASSIGN_BIT_AND);
- } else {
- token = Token::BIT_AND;
- }
- break;
-
- case '|':
- // | || |=
- advance();
- if (m_char == '|') {
- token = selectToken(Token::OR);
- } else if (m_char == '=') {
- token = selectToken(Token::ASSIGN_BIT_OR);
- } else {
- token = Token::BIT_OR;
+ m_next_token.literal.clear();
+ Token::Value token;
+ do
+ {
+ // Remember the position of the next token
+ m_next_token.location.start = getSourcePos();
+ switch (m_char)
+ {
+ case '\n':
+ m_hasLineTerminatorBeforeNext = true; // fall-through
+ case ' ':
+ case '\t':
+ token = selectToken(Token::WHITESPACE);
+ break;
+ case '"':
+ case '\'':
+ token = scanString();
+ break;
+ case '<':
+ // < <= << <<=
+ advance();
+ if (m_char == '=')
+ token = selectToken(Token::LTE);
+ else if (m_char == '<')
+ token = selectToken('=', Token::ASSIGN_SHL, Token::SHL);
+ else
+ token = Token::LT;
+ break;
+ case '>':
+ // > >= >> >>= >>> >>>=
+ advance();
+ if (m_char == '=')
+ token = selectToken(Token::GTE);
+ else if (m_char == '>')
+ {
+ // >> >>= >>> >>>=
+ advance();
+ if (m_char == '=')
+ token = selectToken(Token::ASSIGN_SAR);
+ else if (m_char == '>')
+ token = selectToken('=', Token::ASSIGN_SHR, Token::SHR);
+ else
+ token = Token::SAR;
+ }
+ else
+ token = Token::GT;
+ break;
+ case '=':
+ // = == =>
+ advance();
+ if (m_char == '=')
+ token = selectToken(Token::EQ);
+ else if (m_char == '>')
+ token = selectToken(Token::ARROW);
+ else
+ token = Token::ASSIGN;
+ break;
+ case '!':
+ // ! !=
+ advance();
+ if (m_char == '=')
+ token = selectToken(Token::NE);
+ else
+ token = Token::NOT;
+ break;
+ case '+':
+ // + ++ +=
+ advance();
+ if (m_char == '+')
+ token = selectToken(Token::INC);
+ else if (m_char == '=')
+ token = selectToken(Token::ASSIGN_ADD);
+ else
+ token = Token::ADD;
+ break;
+ case '-':
+ // - -- -=
+ advance();
+ if (m_char == '-')
+ {
+ advance();
+ token = Token::DEC;
+ }
+ else if (m_char == '=')
+ token = selectToken(Token::ASSIGN_SUB);
+ else
+ token = Token::SUB;
+ break;
+ case '*':
+ // * *=
+ token = selectToken('=', Token::ASSIGN_MUL, Token::MUL);
+ break;
+ case '%':
+ // % %=
+ token = selectToken('=', Token::ASSIGN_MOD, Token::MOD);
+ break;
+ case '/':
+ // / // /* /=
+ advance();
+ if (m_char == '/')
+ token = skipSingleLineComment();
+ else if (m_char == '*')
+ token = skipMultiLineComment();
+ else if (m_char == '=')
+ token = selectToken(Token::ASSIGN_DIV);
+ else
+ token = Token::DIV;
+ break;
+ case '&':
+ // & && &=
+ advance();
+ if (m_char == '&')
+ token = selectToken(Token::AND);
+ else if (m_char == '=')
+ token = selectToken(Token::ASSIGN_BIT_AND);
+ else
+ token = Token::BIT_AND;
+ break;
+ case '|':
+ // | || |=
+ advance();
+ if (m_char == '|')
+ token = selectToken(Token::OR);
+ else if (m_char == '=')
+ token = selectToken(Token::ASSIGN_BIT_OR);
+ else
+ token = Token::BIT_OR;
+ break;
+ case '^':
+ // ^ ^=
+ token = selectToken('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
+ break;
+ case '.':
+ // . Number
+ advance();
+ if (IsDecimalDigit(m_char))
+ token = scanNumber(true);
+ else
+ token = Token::PERIOD;
+ break;
+ case ':':
+ token = selectToken(Token::COLON);
+ break;
+ case ';':
+ token = selectToken(Token::SEMICOLON);
+ break;
+ case ',':
+ token = selectToken(Token::COMMA);
+ break;
+ case '(':
+ token = selectToken(Token::LPAREN);
+ break;
+ case ')':
+ token = selectToken(Token::RPAREN);
+ break;
+ case '[':
+ token = selectToken(Token::LBRACK);
+ break;
+ case ']':
+ token = selectToken(Token::RBRACK);
+ break;
+ case '{':
+ token = selectToken(Token::LBRACE);
+ break;
+ case '}':
+ token = selectToken(Token::RBRACE);
+ break;
+ case '?':
+ token = selectToken(Token::CONDITIONAL);
+ break;
+ case '~':
+ token = selectToken(Token::BIT_NOT);
+ break;
+ default:
+ if (IsIdentifierStart(m_char))
+ token = scanIdentifierOrKeyword();
+ else if (IsDecimalDigit(m_char))
+ token = scanNumber(false);
+ else if (skipWhitespace())
+ token = Token::WHITESPACE;
+ else if (isSourcePastEndOfInput())
+ token = Token::EOS;
+ else
+ token = selectToken(Token::ILLEGAL);
+ break;
}
- break;
-
- case '^':
- // ^ ^=
- token = selectToken('=', Token::ASSIGN_BIT_XOR, Token::BIT_XOR);
- break;
-
- case '.':
- // . Number
- advance();
- if (IsDecimalDigit(m_char)) {
- token = scanNumber(true);
- } else {
- token = Token::PERIOD;
- }
- break;
-
- case ':':
- token = selectToken(Token::COLON);
- break;
-
- case ';':
- token = selectToken(Token::SEMICOLON);
- break;
-
- case ',':
- token = selectToken(Token::COMMA);
- break;
-
- case '(':
- token = selectToken(Token::LPAREN);
- break;
-
- case ')':
- token = selectToken(Token::RPAREN);
- break;
-
- case '[':
- token = selectToken(Token::LBRACK);
- break;
-
- case ']':
- token = selectToken(Token::RBRACK);
- break;
-
- case '{':
- token = selectToken(Token::LBRACE);
- break;
-
- case '}':
- token = selectToken(Token::RBRACE);
- break;
-
- case '?':
- token = selectToken(Token::CONDITIONAL);
- break;
-
- case '~':
- token = selectToken(Token::BIT_NOT);
- break;
-
- default:
- if (IsIdentifierStart(m_char)) {
- token = scanIdentifierOrKeyword();
- } else if (IsDecimalDigit(m_char)) {
- token = scanNumber(false);
- } else if (skipWhitespace()) {
- token = Token::WHITESPACE;
- } else if (isSourcePastEndOfInput()) {
- token = Token::EOS;
- } else {
- token = selectToken(Token::ILLEGAL);
- }
- break;
+ // Continue scanning for tokens as long as we're just skipping
+ // whitespace.
}
-
- // Continue scanning for tokens as long as we're just skipping
- // whitespace.
- } while (token == Token::WHITESPACE);
-
- m_next_token.location.end = getSourcePos();
- m_next_token.token = token;
+ while (token == Token::WHITESPACE);
+ m_next_token.location.end = getSourcePos();
+ m_next_token.token = token;
}
bool Scanner::scanEscape()
{
char c = m_char;
advance();
-
// Skip escaped newlines.
if (IsLineTerminator(c))
return true;
-
- switch (c) {
+ switch (c)
+ {
case '\'': // fall through
case '"' : // fall through
- case '\\': break;
- case 'b' : c = '\b'; break;
- case 'f' : c = '\f'; break;
- case 'n' : c = '\n'; break;
- case 'r' : c = '\r'; break;
- case 't' : c = '\t'; break;
- case 'u' : {
+ case '\\':
+ break;
+ case 'b' :
+ c = '\b';
+ break;
+ case 'f' :
+ c = '\f';
+ break;
+ case 'n' :
+ c = '\n';
+ break;
+ case 'r' :
+ c = '\r';
+ break;
+ case 't' :
+ c = '\t';
+ break;
+ case 'u' :
if (!scanHexNumber(c, 4)) return false;
break;
- }
- case 'v' : c = '\v'; break;
- case 'x' : {
+ case 'v' :
+ c = '\v';
+ break;
+ case 'x' :
if (!scanHexNumber(c, 2)) return false;
break;
}
- }
-
// According to ECMA-262, section 7.8.4, characters not covered by the
// above cases should be illegal, but they are commonly handled as
// non-escaped characters by JS VMs.
@@ -449,20 +434,21 @@ Token::Value Scanner::scanString()
{
const char quote = m_char;
advance(); // consume quote
-
LiteralScope literal(this);
- while (m_char != quote && !isSourcePastEndOfInput() && !IsLineTerminator(m_char)) {
+ while (m_char != quote && !isSourcePastEndOfInput() && !IsLineTerminator(m_char))
+ {
char c = m_char;
advance();
- if (c == '\\') {
- if (isSourcePastEndOfInput() || !scanEscape()) return Token::ILLEGAL;
- } else {
- addLiteralChar(c);
+ if (c == '\\')
+ {
+ if (isSourcePastEndOfInput() || !scanEscape())
+ return Token::ILLEGAL;
}
+ else
+ addLiteralChar(c);
}
if (m_char != quote) return Token::ILLEGAL;
literal.Complete();
-
advance(); // consume quote
return Token::STRING_LITERAL;
}
@@ -477,71 +463,66 @@ void Scanner::scanDecimalDigits()
Token::Value Scanner::scanNumber(bool _periodSeen)
{
- BOOST_ASSERT(IsDecimalDigit(m_char)); // the first digit of the number or the fraction
-
- enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL;
-
- LiteralScope literal(this);
- if (_periodSeen) {
- // we have already seen a decimal point of the float
- addLiteralChar('.');
- scanDecimalDigits(); // we know we have at least one digit
- } else {
- // if the first character is '0' we must check for octals and hex
- if (m_char == '0') {
- addLiteralCharAndAdvance();
-
- // either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or
- // an octal number.
- if (m_char == 'x' || m_char == 'X') {
- // hex number
- kind = HEX;
- addLiteralCharAndAdvance();
- if (!IsHexDigit(m_char)) {
- // we must have at least one hex digit after 'x'/'X'
- return Token::ILLEGAL;
+ BOOST_ASSERT(IsDecimalDigit(m_char)); // the first digit of the number or the fraction
+ enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL;
+ LiteralScope literal(this);
+ if (_periodSeen)
+ {
+ // we have already seen a decimal point of the float
+ addLiteralChar('.');
+ scanDecimalDigits(); // we know we have at least one digit
+ }
+ else
+ {
+ // if the first character is '0' we must check for octals and hex
+ if (m_char == '0')
+ {
+ addLiteralCharAndAdvance();
+ // either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or
+ // an octal number.
+ if (m_char == 'x' || m_char == 'X')
+ {
+ // hex number
+ kind = HEX;
+ addLiteralCharAndAdvance();
+ if (!IsHexDigit(m_char))
+ return Token::ILLEGAL; // we must have at least one hex digit after 'x'/'X'
+ while (IsHexDigit(m_char))
+ addLiteralCharAndAdvance();
+ }
}
- while (IsHexDigit(m_char)) {
- addLiteralCharAndAdvance();
+ // Parse decimal digits and allow trailing fractional part.
+ if (kind == DECIMAL)
+ {
+ scanDecimalDigits(); // optional
+ if (m_char == '.')
+ {
+ addLiteralCharAndAdvance();
+ scanDecimalDigits(); // optional
+ }
}
- }
}
-
- // Parse decimal digits and allow trailing fractional part.
- if (kind == DECIMAL) {
- scanDecimalDigits(); // optional
- if (m_char == '.') {
+ // scan exponent, if any
+ if (m_char == 'e' || m_char == 'E')
+ {
+ BOOST_ASSERT(kind != HEX); // 'e'/'E' must be scanned as part of the hex number
+ if (kind != DECIMAL) return Token::ILLEGAL;
+ // scan exponent
addLiteralCharAndAdvance();
- scanDecimalDigits(); // optional
- }
+ if (m_char == '+' || m_char == '-')
+ addLiteralCharAndAdvance();
+ if (!IsDecimalDigit(m_char))
+ return Token::ILLEGAL; // we must have at least one decimal digit after 'e'/'E'
+ scanDecimalDigits();
}
- }
-
- // scan exponent, if any
- if (m_char == 'e' || m_char == 'E') {
- BOOST_ASSERT(kind != HEX); // 'e'/'E' must be scanned as part of the hex number
- if (kind != DECIMAL) return Token::ILLEGAL;
- // scan exponent
- addLiteralCharAndAdvance();
- if (m_char == '+' || m_char == '-')
- addLiteralCharAndAdvance();
- if (!IsDecimalDigit(m_char)) {
- // we must have at least one decimal digit after 'e'/'E'
- return Token::ILLEGAL;
- }
- scanDecimalDigits();
- }
-
- // The source character immediately following a numeric literal must
- // not be an identifier start or a decimal digit; see ECMA-262
- // section 7.8.3, page 17 (note that we read only one decimal digit
- // if the value is 0).
- if (IsDecimalDigit(m_char) || IsIdentifierStart(m_char))
- return Token::ILLEGAL;
-
- literal.Complete();
-
- return Token::NUMBER;
+ // The source character immediately following a numeric literal must
+ // not be an identifier start or a decimal digit; see ECMA-262
+ // section 7.8.3, page 17 (note that we read only one decimal digit
+ // if the value is 0).
+ if (IsDecimalDigit(m_char) || IsIdentifierStart(m_char))
+ return Token::ILLEGAL;
+ literal.Complete();
+ return Token::NUMBER;
}
@@ -549,130 +530,126 @@ Token::Value Scanner::scanNumber(bool _periodSeen)
// Keyword Matcher
#define KEYWORDS(KEYWORD_GROUP, KEYWORD) \
- KEYWORD_GROUP('a') \
- KEYWORD("address", Token::ADDRESS) \
- 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) \
- KEYWORD("delete", Token::DELETE) \
- KEYWORD("do", Token::DO) \
- KEYWORD_GROUP('e') \
- KEYWORD("else", Token::ELSE) \
- KEYWORD("enum", Token::FUTURE_RESERVED_WORD) \
- KEYWORD_GROUP('f') \
- KEYWORD("false", Token::FALSE_LITERAL) \
- 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("mapping", Token::MAPPING) \
- KEYWORD_GROUP('n') \
- KEYWORD("new", Token::NEW) \
- KEYWORD("null", Token::NULL_LITERAL) \
- KEYWORD_GROUP('p') \
- KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD) \
- KEYWORD("private", Token::PRIVATE) \
- KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD) \
- KEYWORD("public", Token::PUBLIC) \
- KEYWORD_GROUP('r') \
- KEYWORD("real", Token::REAL) \
- KEYWORD("return", Token::RETURN) \
- KEYWORD("returns", Token::RETURNS) \
- 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) \
- KEYWORD_GROUP('w') \
- KEYWORD("while", Token::WHILE) \
- KEYWORD("with", Token::WITH)
+ KEYWORD_GROUP('a') \
+ KEYWORD("address", Token::ADDRESS) \
+ 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) \
+ KEYWORD("delete", Token::DELETE) \
+ KEYWORD("do", Token::DO) \
+ KEYWORD_GROUP('e') \
+ KEYWORD("else", Token::ELSE) \
+ KEYWORD("enum", Token::FUTURE_RESERVED_WORD) \
+ KEYWORD_GROUP('f') \
+ KEYWORD("false", Token::FALSE_LITERAL) \
+ 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("mapping", Token::MAPPING) \
+ KEYWORD_GROUP('n') \
+ KEYWORD("new", Token::NEW) \
+ KEYWORD("null", Token::NULL_LITERAL) \
+ KEYWORD_GROUP('p') \
+ KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD) \
+ KEYWORD("private", Token::PRIVATE) \
+ KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD) \
+ KEYWORD("public", Token::PUBLIC) \
+ KEYWORD_GROUP('r') \
+ KEYWORD("real", Token::REAL) \
+ KEYWORD("return", Token::RETURN) \
+ KEYWORD("returns", Token::RETURNS) \
+ 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) \
+ KEYWORD_GROUP('w') \
+ KEYWORD("while", Token::WHILE) \
+ KEYWORD("with", Token::WITH)
static Token::Value KeywordOrIdentifierToken(const std::string& input)
{
- BOOST_ASSERT(!input.empty());
- const int kMinLength = 2;
- const int kMaxLength = 10;
- if (input.size() < kMinLength || input.size() > kMaxLength) {
- return Token::IDENTIFIER;
- }
- switch (input[0]) {
+ BOOST_ASSERT(!input.empty());
+ const int kMinLength = 2;
+ const int kMaxLength = 10;
+ if (input.size() < kMinLength || input.size() > kMaxLength)
+ return Token::IDENTIFIER;
+ switch (input[0])
+ {
default:
#define KEYWORD_GROUP_CASE(ch) \
- break; \
- case ch:
+ break; \
+case ch:
#define KEYWORD(keyword, token) \
{ \
- /* 'keyword' is a char array, so sizeof(keyword) is */ \
- /* strlen(keyword) plus 1 for the NUL char. */ \
- const int keyword_length = sizeof(keyword) - 1; \
- BOOST_STATIC_ASSERT(keyword_length >= kMinLength); \
- BOOST_STATIC_ASSERT(keyword_length <= kMaxLength); \
- if (input == keyword) { \
- return token; \
- } \
+ /* 'keyword' is a char array, so sizeof(keyword) is */ \
+ /* strlen(keyword) plus 1 for the NUL char. */ \
+ const int keyword_length = sizeof(keyword) - 1; \
+ BOOST_STATIC_ASSERT(keyword_length >= kMinLength); \
+ BOOST_STATIC_ASSERT(keyword_length <= kMaxLength); \
+ if (input == keyword) { \
+ return token; \
+ } \
}
- KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD)
- }
- return Token::IDENTIFIER;
+ KEYWORDS(KEYWORD_GROUP_CASE, KEYWORD)
+ }
+ return Token::IDENTIFIER;
}
Token::Value Scanner::scanIdentifierOrKeyword()
{
BOOST_ASSERT(IsIdentifierStart(m_char));
LiteralScope literal(this);
-
addLiteralCharAndAdvance();
-
// Scan the rest of the identifier characters.
while (IsIdentifierPart(m_char))
addLiteralCharAndAdvance();
-
literal.Complete();
-
return KeywordOrIdentifierToken(m_next_token.literal);
}
@@ -697,17 +674,17 @@ std::tuple<int, int> CharStream::translatePositionToLineColumn(int _position) co
using size_type = std::string::size_type;
size_type searchPosition = std::min<size_type>(m_source.size(), _position);
int lineNumber = std::count(m_source.begin(), m_source.begin() + searchPosition, '\n');
-
size_type lineStart;
- if (searchPosition == 0) {
+ if (searchPosition == 0)
lineStart = 0;
- } else {
+ else
+ {
lineStart = m_source.rfind('\n', searchPosition - 1);
lineStart = lineStart == std::string::npos ? 0 : lineStart + 1;
}
-
return std::tuple<int, int>(lineNumber, searchPosition - lineStart);
}
-} }
+}
+}
diff --git a/Scanner.h b/Scanner.h
index 4bc84111..ea7c6b71 100644
--- a/Scanner.h
+++ b/Scanner.h
@@ -50,33 +50,36 @@
#include <libsolidity/BaseTypes.h>
#include <libsolidity/Token.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
class AstRawString;
class AstValueFactory;
class ParserRecorder;
-class CharStream {
+class CharStream
+{
public:
CharStream()
: m_pos(0)
{}
- explicit CharStream(const std::string& _source)
- : m_source(_source), m_pos(0)
- {}
+ explicit CharStream(const std::string& _source) : m_source(_source), m_pos(0) {}
int getPos() const { return m_pos; }
bool isPastEndOfInput() const { return m_pos >= m_source.size(); }
char get() const { return m_source[m_pos]; }
- char advanceAndGet() {
+ char advanceAndGet()
+ {
if (isPastEndOfInput()) return 0;
++m_pos;
if (isPastEndOfInput()) return 0;
return get();
}
- char rollback(size_t _amount) {
+ char rollback(size_t _amount)
+ {
BOOST_ASSERT(m_pos >= _amount);
m_pos -= _amount;
return get();
@@ -96,22 +99,17 @@ private:
// ----------------------------------------------------------------------------
// JavaScript Scanner.
-class Scanner {
+class Scanner
+{
public:
// Scoped helper for literal recording. Automatically drops the literal
// if aborting the scanning before it's complete.
- class LiteralScope {
+ class LiteralScope
+ {
public:
- explicit LiteralScope(Scanner* self)
- : scanner_(self), complete_(false) {
- scanner_->startNewLiteral();
- }
- ~LiteralScope() {
- if (!complete_) scanner_->dropLiteral();
- }
- void Complete() {
- complete_ = true;
- }
+ explicit LiteralScope(Scanner* self) : scanner_(self), complete_(false) { scanner_->startNewLiteral(); }
+ ~LiteralScope() { if (!complete_) scanner_->dropLiteral(); }
+ void Complete() { complete_ = true; }
private:
Scanner* scanner_;
@@ -143,7 +141,10 @@ public:
/// Functions that help pretty-printing parse errors.
/// Do only use in error cases, they are quite expensive.
/// @{
- std::string getLineAtPosition(int _position) const { return m_source.getLineAtPosition(_position); }
+ std::string getLineAtPosition(int _position) const
+ {
+ return m_source.getLineAtPosition(_position);
+ }
std::tuple<int, int> translatePositionToLineColumn(int _position) const
{
return m_source.translatePositionToLineColumn(_position);
@@ -152,56 +153,46 @@ public:
// Returns true if there was a line terminator before the peek'ed token,
// possibly inside a multi-line comment.
- bool hasAnyLineTerminatorBeforeNext() const {
+ bool hasAnyLineTerminatorBeforeNext() const
+ {
return m_hasLineTerminatorBeforeNext ||
- m_hasMultilineCommentBeforeNext;
+ m_hasMultilineCommentBeforeNext;
}
private:
// Used for the current and look-ahead token.
- struct TokenDesc {
+ struct TokenDesc
+ {
Token::Value token;
Location location;
std::string literal;
};
// Literal buffer support
- inline void startNewLiteral() {
- m_next_token.literal.clear();
- }
+ inline void startNewLiteral() { m_next_token.literal.clear(); }
- inline void addLiteralChar(char c) {
- m_next_token.literal.push_back(c);
- }
+ inline void addLiteralChar(char c) { m_next_token.literal.push_back(c); }
- inline void dropLiteral() {
- m_next_token.literal.clear();
- }
+ inline void dropLiteral() { m_next_token.literal.clear(); }
- inline void addLiteralCharAndAdvance() {
- addLiteralChar(m_char);
- advance();
- }
+ inline void addLiteralCharAndAdvance() { addLiteralChar(m_char); advance(); }
// Low-level scanning support.
bool advance() { m_char = m_source.advanceAndGet(); return !m_source.isPastEndOfInput(); }
- void rollback(int amount) {
- m_char = m_source.rollback(amount);
- }
+ void rollback(int amount) { m_char = m_source.rollback(amount); }
- inline Token::Value selectToken(Token::Value tok) {
- advance();
- return tok;
- }
+ inline Token::Value selectToken(Token::Value tok) { advance(); return tok; }
- inline Token::Value selectToken(char next, Token::Value then, Token::Value else_) {
+ inline Token::Value selectToken(char next, Token::Value then, Token::Value else_)
+ {
advance();
- if (m_char == next) {
+ if (m_char == next)
+ {
advance();
return then;
- } else {
- return else_;
}
+ else
+ return else_;
}
bool scanHexNumber(char& scanned_number, int expected_length);
@@ -225,12 +216,8 @@ private:
bool scanEscape();
// Return the current source position.
- int getSourcePos() {
- return m_source.getPos();
- }
- bool isSourcePastEndOfInput() {
- return m_source.isPastEndOfInput();
- }
+ int getSourcePos() { return m_source.getPos(); }
+ bool isSourcePastEndOfInput() { return m_source.isPastEndOfInput(); }
TokenDesc m_current_token; // desc for current token (as returned by Next())
TokenDesc m_next_token; // desc for next token (one token look-ahead)
@@ -249,4 +236,5 @@ private:
bool m_hasMultilineCommentBeforeNext;
};
-} }
+}
+}
diff --git a/Scope.cpp b/Scope.cpp
index 27298f87..7c298b72 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -23,8 +23,10 @@
#include <libsolidity/Scope.h>
#include <libsolidity/AST.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
bool Scope::registerDeclaration(Declaration& _declaration)
@@ -35,7 +37,7 @@ bool Scope::registerDeclaration(Declaration& _declaration)
return true;
}
-Declaration*Scope::resolveName(ASTString const& _name, bool _recursive) const
+Declaration* Scope::resolveName(ASTString const& _name, bool _recursive) const
{
auto result = m_declarations.find(_name);
if (result != m_declarations.end())
@@ -45,4 +47,5 @@ Declaration*Scope::resolveName(ASTString const& _name, bool _recursive) const
return nullptr;
}
-} }
+}
+}
diff --git a/Scope.h b/Scope.h
index e3b024ec..b3686ec0 100644
--- a/Scope.h
+++ b/Scope.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -28,8 +28,10 @@
#include <libsolidity/ASTForward.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
class Scope
{
@@ -46,4 +48,5 @@ private:
std::map<ASTString, Declaration*> m_declarations;
};
-} }
+}
+}
diff --git a/Token.cpp b/Token.cpp
index 0264f7e8..564be734 100644
--- a/Token.cpp
+++ b/Token.cpp
@@ -42,25 +42,30 @@
#include <libsolidity/Token.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
#define T(name, string, precedence) #name,
-const char* const Token::m_name[NUM_TOKENS] = {
+const char* const Token::m_name[NUM_TOKENS] =
+{
TOKEN_LIST(T, T)
};
#undef T
#define T(name, string, precedence) string,
-const char* const Token::m_string[NUM_TOKENS] = {
+const char* const Token::m_string[NUM_TOKENS] =
+{
TOKEN_LIST(T, T)
};
#undef T
#define T(name, string, precedence) precedence,
-const int8_t Token::m_precedence[NUM_TOKENS] = {
+const int8_t Token::m_precedence[NUM_TOKENS] =
+{
TOKEN_LIST(T, T)
};
#undef T
@@ -68,10 +73,12 @@ const int8_t Token::m_precedence[NUM_TOKENS] = {
#define KT(a, b, c) 'T',
#define KK(a, b, c) 'K',
-const char Token::m_tokenType[] = {
+const char Token::m_tokenType[] =
+{
TOKEN_LIST(KT, KK)
};
#undef KT
#undef KK
-} }
+}
+}
diff --git a/Token.h b/Token.h
index d1db4134..9e389667 100644
--- a/Token.h
+++ b/Token.h
@@ -47,8 +47,10 @@
#include <libdevcore/Common.h>
#include <libdevcore/Log.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
// TOKEN_LIST takes a list of 3 macros M, all of which satisfy the
// same signature M(name, string, precedence), where name is the
@@ -68,7 +70,7 @@ namespace solidity {
#define TOKEN_LIST(T, K) \
/* End of source indicator. */ \
T(EOS, "EOS", 0) \
- \
+ \
/* Punctuators (ECMA-262, section 7.7, page 15). */ \
T(LPAREN, "(", 0) \
T(RPAREN, ")", 0) \
@@ -83,7 +85,7 @@ namespace solidity {
T(INC, "++", 0) \
T(DEC, "--", 0) \
T(ARROW, "=>", 0) \
- \
+ \
/* Assignment operators. */ \
/* IsAssignmentOp() and Assignment::is_compound() relies on */ \
/* this block of enum values being contiguous and sorted in the */ \
@@ -105,7 +107,7 @@ namespace solidity {
T(ASSIGN_MUL, "*=", 2) \
T(ASSIGN_DIV, "/=", 2) \
T(ASSIGN_MOD, "%=", 2) \
- \
+ \
/* Binary operators sorted by precedence. */ \
/* IsBinaryOp() relies on this block of enum values */ \
/* being contiguous and sorted in the same order! */ \
@@ -123,7 +125,7 @@ namespace solidity {
T(MUL, "*", 13) \
T(DIV, "/", 13) \
T(MOD, "%", 13) \
- \
+ \
/* Compare operators sorted by precedence. */ \
/* IsCompareOp() relies on this block of enum values */ \
/* being contiguous and sorted in the same order! */ \
@@ -137,7 +139,7 @@ namespace solidity {
T(GTE, ">=", 10) \
K(INSTANCEOF, "instanceof", 10) \
K(IN, "in", 10) \
- \
+ \
/* Unary operators. */ \
/* IsUnaryOp() relies on this block of enum values */ \
/* being contiguous and sorted in the same order! */ \
@@ -146,7 +148,7 @@ namespace solidity {
K(DELETE, "delete", 0) \
K(TYPEOF, "typeof", 0) \
K(VOID, "void", 0) \
- \
+ \
/* Keywords (ECMA-262, section 7.5.2, page 13). */ \
K(BREAK, "break", 0) \
K(CASE, "case", 0) \
@@ -180,7 +182,7 @@ namespace solidity {
/* VOID */ \
K(WHILE, "while", 0) \
K(WITH, "with", 0) \
- \
+ \
/* type keywords, keep them in this order, keep int as first keyword
* the implementation in Types.cpp has to be synced to this here
* TODO more to be added */ \
@@ -206,17 +208,17 @@ namespace solidity {
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_LITERAL, NULL, 0) \
- \
+ \
/* Identifiers (not keywords or future reserved words). */ \
T(IDENTIFIER, NULL, 0) \
- \
+ \
/* Future reserved words (ECMA-262, section 7.6.1.2). */ \
T(FUTURE_RESERVED_WORD, NULL, 0) \
T(FUTURE_STRICT_RESERVED_WORD, NULL, 0) \
@@ -227,21 +229,23 @@ namespace solidity {
K(IMPORT, "import", 0) \
K(LET, "let", 0) \
K(STATIC, "static", 0) \
-/* K(YIELD, "yield", 0) */ \
+ /* K(YIELD, "yield", 0) */ \
K(SUPER, "super", 0) \
- \
+ \
/* Illegal token - not able to scan. */ \
T(ILLEGAL, "ILLEGAL", 0) \
- \
+ \
/* Scanner-internal use only. */ \
T(WHITESPACE, NULL, 0)
-class Token {
+class Token
+{
public:
// All token values.
#define T(name, string, precedence) name,
- enum Value {
+ enum Value
+ {
TOKEN_LIST(T, T)
NUM_TOKENS
};
@@ -249,123 +253,110 @@ public:
// Returns a string corresponding to the C++ token name
// (e.g. "LT" for the token LT).
- static const char* Name(Value tok) {
+ static const char* getName(Value tok)
+ {
BOOST_ASSERT(tok < NUM_TOKENS); // tok is unsigned
return m_name[tok];
}
// Predicates
- static bool IsKeyword(Value tok) {
- return m_tokenType[tok] == 'K';
- }
-
- static bool IsIdentifier(Value tok) {
- 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;
- }
-
- static bool IsBinaryOp(Value op) {
- return COMMA <= op && op <= MOD;
- }
-
- static bool IsTruncatingBinaryOp(Value op) {
- return BIT_OR <= op && op <= SHR;
- }
-
- static bool IsCompareOp(Value op) {
- return EQ <= op && op <= IN;
- }
-
- static bool IsOrderedRelationalCompareOp(Value op) {
+ static bool isKeyword(Value tok) { return m_tokenType[tok] == 'K'; }
+ static bool isIdentifier(Value tok) { 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; }
+ static bool isBinaryOp(Value op) { return COMMA <= op && op <= MOD; }
+ static bool isTruncatingBinaryOp(Value op) { return BIT_OR <= op && op <= SHR; }
+ static bool isCompareOp(Value op) { return EQ <= op && op <= IN; }
+ static bool isOrderedRelationalCompareOp(Value op)
+ {
return op == LT || op == LTE || op == GT || op == GTE;
}
-
- static bool IsEqualityOp(Value op) {
- return op == EQ || op == EQ_STRICT;
- }
-
- static bool IsInequalityOp(Value op) {
- return op == NE || op == NE_STRICT;
+ static bool isEqualityOp(Value op) { return op == EQ || op == EQ_STRICT; }
+ static bool isInequalityOp(Value op) { return op == NE || op == NE_STRICT; }
+ static bool isArithmeticCompareOp(Value op)
+ {
+ return isOrderedRelationalCompareOp(op) ||
+ isEqualityOp(op) || isInequalityOp(op);
}
- static bool IsArithmeticCompareOp(Value op) {
- return IsOrderedRelationalCompareOp(op) ||
- IsEqualityOp(op) || IsInequalityOp(op);
- }
-
- static Value NegateCompareOp(Value op) {
- BOOST_ASSERT(IsArithmeticCompareOp(op));
- switch (op) {
- case EQ: return NE;
- case NE: return EQ;
- case EQ_STRICT: return NE_STRICT;
- case NE_STRICT: return EQ_STRICT;
- case LT: return GTE;
- case GT: return LTE;
- case LTE: return GT;
- case GTE: return LT;
+ static Value negateCompareOp(Value op)
+ {
+ BOOST_ASSERT(isArithmeticCompareOp(op));
+ switch (op)
+ {
+ case EQ:
+ return NE;
+ case NE:
+ return EQ;
+ case EQ_STRICT:
+ return NE_STRICT;
+ case NE_STRICT:
+ return EQ_STRICT;
+ case LT:
+ return GTE;
+ case GT:
+ return LTE;
+ case LTE:
+ return GT;
+ case GTE:
+ return LT;
default:
BOOST_ASSERT(false); // should not get here
return op;
}
}
- static Value ReverseCompareOp(Value op) {
- BOOST_ASSERT(IsArithmeticCompareOp(op));
- switch (op) {
- case EQ: return EQ;
- case NE: return NE;
- case EQ_STRICT: return EQ_STRICT;
- case NE_STRICT: return NE_STRICT;
- case LT: return GT;
- case GT: return LT;
- case LTE: return GTE;
- case GTE: return LTE;
+ static Value reverseCompareOp(Value op)
+ {
+ BOOST_ASSERT(isArithmeticCompareOp(op));
+ switch (op)
+ {
+ case EQ:
+ return EQ;
+ case NE:
+ return NE;
+ case EQ_STRICT:
+ return EQ_STRICT;
+ case NE_STRICT:
+ return NE_STRICT;
+ case LT:
+ return GT;
+ case GT:
+ return LT;
+ case LTE:
+ return GTE;
+ case GTE:
+ return LTE;
default:
BOOST_ASSERT(false); // should not get here
return op;
}
}
- static Value AssignmentToBinaryOp(Value op) {
- BOOST_ASSERT(IsAssignmentOp(op) && op != ASSIGN);
+ static Value AssignmentToBinaryOp(Value op)
+ {
+ BOOST_ASSERT(isAssignmentOp(op) && op != ASSIGN);
return Token::Value(op + (BIT_OR - ASSIGN_BIT_OR));
}
- static bool IsBitOp(Value op) {
- return (BIT_OR <= op && op <= SHR) || op == BIT_NOT;
- }
-
- static bool IsUnaryOp(Value op) {
- return (NOT <= op && op <= VOID) || op == ADD || op == SUB;
- }
-
- static bool IsCountOp(Value op) {
- return op == INC || op == DEC;
- }
-
- static bool IsShiftOp(Value op) {
- return (SHL <= op) && (op <= SHR);
- }
+ static bool isBitOp(Value op) { return (BIT_OR <= op && op <= SHR) || op == BIT_NOT; }
+ static bool isUnaryOp(Value op) { return (NOT <= op && op <= VOID) || op == ADD || op == SUB; }
+ static bool isCountOp(Value op) { return op == INC || op == DEC; }
+ static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); }
// Returns a string corresponding to the JS token string
// (.e., "<" for the token LT) or NULL if the token doesn't
// have a (unique) string (e.g. an IDENTIFIER).
- static const char* String(Value tok) {
+ static const char* toString(Value tok)
+ {
BOOST_ASSERT(tok < NUM_TOKENS); // tok is unsigned.
return m_string[tok];
}
// Returns the precedence > 0 for binary and compare
// operators; returns 0 otherwise.
- static int Precedence(Value tok) {
+ static int precedence(Value tok)
+ {
BOOST_ASSERT(tok < NUM_TOKENS); // tok is unsigned.
return m_precedence[tok];
}
@@ -377,4 +368,5 @@ private:
static const char m_tokenType[NUM_TOKENS];
};
-} }
+}
+}
diff --git a/Types.cpp b/Types.cpp
index 8e8a9d97..c5ee40cb 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -23,12 +23,15 @@
#include <libsolidity/Types.h>
#include <libsolidity/AST.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
ptr<Type> Type::fromElementaryTypeName(Token::Value _typeToken)
{
- if (Token::INT <= _typeToken && _typeToken <= Token::HASH256) {
+ if (Token::INT <= _typeToken && _typeToken <= Token::HASH256)
+ {
int offset = _typeToken - Token::INT;
int bits = offset % 5;
if (bits == 0)
@@ -39,15 +42,14 @@ ptr<Type> Type::fromElementaryTypeName(Token::Value _typeToken)
return std::make_shared<IntegerType>(bits,
modifier == 0 ? IntegerType::Modifier::SIGNED :
modifier == 1 ? IntegerType::Modifier::UNSIGNED :
- IntegerType::Modifier::HASH);
- } else if (_typeToken == Token::ADDRESS) {
+ IntegerType::Modifier::HASH);
+ }
+ else if (_typeToken == Token::ADDRESS)
return std::make_shared<IntegerType>(0, IntegerType::Modifier::ADDRESS);
- } else if (_typeToken == Token::BOOL) {
+ else if (_typeToken == Token::BOOL)
return std::make_shared<BoolType>();
- } else {
- BOOST_ASSERT(false);
- // @todo add other tyes
- }
+ else
+ BOOST_ASSERT(false); // @todo add other tyes
}
ptr<Type> Type::fromUserDefinedTypeName(const UserDefinedTypeName& _typeName)
@@ -63,7 +65,8 @@ ptr<Type> Type::fromMapping(const Mapping&)
ptr<Type> Type::forLiteral(const Literal& _literal)
{
- switch (_literal.getToken()) {
+ switch (_literal.getToken())
+ {
case Token::TRUE_LITERAL:
case Token::FALSE_LITERAL:
return std::make_shared<BoolType>();
@@ -114,13 +117,12 @@ bool IntegerType::isExplicitlyConvertibleTo(const Type& _convertTo) const
bool IntegerType::acceptsBinaryOperator(Token::Value _operator) const
{
- if (isAddress()) {
- return Token::IsCompareOp(_operator);
- } else if (isHash()) {
- return Token::IsCompareOp(_operator) || Token::IsBitOp(_operator);
- } else {
+ if (isAddress())
+ return Token::isCompareOp(_operator);
+ else if (isHash())
+ return Token::isCompareOp(_operator) || Token::isBitOp(_operator);
+ else
return true;
- }
}
bool IntegerType::acceptsUnaryOperator(Token::Value _operator) const
@@ -132,7 +134,8 @@ bool BoolType::isExplicitlyConvertibleTo(const Type& _convertTo) const
{
// conversion to integer is fine, but not to address
// this is an example of explicit conversions being not transitive (though implicit should be)
- if (_convertTo.getCategory() == Category::INTEGER) {
+ if (_convertTo.getCategory() == Category::INTEGER)
+ {
IntegerType const& convertTo = dynamic_cast<IntegerType const&>(_convertTo);
if (!convertTo.isAddress())
return true;
@@ -157,4 +160,5 @@ bool StructType::isImplicitlyConvertibleTo(const Type& _convertTo) const
}
-} }
+}
+}
diff --git a/Types.h b/Types.h
index f73357a2..aed8a7e7 100644
--- a/Types.h
+++ b/Types.h
@@ -1,18 +1,18 @@
/*
- This file is part of cpp-ethereum.
+ 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 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.
+ 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/>.
+ 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>
@@ -29,8 +29,10 @@
#include <libsolidity/Token.h>
-namespace dev {
-namespace solidity {
+namespace dev
+{
+namespace solidity
+{
// AST forward declarations
class ContractDefinition;
@@ -49,7 +51,8 @@ using ptr = std::shared_ptr<T>;
class Type : private boost::noncopyable
{
public:
- enum class Category {
+ enum class Category
+ {
INTEGER, BOOL, REAL, STRING, CONTRACT, STRUCT, FUNCTION, MAPPING, VOID, TYPE
};
@@ -62,7 +65,10 @@ public:
virtual Category getCategory() const = 0;
virtual bool isImplicitlyConvertibleTo(const Type&) const { return false; }
- virtual bool isExplicitlyConvertibleTo(const Type& _convertTo) const { return isImplicitlyConvertibleTo(_convertTo); }
+ virtual bool isExplicitlyConvertibleTo(const Type& _convertTo) const
+ {
+ return isImplicitlyConvertibleTo(_convertTo);
+ }
virtual bool acceptsBinaryOperator(Token::Value) const { return false; }
virtual bool acceptsUnaryOperator(Token::Value) const { return false; }
};
@@ -70,7 +76,8 @@ public:
class IntegerType : public Type
{
public:
- enum class Modifier {
+ enum class Modifier
+ {
UNSIGNED, SIGNED, HASH, ADDRESS
};
virtual Category getCategory() const { return Category::INTEGER; }
@@ -98,12 +105,18 @@ class BoolType : public Type
public:
virtual Category getCategory() const { return Category::BOOL; }
virtual bool isImplicitlyConvertibleTo(const Type& _convertTo) const override
- { return _convertTo.getCategory() == Category::BOOL; }
+ {
+ return _convertTo.getCategory() == Category::BOOL;
+ }
virtual bool isExplicitlyConvertibleTo(const Type& _convertTo) const override;
virtual bool acceptsBinaryOperator(Token::Value _operator) const override
- { return _operator == Token::AND || _operator == Token::OR; }
+ {
+ return _operator == Token::AND || _operator == Token::OR;
+ }
virtual bool acceptsUnaryOperator(Token::Value _operator) const override
- { return _operator == Token::NOT || _operator == Token::DELETE; }
+ {
+ return _operator == Token::NOT || _operator == Token::DELETE;
+ }
};
class ContractType : public Type
@@ -123,7 +136,9 @@ public:
StructType(StructDefinition const& _struct) : m_struct(_struct) {}
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const;
virtual bool acceptsUnaryOperator(Token::Value _operator) const override
- { return _operator == Token::DELETE; }
+ {
+ return _operator == Token::DELETE;
+ }
private:
StructDefinition const& m_struct;
};
@@ -168,4 +183,5 @@ private:
};
-} }
+}
+}