Isolating files shared between Yul- and Solidity language frontend.

This commit is contained in:
Christian Parpart
2018-11-21 18:58:12 +00:00
committed by Alex Beregszaszi
parent d47707abad
commit 87821c53c3
101 changed files with 135 additions and 132 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
# Until we have a clear separation, libyul has to be included here
file(GLOB_RECURSE sources "*.cpp" "../libyul/*.cpp")
file(GLOB_RECURSE headers "*.h" "../libyul/*.h")
file(GLOB_RECURSE sources "*.cpp" "../libyul/*.cpp" "../liblangutil/*.cpp")
file(GLOB_RECURSE headers "*.h" "../libyul/*.h" "../liblangutil/*.h")
find_package(Z3 QUIET)
if (${Z3_FOUND})
+1 -1
View File
@@ -22,7 +22,7 @@
#include <libsolidity/analysis/ConstantEvaluator.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
using namespace std;
using namespace dev;
+1 -1
View File
@@ -19,7 +19,7 @@
#include <libsolidity/ast/AST.h>
#include <libsolidity/ast/ASTVisitor.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <map>
#include <memory>
+1 -1
View File
@@ -23,7 +23,7 @@
#include <libsolidity/analysis/DocStringAnalyser.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <libsolidity/parsing/DocStringParser.h>
using namespace std;
+1 -1
View File
@@ -24,7 +24,7 @@
#include <libsolidity/ast/AST.h>
#include <libsolidity/analysis/TypeChecker.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <libdevcore/StringUtils.h>
#include <boost/algorithm/string.hpp>
+1 -1
View File
@@ -18,7 +18,7 @@
#include <libsolidity/analysis/PostTypeChecker.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/analysis/SemVerHandler.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <libsolidity/interface/Version.h>
#include <libdevcore/Algorithms.h>
+2 -2
View File
@@ -23,12 +23,12 @@
#include <libsolidity/analysis/ReferencesResolver.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/analysis/NameAndTypeResolver.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <libsolidity/analysis/ConstantEvaluator.h>
#include <libsolidity/inlineasm/AsmAnalysis.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
#include <libsolidity/inlineasm/AsmData.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <libdevcore/StringUtils.h>
+1 -1
View File
@@ -23,7 +23,7 @@
#pragma once
#include <vector>
#include <libsolidity/parsing/Token.h>
#include <liblangutil/Token.h>
namespace dev
{
+1 -1
View File
@@ -23,7 +23,7 @@
#include <libsolidity/analysis/StaticAnalyzer.h>
#include <libsolidity/analysis/ConstantEvaluator.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <memory>
using namespace std;
+1 -1
View File
@@ -20,7 +20,7 @@
#include <libsolidity/ast/AST.h>
#include <libsolidity/ast/ExperimentalFeatures.h>
#include <libsolidity/analysis/SemVerHandler.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <libsolidity/interface/Version.h>
#include <boost/algorithm/cxx11/all_of.hpp>
+1 -1
View File
@@ -30,7 +30,7 @@
#include <libsolidity/inlineasm/AsmAnalysis.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
#include <libsolidity/inlineasm/AsmData.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <libdevcore/Algorithms.h>
using namespace std;
+1 -1
View File
@@ -22,7 +22,7 @@
#pragma once
#include <libsolidity/interface/EVMVersion.h>
#include <liblangutil/EVMVersion.h>
#include <libsolidity/ast/Types.h>
#include <libsolidity/ast/ASTAnnotations.h>
+1 -1
View File
@@ -21,7 +21,7 @@
#include <libsolidity/ast/ASTForward.h>
#include <libsolidity/ast/ASTVisitor.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <map>
#include <memory>
+2 -2
View File
@@ -24,12 +24,12 @@
#include <libsolidity/ast/ASTForward.h>
#include <libsolidity/parsing/Token.h>
#include <liblangutil/Token.h>
#include <libsolidity/ast/Types.h>
#include <libsolidity/ast/ASTAnnotations.h>
#include <libsolidity/ast/ASTEnums.h>
#include <libevmasm/SourceLocation.h>
#include <liblangutil/SourceLocation.h>
#include <libevmasm/Instruction.h>
#include <libdevcore/FixedHash.h>
+1 -1
View File
@@ -21,7 +21,7 @@
#pragma once
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <string>
+1 -1
View File
@@ -25,7 +25,7 @@
#include <ostream>
#include <stack>
#include <libsolidity/ast/ASTVisitor.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <libsolidity/ast/ASTAnnotations.h>
#include <json/json.h>
+2 -2
View File
@@ -22,10 +22,10 @@
#pragma once
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <libsolidity/ast/ASTForward.h>
#include <libsolidity/ast/ASTEnums.h>
#include <libsolidity/parsing/Token.h>
#include <liblangutil/Token.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
+1 -1
View File
@@ -22,7 +22,7 @@
#pragma once
#include <libsolidity/interface/EVMVersion.h>
#include <liblangutil/EVMVersion.h>
#include <libsolidity/ast/ASTForward.h>
+1 -1
View File
@@ -25,7 +25,7 @@
#include <libsolidity/codegen/CompilerContext.h>
#include <libsolidity/codegen/CompilerUtils.h>
#include <libsolidity/ast/Types.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <libsolidity/codegen/LValue.h>
using namespace std;
+1 -1
View File
@@ -23,7 +23,7 @@
#pragma once
#include <libsolidity/codegen/CompilerContext.h>
#include <libsolidity/interface/EVMVersion.h>
#include <liblangutil/EVMVersion.h>
#include <libevmasm/Assembly.h>
+2 -2
View File
@@ -25,9 +25,9 @@
#include <libsolidity/ast/AST.h>
#include <libsolidity/codegen/Compiler.h>
#include <libsolidity/interface/Version.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <libsolidity/interface/SourceReferenceFormatter.h>
#include <libsolidity/parsing/Scanner.h>
#include <liblangutil/Scanner.h>
#include <libsolidity/inlineasm/AsmParser.h>
#include <libsolidity/inlineasm/AsmCodeGen.h>
#include <libsolidity/inlineasm/AsmAnalysis.h>
+1 -1
View File
@@ -24,7 +24,7 @@
#include <libsolidity/codegen/ABIFunctions.h>
#include <libsolidity/interface/EVMVersion.h>
#include <liblangutil/EVMVersion.h>
#include <libsolidity/ast/ASTForward.h>
#include <libsolidity/ast/Types.h>
+1 -1
View File
@@ -23,7 +23,7 @@
#include <libsolidity/codegen/ContractCompiler.h>
#include <libsolidity/inlineasm/AsmCodeGen.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <libsolidity/codegen/ExpressionCompiler.h>
#include <libsolidity/codegen/CompilerUtils.h>
+2 -2
View File
@@ -25,10 +25,10 @@
#include <memory>
#include <boost/noncopyable.hpp>
#include <libdevcore/Common.h>
#include <libevmasm/SourceLocation.h>
#include <liblangutil/SourceLocation.h>
#include <libsolidity/ast/ASTVisitor.h>
#include <libsolidity/codegen/LValue.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
namespace dev {
namespace eth
+1 -1
View File
@@ -24,7 +24,7 @@
#include <memory>
#include <vector>
#include <libevmasm/SourceLocation.h>
#include <liblangutil/SourceLocation.h>
#include <libsolidity/codegen/ArrayUtils.h>
namespace dev
+1 -1
View File
@@ -17,7 +17,7 @@
#include <libsolidity/formal/CVC4Interface.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <libdevcore/CommonIO.h>
+1 -1
View File
@@ -22,7 +22,7 @@
#include <libsolidity/formal/VariableUsage.h>
#include <libsolidity/formal/SymbolicTypes.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <boost/range/adaptor/map.hpp>
#include <boost/algorithm/string/replace.hpp>
+1 -1
View File
@@ -25,7 +25,7 @@
#include <libsolidity/interface/ReadFile.h>
#include <libsolidity/parsing/Scanner.h>
#include <liblangutil/Scanner.h>
#include <unordered_map>
#include <string>
+1 -1
View File
@@ -17,7 +17,7 @@
#include <libsolidity/formal/SMTLib2Interface.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <libsolidity/interface/ReadFile.h>
#include <boost/algorithm/string/predicate.hpp>
+1 -1
View File
@@ -19,7 +19,7 @@
#include <libsolidity/formal/SolverInterface.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <libsolidity/interface/ReadFile.h>
#include <libdevcore/Common.h>
+1 -1
View File
@@ -17,7 +17,7 @@
#pragma once
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <libsolidity/interface/ReadFile.h>
#include <libdevcore/Common.h>
+1 -1
View File
@@ -17,7 +17,7 @@
#include <libsolidity/formal/Z3Interface.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <libdevcore/CommonIO.h>
+1 -1
View File
@@ -25,7 +25,7 @@
#include <libsolidity/inlineasm/AsmScope.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/algorithm/string.hpp>
+2 -2
View File
@@ -20,8 +20,8 @@
#pragma once
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/interface/EVMVersion.h>
#include <liblangutil/Exceptions.h>
#include <liblangutil/EVMVersion.h>
#include <libsolidity/inlineasm/AsmScope.h>
+1 -1
View File
@@ -29,7 +29,7 @@
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
#include <libevmasm/Assembly.h>
#include <libevmasm/SourceLocation.h>
#include <liblangutil/SourceLocation.h>
#include <libevmasm/Instruction.h>
#include <libyul/backends/evm/AbstractAssembly.h>
+1 -1
View File
@@ -25,7 +25,7 @@
#include <libsolidity/inlineasm/AsmDataForward.h>
#include <libevmasm/Instruction.h>
#include <libevmasm/SourceLocation.h>
#include <liblangutil/SourceLocation.h>
#include <libyul/YulString.h>
+2 -2
View File
@@ -21,8 +21,8 @@
*/
#include <libsolidity/inlineasm/AsmParser.h>
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/Scanner.h>
#include <liblangutil/ErrorReporter.h>
#include <boost/algorithm/string.hpp>
+1 -1
View File
@@ -25,7 +25,7 @@
#include <memory>
#include <vector>
#include <libsolidity/inlineasm/AsmData.h>
#include <libsolidity/parsing/ParserBase.h>
#include <liblangutil/ParserBase.h>
namespace dev
{
+1 -1
View File
@@ -22,7 +22,7 @@
#include <libsolidity/inlineasm/AsmPrinter.h>
#include <libsolidity/inlineasm/AsmData.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <libdevcore/CommonData.h>
+1 -1
View File
@@ -20,7 +20,7 @@
#pragma once
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <libyul/YulString.h>
+2 -2
View File
@@ -24,8 +24,8 @@
#include <libsolidity/inlineasm/AsmScope.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/ErrorReporter.h>
#include <liblangutil/Exceptions.h>
#include <libdevcore/CommonData.h>
+1 -1
View File
@@ -22,7 +22,7 @@
#include <libsolidity/interface/AssemblyStack.h>
#include <libsolidity/parsing/Scanner.h>
#include <liblangutil/Scanner.h>
#include <libsolidity/inlineasm/AsmPrinter.h>
#include <libsolidity/inlineasm/AsmParser.h>
#include <libsolidity/inlineasm/AsmAnalysis.h>
+2 -2
View File
@@ -21,8 +21,8 @@
#pragma once
#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/interface/EVMVersion.h>
#include <liblangutil/ErrorReporter.h>
#include <liblangutil/EVMVersion.h>
#include <libevmasm/LinkerObject.h>
+1 -1
View File
@@ -27,7 +27,7 @@
#include <libsolidity/interface/Version.h>
#include <libsolidity/analysis/SemVerHandler.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/parsing/Scanner.h>
#include <liblangutil/Scanner.h>
#include <libsolidity/parsing/Parser.h>
#include <libsolidity/analysis/ControlFlowAnalyzer.h>
#include <libsolidity/analysis/ControlFlowGraph.h>
+3 -3
View File
@@ -23,11 +23,11 @@
#pragma once
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
#include <libsolidity/interface/ReadFile.h>
#include <libsolidity/interface/EVMVersion.h>
#include <liblangutil/EVMVersion.h>
#include <libevmasm/SourceLocation.h>
#include <liblangutil/SourceLocation.h>
#include <libevmasm/LinkerObject.h>
#include <libdevcore/Common.h>
-94
View File
@@ -1,94 +0,0 @@
/*
This file is part of solidity.
solidity 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.
solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* EVM versioning.
*/
#pragma once
#include <string>
#include <boost/optional.hpp>
#include <boost/operators.hpp>
namespace dev
{
namespace solidity
{
/**
* A version specifier of the EVM we want to compile to.
* Defaults to the latest version.
*/
class EVMVersion:
boost::less_than_comparable<EVMVersion>,
boost::equality_comparable<EVMVersion>
{
public:
EVMVersion() {}
static EVMVersion homestead() { return {Version::Homestead}; }
static EVMVersion tangerineWhistle() { return {Version::TangerineWhistle}; }
static EVMVersion spuriousDragon() { return {Version::SpuriousDragon}; }
static EVMVersion byzantium() { return {Version::Byzantium}; }
static EVMVersion constantinople() { return {Version::Constantinople}; }
static boost::optional<EVMVersion> fromString(std::string const& _version)
{
for (auto const& v: {homestead(), tangerineWhistle(), spuriousDragon(), byzantium(), constantinople()})
if (_version == v.name())
return v;
return {};
}
bool operator==(EVMVersion const& _other) const { return m_version == _other.m_version; }
bool operator<(EVMVersion const& _other) const { return m_version < _other.m_version; }
std::string name() const
{
switch (m_version)
{
case Version::Homestead: return "homestead";
case Version::TangerineWhistle: return "tangerineWhistle";
case Version::SpuriousDragon: return "spuriousDragon";
case Version::Byzantium: return "byzantium";
case Version::Constantinople: return "constantinople";
}
return "INVALID";
}
/// Has the RETURNDATACOPY and RETURNDATASIZE opcodes.
bool supportsReturndata() const { return *this >= byzantium(); }
bool hasStaticCall() const { return *this >= byzantium(); }
bool hasBitwiseShifting() const { return *this >= constantinople(); }
bool hasCreate2() const { return *this >= constantinople(); }
/// Whether we have to retain the costs for the call opcode itself (false),
/// or whether we can just forward easily all remaining gas (true).
bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); }
private:
enum class Version { Homestead, TangerineWhistle, SpuriousDragon, Byzantium, Constantinople };
EVMVersion(Version _version): m_version(_version) {}
Version m_version = Version::Byzantium;
};
}
}
-226
View File
@@ -1,226 +0,0 @@
/*
This file is part of solidity.
solidity 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.
solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Rhett <roadriverrail@gmail.com>
* @date 2017
* Error helper class.
*/
#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/ast/AST.h>
#include <memory>
using namespace std;
using namespace dev;
using namespace dev::solidity;
ErrorReporter& ErrorReporter::operator=(ErrorReporter const& _errorReporter)
{
if (&_errorReporter == this)
return *this;
m_errorList = _errorReporter.m_errorList;
return *this;
}
void ErrorReporter::warning(string const& _description)
{
error(Error::Type::Warning, SourceLocation(), _description);
}
void ErrorReporter::warning(
SourceLocation const& _location,
string const& _description
)
{
error(Error::Type::Warning, _location, _description);
}
void ErrorReporter::warning(
SourceLocation const& _location,
string const& _description,
SecondarySourceLocation const& _secondaryLocation
)
{
error(Error::Type::Warning, _location, _secondaryLocation, _description);
}
void ErrorReporter::error(Error::Type _type, SourceLocation const& _location, string const& _description)
{
if (checkForExcessiveErrors(_type))
return;
auto err = make_shared<Error>(_type);
*err <<
errinfo_sourceLocation(_location) <<
errinfo_comment(_description);
m_errorList.push_back(err);
}
void ErrorReporter::error(Error::Type _type, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, string const& _description)
{
if (checkForExcessiveErrors(_type))
return;
auto err = make_shared<Error>(_type);
*err <<
errinfo_sourceLocation(_location) <<
errinfo_secondarySourceLocation(_secondaryLocation) <<
errinfo_comment(_description);
m_errorList.push_back(err);
}
bool ErrorReporter::checkForExcessiveErrors(Error::Type _type)
{
if (_type == Error::Type::Warning)
{
m_warningCount++;
if (m_warningCount == c_maxWarningsAllowed)
{
auto err = make_shared<Error>(Error::Type::Warning);
*err << errinfo_comment("There are more than 256 warnings. Ignoring the rest.");
m_errorList.push_back(err);
}
if (m_warningCount >= c_maxWarningsAllowed)
return true;
}
else
{
m_errorCount++;
if (m_errorCount > c_maxErrorsAllowed)
{
auto err = make_shared<Error>(Error::Type::Warning);
*err << errinfo_comment("There are more than 256 errors. Aborting.");
m_errorList.push_back(err);
BOOST_THROW_EXCEPTION(FatalError());
}
}
return false;
}
void ErrorReporter::fatalError(Error::Type _type, SourceLocation const& _location, string const& _description)
{
error(_type, _location, _description);
BOOST_THROW_EXCEPTION(FatalError());
}
ErrorList const& ErrorReporter::errors() const
{
return m_errorList;
}
void ErrorReporter::clear()
{
m_errorList.clear();
}
void ErrorReporter::declarationError(SourceLocation const& _location, SecondarySourceLocation const&_secondaryLocation, string const& _description)
{
error(
Error::Type::DeclarationError,
_location,
_secondaryLocation,
_description
);
}
void ErrorReporter::declarationError(SourceLocation const& _location, string const& _description)
{
error(
Error::Type::DeclarationError,
_location,
_description
);
}
void ErrorReporter::fatalDeclarationError(SourceLocation const& _location, std::string const& _description)
{
fatalError(
Error::Type::DeclarationError,
_location,
_description);
}
void ErrorReporter::parserError(SourceLocation const& _location, string const& _description)
{
error(
Error::Type::ParserError,
_location,
_description
);
}
void ErrorReporter::fatalParserError(SourceLocation const& _location, string const& _description)
{
fatalError(
Error::Type::ParserError,
_location,
_description
);
}
void ErrorReporter::syntaxError(SourceLocation const& _location, string const& _description)
{
error(
Error::Type::SyntaxError,
_location,
_description
);
}
void ErrorReporter::typeError(SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, string const& _description)
{
error(
Error::Type::TypeError,
_location,
_secondaryLocation,
_description
);
}
void ErrorReporter::typeError(SourceLocation const& _location, string const& _description)
{
error(
Error::Type::TypeError,
_location,
_description
);
}
void ErrorReporter::fatalTypeError(SourceLocation const& _location, string const& _description)
{
fatalError(Error::Type::TypeError,
_location,
_description
);
}
void ErrorReporter::docstringParsingError(string const& _description)
{
error(
Error::Type::DocstringParsingError,
SourceLocation(),
_description
);
}
-126
View File
@@ -1,126 +0,0 @@
/*
This file is part of solidity.
solidity 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.
solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Rhett <roadriverrail@gmail.com>
* @date 2017
* Error reporting helper class.
*/
#pragma once
#include <libsolidity/interface/Exceptions.h>
#include <libevmasm/SourceLocation.h>
namespace dev
{
namespace solidity
{
class ASTNode;
class ErrorReporter
{
public:
explicit ErrorReporter(ErrorList& _errors):
m_errorList(_errors) { }
ErrorReporter(ErrorReporter const& _errorReporter) noexcept:
m_errorList(_errorReporter.m_errorList) { }
ErrorReporter& operator=(ErrorReporter const& _errorReporter);
void warning(std::string const& _description);
void warning(SourceLocation const& _location, std::string const& _description);
void warning(
SourceLocation const& _location,
std::string const& _description,
SecondarySourceLocation const& _secondaryLocation
);
void error(
Error::Type _type,
SourceLocation const& _location,
std::string const& _description
);
void declarationError(
SourceLocation const& _location,
SecondarySourceLocation const& _secondaryLocation,
std::string const& _description
);
void declarationError(SourceLocation const& _location, std::string const& _description);
void fatalDeclarationError(SourceLocation const& _location, std::string const& _description);
void parserError(SourceLocation const& _location, std::string const& _description);
void fatalParserError(SourceLocation const& _location, std::string const& _description);
void syntaxError(SourceLocation const& _location, std::string const& _description);
void typeError(
SourceLocation const& _location,
SecondarySourceLocation const& _secondaryLocation = SecondarySourceLocation(),
std::string const& _description = std::string()
);
void typeError(SourceLocation const& _location, std::string const& _description);
void fatalTypeError(SourceLocation const& _location, std::string const& _description);
void docstringParsingError(std::string const& _description);
ErrorList const& errors() const;
void clear();
/// @returns true iff there is any error (ignores warnings).
bool hasErrors() const
{
return m_errorCount > 0;
}
private:
void error(Error::Type _type,
SourceLocation const& _location,
SecondarySourceLocation const& _secondaryLocation,
std::string const& _description = std::string());
void fatalError(Error::Type _type,
SourceLocation const& _location = SourceLocation(),
std::string const& _description = std::string());
// @returns true if error shouldn't be stored
bool checkForExcessiveErrors(Error::Type _type);
ErrorList& m_errorList;
unsigned m_errorCount = 0;
unsigned m_warningCount = 0;
const unsigned c_maxWarningsAllowed = 256;
const unsigned c_maxErrorsAllowed = 256;
};
}
}
-66
View File
@@ -1,66 +0,0 @@
/*
This file is part of solidity.
solidity 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.
solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Liana <liana@ethdev.com>
* @date 2015
* Solidity exception hierarchy.
*/
#include <libsolidity/interface/Exceptions.h>
using namespace std;
using namespace dev;
using namespace dev::solidity;
Error::Error(Type _type, SourceLocation const& _location, string const& _description):
m_type(_type)
{
switch(m_type)
{
case Type::DeclarationError:
m_typeName = "DeclarationError";
break;
case Type::DocstringParsingError:
m_typeName = "DocstringParsingError";
break;
case Type::ParserError:
m_typeName = "ParserError";
break;
case Type::SyntaxError:
m_typeName = "SyntaxError";
break;
case Type::TypeError:
m_typeName = "TypeError";
break;
case Type::Warning:
m_typeName = "Warning";
break;
}
if (!_location.isEmpty())
*this << errinfo_sourceLocation(_location);
if (!_description.empty())
*this << errinfo_comment(_description);
}
Error::Error(Error::Type _type, const std::string& _description, const SourceLocation& _location):
Error(_type)
{
if (!_location.isEmpty())
*this << errinfo_sourceLocation(_location);
*this << errinfo_comment(_description);
}
-132
View File
@@ -1,132 +0,0 @@
/*
This file is part of solidity.
solidity 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.
solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
* @date 2014
* Solidity exception hierarchy.
*/
#pragma once
#include <string>
#include <utility>
#include <libdevcore/Exceptions.h>
#include <libdevcore/Assertions.h>
#include <libevmasm/SourceLocation.h>
namespace dev
{
namespace solidity
{
class Error;
using ErrorList = std::vector<std::shared_ptr<Error const>>;
struct CompilerError: virtual Exception {};
struct InternalCompilerError: virtual Exception {};
struct FatalError: virtual Exception {};
struct UnimplementedFeatureError: virtual Exception{};
/// Assertion that throws an InternalCompilerError containing the given description if it is not met.
#define solAssert(CONDITION, DESCRIPTION) \
assertThrow(CONDITION, ::dev::solidity::InternalCompilerError, DESCRIPTION)
#define solUnimplementedAssert(CONDITION, DESCRIPTION) \
assertThrow(CONDITION, ::dev::solidity::UnimplementedFeatureError, DESCRIPTION)
#define solUnimplemented(DESCRIPTION) \
solUnimplementedAssert(false, DESCRIPTION)
class Error: virtual public Exception
{
public:
enum class Type
{
DeclarationError,
DocstringParsingError,
ParserError,
TypeError,
SyntaxError,
Warning
};
explicit Error(
Type _type,
SourceLocation const& _location = SourceLocation(),
std::string const& _description = std::string()
);
Error(Type _type, std::string const& _description, SourceLocation const& _location = SourceLocation());
Type type() const { return m_type; }
std::string const& typeName() const { return m_typeName; }
/// helper functions
static Error const* containsErrorOfType(ErrorList const& _list, Error::Type _type)
{
for (auto e: _list)
{
if (e->type() == _type)
return e.get();
}
return nullptr;
}
static bool containsOnlyWarnings(ErrorList const& _list)
{
for (auto e: _list)
{
if (e->type() != Type::Warning)
return false;
}
return true;
}
private:
Type m_type;
std::string m_typeName;
};
using errorSourceLocationInfo = std::pair<std::string, SourceLocation>;
class SecondarySourceLocation
{
public:
SecondarySourceLocation& append(std::string const& _errMsg, SourceLocation const& _sourceLocation)
{
infos.push_back(std::make_pair(_errMsg, _sourceLocation));
return *this;
}
/// Limits the number of secondary source locations to 32 and appends a notice to the
/// error message.
void limitSize(std::string& _message)
{
size_t occurrences = infos.size();
if (occurrences > 32)
{
infos.resize(32);
_message += " Truncated from " + std::to_string(occurrences) + " to the first 32 occurrences.";
}
}
std::vector<errorSourceLocationInfo> infos;
};
using errinfo_sourceLocation = boost::error_info<struct tag_sourceLocation, SourceLocation>;
using errinfo_secondarySourceLocation = boost::error_info<struct tag_secondarySourceLocation, SecondarySourceLocation>;
}
}
+1 -1
View File
@@ -22,7 +22,7 @@
#pragma once
#include <libsolidity/interface/EVMVersion.h>
#include <liblangutil/EVMVersion.h>
#include <libevmasm/GasMeter.h>
#include <libevmasm/Assembly.h>
@@ -21,8 +21,8 @@
*/
#include <libsolidity/interface/SourceReferenceFormatter.h>
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Scanner.h>
#include <liblangutil/Exceptions.h>
using namespace std;
@@ -25,7 +25,7 @@
#include <ostream>
#include <sstream>
#include <functional>
#include <libevmasm/SourceLocation.h>
#include <liblangutil/SourceLocation.h>
namespace dev
{
+1 -1
View File
@@ -24,7 +24,7 @@
#include <string>
#include <libdevcore/CommonData.h>
#include <libdevcore/Common.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/Exceptions.h>
#include <solidity/BuildInfo.h>
using namespace dev;
+2 -2
View File
@@ -1,7 +1,7 @@
#include <libsolidity/parsing/DocStringParser.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/interface/Exceptions.h>
#include <liblangutil/ErrorReporter.h>
#include <liblangutil/Exceptions.h>
#include <boost/range/irange.hpp>
#include <boost/range/algorithm.hpp>
+3 -3
View File
@@ -22,11 +22,11 @@
#include <cctype>
#include <vector>
#include <libevmasm/SourceLocation.h>
#include <liblangutil/SourceLocation.h>
#include <libsolidity/parsing/Parser.h>
#include <libsolidity/parsing/Scanner.h>
#include <liblangutil/Scanner.h>
#include <libsolidity/inlineasm/AsmParser.h>
#include <libsolidity/interface/ErrorReporter.h>
#include <liblangutil/ErrorReporter.h>
using namespace std;
+1 -1
View File
@@ -23,7 +23,7 @@
#pragma once
#include <libsolidity/ast/AST.h>
#include <libsolidity/parsing/ParserBase.h>
#include <liblangutil/ParserBase.h>
namespace dev
{
-115
View File
@@ -1,115 +0,0 @@
/*
This file is part of solidity.
solidity 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.
solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
* @date 2016
* Solidity parser shared functionality.
*/
#include <libsolidity/parsing/ParserBase.h>
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/interface/ErrorReporter.h>
using namespace std;
using namespace dev;
using namespace dev::solidity;
std::shared_ptr<string const> const& ParserBase::sourceName() const
{
return m_scanner->sourceName();
}
int ParserBase::position() const
{
return m_scanner->currentLocation().start;
}
int ParserBase::endPosition() const
{
return m_scanner->currentLocation().end;
}
Token ParserBase::currentToken() const
{
return m_scanner->currentToken();
}
Token ParserBase::peekNextToken() const
{
return m_scanner->peekNextToken();
}
std::string ParserBase::currentLiteral() const
{
return m_scanner->currentLiteral();
}
Token ParserBase::advance()
{
return m_scanner->next();
}
void ParserBase::expectToken(Token _value, bool _advance)
{
Token tok = m_scanner->currentToken();
if (tok != _value)
{
auto tokenName = [this](Token _token)
{
if (_token == Token::Identifier)
return string("identifier");
else if (_token == Token::EOS)
return string("end of source");
else if (TokenTraits::isReservedKeyword(_token))
return string("reserved keyword '") + TokenTraits::friendlyName(_token) + "'";
else if (TokenTraits::isElementaryTypeName(_token)) //for the sake of accuracy in reporting
{
ElementaryTypeNameToken elemTypeName = m_scanner->currentElementaryTypeNameToken();
return string("'") + elemTypeName.toString() + "'";
}
else
return string("'") + TokenTraits::friendlyName(_token) + "'";
};
fatalParserError(string("Expected ") + tokenName(_value) + string(" but got ") + tokenName(tok));
}
if (_advance)
m_scanner->next();
}
void ParserBase::increaseRecursionDepth()
{
m_recursionDepth++;
if (m_recursionDepth >= 2560)
fatalParserError("Maximum recursion depth reached during parsing.");
}
void ParserBase::decreaseRecursionDepth()
{
solAssert(m_recursionDepth > 0, "");
m_recursionDepth--;
}
void ParserBase::parserError(string const& _description)
{
m_errorReporter.parserError(SourceLocation(position(), endPosition(), sourceName()), _description);
}
void ParserBase::fatalParserError(string const& _description)
{
m_errorReporter.fatalParserError(SourceLocation(position(), endPosition(), sourceName()), _description);
}
-93
View File
@@ -1,93 +0,0 @@
/*
This file is part of solidity.
solidity 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.
solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @author Christian <c@ethdev.com>
* @date 2016
* Solidity parser shared functionality.
*/
#pragma once
#include <memory>
#include <libsolidity/parsing/Token.h>
namespace dev
{
namespace solidity
{
class ErrorReporter;
class Scanner;
class ParserBase
{
public:
explicit ParserBase(ErrorReporter& errorReporter): m_errorReporter(errorReporter) {}
std::shared_ptr<std::string const> const& sourceName() const;
protected:
/// Utility class that creates an error and throws an exception if the
/// recursion depth is too deep.
class RecursionGuard
{
public:
explicit RecursionGuard(ParserBase& _parser): m_parser(_parser)
{
m_parser.increaseRecursionDepth();
}
~RecursionGuard() { m_parser.decreaseRecursionDepth(); }
private:
ParserBase& m_parser;
};
/// Start position of the current token
int position() const;
/// End position of the current token
int endPosition() const;
///@{
///@name Helper functions
/// If current token value is not _value, throw exception otherwise advance token.
void expectToken(Token _value, bool _advance = true);
Token currentToken() const;
Token peekNextToken() const;
std::string currentLiteral() const;
Token advance();
///@}
/// Increases the recursion depth and throws an exception if it is too deep.
void increaseRecursionDepth();
void decreaseRecursionDepth();
/// Creates a @ref ParserError and annotates it with the current position and the
/// given @a _description.
void parserError(std::string const& _description);
/// Creates a @ref ParserError and annotates it with the current position and the
/// given @a _description. Throws the FatalError.
void fatalParserError(std::string const& _description);
std::shared_ptr<Scanner> m_scanner;
/// The reference to the list of errors and warning to add errors/warnings during parsing
ErrorReporter& m_errorReporter;
/// Current recursion depth during parsing.
size_t m_recursionDepth = 0;
};
}
}
-920
View File
@@ -1,920 +0,0 @@
/*
This file is part of solidity.
solidity 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.
solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
This file is derived from the file "scanner.cc", which was part of the
V8 project. The original copyright header follows:
Copyright 2006-2012, the V8 project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @author Christian <c@ethdev.com>
* @date 2014
* Solidity scanner.
*/
#include <algorithm>
#include <tuple>
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/parsing/Scanner.h>
using namespace std;
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' || c == '\r';
}
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;
}
} // end anonymous namespace
/// Scoped helper for literal recording. Automatically drops the literal
/// if aborting the scanning before it's complete.
enum LiteralType {
LITERAL_TYPE_STRING,
LITERAL_TYPE_NUMBER, // not really different from string type in behaviour
LITERAL_TYPE_COMMENT
};
class LiteralScope
{
public:
explicit LiteralScope(Scanner* _self, enum LiteralType _type): m_type(_type)
, m_scanner(_self)
, m_complete(false)
{
if (_type == LITERAL_TYPE_COMMENT)
m_scanner->m_nextSkippedComment.literal.clear();
else
m_scanner->m_nextToken.literal.clear();
}
~LiteralScope()
{
if (!m_complete)
{
if (m_type == LITERAL_TYPE_COMMENT)
m_scanner->m_nextSkippedComment.literal.clear();
else
m_scanner->m_nextToken.literal.clear();
}
}
void complete() { m_complete = true; }
private:
enum LiteralType m_type;
Scanner* m_scanner;
bool m_complete;
}; // end of LiteralScope class
void Scanner::reset(CharStream const& _source, string const& _sourceName)
{
m_source = _source;
m_sourceName = make_shared<string const>(_sourceName);
reset();
}
void Scanner::reset()
{
m_source.reset();
m_char = m_source.get();
skipWhitespace();
scanToken();
next();
}
bool Scanner::scanHexByte(char& o_scannedByte)
{
char x = 0;
for (int i = 0; i < 2; i++)
{
int d = hexValue(m_char);
if (d < 0)
{
rollback(i);
return false;
}
x = x * 16 + d;
advance();
}
o_scannedByte = x;
return true;
}
bool Scanner::scanUnicode(unsigned & o_codepoint)
{
unsigned x = 0;
for (int i = 0; i < 4; i++)
{
int d = hexValue(m_char);
if (d < 0)
{
rollback(i);
return false;
}
x = x * 16 + d;
advance();
}
o_codepoint = x;
return true;
}
// This supports codepoints between 0000 and FFFF.
void Scanner::addUnicodeAsUTF8(unsigned codepoint)
{
if (codepoint <= 0x7f)
addLiteralChar(codepoint);
else if (codepoint <= 0x7ff)
{
addLiteralChar(0xc0 | (codepoint >> 6));
addLiteralChar(0x80 | (codepoint & 0x3f));
}
else
{
addLiteralChar(0xe0 | (codepoint >> 12));
addLiteralChar(0x80 | ((codepoint >> 6) & 0x3f));
addLiteralChar(0x80 | (codepoint & 0x3f));
}
}
// Ensure that tokens can be stored in a byte.
BOOST_STATIC_ASSERT(TokenTraits::count() <= 0x100);
Token Scanner::next()
{
m_currentToken = m_nextToken;
m_skippedComment = m_nextSkippedComment;
scanToken();
return m_currentToken.token;
}
Token Scanner::selectToken(char _next, Token _then, Token _else)
{
advance();
if (m_char == _next)
return selectToken(_then);
else
return _else;
}
bool Scanner::skipWhitespace()
{
int const startPosition = sourcePos();
while (isWhiteSpace(m_char))
advance();
// Return whether or not we skipped any characters.
return sourcePos() != startPosition;
}
void Scanner::skipWhitespaceExceptUnicodeLinebreak()
{
while (isWhiteSpace(m_char) && !isUnicodeLinebreak())
advance();
}
Token Scanner::skipSingleLineComment()
{
// Line terminator is not part of the comment. If it is a
// non-ascii line terminator, it will result in a parser error.
while (!isUnicodeLinebreak())
if (!advance()) break;
return Token::Whitespace;
}
Token Scanner::scanSingleLineDocComment()
{
LiteralScope literal(this, LITERAL_TYPE_COMMENT);
advance(); //consume the last '/' at ///
skipWhitespaceExceptUnicodeLinebreak();
while (!isSourcePastEndOfInput())
{
if (isLineTerminator(m_char))
{
// check if next line is also a documentation comment
skipWhitespace();
if (!m_source.isPastEndOfInput(3) &&
m_source.get(0) == '/' &&
m_source.get(1) == '/' &&
m_source.get(2) == '/')
{
addCommentLiteralChar('\n');
m_char = m_source.advanceAndGet(3);
}
else
break; // next line is not a documentation comment, we are done
}
else if (isUnicodeLinebreak())
// Any line terminator that is not '\n' is considered to end the
// comment.
break;
addCommentLiteralChar(m_char);
advance();
}
literal.complete();
return Token::CommentLiteral;
}
Token Scanner::skipMultiLineComment()
{
advance();
while (!isSourcePastEndOfInput())
{
char ch = m_char;
advance();
// 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 == '/')
{
m_char = ' ';
return Token::Whitespace;
}
}
// Unterminated multi-line comment.
return Token::Illegal;
}
Token Scanner::scanMultiLineDocComment()
{
LiteralScope literal(this, LITERAL_TYPE_COMMENT);
bool endFound = false;
bool charsAdded = false;
while (isWhiteSpace(m_char) && !isLineTerminator(m_char))
advance();
while (!isSourcePastEndOfInput())
{
//handle newlines in multline comments
if (isLineTerminator(m_char))
{
skipWhitespace();
if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '*')
{ // it is unknown if this leads to the end of the comment
addCommentLiteralChar('*');
advance();
}
else if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) != '/')
{ // skip first '*' in subsequent lines
if (charsAdded)
addCommentLiteralChar('\n');
m_char = m_source.advanceAndGet(2);
}
else if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '/')
{ // if after newline the comment ends, don't insert the newline
m_char = m_source.advanceAndGet(2);
endFound = true;
break;
}
else if (charsAdded)
addCommentLiteralChar('\n');
}
if (!m_source.isPastEndOfInput(1) && m_source.get(0) == '*' && m_source.get(1) == '/')
{
m_char = m_source.advanceAndGet(2);
endFound = true;
break;
}
addCommentLiteralChar(m_char);
charsAdded = true;
advance();
}
literal.complete();
if (!endFound)
return Token::Illegal;
else
return Token::CommentLiteral;
}
Token Scanner::scanSlash()
{
int firstSlashPosition = sourcePos();
advance();
if (m_char == '/')
{
if (!advance()) /* double slash comment directly before EOS */
return Token::Whitespace;
else if (m_char == '/')
{
// doxygen style /// comment
Token comment;
m_nextSkippedComment.location.start = firstSlashPosition;
comment = scanSingleLineDocComment();
m_nextSkippedComment.location.end = sourcePos();
m_nextSkippedComment.token = comment;
return Token::Whitespace;
}
else
return skipSingleLineComment();
}
else if (m_char == '*')
{
// doxygen style /** natspec comment
if (!advance()) /* slash star comment before EOS */
return Token::Illegal;
else if (m_char == '*')
{
advance(); //consume the last '*' at /**
// "/**/"
if (m_char == '/')
{
advance(); //skip the closing slash
return Token::Whitespace;
}
// we actually have a multiline documentation comment
Token comment;
m_nextSkippedComment.location.start = firstSlashPosition;
comment = scanMultiLineDocComment();
m_nextSkippedComment.location.end = sourcePos();
m_nextSkippedComment.token = comment;
if (comment == Token::Illegal)
return Token::Illegal;
else
return Token::Whitespace;
}
else
return skipMultiLineComment();
}
else if (m_char == '=')
return selectToken(Token::AssignDiv);
else
return Token::Div;
}
void Scanner::scanToken()
{
m_nextToken.literal.clear();
m_nextToken.extendedTokenInfo = make_tuple(0, 0);
m_nextSkippedComment.literal.clear();
m_nextSkippedComment.extendedTokenInfo = make_tuple(0, 0);
Token token;
// M and N are for the purposes of grabbing different type sizes
unsigned m;
unsigned n;
do
{
// Remember the position of the next token
m_nextToken.location.start = sourcePos();
switch (m_char)
{
case '"':
case '\'':
token = scanString();
break;
case '<':
// < <= << <<=
advance();
if (m_char == '=')
token = selectToken(Token::LessThanOrEqual);
else if (m_char == '<')
token = selectToken('=', Token::AssignShl, Token::SHL);
else
token = Token::LessThan;
break;
case '>':
// > >= >> >>= >>> >>>=
advance();
if (m_char == '=')
token = selectToken(Token::GreaterThanOrEqual);
else if (m_char == '>')
{
// >> >>= >>> >>>=
advance();
if (m_char == '=')
token = selectToken(Token::AssignSar);
else if (m_char == '>')
token = selectToken('=', Token::AssignShr, Token::SHR);
else
token = Token::SAR;
}
else
token = Token::GreaterThan;
break;
case '=':
// = == =>
advance();
if (m_char == '=')
token = selectToken(Token::Equal);
else if (m_char == '>')
token = selectToken(Token::Arrow);
else
token = Token::Assign;
break;
case '!':
// ! !=
advance();
if (m_char == '=')
token = selectToken(Token::NotEqual);
else
token = Token::Not;
break;
case '+':
// + ++ +=
advance();
if (m_char == '+')
token = selectToken(Token::Inc);
else if (m_char == '=')
token = selectToken(Token::AssignAdd);
else
token = Token::Add;
break;
case '-':
// - -- -=
advance();
if (m_char == '-')
token = selectToken(Token::Dec);
else if (m_char == '=')
token = selectToken(Token::AssignSub);
else
token = Token::Sub;
break;
case '*':
// * ** *=
advance();
if (m_char == '*')
token = selectToken(Token::Exp);
else if (m_char == '=')
token = selectToken(Token::AssignMul);
else
token = Token::Mul;
break;
case '%':
// % %=
token = selectToken('=', Token::AssignMod, Token::Mod);
break;
case '/':
// / // /* /=
token = scanSlash();
break;
case '&':
// & && &=
advance();
if (m_char == '&')
token = selectToken(Token::And);
else if (m_char == '=')
token = selectToken(Token::AssignBitAnd);
else
token = Token::BitAnd;
break;
case '|':
// | || |=
advance();
if (m_char == '|')
token = selectToken(Token::Or);
else if (m_char == '=')
token = selectToken(Token::AssignBitOr);
else
token = Token::BitOr;
break;
case '^':
// ^ ^=
token = selectToken('=', Token::AssignBitXor, Token::BitXor);
break;
case '.':
// . Number
advance();
if (isDecimalDigit(m_char))
token = scanNumber('.');
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::BitNot);
break;
default:
if (isIdentifierStart(m_char))
{
tie(token, m, n) = scanIdentifierOrKeyword();
// Special case for hexadecimal literals
if (token == Token::Hex)
{
// reset
m = 0;
n = 0;
// Special quoted hex string must follow
if (m_char == '"' || m_char == '\'')
token = scanHexString();
else
token = Token::IllegalHex;
}
}
else if (isDecimalDigit(m_char))
token = scanNumber();
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.
}
while (token == Token::Whitespace);
m_nextToken.location.end = sourcePos();
m_nextToken.token = token;
m_nextToken.extendedTokenInfo = make_tuple(m, n);
}
bool Scanner::scanEscape()
{
char c = m_char;
advance();
// Skip escaped newlines.
if (isLineTerminator(c))
return true;
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 'v':
c = '\v';
break;
case 'u':
{
unsigned codepoint;
if (!scanUnicode(codepoint))
return false;
addUnicodeAsUTF8(codepoint);
return true;
}
case 'x':
if (!scanHexByte(c))
return false;
break;
default:
return false;
}
addLiteralChar(c);
return true;
}
bool Scanner::isUnicodeLinebreak()
{
if (0x0a <= m_char && m_char <= 0x0d)
// line feed, vertical tab, form feed, carriage return
return true;
else if (!m_source.isPastEndOfInput(1) && uint8_t(m_source.get(0)) == 0xc2 && uint8_t(m_source.get(1)) == 0x85)
// NEL - U+0085, C2 85 in utf8
return true;
else if (!m_source.isPastEndOfInput(2) && uint8_t(m_source.get(0)) == 0xe2 && uint8_t(m_source.get(1)) == 0x80 && (
uint8_t(m_source.get(2)) == 0xa8 || uint8_t(m_source.get(2)) == 0xa9
))
// LS - U+2028, E2 80 A8 in utf8
// PS - U+2029, E2 80 A9 in utf8
return true;
else
return false;
}
Token Scanner::scanString()
{
char const quote = m_char;
advance(); // consume quote
LiteralScope literal(this, LITERAL_TYPE_STRING);
while (m_char != quote && !isSourcePastEndOfInput() && !isUnicodeLinebreak())
{
char c = m_char;
advance();
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::StringLiteral;
}
Token Scanner::scanHexString()
{
char const quote = m_char;
advance(); // consume quote
LiteralScope literal(this, LITERAL_TYPE_STRING);
while (m_char != quote && !isSourcePastEndOfInput())
{
char c = m_char;
if (!scanHexByte(c))
return Token::IllegalHex;
addLiteralChar(c);
}
if (m_char != quote)
return Token::IllegalHex;
literal.complete();
advance(); // consume quote
return Token::StringLiteral;
}
// Parse for regex [:digit:]+(_[:digit:]+)*
void Scanner::scanDecimalDigits()
{
// MUST begin with a decimal digit.
if (!isDecimalDigit(m_char))
return;
// May continue with decimal digit or underscore for grouping.
do addLiteralCharAndAdvance();
while (!m_source.isPastEndOfInput() && (isDecimalDigit(m_char) || m_char == '_'));
// Defer further validation of underscore to SyntaxChecker.
}
Token Scanner::scanNumber(char _charSeen)
{
enum { DECIMAL, HEX, BINARY } kind = DECIMAL;
LiteralScope literal(this, LITERAL_TYPE_NUMBER);
if (_charSeen == '.')
{
// we have already seen a decimal point of the float
addLiteralChar('.');
if (m_char == '_')
return Token::Illegal;
scanDecimalDigits(); // we know we have at least one digit
}
else
{
solAssert(_charSeen == 0, "");
// if the first character is '0' we must check for octals and hex
if (m_char == '0')
{
addLiteralCharAndAdvance();
// either 0, 0exxx, 0Exxx, 0.xxx or a hex number
if (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'
while (isHexDigit(m_char) || m_char == '_') // We keep the underscores for later validation
addLiteralCharAndAdvance();
}
else if (isDecimalDigit(m_char))
// We do not allow octal numbers
return Token::Illegal;
}
// Parse decimal digits and allow trailing fractional part.
if (kind == DECIMAL)
{
scanDecimalDigits(); // optional
if (m_char == '.')
{
if (!m_source.isPastEndOfInput(1) && m_source.get(1) == '_')
{
// Assume the input may be a floating point number with leading '_' in fraction part.
// Recover by consuming it all but returning `Illegal` right away.
addLiteralCharAndAdvance(); // '.'
addLiteralCharAndAdvance(); // '_'
scanDecimalDigits();
}
if (m_source.isPastEndOfInput() || !isDecimalDigit(m_source.get(1)))
{
// A '.' has to be followed by a number.
literal.complete();
return Token::Number;
}
addLiteralCharAndAdvance();
scanDecimalDigits();
}
}
}
// scan exponent, if any
if (m_char == 'e' || m_char == 'E')
{
solAssert(kind != HEX, "'e'/'E' must be scanned as part of the hex number");
if (kind != DECIMAL)
return Token::Illegal;
else if (!m_source.isPastEndOfInput(1) && m_source.get(1) == '_')
{
// Recover from wrongly placed underscore as delimiter in literal with scientific
// notation by consuming until the end.
addLiteralCharAndAdvance(); // 'e'
addLiteralCharAndAdvance(); // '_'
scanDecimalDigits();
literal.complete();
return Token::Number;
}
// scan exponent
addLiteralCharAndAdvance(); // 'e' | 'E'
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();
}
// 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;
}
tuple<Token, unsigned, unsigned> Scanner::scanIdentifierOrKeyword()
{
solAssert(isIdentifierStart(m_char), "");
LiteralScope literal(this, LITERAL_TYPE_STRING);
addLiteralCharAndAdvance();
// Scan the rest of the identifier characters.
while (isIdentifierPart(m_char)) //get full literal
addLiteralCharAndAdvance();
literal.complete();
return TokenTraits::fromIdentifierOrKeyword(m_nextToken.literal);
}
char CharStream::advanceAndGet(size_t _chars)
{
if (isPastEndOfInput())
return 0;
m_position += _chars;
if (isPastEndOfInput())
return 0;
return m_source[m_position];
}
char CharStream::rollback(size_t _amount)
{
solAssert(m_position >= _amount, "");
m_position -= _amount;
return get();
}
string CharStream::lineAtPosition(int _position) const
{
// if _position points to \n, it returns the line before the \n
using size_type = string::size_type;
size_type searchStart = min<size_type>(m_source.size(), _position);
if (searchStart > 0)
searchStart--;
size_type lineStart = m_source.rfind('\n', searchStart);
if (lineStart == string::npos)
lineStart = 0;
else
lineStart++;
return m_source.substr(lineStart, min(m_source.find('\n', lineStart),
m_source.size()) - lineStart);
}
tuple<int, int> CharStream::translatePositionToLineColumn(int _position) const
{
using size_type = string::size_type;
size_type searchPosition = min<size_type>(m_source.size(), _position);
int lineNumber = count(m_source.begin(), m_source.begin() + searchPosition, '\n');
size_type lineStart;
if (searchPosition == 0)
lineStart = 0;
else
{
lineStart = m_source.rfind('\n', searchPosition - 1);
lineStart = lineStart == string::npos ? 0 : lineStart + 1;
}
return tuple<int, int>(lineNumber, searchPosition - lineStart);
}
}
}
-249
View File
@@ -1,249 +0,0 @@
/*
This file is part of solidity.
solidity 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.
solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
This file is derived from the file "scanner.h", which was part of the
V8 project. The original copyright header follows:
Copyright 2006-2012, the V8 project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @author Christian <c@ethdev.com>
* @date 2014
* Solidity scanner.
*/
#pragma once
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libevmasm/SourceLocation.h>
#include <libsolidity/parsing/Token.h>
namespace dev
{
namespace solidity
{
class AstRawString;
class AstValueFactory;
class ParserRecorder;
class CharStream
{
public:
CharStream(): m_position(0) {}
explicit CharStream(std::string const& _source): m_source(_source), m_position(0) {}
int position() const { return m_position; }
bool isPastEndOfInput(size_t _charsForward = 0) const { return (m_position + _charsForward) >= m_source.size(); }
char get(size_t _charsForward = 0) const { return m_source[m_position + _charsForward]; }
char advanceAndGet(size_t _chars = 1);
char rollback(size_t _amount);
void reset() { m_position = 0; }
std::string const& source() const { return m_source; }
///@{
///@name Error printing helper functions
/// Functions that help pretty-printing parse errors
/// Do only use in error cases, they are quite expensive.
std::string lineAtPosition(int _position) const;
std::tuple<int, int> translatePositionToLineColumn(int _position) const;
///@}
private:
std::string m_source;
size_t m_position;
};
class Scanner
{
friend class LiteralScope;
public:
explicit Scanner(CharStream const& _source = CharStream(), std::string const& _sourceName = "") { reset(_source, _sourceName); }
std::string source() const { return m_source.source(); }
/// Resets the scanner as if newly constructed with _source and _sourceName as input.
void reset(CharStream const& _source, std::string const& _sourceName);
/// Resets scanner to the start of input.
void reset();
/// @returns the next token and advances input
Token next();
///@{
///@name Information about the current token
/// @returns the current token
Token currentToken() const
{
return m_currentToken.token;
}
ElementaryTypeNameToken currentElementaryTypeNameToken() const
{
unsigned firstSize;
unsigned secondSize;
std::tie(firstSize, secondSize) = m_currentToken.extendedTokenInfo;
return ElementaryTypeNameToken(m_currentToken.token, firstSize, secondSize);
}
SourceLocation currentLocation() const { return m_currentToken.location; }
std::string const& currentLiteral() const { return m_currentToken.literal; }
std::tuple<unsigned, unsigned> const& currentTokenInfo() const { return m_currentToken.extendedTokenInfo; }
///@}
///@{
///@name Information about the current comment token
SourceLocation currentCommentLocation() const { return m_skippedComment.location; }
std::string const& currentCommentLiteral() const { return m_skippedComment.literal; }
/// Called by the parser during FunctionDefinition parsing to clear the current comment
void clearCurrentCommentLiteral() { m_skippedComment.literal.clear(); }
///@}
///@{
///@name Information about the next token
/// @returns the next token without advancing input.
Token peekNextToken() const { return m_nextToken.token; }
SourceLocation peekLocation() const { return m_nextToken.location; }
std::string const& peekLiteral() const { return m_nextToken.literal; }
///@}
std::shared_ptr<std::string const> const& sourceName() const { return m_sourceName; }
///@{
///@name Error printing helper functions
/// Functions that help pretty-printing parse errors
/// Do only use in error cases, they are quite expensive.
std::string lineAtPosition(int _position) const { return m_source.lineAtPosition(_position); }
std::tuple<int, int> translatePositionToLineColumn(int _position) const { return m_source.translatePositionToLineColumn(_position); }
std::string sourceAt(SourceLocation const& _location) const
{
solAssert(!_location.isEmpty(), "");
solAssert(m_sourceName && _location.sourceName, "");
solAssert(*m_sourceName == *_location.sourceName, "");
return m_source.source().substr(_location.start, _location.end - _location.start);
}
///@}
private:
/// Used for the current and look-ahead token and comments
struct TokenDesc
{
Token token;
SourceLocation location;
std::string literal;
std::tuple<unsigned, unsigned> extendedTokenInfo;
};
///@{
///@name Literal buffer support
inline void addLiteralChar(char c) { m_nextToken.literal.push_back(c); }
inline void addCommentLiteralChar(char c) { m_nextSkippedComment.literal.push_back(c); }
inline void addLiteralCharAndAdvance() { addLiteralChar(m_char); advance(); }
void addUnicodeAsUTF8(unsigned codepoint);
///@}
bool advance() { m_char = m_source.advanceAndGet(); return !m_source.isPastEndOfInput(); }
void rollback(int _amount) { m_char = m_source.rollback(_amount); }
inline Token selectToken(Token _tok) { advance(); return _tok; }
/// If the next character is _next, advance and return _then, otherwise return _else.
inline Token selectToken(char _next, Token _then, Token _else);
bool scanHexByte(char& o_scannedByte);
bool scanUnicode(unsigned& o_codepoint);
/// Scans a single Solidity token.
void scanToken();
/// Skips all whitespace and @returns true if something was skipped.
bool skipWhitespace();
/// Skips all whitespace that are neither '\r' nor '\n'.
void skipWhitespaceExceptUnicodeLinebreak();
Token skipSingleLineComment();
Token skipMultiLineComment();
void scanDecimalDigits();
Token scanNumber(char _charSeen = 0);
std::tuple<Token, unsigned, unsigned> scanIdentifierOrKeyword();
Token scanString();
Token scanHexString();
Token scanSingleLineDocComment();
Token scanMultiLineDocComment();
/// Scans a slash '/' and depending on the characters returns the appropriate token
Token scanSlash();
/// Scans an escape-sequence which is part of a string and adds the
/// decoded character to the current literal. Returns true if a pattern
/// is scanned.
bool scanEscape();
/// @returns true iff we are currently positioned at a unicode line break.
bool isUnicodeLinebreak();
/// Return the current source position.
int sourcePos() const { return m_source.position(); }
bool isSourcePastEndOfInput() const { return m_source.isPastEndOfInput(); }
TokenDesc m_skippedComment; // desc for current skipped comment
TokenDesc m_nextSkippedComment; // desc for next skipped comment
TokenDesc m_currentToken; // desc for current token (as returned by Next())
TokenDesc m_nextToken; // desc for next token (one token look-ahead)
CharStream m_source;
std::shared_ptr<std::string const> m_sourceName;
/// one character look-ahead, equals 0 at end of input
char m_char;
};
}
}
-207
View File
@@ -1,207 +0,0 @@
// Copyright 2006-2012, the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Modifications as part of solidity under the following license:
//
// solidity 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.
//
// solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
#include <map>
#include <libsolidity/parsing/Token.h>
#include <boost/range/iterator_range.hpp>
using namespace std;
namespace dev
{
namespace solidity
{
void ElementaryTypeNameToken::assertDetails(Token _baseType, unsigned const& _first, unsigned const& _second)
{
solAssert(TokenTraits::isElementaryTypeName(_baseType), "Expected elementary type name: " + string(TokenTraits::toString(_baseType)));
if (_baseType == Token::BytesM)
{
solAssert(_second == 0, "There should not be a second size argument to type bytesM.");
solAssert(_first <= 32, "No elementary type bytes" + to_string(_first) + ".");
}
else if (_baseType == Token::UIntM || _baseType == Token::IntM)
{
solAssert(_second == 0, "There should not be a second size argument to type " + string(TokenTraits::toString(_baseType)) + ".");
solAssert(
_first <= 256 && _first % 8 == 0,
"No elementary type " + string(TokenTraits::toString(_baseType)) + to_string(_first) + "."
);
}
else if (_baseType == Token::UFixedMxN || _baseType == Token::FixedMxN)
{
solAssert(
_first >= 8 && _first <= 256 && _first % 8 == 0 && _second <= 80,
"No elementary type " + string(TokenTraits::toString(_baseType)) + to_string(_first) + "x" + to_string(_second) + "."
);
}
m_token = _baseType;
m_firstNumber = _first;
m_secondNumber = _second;
}
namespace TokenTraits
{
char const* toString(Token tok)
{
switch (tok)
{
#define T(name, string, precedence) case Token::name: return string;
TOKEN_LIST(T, T)
#undef T
default: // Token::NUM_TOKENS:
return "";
}
}
char const* name(Token tok)
{
#define T(name, string, precedence) #name,
static char const* const names[TokenTraits::count()] = { TOKEN_LIST(T, T) };
#undef T
solAssert(static_cast<size_t>(tok) < TokenTraits::count(), "");
return names[static_cast<size_t>(tok)];
}
std::string friendlyName(Token tok)
{
char const* ret = toString(tok);
if (ret)
return std::string(ret);
ret = name(tok);
solAssert(ret != nullptr, "");
return std::string(ret);
}
#define T(name, string, precedence) precedence,
int precedence(Token tok)
{
int8_t const static precs[TokenTraits::count()] =
{
TOKEN_LIST(T, T)
};
return precs[static_cast<size_t>(tok)];
}
#undef T
int parseSize(string::const_iterator _begin, string::const_iterator _end)
{
try
{
unsigned int m = boost::lexical_cast<int>(boost::make_iterator_range(_begin, _end));
return m;
}
catch(boost::bad_lexical_cast const&)
{
return -1;
}
}
static Token keywordByName(string const& _name)
{
// The following macros are used inside TOKEN_LIST and cause non-keyword tokens to be ignored
// and keywords to be put inside the keywords variable.
#define KEYWORD(name, string, precedence) {string, Token::name},
#define TOKEN(name, string, precedence)
static const map<string, Token> keywords({TOKEN_LIST(TOKEN, KEYWORD)});
#undef KEYWORD
#undef TOKEN
auto it = keywords.find(_name);
return it == keywords.end() ? Token::Identifier : it->second;
}
tuple<Token, unsigned int, unsigned int> fromIdentifierOrKeyword(string const& _literal)
{
auto positionM = find_if(_literal.begin(), _literal.end(), ::isdigit);
if (positionM != _literal.end())
{
string baseType(_literal.begin(), positionM);
auto positionX = find_if_not(positionM, _literal.end(), ::isdigit);
int m = parseSize(positionM, positionX);
Token keyword = keywordByName(baseType);
if (keyword == Token::Bytes)
{
if (0 < m && m <= 32 && positionX == _literal.end())
return make_tuple(Token::BytesM, m, 0);
}
else if (keyword == Token::UInt || keyword == Token::Int)
{
if (0 < m && m <= 256 && m % 8 == 0 && positionX == _literal.end())
{
if (keyword == Token::UInt)
return make_tuple(Token::UIntM, m, 0);
else
return make_tuple(Token::IntM, m, 0);
}
}
else if (keyword == Token::UFixed || keyword == Token::Fixed)
{
if (
positionM < positionX &&
positionX < _literal.end() &&
*positionX == 'x' &&
all_of(positionX + 1, _literal.end(), ::isdigit)
) {
int n = parseSize(positionX + 1, _literal.end());
if (
8 <= m && m <= 256 && m % 8 == 0 &&
0 <= n && n <= 80
) {
if (keyword == Token::UFixed)
return make_tuple(Token::UFixedMxN, m, n);
else
return make_tuple(Token::FixedMxN, m, n);
}
}
}
return make_tuple(Token::Identifier, 0, 0);
}
return make_tuple(keywordByName(_literal), 0, 0);
}
}
}
}
-378
View File
@@ -1,378 +0,0 @@
// Copyright 2006-2012, the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Modifications as part of solidity under the following license:
//
// solidity 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.
//
// solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <libdevcore/Common.h>
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/parsing/UndefMacros.h>
#include <iosfwd>
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
// symbolic token name, string is the corresponding syntactic symbol
// (or NULL, for literals), and precedence is the precedence (or 0).
// The parameters are invoked for token categories as follows:
//
// T: Non-keyword tokens
// K: Keyword tokens
// IGNORE_TOKEN is a convenience macro that can be supplied as
// an argument (at any position) for a TOKEN_LIST call. It does
// nothing with tokens belonging to the respective category.
#define IGNORE_TOKEN(name, string, precedence)
#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) \
T(LBrack, "[", 0) \
T(RBrack, "]", 0) \
T(LBrace, "{", 0) \
T(RBrace, "}", 0) \
T(Colon, ":", 0) \
T(Semicolon, ";", 0) \
T(Period, ".", 0) \
T(Conditional, "?", 3) \
T(Arrow, "=>", 0) \
\
/* Assignment operators. */ \
/* IsAssignmentOp() relies on this block of enum values being */ \
/* contiguous and sorted in the same order!*/ \
T(Assign, "=", 2) \
/* The following have to be in exactly the same order as the simple binary operators*/ \
T(AssignBitOr, "|=", 2) \
T(AssignBitXor, "^=", 2) \
T(AssignBitAnd, "&=", 2) \
T(AssignShl, "<<=", 2) \
T(AssignSar, ">>=", 2) \
T(AssignShr, ">>>=", 2) \
T(AssignAdd, "+=", 2) \
T(AssignSub, "-=", 2) \
T(AssignMul, "*=", 2) \
T(AssignDiv, "/=", 2) \
T(AssignMod, "%=", 2) \
\
/* Binary operators sorted by precedence. */ \
/* IsBinaryOp() relies on this block of enum values */ \
/* being contiguous and sorted in the same order! */ \
T(Comma, ",", 1) \
T(Or, "||", 4) \
T(And, "&&", 5) \
T(BitOr, "|", 8) \
T(BitXor, "^", 9) \
T(BitAnd, "&", 10) \
T(SHL, "<<", 11) \
T(SAR, ">>", 11) \
T(SHR, ">>>", 11) \
T(Add, "+", 12) \
T(Sub, "-", 12) \
T(Mul, "*", 13) \
T(Div, "/", 13) \
T(Mod, "%", 13) \
T(Exp, "**", 14) \
\
/* Compare operators sorted by precedence. */ \
/* IsCompareOp() relies on this block of enum values */ \
/* being contiguous and sorted in the same order! */ \
T(Equal, "==", 6) \
T(NotEqual, "!=", 6) \
T(LessThan, "<", 7) \
T(GreaterThan, ">", 7) \
T(LessThanOrEqual, "<=", 7) \
T(GreaterThanOrEqual, ">=", 7) \
\
/* Unary operators. */ \
/* IsUnaryOp() relies on this block of enum values */ \
/* being contiguous and sorted in the same order! */ \
T(Not, "!", 0) \
T(BitNot, "~", 0) \
T(Inc, "++", 0) \
T(Dec, "--", 0) \
K(Delete, "delete", 0) \
\
/* Keywords */ \
K(Anonymous, "anonymous", 0) \
K(As, "as", 0) \
K(Assembly, "assembly", 0) \
K(Break, "break", 0) \
K(Constant, "constant", 0) \
K(Constructor, "constructor", 0) \
K(Continue, "continue", 0) \
K(Contract, "contract", 0) \
K(Do, "do", 0) \
K(Else, "else", 0) \
K(Enum, "enum", 0) \
K(Emit, "emit", 0) \
K(Event, "event", 0) \
K(External, "external", 0) \
K(For, "for", 0) \
K(Function, "function", 0) \
K(Hex, "hex", 0) \
K(If, "if", 0) \
K(Indexed, "indexed", 0) \
K(Interface, "interface", 0) \
K(Internal, "internal", 0) \
K(Import, "import", 0) \
K(Is, "is", 0) \
K(Library, "library", 0) \
K(Mapping, "mapping", 0) \
K(Memory, "memory", 0) \
K(Modifier, "modifier", 0) \
K(New, "new", 0) \
K(Payable, "payable", 0) \
K(Public, "public", 0) \
K(Pragma, "pragma", 0) \
K(Private, "private", 0) \
K(Pure, "pure", 0) \
K(Return, "return", 0) \
K(Returns, "returns", 0) \
K(Storage, "storage", 0) \
K(CallData, "calldata", 0) \
K(Struct, "struct", 0) \
K(Throw, "throw", 0) \
K(Using, "using", 0) \
K(Var, "var", 0) \
K(View, "view", 0) \
K(While, "while", 0) \
\
/* Ether subdenominations */ \
K(SubWei, "wei", 0) \
K(SubSzabo, "szabo", 0) \
K(SubFinney, "finney", 0) \
K(SubEther, "ether", 0) \
K(SubSecond, "seconds", 0) \
K(SubMinute, "minutes", 0) \
K(SubHour, "hours", 0) \
K(SubDay, "days", 0) \
K(SubWeek, "weeks", 0) \
K(SubYear, "years", 0) \
/* type keywords*/ \
K(Int, "int", 0) \
K(UInt, "uint", 0) \
K(Bytes, "bytes", 0) \
K(Byte, "byte", 0) \
K(String, "string", 0) \
K(Address, "address", 0) \
K(Bool, "bool", 0) \
K(Fixed, "fixed", 0) \
K(UFixed, "ufixed", 0) \
T(IntM, "intM", 0) \
T(UIntM, "uintM", 0) \
T(BytesM, "bytesM", 0) \
T(FixedMxN, "fixedMxN", 0) \
T(UFixedMxN, "ufixedMxN", 0) \
T(TypesEnd, NULL, 0) /* used as type enum end marker */ \
\
/* Literals */ \
K(TrueLiteral, "true", 0) \
K(FalseLiteral, "false", 0) \
T(Number, NULL, 0) \
T(StringLiteral, NULL, 0) \
T(CommentLiteral, NULL, 0) \
\
/* Identifiers (not keywords or future reserved words). */ \
T(Identifier, NULL, 0) \
\
/* Keywords reserved for future use. */ \
K(Abstract, "abstract", 0) \
K(After, "after", 0) \
K(Alias, "alias", 0) \
K(Apply, "apply", 0) \
K(Auto, "auto", 0) \
K(Case, "case", 0) \
K(Catch, "catch", 0) \
K(CopyOf, "copyof", 0) \
K(Default, "default", 0) \
K(Define, "define", 0) \
K(Final, "final", 0) \
K(Immutable, "immutable", 0) \
K(Implements, "implements", 0) \
K(In, "in", 0) \
K(Inline, "inline", 0) \
K(Let, "let", 0) \
K(Macro, "macro", 0) \
K(Match, "match", 0) \
K(Mutable, "mutable", 0) \
K(NullLiteral, "null", 0) \
K(Of, "of", 0) \
K(Override, "override", 0) \
K(Partial, "partial", 0) \
K(Promise, "promise", 0) \
K(Reference, "reference", 0) \
K(Relocatable, "relocatable", 0) \
K(Sealed, "sealed", 0) \
K(Sizeof, "sizeof", 0) \
K(Static, "static", 0) \
K(Supports, "supports", 0) \
K(Switch, "switch", 0) \
K(Try, "try", 0) \
K(Type, "type", 0) \
K(Typedef, "typedef", 0) \
K(TypeOf, "typeof", 0) \
K(Unchecked, "unchecked", 0) \
\
/* Illegal token - not able to scan. */ \
T(Illegal, "ILLEGAL", 0) \
/* Illegal hex token */ \
T(IllegalHex, "ILLEGAL_HEX", 0) \
\
/* Scanner-internal use only. */ \
T(Whitespace, NULL, 0)
// All token values.
// attention! msvc issue:
// http://stackoverflow.com/questions/9567868/compile-errors-after-adding-v8-to-my-project-c2143-c2059
// @todo: avoid TOKEN_LIST macro
enum class Token : unsigned int {
#define T(name, string, precedence) name,
TOKEN_LIST(T, T)
NUM_TOKENS
#undef T
};
namespace TokenTraits
{
constexpr size_t count() { return static_cast<size_t>(Token::NUM_TOKENS); }
// Predicates
constexpr bool isElementaryTypeName(Token tok) { return Token::Int <= tok && tok < Token::TypesEnd; }
constexpr bool isAssignmentOp(Token tok) { return Token::Assign <= tok && tok <= Token::AssignMod; }
constexpr bool isBinaryOp(Token op) { return Token::Comma <= op && op <= Token::Exp; }
constexpr bool isCommutativeOp(Token op) { return op == Token::BitOr || op == Token::BitXor || op == Token::BitAnd ||
op == Token::Add || op == Token::Mul || op == Token::Equal || op == Token::NotEqual; }
constexpr bool isArithmeticOp(Token op) { return Token::Add <= op && op <= Token::Exp; }
constexpr bool isCompareOp(Token op) { return Token::Equal <= op && op <= Token::GreaterThanOrEqual; }
constexpr bool isBitOp(Token op) { return (Token::BitOr <= op && op <= Token::BitAnd) || op == Token::BitNot; }
constexpr bool isBooleanOp(Token op) { return (Token::Or <= op && op <= Token::And) || op == Token::Not; }
constexpr bool isUnaryOp(Token op) { return (Token::Not <= op && op <= Token::Delete) || op == Token::Add || op == Token::Sub; }
constexpr bool isCountOp(Token op) { return op == Token::Inc || op == Token::Dec; }
constexpr bool isShiftOp(Token op) { return (Token::SHL <= op) && (op <= Token::SHR); }
constexpr bool isVariableVisibilitySpecifier(Token op) { return op == Token::Public || op == Token::Private || op == Token::Internal; }
constexpr bool isVisibilitySpecifier(Token op) { return isVariableVisibilitySpecifier(op) || op == Token::External; }
constexpr bool isLocationSpecifier(Token op) { return op == Token::Memory || op == Token::Storage || op == Token::CallData; }
constexpr bool isStateMutabilitySpecifier(Token op, bool _allowConstant = true)
{
return (op == Token::Constant && _allowConstant)
|| op == Token::Pure || op == Token::View || op == Token::Payable;
}
constexpr bool isEtherSubdenomination(Token op) { return op == Token::SubWei || op == Token::SubSzabo || op == Token::SubFinney || op == Token::SubEther; }
constexpr bool isTimeSubdenomination(Token op) { return op == Token::SubSecond || op == Token::SubMinute || op == Token::SubHour || op == Token::SubDay || op == Token::SubWeek || op == Token::SubYear; }
constexpr bool isReservedKeyword(Token op) { return (Token::Abstract <= op && op <= Token::Unchecked); }
inline Token AssignmentToBinaryOp(Token op)
{
solAssert(isAssignmentOp(op) && op != Token::Assign, "");
return static_cast<Token>(static_cast<int>(op) + (static_cast<int>(Token::BitOr) - static_cast<int>(Token::AssignBitOr)));
}
// @returns the precedence > 0 for binary and compare
// operators; returns 0 otherwise.
int precedence(Token tok);
std::tuple<Token, unsigned int, unsigned int> fromIdentifierOrKeyword(std::string const& _literal);
// @returns a string corresponding to the C++ token name
// (e.g. "LT" for the token LT).
char const* name(Token tok);
// @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).
char const* toString(Token tok);
std::string friendlyName(Token tok);
}
inline std::ostream& operator<<(std::ostream& os, Token token)
{
os << TokenTraits::friendlyName(token);
return os;
}
class ElementaryTypeNameToken
{
public:
ElementaryTypeNameToken(Token _token, unsigned const& _firstNumber, unsigned const& _secondNumber)
{
assertDetails(_token, _firstNumber, _secondNumber);
}
unsigned int firstNumber() const { return m_firstNumber; }
unsigned int secondNumber() const { return m_secondNumber; }
Token token() const { return m_token; }
///if tokValue is set to true, then returns the actual token type name, otherwise, returns full type
std::string toString(bool const& tokenValue = false) const
{
std::string name = TokenTraits::toString(m_token);
if (tokenValue || (firstNumber() == 0 && secondNumber() == 0))
return name;
solAssert(name.size() >= 3, "Token name size should be greater than 3. Should not reach here.");
if (m_token == Token::FixedMxN || m_token == Token::UFixedMxN)
return name.substr(0, name.size() - 3) + std::to_string(m_firstNumber) + "x" + std::to_string(m_secondNumber);
else
return name.substr(0, name.size() - 1) + std::to_string(m_firstNumber);
}
private:
Token m_token;
unsigned int m_firstNumber;
unsigned int m_secondNumber;
/// throws if type is not properly sized
void assertDetails(Token _baseType, unsigned const& _first, unsigned const& _second);
};
}
}
-46
View File
@@ -1,46 +0,0 @@
/*
This file is part of solidity.
solidity 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.
solidity 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 solidity. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file UndefMacros.h
* @author Lefteris <lefteris@ethdev.com>
* @date 2015
*
* This header should be used to #undef some really evil macros defined by
* windows.h which result in conflict with our Token.h
*/
#pragma once
#if defined(_MSC_VER) || defined(__MINGW32__)
#undef DELETE
#undef IN
#undef VOID
#undef THIS
#undef CONST
// Conflicting define on MinGW in windows.h
// windows.h(19): #define interface struct
#ifdef interface
#undef interface
#endif
#elif defined(DELETE) || defined(IN) || defined(VOID) || defined(THIS) || defined(CONST) || defined(interface)
#error "The preceding macros in this header file are reserved for V8's "\
"TOKEN_LIST. Please add a platform specific define above to undefine "\
"overlapping macros."
#endif