added const correctness to extract functions in Token

optimizations added in

more elegant solution created for m declaration

ubuntu wants to get rid of 0 <= first statement...so I will

change returnToken to token
This commit is contained in:
RJ Catalano 2016-02-15 10:34:45 -06:00
parent 84f2eb461b
commit d2c0712f36
4 changed files with 50 additions and 113 deletions

View File

@ -118,20 +118,20 @@ u256 const& MemberList::storageSize() const
TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type) TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
{ {
string tokenString = _type.toString(); string tokenString = _type.toString();
solAssert(Token::isElementaryTypeName(_type.returnTok()), solAssert(Token::isElementaryTypeName(_type.token()),
"Expected an elementary type name but got " + tokenString); "Expected an elementary type name but got " + tokenString);
Token::Value token = _type.returnTok(); Token::Value token = _type.token();
unsigned int M = _type.firstNumber(); unsigned int m = _type.firstNumber();
switch (token) switch (token)
{ {
case Token::IntM: case Token::IntM:
return make_shared<IntegerType>(M, IntegerType::Modifier::Signed); return make_shared<IntegerType>(m, IntegerType::Modifier::Signed);
case Token::UIntM: case Token::UIntM:
return make_shared<IntegerType>(M, IntegerType::Modifier::Unsigned); return make_shared<IntegerType>(m, IntegerType::Modifier::Unsigned);
case Token::BytesM: case Token::BytesM:
return make_shared<FixedBytesType>(M); return make_shared<FixedBytesType>(m);
case Token::Int: case Token::Int:
return make_shared<IntegerType>(256, IntegerType::Modifier::Signed); return make_shared<IntegerType>(256, IntegerType::Modifier::Signed);
case Token::UInt: case Token::UInt:

View File

@ -387,8 +387,8 @@ void Scanner::scanToken()
Token::Value token; Token::Value token;
// M and N are for the purposes of grabbing different type sizes // M and N are for the purposes of grabbing different type sizes
unsigned M; unsigned m;
unsigned N; unsigned n;
do do
{ {
// Remember the position of the next token // Remember the position of the next token
@ -556,7 +556,7 @@ void Scanner::scanToken()
break; break;
default: default:
if (isIdentifierStart(m_char)) if (isIdentifierStart(m_char))
tie(token, M, N) = scanIdentifierOrKeyword(); tie(token, m, n) = scanIdentifierOrKeyword();
else if (isDecimalDigit(m_char)) else if (isDecimalDigit(m_char))
token = scanNumber(); token = scanNumber();
else if (skipWhitespace()) else if (skipWhitespace())
@ -573,7 +573,7 @@ void Scanner::scanToken()
while (token == Token::Whitespace); while (token == Token::Whitespace);
m_nextToken.location.end = sourcePos(); m_nextToken.location.end = sourcePos();
m_nextToken.token = token; m_nextToken.token = token;
m_nextToken.extendedTokenInfo = make_tuple(M,N); m_nextToken.extendedTokenInfo = make_tuple(m, n);
} }
bool Scanner::scanEscape() bool Scanner::scanEscape()

View File

@ -50,65 +50,26 @@ namespace dev
namespace solidity namespace solidity
{ {
void ElementaryTypeNameToken::parseDetails(Token::Value _baseType, unsigned const& _first, unsigned const& _second) void ElementaryTypeNameToken::assertDetails(Token::Value _baseType, unsigned const& _first, unsigned const& _second)
{ {
solAssert(Token::isElementaryTypeName(_baseType), ""); solAssert(Token::isElementaryTypeName(_baseType), "");
string baseType = Token::toString(_baseType); string tokenString = Token::toString(_baseType);
if (_first == 0 && _second == 0) if (_baseType == Token::BytesM)
{
m_name = baseType;
m_firstNumber = _first;
m_secondNumber = _second;
}
if (baseType == "bytesM")
{ {
solAssert(_second == 0, "There should not be a second size argument to type bytesM."); solAssert(_second == 0, "There should not be a second size argument to type bytesM.");
for (unsigned m = 1; m <= 32; m++) solAssert(_first <= 32, "No elementary type bytes" + to_string(_first) + ".");
if (m == _first)
{
m_name = baseType.substr(0, baseType.size()-1) + to_string(_first);
m_firstNumber = _first;
m_secondNumber = _second;
}
} }
else if (baseType == "uintM" || baseType == "intM") else if (_baseType == Token::UIntM || _baseType == Token::IntM)
{ {
solAssert(_second == 0, "There should not be a second size argument to type " + baseType + "."); solAssert(_second == 0, "There should not be a second size argument to type " + tokenString + ".");
for (unsigned m = 8; m <= 256; m+=8) solAssert(
if (m == _first) _first <= 256 && _first % 8 == 0,
{ "No elementary type " + tokenString + to_string(_first) + "."
m_name = baseType.substr(0, baseType.size()-1) + to_string(_first); );
m_firstNumber = _first;
m_secondNumber = _second;
}
} }
else if (baseType == "ufixedMxN" || baseType == "fixedMxN") m_token = _baseType;
{ m_firstNumber = _first;
for (unsigned m = 0; m <= 256; m+=8) m_secondNumber = _second;
for (unsigned n = 8; m + n <= 256; n+=8)
if (m == _first && n == _second)
{
m_name = baseType.substr(0, baseType.size()-3) +
to_string(_first) +
"x" +
to_string(_second);
m_firstNumber = _first;
m_secondNumber = _second;
}
}
if (m_name.empty())
BOOST_THROW_EXCEPTION(Error(Error::Type::TypeError) <<
errinfo_comment(
"Cannot create elementary type name token out of type " +
baseType +
" and size(s) " +
to_string(_first) +
" and " +
to_string(_second)
)
);
} }
#define T(name, string, precedence) #name, #define T(name, string, precedence) #name,
@ -141,11 +102,11 @@ char const Token::m_tokenType[] =
{ {
TOKEN_LIST(KT, KK) TOKEN_LIST(KT, KK)
}; };
unsigned Token::extractM(string _literal) unsigned Token::extractM(string const& _literal)
{ {
try try
{ {
unsigned short m = stoi(_literal.substr(_literal.find_first_of("0123456789"))); unsigned short m = stoi(_literal);
return m; return m;
} }
catch(out_of_range& e) catch(out_of_range& e)
@ -153,57 +114,31 @@ unsigned Token::extractM(string _literal)
return 0; return 0;
} }
} }
pair<unsigned, unsigned> Token::extractMxN(string _literal)
{
try
{
unsigned short m = stoi(_literal.substr(0, _literal.find_last_of("x") - 1));
unsigned short n = stoi(_literal.substr(_literal.find_last_of("x") + 1));
return make_pair(m, n);
}
catch (out_of_range& e)
{
return make_pair(0, 0);
}
}
tuple<Token::Value, unsigned short, unsigned short> Token::fromIdentifierOrKeyword(string const& _literal) tuple<Token::Value, unsigned short, unsigned short> Token::fromIdentifierOrKeyword(string const& _literal)
{ {
if (_literal.find_first_of("0123456789") != string::npos) auto positionM = find_if(_literal.begin(), _literal.end(), ::isdigit);
if (positionM != _literal.end())
{ {
string baseType = _literal.substr(0, _literal.find_first_of("0123456789")); string baseType(_literal.begin(), positionM);
if (baseType == "bytes") auto positionX = find(positionM, _literal.end(), 'x');
unsigned short m = extractM(string(positionM, positionX));
if (baseType == toString(Token::Bytes))
{ {
unsigned short m = extractM(_literal);
if (0 < m && m <= 32) if (0 < m && m <= 32)
return make_tuple(Token::BytesM, m, 0); return make_tuple(Token::BytesM, m, 0);
return make_tuple(Token::Identifier, 0, 0); return make_tuple(Token::Identifier, 0, 0);
} }
else if (baseType == "uint" || baseType == "int") else if (baseType == toString(Token::UInt) || baseType == toString(Token::Int))
{ {
unsigned short m = extractM(_literal);
if (0 < m && m <= 256 && m % 8 == 0) if (0 < m && m <= 256 && m % 8 == 0)
{ {
if (baseType == "uint") if (baseType == toString(Token::UInt))
return make_tuple(Token::UIntM, m, 0); return make_tuple(Token::UIntM, m, 0);
else else
return make_tuple(Token::IntM, m, 0); return make_tuple(Token::IntM, m, 0);
} }
return make_tuple(Token::Identifier, 0, 0); return make_tuple(Token::Identifier, 0, 0);
} }
else if (baseType == "ufixed" || baseType == "fixed")
{
unsigned short m;
unsigned short n;
tie(m, n) = extractMxN(_literal);
if (0 < n + m && n + m <= 256 && ((n % 8 == 0) && (m % 8 == 0)))
{
if (baseType == "ufixed")
return make_tuple(Token::UFixedMxN, m, n);
else
return make_tuple(Token::FixedMxN, m, n);
}
return make_tuple(Token::Identifier, 0, 0);
}
} }
// The following macros are used inside TOKEN_LIST and cause non-keyword tokens to be ignored // 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. // and keywords to be put inside the keywords variable.

View File

@ -198,10 +198,8 @@ namespace solidity
K(String, "string", 0) \ K(String, "string", 0) \
K(Address, "address", 0) \ K(Address, "address", 0) \
K(Bool, "bool", 0) \ K(Bool, "bool", 0) \
K(Fixed, "fixed", 0) \ K(Real, "real", 0) \
T(FixedMxN, "fixedMxN", 0) \ K(UReal, "ureal", 0) \
K(UFixed, "ufixed", 0) \
T(UFixedMxN, "ufixedMxN", 0) \
T(TypesEnd, NULL, 0) /* used as type enum end marker */ \ T(TypesEnd, NULL, 0) /* used as type enum end marker */ \
\ \
/* Literals */ \ /* Literals */ \
@ -305,11 +303,10 @@ public:
static std::tuple<Token::Value, unsigned short, unsigned short> fromIdentifierOrKeyword(std::string const& _literal); static std::tuple<Token::Value, unsigned short, unsigned short> fromIdentifierOrKeyword(std::string const& _literal);
private: private:
// extractM and extractMxN provide a safe way to extract numbers, // extractM provides a safe way to extract numbers,
// if out_of_range error is thrown, they returns 0s, therefore securing // if out_of_range error is thrown, they returns 0s, therefore securing
// the variable's identity as an identifier. // the variable's identity as an identifier.
static unsigned extractM(std::string _literal); static unsigned extractM(std::string const& _literal);
static std::pair<unsigned, unsigned> extractMxN(std::string _literal);
static char const* const m_name[NUM_TOKENS]; static char const* const m_name[NUM_TOKENS];
static char const* const m_string[NUM_TOKENS]; static char const* const m_string[NUM_TOKENS];
static int8_t const m_precedence[NUM_TOKENS]; static int8_t const m_precedence[NUM_TOKENS];
@ -321,23 +318,28 @@ class ElementaryTypeNameToken
public: public:
ElementaryTypeNameToken(Token::Value _token, unsigned const& _firstNumber, unsigned const& _secondNumber) ElementaryTypeNameToken(Token::Value _token, unsigned const& _firstNumber, unsigned const& _secondNumber)
{ {
parseDetails(_token, _firstNumber, _secondNumber); assertDetails(_token, _firstNumber, _secondNumber);
m_token = _token;
} }
unsigned int const& firstNumber() const { return m_firstNumber; } unsigned int firstNumber() const { return m_firstNumber; }
unsigned int const& secondNumber() const { return m_secondNumber; } unsigned int secondNumber() const { return m_secondNumber; }
Token::Value const& returnTok() const { return m_token; } Token::Value token() const { return m_token; }
///if tokValue is set to true, then returns the actual token type name, otherwise, returns full type ///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; } std::string toString(bool const& tokenValue = false) const
{
std::string name = Token::toString(m_token);
if (tokenValue || (firstNumber() == 0 && secondNumber() == 0))
return name;
//need to set it up this way for fixed types construction in future
return name.substr(0, name.size() - 1) + std::to_string(m_firstNumber);
}
private: private:
Token::Value m_token; Token::Value m_token;
std::string m_name;
unsigned int m_firstNumber; unsigned int m_firstNumber;
unsigned int m_secondNumber; unsigned int m_secondNumber;
/// throws if type is not properly sized /// throws if type is not properly sized
void parseDetails(Token::Value _baseType, unsigned const& _first, unsigned const& _second); void assertDetails(Token::Value _baseType, unsigned const& _first, unsigned const& _second);
}; };
} }