Support for negative literals.

This commit is contained in:
Christian 2014-11-05 08:40:21 +01:00
parent b5e77678c9
commit 627c80f0a8
3 changed files with 17 additions and 15 deletions

View File

@ -271,7 +271,7 @@ void Scanner::scanToken()
token = Token::ADD; token = Token::ADD;
break; break;
case '-': case '-':
// - -- -= // - -- -= Number
advance(); advance();
if (m_char == '-') if (m_char == '-')
{ {
@ -280,6 +280,8 @@ void Scanner::scanToken()
} }
else if (m_char == '=') else if (m_char == '=')
token = selectToken(Token::ASSIGN_SUB); token = selectToken(Token::ASSIGN_SUB);
else if (m_char == '.' || IsDecimalDigit(m_char))
token = scanNumber('-');
else else
token = Token::SUB; token = Token::SUB;
break; break;
@ -331,7 +333,7 @@ void Scanner::scanToken()
// . Number // . Number
advance(); advance();
if (IsDecimalDigit(m_char)) if (IsDecimalDigit(m_char))
token = scanNumber(true); token = scanNumber('.');
else else
token = Token::PERIOD; token = Token::PERIOD;
break; break;
@ -372,7 +374,7 @@ void Scanner::scanToken()
if (IsIdentifierStart(m_char)) if (IsIdentifierStart(m_char))
token = scanIdentifierOrKeyword(); token = scanIdentifierOrKeyword();
else if (IsDecimalDigit(m_char)) else if (IsDecimalDigit(m_char))
token = scanNumber(false); token = scanNumber();
else if (skipWhitespace()) else if (skipWhitespace())
token = Token::WHITESPACE; token = Token::WHITESPACE;
else if (isSourcePastEndOfInput()) else if (isSourcePastEndOfInput())
@ -461,14 +463,11 @@ void Scanner::scanDecimalDigits()
} }
Token::Value Scanner::scanNumber(bool _periodSeen) Token::Value Scanner::scanNumber(char _charSeen)
{ {
// the first digit of the number or the fraction enum { DECIMAL, HEX, BINARY } kind = DECIMAL;
if (asserts(IsDecimalDigit(m_char)))
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Number does not start with decimal digit."));
enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL;
LiteralScope literal(this); LiteralScope literal(this);
if (_periodSeen) if (_charSeen == '.')
{ {
// we have already seen a decimal point of the float // we have already seen a decimal point of the float
addLiteralChar('.'); addLiteralChar('.');
@ -476,12 +475,13 @@ Token::Value Scanner::scanNumber(bool _periodSeen)
} }
else else
{ {
if (_charSeen == '-')
addLiteralChar('-');
// if the first character is '0' we must check for octals and hex // if the first character is '0' we must check for octals and hex
if (m_char == '0') if (m_char == '0')
{ {
addLiteralCharAndAdvance(); addLiteralCharAndAdvance();
// either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or // either 0, 0exxx, 0Exxx, 0.xxx or a hex number
// an octal number.
if (m_char == 'x' || m_char == 'X') if (m_char == 'x' || m_char == 'X')
{ {
// hex number // hex number

View File

@ -180,7 +180,7 @@ private:
Token::Value skipMultiLineComment(); Token::Value skipMultiLineComment();
void scanDecimalDigits(); void scanDecimalDigits();
Token::Value scanNumber(bool _periodSeen); Token::Value scanNumber(char _charSeen = 0);
Token::Value scanIdentifierOrKeyword(); Token::Value scanIdentifierOrKeyword();
Token::Value scanString(); Token::Value scanString();

View File

@ -89,10 +89,14 @@ shared_ptr<Type> Type::forLiteral(Literal const& _literal)
shared_ptr<IntegerType> IntegerType::smallestTypeForLiteral(string const& _literal) shared_ptr<IntegerType> IntegerType::smallestTypeForLiteral(string const& _literal)
{ {
bigint value(_literal); bigint value(_literal);
bool isSigned = value < 0 || (!_literal.empty() && _literal.front() == '-');
if (isSigned)
// convert to positive number of same bit requirements
value = ((-value) - 1) << 1;
unsigned bytes = max(bytesRequired(value), 1u); unsigned bytes = max(bytesRequired(value), 1u);
if (bytes > 32) if (bytes > 32)
return shared_ptr<IntegerType>(); return shared_ptr<IntegerType>();
return make_shared<IntegerType>(bytes * 8, Modifier::UNSIGNED); return make_shared<IntegerType>(bytes * 8, isSigned ? Modifier::SIGNED : Modifier::UNSIGNED);
} }
IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier): IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier):
@ -169,8 +173,6 @@ string IntegerType::toString() const
u256 IntegerType::literalValue(Literal const& _literal) const u256 IntegerType::literalValue(Literal const& _literal) const
{ {
bigint value(_literal.getValue()); bigint value(_literal.getValue());
//@todo check that the number is not too large
//@todo does this work for signed numbers?
return u256(value); return u256(value);
} }