From 627c80f0a8b37426c2c6625ff4852d77e4d43464 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 5 Nov 2014 08:40:21 +0100 Subject: [PATCH] Support for negative literals. --- Scanner.cpp | 22 +++++++++++----------- Scanner.h | 2 +- Types.cpp | 8 +++++--- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Scanner.cpp b/Scanner.cpp index 63deba495..b13e52d7e 100644 --- a/Scanner.cpp +++ b/Scanner.cpp @@ -271,7 +271,7 @@ void Scanner::scanToken() token = Token::ADD; break; case '-': - // - -- -= + // - -- -= Number advance(); if (m_char == '-') { @@ -280,6 +280,8 @@ void Scanner::scanToken() } else if (m_char == '=') token = selectToken(Token::ASSIGN_SUB); + else if (m_char == '.' || IsDecimalDigit(m_char)) + token = scanNumber('-'); else token = Token::SUB; break; @@ -331,7 +333,7 @@ void Scanner::scanToken() // . Number advance(); if (IsDecimalDigit(m_char)) - token = scanNumber(true); + token = scanNumber('.'); else token = Token::PERIOD; break; @@ -372,7 +374,7 @@ void Scanner::scanToken() if (IsIdentifierStart(m_char)) token = scanIdentifierOrKeyword(); else if (IsDecimalDigit(m_char)) - token = scanNumber(false); + token = scanNumber(); else if (skipWhitespace()) token = Token::WHITESPACE; 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 - 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; + enum { DECIMAL, HEX, BINARY } kind = DECIMAL; LiteralScope literal(this); - if (_periodSeen) + if (_charSeen == '.') { // we have already seen a decimal point of the float addLiteralChar('.'); @@ -476,12 +475,13 @@ Token::Value Scanner::scanNumber(bool _periodSeen) } else { + if (_charSeen == '-') + addLiteralChar('-'); // if the first character is '0' we must check for octals and hex if (m_char == '0') { addLiteralCharAndAdvance(); - // either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or - // an octal number. + // either 0, 0exxx, 0Exxx, 0.xxx or a hex number if (m_char == 'x' || m_char == 'X') { // hex number diff --git a/Scanner.h b/Scanner.h index 537c2434e..997365f3c 100644 --- a/Scanner.h +++ b/Scanner.h @@ -180,7 +180,7 @@ private: Token::Value skipMultiLineComment(); void scanDecimalDigits(); - Token::Value scanNumber(bool _periodSeen); + Token::Value scanNumber(char _charSeen = 0); Token::Value scanIdentifierOrKeyword(); Token::Value scanString(); diff --git a/Types.cpp b/Types.cpp index 334f50444..7354255e1 100644 --- a/Types.cpp +++ b/Types.cpp @@ -89,10 +89,14 @@ shared_ptr Type::forLiteral(Literal const& _literal) shared_ptr IntegerType::smallestTypeForLiteral(string const& _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); if (bytes > 32) return shared_ptr(); - return make_shared(bytes * 8, Modifier::UNSIGNED); + return make_shared(bytes * 8, isSigned ? Modifier::SIGNED : Modifier::UNSIGNED); } IntegerType::IntegerType(int _bits, IntegerType::Modifier _modifier): @@ -169,8 +173,6 @@ string IntegerType::toString() const u256 IntegerType::literalValue(Literal const& _literal) const { bigint value(_literal.getValue()); - //@todo check that the number is not too large - //@todo does this work for signed numbers? return u256(value); }