aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/parsing
diff options
context:
space:
mode:
authorChristian Parpart <christian@ethereum.org>2018-11-14 21:59:30 +0800
committerAlex Beregszaszi <alex@rtfs.hu>2018-11-22 02:58:12 +0800
commit87821c53c3a73d3e35a0e50a7c159d9aa5d6b253 (patch)
treed0335db1bfe77f91168e14599e943105b7c9a2c3 /libsolidity/parsing
parentd47707abaddfd6820d8ff1f9ec5ec0d2a61ee622 (diff)
downloaddexon-solidity-87821c53c3a73d3e35a0e50a7c159d9aa5d6b253.tar.gz
dexon-solidity-87821c53c3a73d3e35a0e50a7c159d9aa5d6b253.tar.zst
dexon-solidity-87821c53c3a73d3e35a0e50a7c159d9aa5d6b253.zip
Isolating files shared between Yul- and Solidity language frontend.
Diffstat (limited to 'libsolidity/parsing')
-rw-r--r--libsolidity/parsing/DocStringParser.cpp4
-rw-r--r--libsolidity/parsing/Parser.cpp6
-rw-r--r--libsolidity/parsing/Parser.h2
-rw-r--r--libsolidity/parsing/ParserBase.cpp115
-rw-r--r--libsolidity/parsing/ParserBase.h93
-rw-r--r--libsolidity/parsing/Scanner.cpp920
-rw-r--r--libsolidity/parsing/Scanner.h249
-rw-r--r--libsolidity/parsing/Token.cpp207
-rw-r--r--libsolidity/parsing/Token.h378
-rw-r--r--libsolidity/parsing/UndefMacros.h46
10 files changed, 6 insertions, 2014 deletions
diff --git a/libsolidity/parsing/DocStringParser.cpp b/libsolidity/parsing/DocStringParser.cpp
index d9588e5c..17a7b691 100644
--- a/libsolidity/parsing/DocStringParser.cpp
+++ b/libsolidity/parsing/DocStringParser.cpp
@@ -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>
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index b17dad9a..f070620d 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -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;
diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h
index fa974171..f20f01c5 100644
--- a/libsolidity/parsing/Parser.h
+++ b/libsolidity/parsing/Parser.h
@@ -23,7 +23,7 @@
#pragma once
#include <libsolidity/ast/AST.h>
-#include <libsolidity/parsing/ParserBase.h>
+#include <liblangutil/ParserBase.h>
namespace dev
{
diff --git a/libsolidity/parsing/ParserBase.cpp b/libsolidity/parsing/ParserBase.cpp
deleted file mode 100644
index 1d4cb1e2..00000000
--- a/libsolidity/parsing/ParserBase.cpp
+++ /dev/null
@@ -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);
-}
diff --git a/libsolidity/parsing/ParserBase.h b/libsolidity/parsing/ParserBase.h
deleted file mode 100644
index e01f37d8..00000000
--- a/libsolidity/parsing/ParserBase.h
+++ /dev/null
@@ -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;
-};
-
-}
-}
diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp
deleted file mode 100644
index e9dad2ad..00000000
--- a/libsolidity/parsing/Scanner.cpp
+++ /dev/null
@@ -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);
-}
-
-
-}
-}
diff --git a/libsolidity/parsing/Scanner.h b/libsolidity/parsing/Scanner.h
deleted file mode 100644
index 14eeb66e..00000000
--- a/libsolidity/parsing/Scanner.h
+++ /dev/null
@@ -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;
-};
-
-}
-}
diff --git a/libsolidity/parsing/Token.cpp b/libsolidity/parsing/Token.cpp
deleted file mode 100644
index dccd9037..00000000
--- a/libsolidity/parsing/Token.cpp
+++ /dev/null
@@ -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);
-}
-
-}
-}
-}
diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h
deleted file mode 100644
index 81e8dd98..00000000
--- a/libsolidity/parsing/Token.h
+++ /dev/null
@@ -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);
-};
-
-}
-}
diff --git a/libsolidity/parsing/UndefMacros.h b/libsolidity/parsing/UndefMacros.h
deleted file mode 100644
index d96e242e..00000000
--- a/libsolidity/parsing/UndefMacros.h
+++ /dev/null
@@ -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