From 574e48b0b51bbf890702a0c0fbae799473945bdb Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Mon, 14 Dec 2015 17:40:35 -0600 Subject: Inline array declarations complete --- libsolidity/ast/AST.h | 22 ++++++++++++++++++++-- libsolidity/parsing/Parser.cpp | 22 ++++++++++++++++++++++ test/libsolidity/SolidityParser.cpp | 10 ++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 1217d945..0c37dad3 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1126,9 +1126,10 @@ private: ASTPointer m_rightHandSide; }; + /** - * Tuple or just parenthesized expression. - * Examples: (1, 2), (x,), (x), () + * Tuple, parenthesized expression, or bracketed expression. + * Examples: (1, 2), (x,), (x), (), [1, 2], * Individual components might be empty shared pointers (as in the second example). * The respective types in lvalue context are: 2-tuple, 2-tuple (with wildcard), type of x, 0-tuple * Not in lvalue context: 2-tuple, _1_-tuple, type of x, 0-tuple. @@ -1150,6 +1151,23 @@ private: std::vector> m_components; }; +class InlineArrayExpression: public Expression +{ +public: + InlineArrayExpression( + SourceLocation const& _location, + std::vector> const& _components + ): + Expression(_location), m_components(_components) {} + virtual void accept(ASTVisitor& _visitor) override; + virtual void accept(ASTConstVisitor& _visitor) const override; + + std::vector> const& components() const { return m_components; } + +private: + std::vector> m_components; +}; + /** * Operation involving a unary operator, pre- or postfix. * Examples: ++i, delete x or !true diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 2b886121..50e4d29d 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1056,6 +1056,28 @@ ASTPointer Parser::parsePrimaryExpression() expectToken(Token::RParen); return nodeFactory.createNode(components); } + case Token::LBrack: + { + // Inline array expression + // Special cases: [] is empty tuple type, (x) is not a real tuple, (x,) is one-dimensional tuple + m_scanner->next(); + vector> components; + if (m_scanner->currentToken() != Token::RBrack) + while (true) + { + if (m_scanner->currentToken() != Token::Comma && m_scanner->currentToken() != Token::RBrack) + components.push_back(parseExpression()); + else + components.push_back(ASTPointer()); + if (m_scanner->currentToken() == Token::RBrack) + break; + else if (m_scanner->currentToken() == Token::Comma) + m_scanner->next(); + } + nodeFactory.markEndPosition(); + expectToken(Token::RBrack); + return nodeFactory.createNode(components); + } default: if (Token::isElementaryTypeName(token)) { diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index fd9076c3..53ffb618 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -1047,6 +1047,16 @@ BOOST_AUTO_TEST_CASE(using_for) BOOST_CHECK(successParse(text)); } +BOOST_AUTO_TEST_CASE(inline_array_declaration) +{ + char const* text = R"( + contract C { + uint[] x = [0, 1, 2, 3]; + } + )"; + BOOST_CHECK(successParse(text)); +} + BOOST_AUTO_TEST_SUITE_END() } -- cgit From 42c43394040e68c3bb32ed1e73992e096e5d10d2 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Tue, 15 Dec 2015 10:57:57 -0600 Subject: updated attempt, a couple of more things to sort through and change --- libsolidity/parsing/Parser.cpp | 10 ++++++---- test/libsolidity/SolidityParser.cpp | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 2b886121..5a3ed56e 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1034,26 +1034,28 @@ ASTPointer Parser::parsePrimaryExpression() nodeFactory.markEndPosition(); expression = nodeFactory.createNode(getLiteralAndAdvance()); break; - case Token::LParen: + case Token::LParen || Token::LBrack: { // Tuple or parenthesized expression. // Special cases: () is empty tuple type, (x) is not a real tuple, (x,) is one-dimensional tuple m_scanner->next(); vector> components; + Token::Value oppositeToken = (token == LParen ? Token::RParen : Token::RBrack); + if (m_scanner->currentToken() != Token::RParen) while (true) { - if (m_scanner->currentToken() != Token::Comma && m_scanner->currentToken() != Token::RParen) + if (m_scanner->currentToken() != Token::Comma && m_scanner->currentToken() != oppositeToken) components.push_back(parseExpression()); else components.push_back(ASTPointer()); - if (m_scanner->currentToken() == Token::RParen) + if (m_scanner->currentToken() == oppositeToken) break; else if (m_scanner->currentToken() == Token::Comma) m_scanner->next(); } nodeFactory.markEndPosition(); - expectToken(Token::RParen); + expectToken(oppositeToken); return nodeFactory.createNode(components); } default: diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index fd9076c3..d8c1a3e6 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -1047,6 +1047,20 @@ BOOST_AUTO_TEST_CASE(using_for) BOOST_CHECK(successParse(text)); } +BOOST_AUTO_TEST_CASE(inline_array_declaration) +{ + char const* text = R"( + contract c { + uint[] a; + function f() returns (uint, uint) { + a = [1,2,3]; + return (a[3], [3,4][0]); + } + } + )"; + BOOST_CHECK(successParse(text)); +} + BOOST_AUTO_TEST_SUITE_END() } -- cgit From 767103be57d004d94a3711de5c3c0a119f3bc722 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Tue, 15 Dec 2015 11:16:54 -0600 Subject: changing Tuple Constructor --- libsolidity/ast/AST.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index b267b6a4..55274f0d 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1140,9 +1140,12 @@ class TupleExpression: public Expression public: TupleExpression( SourceLocation const& _location, - std::vector> const& _components + std::vector> const& _components, + bool _isArray ): - Expression(_location), m_components(_components) {} + Expression(_location), + m_components(_components), + m_isArray(_isArray) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; -- cgit From 5a462afd03dc425ab77e718e430f19512740c6b1 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Tue, 15 Dec 2015 11:37:00 -0600 Subject: fixed case statements --- libsolidity/ast/AST.h | 1 + libsolidity/parsing/Parser.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 55274f0d..372f78a2 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1153,6 +1153,7 @@ public: private: std::vector> m_components; + bool isInlineArray() const { return m_isArray; } }; /** diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index ba92d2aa..149948f7 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1034,7 +1034,8 @@ ASTPointer Parser::parsePrimaryExpression() nodeFactory.markEndPosition(); expression = nodeFactory.createNode(getLiteralAndAdvance()); break; - case Token::LParen || Token::LBrack: + case Token::LParen: + case Token::LBrack: { // Tuple or parenthesized expression. // Special cases: () is empty tuple type, (x) is not a real tuple, (x,) is one-dimensional tuple -- cgit From aebce8a1d5aa8bf06719341432f487acd347d297 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Tue, 15 Dec 2015 12:22:52 -0600 Subject: now is compiling and passing soltest...but I think there may be a few more things to do --- libsolidity/ast/AST.h | 4 +++- libsolidity/parsing/Parser.cpp | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 372f78a2..964c83fa 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1150,10 +1150,12 @@ public: virtual void accept(ASTConstVisitor& _visitor) const override; std::vector> const& components() const { return m_components; } + bool isInlineArray() const { return m_isArray; } private: std::vector> m_components; - bool isInlineArray() const { return m_isArray; } + bool m_isArray; + }; /** diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 149948f7..cb5968e9 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1037,11 +1037,13 @@ ASTPointer Parser::parsePrimaryExpression() case Token::LParen: case Token::LBrack: { - // Tuple or parenthesized expression. - // Special cases: () is empty tuple type, (x) is not a real tuple, (x,) is one-dimensional tuple + // Tuple/parenthesized expression or inline array/bracketed expression. + // Special cases: ()/[] is empty tuple/array type, (x)/[] is not a real tuple/array, + // (x,) is one-dimensional tuple m_scanner->next(); vector> components; - Token::Value oppositeToken = (token == LParen ? Token::RParen : Token::RBrack); + Token::Value oppositeToken = (token == Token::LParen ? Token::RParen : Token::RBrack); + bool isArray = (token == Token::LParen ? false : true); if (m_scanner->currentToken() != Token::RParen) while (true) @@ -1057,7 +1059,7 @@ ASTPointer Parser::parsePrimaryExpression() } nodeFactory.markEndPosition(); expectToken(oppositeToken); - return nodeFactory.createNode(components); + return nodeFactory.createNode(components, isArray); } default: -- cgit From 9ab066de8c157726b9976588b4907496c3489f42 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Tue, 15 Dec 2015 14:47:09 -0600 Subject: new tests --- libsolidity/ast/AST.h | 1 - test/libsolidity/SolidityNameAndTypeResolution.cpp | 26 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 964c83fa..1ba4f65b 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1155,7 +1155,6 @@ public: private: std::vector> m_components; bool m_isArray; - }; /** diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 73a9b660..605771db 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2743,6 +2743,32 @@ BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) BOOST_CHECK(expectError(text) == Error::Type::TypeError); } +BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing) +{ + char const* text = R"( + contract C { + uint[] a; + function f() returns (uint, uint) { + a = [1,2,3]; + return (a[3], [3,4][0]); + } + } + )"; + BOOST_CHECK(success(text)); +} + +BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) +{ + char const* text = R"( + contract C { + function f() { + uint[] x = [45, "foo", true]; + } + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } -- cgit From c8e4e9c05c9074152063d2176c25a851b537d571 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Tue, 15 Dec 2015 16:44:11 -0600 Subject: still not able to get types resolved, however it is compiling --- libsolidity/analysis/TypeChecker.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 01de5eb0..2d6b6151 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -779,6 +779,7 @@ bool TypeChecker::visit(Assignment const& _assignment) bool TypeChecker::visit(TupleExpression const& _tuple) { + vector> const& components = _tuple.components(); TypePointers types; if (_tuple.annotation().lValueRequested) @@ -791,7 +792,10 @@ bool TypeChecker::visit(TupleExpression const& _tuple) } else types.push_back(TypePointer()); - _tuple.annotation().type = make_shared(types); + if (_tuple.isInlineArray()) + _tuple.annotation().type = make_shared(DataLocation::Storage, _tuple.annotation().type, types.size()); + else + _tuple.annotation().type = make_shared(types); // If some of the components are not LValues, the error is reported above. _tuple.annotation().isLValue = true; } @@ -801,7 +805,10 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { // Outside of an lvalue-context, the only situation where a component can be empty is (x,). if (!components[i] && !(i == 1 && components.size() == 2)) - fatalTypeError(_tuple.location(), "Tuple component cannot be empty."); + _tuple.isInlineArray() ? + fatalTypeError(_tuple.location(), "Array component cannot have empty cells.") + : + fatalTypeError(_tuple.location(), "Tuple component cannot be empty."); else if (components[i]) { components[i]->accept(*this); -- cgit From caa6202f62749567870e38c3e4d284984349ca75 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Wed, 16 Dec 2015 10:34:16 -0600 Subject: temporary assert added --- libsolidity/analysis/TypeChecker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 2d6b6151..f2113d2f 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -781,6 +781,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { vector> const& components = _tuple.components(); + solAssert(!_tuple.isInlineArray(), "Tuple type not properly declared"); TypePointers types; if (_tuple.annotation().lValueRequested) { -- cgit From 0ba24a5289eaaf1941c1e84e774f938353b9b94c Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Wed, 16 Dec 2015 12:55:52 -0600 Subject: changed a couple of small nuances, made an attempt at fixing the parsing in the inline arrays case (fails), and added test for inline arrays per Chriseth request --- libsolidity/analysis/TypeChecker.cpp | 11 ++--------- libsolidity/parsing/Parser.cpp | 9 ++++++--- test/libsolidity/SolidityParser.cpp | 26 ++++++++++++++++++++------ 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index f2113d2f..9718bf75 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -779,7 +779,6 @@ bool TypeChecker::visit(Assignment const& _assignment) bool TypeChecker::visit(TupleExpression const& _tuple) { - vector> const& components = _tuple.components(); solAssert(!_tuple.isInlineArray(), "Tuple type not properly declared"); TypePointers types; @@ -793,10 +792,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple) } else types.push_back(TypePointer()); - if (_tuple.isInlineArray()) - _tuple.annotation().type = make_shared(DataLocation::Storage, _tuple.annotation().type, types.size()); - else - _tuple.annotation().type = make_shared(types); + _tuple.annotation().type = make_shared(types); // If some of the components are not LValues, the error is reported above. _tuple.annotation().isLValue = true; } @@ -806,10 +802,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { // Outside of an lvalue-context, the only situation where a component can be empty is (x,). if (!components[i] && !(i == 1 && components.size() == 2)) - _tuple.isInlineArray() ? - fatalTypeError(_tuple.location(), "Array component cannot have empty cells.") - : - fatalTypeError(_tuple.location(), "Tuple component cannot be empty."); + fatalTypeError(_tuple.location(), "Tuple component cannot be empty."); else if (components[i]) { components[i]->accept(*this); diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index cb5968e9..e7391dff 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1043,9 +1043,10 @@ ASTPointer Parser::parsePrimaryExpression() m_scanner->next(); vector> components; Token::Value oppositeToken = (token == Token::LParen ? Token::RParen : Token::RBrack); - bool isArray = (token == Token::LParen ? false : true); - - if (m_scanner->currentToken() != Token::RParen) + bool isArray = (token == Token::RBrace ? true : false); + if (isArray && (m_scanner->currentToken() == Token::Comma)) + fatalParserError("Expected value in array cell after '[' ."); + if (m_scanner->currentToken() != oppositeToken) while (true) { if (m_scanner->currentToken() != Token::Comma && m_scanner->currentToken() != oppositeToken) @@ -1055,6 +1056,8 @@ ASTPointer Parser::parsePrimaryExpression() if (m_scanner->currentToken() == oppositeToken) break; else if (m_scanner->currentToken() == Token::Comma) + if (isArray && (m_scanner->peekNextToken() == (Token::Comma || oppositeToken))) + fatalParserError("Expected value in array cell after ',' ."); m_scanner->next(); } nodeFactory.markEndPosition(); diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index d8c1a3e6..b1af54e0 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -1051,16 +1051,30 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration) { char const* text = R"( contract c { - uint[] a; - function f() returns (uint, uint) { - a = [1,2,3]; - return (a[3], [3,4][0]); - } - } + uint[] a; + function f() returns (uint, uint) { + a = [1,2,3]; + return (a[3], [3,4][0]); + } + } )"; BOOST_CHECK(successParse(text)); } +BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check) +{ + char const* text = R"( + contract c { + uint[] a; + function f() returns (uint, uint) { + a = [,2,3]; + return (a[3], [3,4][0]); + } + } + )"; + BOOST_CHECK(!successParse(text)); +} + BOOST_AUTO_TEST_SUITE_END() } -- cgit From de969945ea819b06a787e8aba47a2c5353a966ba Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Wed, 16 Dec 2015 13:17:41 -0600 Subject: Parsing is complete --- libsolidity/parsing/Parser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index e7391dff..3df3ac17 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1043,9 +1043,9 @@ ASTPointer Parser::parsePrimaryExpression() m_scanner->next(); vector> components; Token::Value oppositeToken = (token == Token::LParen ? Token::RParen : Token::RBrack); - bool isArray = (token == Token::RBrace ? true : false); + bool isArray = (token == Token::LBrack ? true : false); if (isArray && (m_scanner->currentToken() == Token::Comma)) - fatalParserError("Expected value in array cell after '[' ."); + fatalParserError(std::string("Expected value in array cell after '[' .")); if (m_scanner->currentToken() != oppositeToken) while (true) { @@ -1057,7 +1057,7 @@ ASTPointer Parser::parsePrimaryExpression() break; else if (m_scanner->currentToken() == Token::Comma) if (isArray && (m_scanner->peekNextToken() == (Token::Comma || oppositeToken))) - fatalParserError("Expected value in array cell after ',' ."); + fatalParserError(std::string("Expected value in array cell after ',' .")); m_scanner->next(); } nodeFactory.markEndPosition(); -- cgit From df41812442548a8399f7a7cd0ef6aefcd40740c1 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Wed, 16 Dec 2015 13:23:05 -0600 Subject: making this purely about parsing...type checking will go in a different PR --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 605771db..847f3eaa 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2743,7 +2743,7 @@ BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) BOOST_CHECK(expectError(text) == Error::Type::TypeError); } -BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing) +/*BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing) { char const* text = R"( contract C { @@ -2755,7 +2755,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing) } )"; BOOST_CHECK(success(text)); -} +}*/ BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) { -- cgit From f7a1860abd2abe63efcdd9318a54af530e30361c Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Wed, 16 Dec 2015 13:35:28 -0600 Subject: forgot about this one...again making this purely about parsing...typechecking will come another day --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 847f3eaa..1242e801 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2755,7 +2755,7 @@ BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) } )"; BOOST_CHECK(success(text)); -}*/ +} BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) { @@ -2767,7 +2767,7 @@ BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) } )"; BOOST_CHECK(expectError(text) == Error::Type::TypeError); -} +}*/ BOOST_AUTO_TEST_SUITE_END() -- cgit From fe04d7f7f7686ae8fa406880b3c3069e60ee1c20 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Wed, 16 Dec 2015 14:50:40 -0600 Subject: added one more test and realized that there was one last change before the parser is perfect --- libsolidity/parsing/Parser.cpp | 2 +- test/libsolidity/SolidityParser.cpp | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 3df3ac17..4fad65bb 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1056,7 +1056,7 @@ ASTPointer Parser::parsePrimaryExpression() if (m_scanner->currentToken() == oppositeToken) break; else if (m_scanner->currentToken() == Token::Comma) - if (isArray && (m_scanner->peekNextToken() == (Token::Comma || oppositeToken))) + if (isArray && (m_scanner->peekNextToken() == Token::Comma || m_scanner->peekNextToken() == oppositeToken)) fatalParserError(std::string("Expected value in array cell after ',' .")); m_scanner->next(); } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index b1af54e0..c5af075a 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -1047,28 +1047,55 @@ BOOST_AUTO_TEST_CASE(using_for) BOOST_CHECK(successParse(text)); } -BOOST_AUTO_TEST_CASE(inline_array_declaration) +BOOST_AUTO_TEST_CASE(inline_array_declaration_lvalue) { char const* text = R"( contract c { uint[] a; - function f() returns (uint, uint) { + function f() returns (uint) { a = [1,2,3]; - return (a[3], [3,4][0]); + return (a[3]); + } + } + )"; + BOOST_CHECK(successParse(text)); +} + +BOOST_AUTO_TEST_CASE(inline_array_declaration_self) +{ + char const* text = R"( + contract c { + uint[] a; + function f() returns (uint) { + return ([1,2,3][0]); } } )"; BOOST_CHECK(successParse(text)); } -BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check) +BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_beginning) { char const* text = R"( contract c { uint[] a; function f() returns (uint, uint) { a = [,2,3]; - return (a[3], [3,4][0]); + return (a[3], [,3,4][0]); + } + } + )"; + BOOST_CHECK(!successParse(text)); +} + +BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_commas) +{ + char const* text = R"( + contract c { + uint[] a; + function f() returns (uint, uint) { + a = [1, ,3]; + return (a[3], [3, ,4][0]); } } )"; -- cgit From 905d55e34f85184d0e549b4b2708eb80b933fa8b Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Wed, 16 Dec 2015 16:47:37 -0600 Subject: updated tests and much simpler algorithm for parsing errors --- libsolidity/parsing/Parser.cpp | 13 ++++++------- test/libsolidity/SolidityParser.cpp | 29 ++++++++--------------------- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 4fad65bb..c7b2bb50 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1038,26 +1038,25 @@ ASTPointer Parser::parsePrimaryExpression() case Token::LBrack: { // Tuple/parenthesized expression or inline array/bracketed expression. - // Special cases: ()/[] is empty tuple/array type, (x)/[] is not a real tuple/array, - // (x,) is one-dimensional tuple + // Special cases: ()/[] is empty tuple/array type, (x) is not a real tuple, + // (x,) is one-dimensional tuple, elements in arrays cannot be left out, only in tuples. m_scanner->next(); vector> components; Token::Value oppositeToken = (token == Token::LParen ? Token::RParen : Token::RBrack); - bool isArray = (token == Token::LBrack ? true : false); - if (isArray && (m_scanner->currentToken() == Token::Comma)) - fatalParserError(std::string("Expected value in array cell after '[' .")); + bool isArray = (token == Token::LBrack); + if (m_scanner->currentToken() != oppositeToken) while (true) { if (m_scanner->currentToken() != Token::Comma && m_scanner->currentToken() != oppositeToken) components.push_back(parseExpression()); + else if (isArray) + parserError(std::string("Expected value in array cell after")); else components.push_back(ASTPointer()); if (m_scanner->currentToken() == oppositeToken) break; else if (m_scanner->currentToken() == Token::Comma) - if (isArray && (m_scanner->peekNextToken() == Token::Comma || m_scanner->peekNextToken() == oppositeToken)) - fatalParserError(std::string("Expected value in array cell after ',' .")); m_scanner->next(); } nodeFactory.markEndPosition(); diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index c5af075a..e6c8a8d8 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -1047,55 +1047,42 @@ BOOST_AUTO_TEST_CASE(using_for) BOOST_CHECK(successParse(text)); } -BOOST_AUTO_TEST_CASE(inline_array_declaration_lvalue) +BOOST_AUTO_TEST_CASE(inline_array_declaration) { char const* text = R"( contract c { uint[] a; - function f() returns (uint) { + function f() returns (uint, uint) { a = [1,2,3]; - return (a[3]); + return (a[3], [2,3,4][0]); } } )"; BOOST_CHECK(successParse(text)); } -BOOST_AUTO_TEST_CASE(inline_array_declaration_self) -{ - char const* text = R"( - contract c { - uint[] a; - function f() returns (uint) { - return ([1,2,3][0]); - } - } - )"; - BOOST_CHECK(successParse(text)); -} -BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_beginning) +BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_lvalue) { char const* text = R"( contract c { uint[] a; - function f() returns (uint, uint) { + function f() returns (uint) { a = [,2,3]; - return (a[3], [,3,4][0]); + return (a[0]); } } )"; BOOST_CHECK(!successParse(text)); } -BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_commas) +BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_without_lvalue) { char const* text = R"( contract c { uint[] a; function f() returns (uint, uint) { - a = [1, ,3]; - return (a[3], [3, ,4][0]); + return ([3, ,4][0]); } } )"; -- cgit From ed1dd50acda058a9c0c5b9c43776fba3642e23e2 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Wed, 16 Dec 2015 17:26:41 -0600 Subject: changed error message --- libsolidity/parsing/Parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index c7b2bb50..caf38b1d 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1051,7 +1051,7 @@ ASTPointer Parser::parsePrimaryExpression() if (m_scanner->currentToken() != Token::Comma && m_scanner->currentToken() != oppositeToken) components.push_back(parseExpression()); else if (isArray) - parserError(std::string("Expected value in array cell after")); + parserError("Expected expression (inline array elements cannot be omitted)."); else components.push_back(ASTPointer()); if (m_scanner->currentToken() == oppositeToken) -- cgit