aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/parsing
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/parsing')
-rw-r--r--libsolidity/parsing/Parser.cpp80
-rw-r--r--libsolidity/parsing/ParserBase.cpp20
-rw-r--r--libsolidity/parsing/ParserBase.h8
-rw-r--r--libsolidity/parsing/Scanner.cpp32
-rw-r--r--libsolidity/parsing/Scanner.h30
-rw-r--r--libsolidity/parsing/Token.cpp98
-rw-r--r--libsolidity/parsing/Token.h145
7 files changed, 203 insertions, 210 deletions
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index ca9a9b57..f99b9ea4 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -112,17 +112,17 @@ ASTPointer<PragmaDirective> Parser::parsePragmaDirective()
ASTNodeFactory nodeFactory(*this);
expectToken(Token::Pragma);
vector<string> literals;
- vector<Token::Value> tokens;
+ vector<Token> tokens;
do
{
- Token::Value token = m_scanner->currentToken();
+ Token token = m_scanner->currentToken();
if (token == Token::Illegal)
parserError("Token incompatible with Solidity parser as part of pragma directive.");
else
{
string literal = m_scanner->currentLiteral();
- if (literal.empty() && Token::toString(token))
- literal = Token::toString(token);
+ if (literal.empty() && TokenTraits::toString(token))
+ literal = TokenTraits::toString(token);
literals.push_back(literal);
tokens.push_back(token);
}
@@ -240,7 +240,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
expectToken(Token::LBrace);
while (true)
{
- Token::Value currentTokenValue = m_scanner->currentToken();
+ Token currentTokenValue = m_scanner->currentToken();
if (currentTokenValue == Token::RBrace)
break;
else if (currentTokenValue == Token::Function || currentTokenValue == Token::Constructor)
@@ -254,7 +254,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
else if (
currentTokenValue == Token::Identifier ||
currentTokenValue == Token::Mapping ||
- Token::isElementaryTypeName(currentTokenValue)
+ TokenTraits::isElementaryTypeName(currentTokenValue)
)
{
VarDeclParserOptions options;
@@ -304,7 +304,7 @@ ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
Declaration::Visibility Parser::parseVisibilitySpecifier()
{
Declaration::Visibility visibility(Declaration::Visibility::Default);
- Token::Value token = m_scanner->currentToken();
+ Token token = m_scanner->currentToken();
switch (token)
{
case Token::Public:
@@ -329,7 +329,7 @@ Declaration::Visibility Parser::parseVisibilitySpecifier()
StateMutability Parser::parseStateMutability()
{
StateMutability stateMutability(StateMutability::NonPayable);
- Token::Value token = m_scanner->currentToken();
+ Token token = m_scanner->currentToken();
switch(token)
{
case Token::Payable:
@@ -386,7 +386,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN
result.parameters = parseParameterList(options);
while (true)
{
- Token::Value token = m_scanner->currentToken();
+ Token token = m_scanner->currentToken();
if (_allowModifiers && token == Token::Identifier)
{
// If the name is empty (and this is not a constructor),
@@ -401,7 +401,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN
else
result.modifiers.push_back(parseModifierInvocation());
}
- else if (Token::isVisibilitySpecifier(token))
+ else if (TokenTraits::isVisibilitySpecifier(token))
{
if (result.visibility != Declaration::Visibility::Default)
{
@@ -423,7 +423,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN
else
result.visibility = parseVisibilitySpecifier();
}
- else if (Token::isStateMutabilitySpecifier(token))
+ else if (TokenTraits::isStateMutabilitySpecifier(token))
{
if (result.stateMutability != StateMutability::NonPayable)
{
@@ -587,8 +587,8 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
while (true)
{
- Token::Value token = m_scanner->currentToken();
- if (_options.isStateVariable && Token::isVariableVisibilitySpecifier(token))
+ Token token = m_scanner->currentToken();
+ if (_options.isStateVariable && TokenTraits::isVariableVisibilitySpecifier(token))
{
nodeFactory.markEndPosition();
if (visibility != Declaration::Visibility::Default)
@@ -609,7 +609,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
isIndexed = true;
else if (token == Token::Constant)
isDeclaredConst = true;
- else if (_options.allowLocationSpecifier && Token::isLocationSpecifier(token))
+ else if (_options.allowLocationSpecifier && TokenTraits::isLocationSpecifier(token))
{
if (location != VariableDeclaration::Location::Unspecified)
parserError(string("Location already specified."));
@@ -806,8 +806,8 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this);
ASTPointer<TypeName> type;
- Token::Value token = m_scanner->currentToken();
- if (Token::isElementaryTypeName(token))
+ Token token = m_scanner->currentToken();
+ if (TokenTraits::isElementaryTypeName(token))
{
unsigned firstSize;
unsigned secondSize;
@@ -817,7 +817,7 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar)
nodeFactory.markEndPosition();
m_scanner->next();
auto stateMutability = boost::make_optional(elemTypeName.token() == Token::Address, StateMutability::NonPayable);
- if (Token::isStateMutabilitySpecifier(m_scanner->currentToken(), false))
+ if (TokenTraits::isStateMutabilitySpecifier(m_scanner->currentToken(), false))
{
if (elemTypeName.token() == Token::Address)
{
@@ -874,8 +874,8 @@ ASTPointer<Mapping> Parser::parseMapping()
expectToken(Token::Mapping);
expectToken(Token::LParen);
ASTPointer<ElementaryTypeName> keyType;
- Token::Value token = m_scanner->currentToken();
- if (!Token::isElementaryTypeName(token))
+ Token token = m_scanner->currentToken();
+ if (!TokenTraits::isElementaryTypeName(token))
fatalParserError(string("Expected elementary type name for mapping key type"));
unsigned firstSize;
unsigned secondSize;
@@ -1252,7 +1252,7 @@ pair<Parser::LookAheadInfo, Parser::IndexAccessedPath> Parser::tryParseIndexAcce
// VariableDeclarationStatement out of it.
IndexAccessedPath iap = parseIndexAccessedPath();
- if (m_scanner->currentToken() == Token::Identifier || Token::isLocationSpecifier(m_scanner->currentToken()))
+ if (m_scanner->currentToken() == Token::Identifier || TokenTraits::isLocationSpecifier(m_scanner->currentToken()))
return make_pair(LookAheadInfo::VariableDeclaration, move(iap));
else
return make_pair(LookAheadInfo::Expression, move(iap));
@@ -1342,16 +1342,16 @@ ASTPointer<Expression> Parser::parseExpression(
{
RecursionGuard recursionGuard(*this);
ASTPointer<Expression> expression = parseBinaryExpression(4, _partiallyParsedExpression);
- if (Token::isAssignmentOp(m_scanner->currentToken()))
+ if (TokenTraits::isAssignmentOp(m_scanner->currentToken()))
{
- Token::Value assignmentOperator = m_scanner->currentToken();
+ Token assignmentOperator = m_scanner->currentToken();
m_scanner->next();
ASTPointer<Expression> rightHandSide = parseExpression();
ASTNodeFactory nodeFactory(*this, expression);
nodeFactory.setEndPositionFromNode(rightHandSide);
return nodeFactory.createNode<Assignment>(expression, assignmentOperator, rightHandSide);
}
- else if (m_scanner->currentToken() == Token::Value::Conditional)
+ else if (m_scanner->currentToken() == Token::Conditional)
{
m_scanner->next();
ASTPointer<Expression> trueExpression = parseExpression();
@@ -1373,11 +1373,11 @@ ASTPointer<Expression> Parser::parseBinaryExpression(
RecursionGuard recursionGuard(*this);
ASTPointer<Expression> expression = parseUnaryExpression(_partiallyParsedExpression);
ASTNodeFactory nodeFactory(*this, expression);
- int precedence = Token::precedence(m_scanner->currentToken());
+ int precedence = TokenTraits::precedence(m_scanner->currentToken());
for (; precedence >= _minPrecedence; --precedence)
- while (Token::precedence(m_scanner->currentToken()) == precedence)
+ while (TokenTraits::precedence(m_scanner->currentToken()) == precedence)
{
- Token::Value op = m_scanner->currentToken();
+ Token op = m_scanner->currentToken();
m_scanner->next();
ASTPointer<Expression> right = parseBinaryExpression(precedence + 1);
nodeFactory.setEndPositionFromNode(right);
@@ -1393,8 +1393,8 @@ ASTPointer<Expression> Parser::parseUnaryExpression(
RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory = _partiallyParsedExpression ?
ASTNodeFactory(*this, _partiallyParsedExpression) : ASTNodeFactory(*this);
- Token::Value token = m_scanner->currentToken();
- if (!_partiallyParsedExpression && (Token::isUnaryOp(token) || Token::isCountOp(token)))
+ Token token = m_scanner->currentToken();
+ if (!_partiallyParsedExpression && (TokenTraits::isUnaryOp(token) || TokenTraits::isCountOp(token)))
{
// prefix expression
m_scanner->next();
@@ -1407,7 +1407,7 @@ ASTPointer<Expression> Parser::parseUnaryExpression(
// potential postfix expression
ASTPointer<Expression> subExpression = parseLeftHandSideExpression(_partiallyParsedExpression);
token = m_scanner->currentToken();
- if (!Token::isCountOp(token))
+ if (!TokenTraits::isCountOp(token))
return subExpression;
nodeFactory.markEndPosition();
m_scanner->next();
@@ -1482,7 +1482,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
{
RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this);
- Token::Value token = m_scanner->currentToken();
+ Token token = m_scanner->currentToken();
ASTPointer<Expression> expression;
switch (token)
@@ -1493,7 +1493,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
expression = nodeFactory.createNode<Literal>(token, getLiteralAndAdvance());
break;
case Token::Number:
- if (Token::isEtherSubdenomination(m_scanner->peekNextToken()))
+ if (TokenTraits::isEtherSubdenomination(m_scanner->peekNextToken()))
{
ASTPointer<ASTString> literal = getLiteralAndAdvance();
nodeFactory.markEndPosition();
@@ -1501,7 +1501,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
m_scanner->next();
expression = nodeFactory.createNode<Literal>(token, literal, subdenomination);
}
- else if (Token::isTimeSubdenomination(m_scanner->peekNextToken()))
+ else if (TokenTraits::isTimeSubdenomination(m_scanner->peekNextToken()))
{
ASTPointer<ASTString> literal = getLiteralAndAdvance();
nodeFactory.markEndPosition();
@@ -1531,7 +1531,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
// (x,) is one-dimensional tuple, elements in arrays cannot be left out, only in tuples.
m_scanner->next();
vector<ASTPointer<Expression>> components;
- Token::Value oppositeToken = (token == Token::LParen ? Token::RParen : Token::RBrack);
+ Token oppositeToken = (token == Token::LParen ? Token::RParen : Token::RBrack);
bool isArray = (token == Token::LBrack);
if (m_scanner->currentToken() != oppositeToken)
@@ -1558,7 +1558,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
fatalParserError("Expected even number of hex-nibbles within double-quotes.");
break;
default:
- if (Token::isElementaryTypeName(token))
+ if (TokenTraits::isElementaryTypeName(token))
{
//used for casts
unsigned firstSize;
@@ -1595,7 +1595,7 @@ pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> Parser::pars
{
RecursionGuard recursionGuard(*this);
pair<vector<ASTPointer<Expression>>, vector<ASTPointer<ASTString>>> ret;
- Token::Value token = m_scanner->currentToken();
+ Token token = m_scanner->currentToken();
if (token == Token::LBrace)
{
// call({arg1 : 1, arg2 : 2 })
@@ -1638,21 +1638,21 @@ Parser::LookAheadInfo Parser::peekStatementType() const
// or a mutability specifier, we also have a variable declaration.
// If we get an identifier followed by a "[" or ".", it can be both ("lib.type[9] a;" or "variable.el[9] = 7;").
// In all other cases, we have an expression statement.
- Token::Value token(m_scanner->currentToken());
- bool mightBeTypeName = (Token::isElementaryTypeName(token) || token == Token::Identifier);
+ Token token(m_scanner->currentToken());
+ bool mightBeTypeName = (TokenTraits::isElementaryTypeName(token) || token == Token::Identifier);
if (token == Token::Mapping || token == Token::Function || token == Token::Var)
return LookAheadInfo::VariableDeclaration;
if (mightBeTypeName)
{
- Token::Value next = m_scanner->peekNextToken();
+ Token next = m_scanner->peekNextToken();
// So far we only allow ``address payable`` in variable declaration statements and in no other
// kind of statement. This means, for example, that we do not allow type expressions of the form
// ``address payable;``.
// If we want to change this in the future, we need to consider another scanner token here.
- if (Token::isElementaryTypeName(token) && Token::isStateMutabilitySpecifier(next, false))
+ if (TokenTraits::isElementaryTypeName(token) && TokenTraits::isStateMutabilitySpecifier(next, false))
return LookAheadInfo::VariableDeclaration;
- if (next == Token::Identifier || Token::isLocationSpecifier(next))
+ if (next == Token::Identifier || TokenTraits::isLocationSpecifier(next))
return LookAheadInfo::VariableDeclaration;
if (next == Token::LBrack || next == Token::Period)
return LookAheadInfo::IndexAccessStructure;
diff --git a/libsolidity/parsing/ParserBase.cpp b/libsolidity/parsing/ParserBase.cpp
index 71133746..1d4cb1e2 100644
--- a/libsolidity/parsing/ParserBase.cpp
+++ b/libsolidity/parsing/ParserBase.cpp
@@ -43,12 +43,12 @@ int ParserBase::endPosition() const
return m_scanner->currentLocation().end;
}
-Token::Value ParserBase::currentToken() const
+Token ParserBase::currentToken() const
{
return m_scanner->currentToken();
}
-Token::Value ParserBase::peekNextToken() const
+Token ParserBase::peekNextToken() const
{
return m_scanner->peekNextToken();
}
@@ -58,31 +58,31 @@ std::string ParserBase::currentLiteral() const
return m_scanner->currentLiteral();
}
-Token::Value ParserBase::advance()
+Token ParserBase::advance()
{
return m_scanner->next();
}
-void ParserBase::expectToken(Token::Value _value, bool _advance)
+void ParserBase::expectToken(Token _value, bool _advance)
{
- Token::Value tok = m_scanner->currentToken();
+ Token tok = m_scanner->currentToken();
if (tok != _value)
{
- auto tokenName = [this](Token::Value _token)
+ auto tokenName = [this](Token _token)
{
if (_token == Token::Identifier)
return string("identifier");
else if (_token == Token::EOS)
return string("end of source");
- else if (Token::isReservedKeyword(_token))
- return string("reserved keyword '") + Token::friendlyName(_token) + "'";
- else if (Token::isElementaryTypeName(_token)) //for the sake of accuracy in reporting
+ 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("'") + Token::friendlyName(_token) + "'";
+ return string("'") + TokenTraits::friendlyName(_token) + "'";
};
fatalParserError(string("Expected ") + tokenName(_value) + string(" but got ") + tokenName(tok));
diff --git a/libsolidity/parsing/ParserBase.h b/libsolidity/parsing/ParserBase.h
index b28e1b1b..e01f37d8 100644
--- a/libsolidity/parsing/ParserBase.h
+++ b/libsolidity/parsing/ParserBase.h
@@ -63,11 +63,11 @@ protected:
///@{
///@name Helper functions
/// If current token value is not _value, throw exception otherwise advance token.
- void expectToken(Token::Value _value, bool _advance = true);
- Token::Value currentToken() const;
- Token::Value peekNextToken() const;
+ void expectToken(Token _value, bool _advance = true);
+ Token currentToken() const;
+ Token peekNextToken() const;
std::string currentLiteral() const;
- Token::Value advance();
+ Token advance();
///@}
/// Increases the recursion depth and throws an exception if it is too deep.
diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp
index 87d7c535..e9dad2ad 100644
--- a/libsolidity/parsing/Scanner.cpp
+++ b/libsolidity/parsing/Scanner.cpp
@@ -214,9 +214,9 @@ void Scanner::addUnicodeAsUTF8(unsigned codepoint)
}
// Ensure that tokens can be stored in a byte.
-BOOST_STATIC_ASSERT(Token::NUM_TOKENS <= 0x100);
+BOOST_STATIC_ASSERT(TokenTraits::count() <= 0x100);
-Token::Value Scanner::next()
+Token Scanner::next()
{
m_currentToken = m_nextToken;
m_skippedComment = m_nextSkippedComment;
@@ -225,7 +225,7 @@ Token::Value Scanner::next()
return m_currentToken.token;
}
-Token::Value Scanner::selectToken(char _next, Token::Value _then, Token::Value _else)
+Token Scanner::selectToken(char _next, Token _then, Token _else)
{
advance();
if (m_char == _next)
@@ -249,7 +249,7 @@ void Scanner::skipWhitespaceExceptUnicodeLinebreak()
advance();
}
-Token::Value Scanner::skipSingleLineComment()
+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.
@@ -259,7 +259,7 @@ Token::Value Scanner::skipSingleLineComment()
return Token::Whitespace;
}
-Token::Value Scanner::scanSingleLineDocComment()
+Token Scanner::scanSingleLineDocComment()
{
LiteralScope literal(this, LITERAL_TYPE_COMMENT);
advance(); //consume the last '/' at ///
@@ -295,7 +295,7 @@ Token::Value Scanner::scanSingleLineDocComment()
return Token::CommentLiteral;
}
-Token::Value Scanner::skipMultiLineComment()
+Token Scanner::skipMultiLineComment()
{
advance();
while (!isSourcePastEndOfInput())
@@ -316,7 +316,7 @@ Token::Value Scanner::skipMultiLineComment()
return Token::Illegal;
}
-Token::Value Scanner::scanMultiLineDocComment()
+Token Scanner::scanMultiLineDocComment()
{
LiteralScope literal(this, LITERAL_TYPE_COMMENT);
bool endFound = false;
@@ -369,7 +369,7 @@ Token::Value Scanner::scanMultiLineDocComment()
return Token::CommentLiteral;
}
-Token::Value Scanner::scanSlash()
+Token Scanner::scanSlash()
{
int firstSlashPosition = sourcePos();
advance();
@@ -380,7 +380,7 @@ Token::Value Scanner::scanSlash()
else if (m_char == '/')
{
// doxygen style /// comment
- Token::Value comment;
+ Token comment;
m_nextSkippedComment.location.start = firstSlashPosition;
comment = scanSingleLineDocComment();
m_nextSkippedComment.location.end = sourcePos();
@@ -406,7 +406,7 @@ Token::Value Scanner::scanSlash()
return Token::Whitespace;
}
// we actually have a multiline documentation comment
- Token::Value comment;
+ Token comment;
m_nextSkippedComment.location.start = firstSlashPosition;
comment = scanMultiLineDocComment();
m_nextSkippedComment.location.end = sourcePos();
@@ -432,7 +432,7 @@ void Scanner::scanToken()
m_nextSkippedComment.literal.clear();
m_nextSkippedComment.extendedTokenInfo = make_tuple(0, 0);
- Token::Value token;
+ Token token;
// M and N are for the purposes of grabbing different type sizes
unsigned m;
unsigned n;
@@ -703,7 +703,7 @@ bool Scanner::isUnicodeLinebreak()
return false;
}
-Token::Value Scanner::scanString()
+Token Scanner::scanString()
{
char const quote = m_char;
advance(); // consume quote
@@ -727,7 +727,7 @@ Token::Value Scanner::scanString()
return Token::StringLiteral;
}
-Token::Value Scanner::scanHexString()
+Token Scanner::scanHexString()
{
char const quote = m_char;
advance(); // consume quote
@@ -760,7 +760,7 @@ void Scanner::scanDecimalDigits()
// Defer further validation of underscore to SyntaxChecker.
}
-Token::Value Scanner::scanNumber(char _charSeen)
+Token Scanner::scanNumber(char _charSeen)
{
enum { DECIMAL, HEX, BINARY } kind = DECIMAL;
LiteralScope literal(this, LITERAL_TYPE_NUMBER);
@@ -854,7 +854,7 @@ Token::Value Scanner::scanNumber(char _charSeen)
return Token::Number;
}
-tuple<Token::Value, unsigned, unsigned> Scanner::scanIdentifierOrKeyword()
+tuple<Token, unsigned, unsigned> Scanner::scanIdentifierOrKeyword()
{
solAssert(isIdentifierStart(m_char), "");
LiteralScope literal(this, LITERAL_TYPE_STRING);
@@ -863,7 +863,7 @@ tuple<Token::Value, unsigned, unsigned> Scanner::scanIdentifierOrKeyword()
while (isIdentifierPart(m_char)) //get full literal
addLiteralCharAndAdvance();
literal.complete();
- return Token::fromIdentifierOrKeyword(m_nextToken.literal);
+ return TokenTraits::fromIdentifierOrKeyword(m_nextToken.literal);
}
char CharStream::advanceAndGet(size_t _chars)
diff --git a/libsolidity/parsing/Scanner.h b/libsolidity/parsing/Scanner.h
index 7564c788..02e0553f 100644
--- a/libsolidity/parsing/Scanner.h
+++ b/libsolidity/parsing/Scanner.h
@@ -112,13 +112,13 @@ public:
void reset();
/// @returns the next token and advances input
- Token::Value next();
+ Token next();
///@{
///@name Information about the current token
/// @returns the current token
- Token::Value currentToken() const
+ Token currentToken() const
{
return m_currentToken.token;
}
@@ -149,7 +149,7 @@ public:
///@name Information about the next token
/// @returns the next token without advancing input.
- Token::Value peekNextToken() const { return m_nextToken.token; }
+ Token peekNextToken() const { return m_nextToken.token; }
SourceLocation peekLocation() const { return m_nextToken.location; }
std::string const& peekLiteral() const { return m_nextToken.literal; }
///@}
@@ -168,7 +168,7 @@ private:
/// Used for the current and look-ahead token and comments
struct TokenDesc
{
- Token::Value token;
+ Token token;
SourceLocation location;
std::string literal;
std::tuple<unsigned, unsigned> extendedTokenInfo;
@@ -185,9 +185,9 @@ private:
bool advance() { m_char = m_source.advanceAndGet(); return !m_source.isPastEndOfInput(); }
void rollback(int _amount) { m_char = m_source.rollback(_amount); }
- inline Token::Value selectToken(Token::Value _tok) { advance(); return _tok; }
+ inline Token selectToken(Token _tok) { advance(); return _tok; }
/// If the next character is _next, advance and return _then, otherwise return _else.
- inline Token::Value selectToken(char _next, Token::Value _then, Token::Value _else);
+ inline Token selectToken(char _next, Token _then, Token _else);
bool scanHexByte(char& o_scannedByte);
bool scanUnicode(unsigned& o_codepoint);
@@ -199,19 +199,19 @@ private:
bool skipWhitespace();
/// Skips all whitespace that are neither '\r' nor '\n'.
void skipWhitespaceExceptUnicodeLinebreak();
- Token::Value skipSingleLineComment();
- Token::Value skipMultiLineComment();
+ Token skipSingleLineComment();
+ Token skipMultiLineComment();
void scanDecimalDigits();
- Token::Value scanNumber(char _charSeen = 0);
- std::tuple<Token::Value, unsigned, unsigned> scanIdentifierOrKeyword();
+ Token scanNumber(char _charSeen = 0);
+ std::tuple<Token, unsigned, unsigned> scanIdentifierOrKeyword();
- Token::Value scanString();
- Token::Value scanHexString();
- Token::Value scanSingleLineDocComment();
- Token::Value scanMultiLineDocComment();
+ Token scanString();
+ Token scanHexString();
+ Token scanSingleLineDocComment();
+ Token scanMultiLineDocComment();
/// Scans a slash '/' and depending on the characters returns the appropriate token
- Token::Value scanSlash();
+ 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
diff --git a/libsolidity/parsing/Token.cpp b/libsolidity/parsing/Token.cpp
index 27acb7d4..dccd9037 100644
--- a/libsolidity/parsing/Token.cpp
+++ b/libsolidity/parsing/Token.cpp
@@ -51,9 +51,9 @@ namespace dev
namespace solidity
{
-void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned const& _first, unsigned const& _second)
+void ElementaryTypeNameToken::assertDetails(Token _baseType, unsigned const& _first, unsigned const& _second)
{
- solAssert(Token::isElementaryTypeName(_baseType), "Expected elementary type name: " + string(Token::toString(_baseType)));
+ 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.");
@@ -61,17 +61,17 @@ void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned con
}
else if (_baseType == Token::UIntM || _baseType == Token::IntM)
{
- solAssert(_second == 0, "There should not be a second size argument to type " + string(Token::toString(_baseType)) + ".");
+ 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(Token::toString(_baseType)) + to_string(_first) + "."
+ "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(Token::toString(_baseType)) + to_string(_first) + "x" + to_string(_second) + "."
+ "No elementary type " + string(TokenTraits::toString(_baseType)) + to_string(_first) + "x" + to_string(_second) + "."
);
}
m_token = _baseType;
@@ -79,38 +79,54 @@ void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned con
m_secondNumber = _second;
}
-#define T(name, string, precedence) #name,
-char const* const Token::m_name[NUM_TOKENS] =
+namespace TokenTraits
{
- TOKEN_LIST(T, T)
-};
-#undef T
+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 "";
+ }
+}
-#define T(name, string, precedence) string,
-char const* const Token::m_string[NUM_TOKENS] =
+char const* name(Token tok)
{
- TOKEN_LIST(T, T)
-};
+#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)];
+}
-#define T(name, string, precedence) precedence,
-int8_t const Token::m_precedence[NUM_TOKENS] =
+std::string friendlyName(Token tok)
{
- TOKEN_LIST(T, T)
-};
-#undef T
+ char const* ret = toString(tok);
+ if (ret)
+ return std::string(ret);
+ ret = name(tok);
+ solAssert(ret != nullptr, "");
+ return std::string(ret);
+}
-#define KT(a, b, c) 'T',
-#define KK(a, b, c) 'K',
-char const Token::m_tokenType[] =
+#define T(name, string, precedence) precedence,
+int precedence(Token tok)
{
- TOKEN_LIST(KT, KK)
-};
+ int8_t const static precs[TokenTraits::count()] =
+ {
+ TOKEN_LIST(T, T)
+ };
+ return precs[static_cast<size_t>(tok)];
+}
+#undef T
-int Token::parseSize(string::const_iterator _begin, string::const_iterator _end)
+int parseSize(string::const_iterator _begin, string::const_iterator _end)
{
try
{
@@ -123,7 +139,20 @@ int Token::parseSize(string::const_iterator _begin, string::const_iterator _end)
}
}
-tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(string const& _literal)
+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())
@@ -131,7 +160,7 @@ tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(s
string baseType(_literal.begin(), positionM);
auto positionX = find_if_not(positionM, _literal.end(), ::isdigit);
int m = parseSize(positionM, positionX);
- Token::Value keyword = keywordByName(baseType);
+ Token keyword = keywordByName(baseType);
if (keyword == Token::Bytes)
{
if (0 < m && m <= 32 && positionX == _literal.end())
@@ -172,20 +201,7 @@ tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(s
return make_tuple(keywordByName(_literal), 0, 0);
}
-Token::Value 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::Value> keywords({TOKEN_LIST(TOKEN, KEYWORD)});
-#undef KEYWORD
-#undef TOKEN
- auto it = keywords.find(_name);
- return it == keywords.end() ? Token::Identifier : it->second;
-}
-#undef KT
-#undef KK
+}
}
}
diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h
index 8ecc850a..81e8dd98 100644
--- a/libsolidity/parsing/Token.h
+++ b/libsolidity/parsing/Token.h
@@ -45,6 +45,7 @@
#include <libdevcore/Common.h>
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/parsing/UndefMacros.h>
+#include <iosfwd>
namespace dev
{
@@ -267,119 +268,95 @@ namespace solidity
/* Scanner-internal use only. */ \
T(Whitespace, NULL, 0)
-
-class Token
-{
-public:
- // 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
+// 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,
- enum Value
- {
- TOKEN_LIST(T, T)
- NUM_TOKENS
- };
+ TOKEN_LIST(T, T)
+ NUM_TOKENS
#undef T
+};
- // @returns a string corresponding to the C++ token name
- // (e.g. "LT" for the token LT).
- static char const* name(Value tok)
- {
- solAssert(tok < NUM_TOKENS, "");
- return m_name[tok];
- }
+namespace TokenTraits
+{
+ constexpr size_t count() { return static_cast<size_t>(Token::NUM_TOKENS); }
// Predicates
- static bool isElementaryTypeName(Value tok) { return Int <= tok && tok < TypesEnd; }
- static bool isAssignmentOp(Value tok) { return Assign <= tok && tok <= AssignMod; }
- static bool isBinaryOp(Value op) { return Comma <= op && op <= Exp; }
- static bool isCommutativeOp(Value op) { return op == BitOr || op == BitXor || op == BitAnd ||
- op == Add || op == Mul || op == Equal || op == NotEqual; }
- static bool isArithmeticOp(Value op) { return Add <= op && op <= Exp; }
- static bool isCompareOp(Value op) { return Equal <= op && op <= GreaterThanOrEqual; }
+ 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; }
- static Value AssignmentToBinaryOp(Value op)
- {
- solAssert(isAssignmentOp(op) && op != Assign, "");
- return Value(op + (BitOr - AssignBitOr));
- }
+ 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; }
- static bool isBitOp(Value op) { return (BitOr <= op && op <= BitAnd) || op == BitNot; }
- static bool isBooleanOp(Value op) { return (Or <= op && op <= And) || op == Not; }
- static bool isUnaryOp(Value op) { return (Not <= op && op <= Delete) || op == Add || op == Sub; }
- static bool isCountOp(Value op) { return op == Inc || op == Dec; }
- static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); }
- static bool isVisibilitySpecifier(Value op) { return isVariableVisibilitySpecifier(op) || op == External; }
- static bool isVariableVisibilitySpecifier(Value op) { return op == Public || op == Private || op == Internal; }
- static bool isLocationSpecifier(Value op) { return op == Memory || op == Storage || op == CallData; }
- static bool isStateMutabilitySpecifier(Value op, bool _allowConstant = true)
+ constexpr bool isStateMutabilitySpecifier(Token op, bool _allowConstant = true)
{
- if (op == Constant && _allowConstant)
- return true;
- return op == Pure || op == View || op == Payable;
+ return (op == Token::Constant && _allowConstant)
+ || op == Token::Pure || op == Token::View || op == Token::Payable;
}
- static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == SubEther; }
- static bool isTimeSubdenomination(Value op) { return op == SubSecond || op == SubMinute || op == SubHour || op == SubDay || op == SubWeek || op == SubYear; }
- static bool isReservedKeyword(Value op) { return (Abstract <= op && op <= Unchecked); }
- // @returns a string corresponding to the JS token string
- // (.e., "<" for the token LT) or NULL if the token doesn't
- // have a (unique) string (e.g. an IDENTIFIER).
- static char const* toString(Value tok)
- {
- solAssert(tok < NUM_TOKENS, "");
- return m_string[tok];
- }
+ 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); }
- static std::string friendlyName(Value tok)
+ inline Token AssignmentToBinaryOp(Token op)
{
- char const* ret = toString(tok);
- if (ret == nullptr)
- {
- ret = name(tok);
- solAssert(ret != nullptr, "");
- }
- return std::string(ret);
+ 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.
- static int precedence(Value tok)
- {
- solAssert(tok < NUM_TOKENS, "");
- return m_precedence[tok];
- }
+ int precedence(Token tok);
- static std::tuple<Token::Value, unsigned int, unsigned int> fromIdentifierOrKeyword(std::string const& _literal);
+ std::tuple<Token, unsigned int, unsigned int> fromIdentifierOrKeyword(std::string const& _literal);
-private:
- // @returns -1 on error (invalid digit or number too large)
- static int parseSize(std::string::const_iterator _begin, std::string::const_iterator _end);
- // @returns the keyword with name @a _name or Token::Identifier of no such keyword exists.
- static Token::Value keywordByName(std::string const& _name);
- static char const* const m_name[NUM_TOKENS];
- static char const* const m_string[NUM_TOKENS];
- static int8_t const m_precedence[NUM_TOKENS];
- static char const m_tokenType[NUM_TOKENS];
-};
+ // @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::Value _token, unsigned const& _firstNumber, unsigned const& _secondNumber)
+ 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::Value token() const { return m_token; }
+ 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 = Token::toString(m_token);
+ 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.");
@@ -390,11 +367,11 @@ public:
}
private:
- Token::Value m_token;
+ Token m_token;
unsigned int m_firstNumber;
unsigned int m_secondNumber;
/// throws if type is not properly sized
- void assertDetails(Token::Value _baseType, unsigned const& _first, unsigned const& _second);
+ void assertDetails(Token _baseType, unsigned const& _first, unsigned const& _second);
};
}