diff options
Diffstat (limited to 'libsolidity/parsing/Token.cpp')
-rw-r--r-- | libsolidity/parsing/Token.cpp | 83 |
1 files changed, 52 insertions, 31 deletions
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 |