aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/ast/Types.cpp14
-rw-r--r--libsolidity/parsing/Parser.cpp2
-rw-r--r--libsolidity/parsing/Scanner.cpp31
-rw-r--r--libsolidity/parsing/Token.cpp83
-rw-r--r--libsolidity/parsing/Token.h30
5 files changed, 84 insertions, 76 deletions
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index df96d412..774be521 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -122,7 +122,7 @@ TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
"Expected an elementary type name but got " + tokenString);
Token::Value token = _type.returnTok();
- unsigned int M = _type.returnM();
+ unsigned int M = _type.firstNumber();
switch (token)
{
@@ -156,14 +156,10 @@ TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
TypePointer Type::fromElementaryTypeName(string const& _name)
{
- string keyword = _name.substr(0, _name.find_first_of("0123456789"));
- string info = "";
- if (_name.find_first_of("0123456789") != string::npos)
- {
- keyword += "M";
- info = _name.substr(_name.find_first_of("0123456789"));
- }
- return fromElementaryTypeName(ElementaryTypeNameToken(Token::fromIdentifierOrKeyword(keyword), info));
+ string details;
+ Token::Value token;
+ tie(token, details) = Token::fromIdentifierOrKeyword(_name);
+ return fromElementaryTypeName(ElementaryTypeNameToken(token, details));
}
TypePointer Type::forLiteral(Literal const& _literal)
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 9f944a0c..74ec5cda 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -195,7 +195,6 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition(bool _isLibrary)
while (true)
{
Token::Value currentTokenValue = m_scanner->currentToken();
- string lit = m_scanner->currentLiteral();
if (currentTokenValue == Token::RBrace)
break;
else if (currentTokenValue == Token::Function)
@@ -1138,6 +1137,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
default:
if (Token::isElementaryTypeName(token))
{
+ //used for casts
ElementaryTypeNameToken elementaryExpression(m_scanner->currentToken(), m_scanner->currentTokenInfo());
expression = nodeFactory.createNode<ElementaryTypeNameExpression>(elementaryExpression);
m_scanner->next();
diff --git a/libsolidity/parsing/Scanner.cpp b/libsolidity/parsing/Scanner.cpp
index 5d40e55b..9307b100 100644
--- a/libsolidity/parsing/Scanner.cpp
+++ b/libsolidity/parsing/Scanner.cpp
@@ -82,11 +82,14 @@ bool isWhiteSpace(char c)
{
return c == ' ' || c == '\n' || c == '\t' || c == '\r';
}
-bool isIdentifierPart(char c)
+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')
@@ -383,7 +386,7 @@ void Scanner::scanToken()
m_nextSkippedComment.extendedTokenInfo.clear();
Token::Value token;
- string tokenExtension = "";
+ string tokenExtension;
do
{
// Remember the position of the next token
@@ -550,7 +553,7 @@ void Scanner::scanToken()
token = selectToken(Token::BitNot);
break;
default:
- if (isIdentifierPart(m_char))
+ if (isIdentifierStart(m_char))
tie(token, tokenExtension) = scanIdentifierOrKeyword();
else if (isDecimalDigit(m_char))
token = scanNumber();
@@ -700,7 +703,7 @@ Token::Value Scanner::scanNumber(char _charSeen)
// 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) || isIdentifierPart(m_char))
+ if (isDecimalDigit(m_char) || isIdentifierStart(m_char))
return Token::Illegal;
literal.complete();
return Token::Number;
@@ -708,26 +711,14 @@ Token::Value Scanner::scanNumber(char _charSeen)
tuple<Token::Value, string> Scanner::scanIdentifierOrKeyword()
{
- solAssert(isIdentifierPart(m_char), "");
+ solAssert(isIdentifierStart(m_char), "");
LiteralScope literal(this, LITERAL_TYPE_STRING);
addLiteralCharAndAdvance();
// Scan the rest of the identifier characters.
- string keyword = "";
- string description = "";
- while (isIdentifierPart(m_char)) //get main keyword
- addLiteralCharAndAdvance();
- keyword = m_nextToken.literal;
- while (isDecimalDigit(m_char) || isIdentifierPart(m_char)) //get the description
+ while (isIdentifierPart(m_char)) //get full literal
addLiteralCharAndAdvance();
literal.complete();
- if (m_nextToken.literal.find_first_of("0123456789") != string::npos)
- {
- description = m_nextToken.literal.substr(m_nextToken.literal.find_first_of("0123456789"));
- keyword += "M";
- if (description.find('x') != string::npos)
- keyword += "xN";
- }
- return make_tuple(Token::fromIdentifierOrKeyword(keyword), description);
+ return Token::fromIdentifierOrKeyword(m_nextToken.literal);
}
char CharStream::advanceAndGet(size_t _chars)
diff --git a/libsolidity/parsing/Token.cpp b/libsolidity/parsing/Token.cpp
index 7ea94112..eaa65344 100644
--- a/libsolidity/parsing/Token.cpp
+++ b/libsolidity/parsing/Token.cpp
@@ -50,42 +50,36 @@ namespace dev
namespace solidity
{
-bool ElementaryTypeNameToken::isElementaryTypeName(Token::Value _baseType, string const& _info)
+tuple<string, unsigned int, unsigned int> ElementaryTypeNameToken::parseDetails(Token::Value _baseType, string const& _details)
{
- if (!Token::isElementaryTypeName(_baseType))
- return false;
+ solAssert(Token::isElementaryTypeName(_baseType), "");
string baseType = Token::toString(_baseType);
- if (baseType.find('M') == string::npos)
- return true;
- short m;
- m = stoi(_info.substr(_info.find_first_of("0123456789")));
+ if (_details.length() == 0)
+ return make_tuple(baseType, 0, 0);
if (baseType == "bytesM")
- return (0 < m && m <= 32) ? true : false;
+ {
+ for (unsigned m = 1; m <= 32; m++)
+ if (to_string(m) == _details)
+ return make_tuple(baseType.substr(0, baseType.size()-1) + to_string(m), m, 0);
+ }
else if (baseType == "uintM" || baseType == "intM")
- return (0 < m && m <= 256 && m % 8 == 0) ? true : false;
+ {
+ for (unsigned m = 8; m <= 256; m+=8)
+ if (to_string(m) == _details)
+ return make_tuple(baseType.substr(0, baseType.size()-1) + to_string(m), m, 0);
+ }
else if (baseType == "ufixedMxN" || baseType == "fixedMxN")
{
- short n;
- m = stoi(_info.substr(_info.find_first_of("0123456789"), _info.find_last_of("x") - 1));
- n = stoi(_info.substr(_info.find_last_of("x") + 1));
- return (0 < n + m && n + m <= 256 && ((n % 8 == 0) && (m % 8 == 0)));
+ for (unsigned m = 0; m <= 256; m+=8)
+ for (unsigned n = 8; m + n <= 256; n+=8)
+ if ((to_string(m) + "x" + to_string(n)) == _details)
+ return make_tuple(baseType.substr(0, baseType.size()-3) + to_string(m) + "x" + to_string(n), m, n);
}
- return false;
-}
-
-tuple<string, unsigned int, unsigned int> ElementaryTypeNameToken::setTypes(Token::Value _baseType, string const& _toSet)
-{
- string baseType = Token::toString(_baseType);
- if (_toSet.find_first_of("0123456789") == string::npos)
- return make_tuple(baseType, 0, 0);
- baseType = baseType.substr(0, baseType.find('M') - 1) + _toSet;
- size_t index = _toSet.find('x') == string::npos ? string::npos : _toSet.find('x') - 1;
- unsigned int m = stoi(_toSet.substr(0, index));
- unsigned int n = 0;
- if (baseType == "fixed" || baseType == "ufixed")
- n = stoi(_toSet.substr(_toSet.find('x') + 1));
- return make_tuple(baseType, m, n);
+
+ BOOST_THROW_EXCEPTION(Error(Error::Type::TypeError) <<
+ errinfo_comment("Cannot create elementary type name token out of type " + baseType + " and size " + _details)
+ );
}
#define T(name, string, precedence) #name,
@@ -118,8 +112,35 @@ char const Token::m_tokenType[] =
{
TOKEN_LIST(KT, KK)
};
-Token::Value Token::fromIdentifierOrKeyword(const string& _name)
+tuple<Token::Value, string> Token::fromIdentifierOrKeyword(const string& _literal)
{
+ string token = _literal;
+ string details;
+ if (_literal == "uintM" || _literal == "intM" || _literal == "fixedMxN" || _literal == "ufixedMxN" || _literal == "bytesM")
+ return make_pair(Token::Identifier, details);
+ if (_literal.find_first_of("0123456789") != string::npos)
+ {
+ string baseType = _literal.substr(0, _literal.find_first_of("0123456789"));
+ short m = stoi(_literal.substr(_literal.find_first_of("0123456789")));
+ if (baseType == "bytes")
+ {
+ details = (0 < m && m <= 32) ? to_string(m) : "";
+ token = details.empty() ? _literal : baseType + "M";
+ }
+ else if (baseType == "uint" || baseType == "int")
+ {
+ details = (0 < m && m <= 256 && m % 8 == 0) ? to_string(m) : "";
+ token = details.empty() ? _literal : baseType + "M";
+ }
+ else if (baseType == "ufixed" || baseType == "fixed")
+ {
+ m = stoi(to_string(m).substr(0, to_string(m).find_first_of("x") - 1));
+ short n = stoi(_literal.substr(_literal.find_last_of("x") + 1));
+ details = (0 < n + m && n + m <= 256 && ((n % 8 == 0) && (m % 8 == 0))) ?
+ to_string(m) + "x" + to_string(n) : "";
+ token = details.empty() ? _literal : baseType + "MxN" ;
+ }
+ }
// 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},
@@ -127,8 +148,8 @@ Token::Value Token::fromIdentifierOrKeyword(const string& _name)
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;
+ auto it = keywords.find(token);
+ return it == keywords.end() ? make_pair(Token::Identifier, details) : make_pair(it->second, details);
}
#undef KT
diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h
index 5f8141ae..55b801db 100644
--- a/libsolidity/parsing/Token.h
+++ b/libsolidity/parsing/Token.h
@@ -302,7 +302,7 @@ public:
return m_precedence[tok];
}
- static Token::Value fromIdentifierOrKeyword(std::string const& _name);
+ static std::tuple<Token::Value, std::string> fromIdentifierOrKeyword(std::string const& _name);
private:
static char const* const m_name[NUM_TOKENS];
@@ -314,25 +314,25 @@ private:
class ElementaryTypeNameToken
{
public:
- ElementaryTypeNameToken(Token::Value token, std::string const& description)
+ ElementaryTypeNameToken(Token::Value _token, std::string const& _detail)
{
- solAssert(isElementaryTypeName(token, description), "");
- std::tie(m_name, M, N) = setTypes(token, description);
- tok = token;
+ std::tie(m_name, m_firstNumber, m_secondNumber) = parseDetails(_token, _detail);
+ m_token = _token;
}
-
- std::string toString(bool const& tokValue = false) const& { return tokValue ? Token::toString(tok) : m_name; }
- unsigned int const& returnM() const& { return M; }
- unsigned int const& returnN() const& { return N; }
- Token::Value const& returnTok() const& { return tok; }
- static bool isElementaryTypeName(Token::Value _baseType, std::string const& _info);
+
+ unsigned int const& firstNumber() const { return m_firstNumber; }
+ unsigned int const& secondNumber() const { return m_secondNumber; }
+ Token::Value const& returnTok() 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& tokValue = false) const { return tokValue ? Token::toString(m_token) : m_name; }
private:
- Token::Value tok;
+ Token::Value m_token;
std::string m_name;
- unsigned int M;
- unsigned int N;
- std::tuple<std::string, unsigned int, unsigned int> setTypes(Token::Value _baseType, std::string const& _toSet);
+ unsigned int m_firstNumber;
+ unsigned int m_secondNumber;
+ /// throws if _details is malformed
+ std::tuple<std::string, unsigned int, unsigned int> parseDetails(Token::Value _baseType, std::string const& _details);
};
}