diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index f0c60e05d..307168ed1 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -599,10 +599,10 @@ Literal::Literal(Location const& _location, Token::Value _token, Token::Value _sub): PrimaryExpression(_location), m_token(_token), m_value(_value) { - solAssert(_sub == Token::ILLEGAL || _sub == Token::ETH_SUB_WEI || - _sub == Token::ETH_SUB_SZABO || _sub == Token::ETH_SUB_FINNEY || - _sub == Token::ETH_SUB_ETHER, "Illegal Token::Value given to Literal ctor"); - m_subDenomination =static_cast(_sub); + if(Token::isEtherSubdenomination(_sub)) + m_subDenomination = static_cast(_sub); + else + m_subDenomination = Literal::ethSubDenomination::NONE; } void Literal::checkTypeRequirements() diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 739bbdd61..6449ba93d 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -694,6 +694,8 @@ ASTPointer Parser::parsePrimaryExpression() case Token::NUMBER: nextToken = m_scanner->peekNextToken(); case Token::STRING_LITERAL: + if (Token::isEtherSubdenomination(nextToken)) + m_scanner->next(); nodeFactory.markEndPosition(); expression = nodeFactory.createNode(token, getLiteralAndAdvance(), nextToken); break; diff --git a/libsolidity/Token.h b/libsolidity/Token.h index 7b9608254..f2beefd9a 100644 --- a/libsolidity/Token.h +++ b/libsolidity/Token.h @@ -383,6 +383,7 @@ public: static bool isCountOp(Value op) { return op == INC || op == DEC; } static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); } static bool isVisibilitySpecifier(Value op) { return op == PUBLIC || op == PRIVATE || op == PROTECTED; } + static bool isEtherSubdenomination(Value op) { return op == ETH_SUB_WEI || op == ETH_SUB_SZABO || op == ETH_SUB_FINNEY || op == Token::ETH_SUB_ETHER; } // Returns a string corresponding to the JS token string // (.e., "<" for the token LT) or NULL if the token doesn't diff --git a/test/SolidityExpressionCompiler.cpp b/test/SolidityExpressionCompiler.cpp index a0cca3a3a..71f40bd25 100644 --- a/test/SolidityExpressionCompiler.cpp +++ b/test/SolidityExpressionCompiler.cpp @@ -91,7 +91,16 @@ bytes compileFirstExpression(const string& _sourceCode, vector> _ { Parser parser; ASTPointer sourceUnit; - BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared(CharStream(_sourceCode)))); + try + { + sourceUnit = parser.parse(make_shared(CharStream(_sourceCode))); + } + catch(boost::exception const& _e) + { + auto msg = std::string("Parsing source code failed with: \n") + boost::diagnostic_information(_e); + BOOST_FAIL(msg); + } + // BOOST_REQUIRE_NO_THROW(sourceUnit = parser.parse(make_shared(CharStream(_sourceCode)))); vector declarations; declarations.reserve(_globalDeclarations.size() + 1); @@ -177,6 +186,28 @@ BOOST_AUTO_TEST_CASE(int_literal) BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } +BOOST_AUTO_TEST_CASE(int_literals_with_ether_subdenominations) +{ + char const* sourceCode = R"( + contract c { + function c () + { + a = 1 wei; + // b = 2 szabo; + // c = 3 finney; +// b = 4 ether; + } + uint256 a; + uint256 b; + uint256 c; + uint256 d; + })"; + bytes code = compileFirstExpression(sourceCode); + + bytes expectation({byte(eth::Instruction::PUSH5), 0x38, 0xd4, 0xa5, 0x10, 0x00}); + BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); +} + BOOST_AUTO_TEST_CASE(comparison) { char const* sourceCode = "contract test {\n" diff --git a/test/SolidityParser.cpp b/test/SolidityParser.cpp index 9ba38a4a1..b6837866c 100644 --- a/test/SolidityParser.cpp +++ b/test/SolidityParser.cpp @@ -660,6 +660,25 @@ BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers) BOOST_CHECK_THROW(parseText(text), ParserError); } +BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations) +{ + char const* text = R"( + contract c { + function c () + { + a = 1 wei; + b = 2 szabo; + c = 3 finney; + b = 4 ether; + } + uint256 a; + uint256 b; + uint256 c; + uint256 d; + })"; + BOOST_CHECK_NO_THROW(parseTextExplainError(text)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/SolidityScanner.cpp b/test/SolidityScanner.cpp index 7dc9ef482..5bd897ab4 100644 --- a/test/SolidityScanner.cpp +++ b/test/SolidityScanner.cpp @@ -255,6 +255,15 @@ BOOST_AUTO_TEST_CASE(comments_mixed_in_sequence) BOOST_CHECK_EQUAL(scanner.getCurrentCommentLiteral(), "documentation comment "); } +BOOST_AUTO_TEST_CASE(ether_subdenominations) +{ + Scanner scanner(CharStream("wei szabo finney ether")); + BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::ETH_SUB_WEI); + BOOST_CHECK_EQUAL(scanner.next(), Token::ETH_SUB_SZABO); + BOOST_CHECK_EQUAL(scanner.next(), Token::ETH_SUB_FINNEY); + BOOST_CHECK_EQUAL(scanner.next(), Token::ETH_SUB_ETHER); +} + BOOST_AUTO_TEST_SUITE_END() }