diff --git a/libyul/AsmParser.cpp b/libyul/AsmParser.cpp index 00cdb4a22..c43066ee0 100644 --- a/libyul/AsmParser.cpp +++ b/libyul/AsmParser.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -138,18 +139,18 @@ Statement Parser::parseStatement() default: break; } + // Options left: - // Simple instruction (might turn into functional), - // literal, - // identifier (might turn into label or functional assignment) - ElementaryOperation elementary(parseElementaryOperation()); + // Expression/FunctionCall + // Assignment + variant elementary(parseLiteralOrIdentifier()); switch (currentToken()) { case Token::LParen: { Expression expr = parseCall(std::move(elementary)); - return ExpressionStatement{locationOf(expr), expr}; + return ExpressionStatement{locationOf(expr), move(expr)}; } case Token::Comma: case Token::AssemblyAssign: @@ -184,7 +185,7 @@ Statement Parser::parseStatement() expectToken(Token::Comma); - elementary = parseElementaryOperation(); + elementary = parseLiteralOrIdentifier(); } expectToken(Token::AssemblyAssign); @@ -192,28 +193,15 @@ Statement Parser::parseStatement() assignment.value = make_unique(parseExpression()); assignment.location.end = locationOf(*assignment.value).end; - return Statement{std::move(assignment)}; + return Statement{move(assignment)}; } default: fatalParserError(6913_error, "Call or assignment expected."); break; } - if (holds_alternative(elementary)) - { - Identifier& identifier = std::get(elementary); - return ExpressionStatement{identifier.location, { move(identifier) }}; - } - else if (holds_alternative(elementary)) - { - Expression expr = std::get(elementary); - return ExpressionStatement{locationOf(expr), expr}; - } - else - { - yulAssert(false, "Invalid elementary operation."); - return {}; - } + yulAssert(false, ""); + return {}; } Case Parser::parseCase() @@ -225,7 +213,7 @@ Case Parser::parseCase() else if (currentToken() == Token::Case) { advance(); - ElementaryOperation literal = parseElementaryOperation(); + variant literal = parseLiteralOrIdentifier(); if (!holds_alternative(literal)) fatalParserError(4805_error, "Literal expected."); _case.value = make_unique(std::get(std::move(literal))); @@ -264,38 +252,37 @@ Expression Parser::parseExpression() { RecursionGuard recursionGuard(*this); - ElementaryOperation operation = parseElementaryOperation(); - if (holds_alternative(operation) || currentToken() == Token::LParen) - return parseCall(std::move(operation)); - else if (holds_alternative(operation)) - return std::get(operation); - else - { - yulAssert(holds_alternative(operation), ""); - return std::get(operation); - } + variant operation = parseLiteralOrIdentifier(); + return visit(GenericVisitor{ + [&](Identifier& _identifier) -> Expression + { + if (currentToken() == Token::LParen) + return parseCall(std::move(operation)); + if (m_dialect.builtin(_identifier.name)) + fatalParserError( + 7104_error, + _identifier.location, + "Builtin function \"" + _identifier.name.str() + "\" must be called." + ); + return move(_identifier); + }, + [&](Literal& _literal) -> Expression + { + return move(_literal); + } + }, operation); } -Parser::ElementaryOperation Parser::parseElementaryOperation() +variant Parser::parseLiteralOrIdentifier() { RecursionGuard recursionGuard(*this); - ElementaryOperation ret; switch (currentToken()) { case Token::Identifier: { - YulString literal{currentLiteral()}; - if (m_dialect.builtin(literal)) - { - Identifier identifier{currentLocation(), literal}; - advance(); - expectToken(Token::LParen, false); - return FunctionCall{identifier.location, identifier, {}}; - } - else - ret = Identifier{currentLocation(), literal}; + Identifier identifier{currentLocation(), YulString{currentLiteral()}}; advance(); - break; + return identifier; } case Token::StringLiteral: case Token::Number: @@ -335,8 +322,7 @@ Parser::ElementaryOperation Parser::parseElementaryOperation() literal.type = expectAsmIdentifier(); } - ret = std::move(literal); - break; + return literal; } case Token::HexStringLiteral: fatalParserError(3772_error, "Hex literals are not valid in this context."); @@ -344,7 +330,7 @@ Parser::ElementaryOperation Parser::parseElementaryOperation() default: fatalParserError(1856_error, "Literal or identifier expected."); } - return ret; + return {}; } VariableDeclaration Parser::parseVariableDeclaration() @@ -418,21 +404,17 @@ FunctionDefinition Parser::parseFunctionDefinition() return funDef; } -Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) +FunctionCall Parser::parseCall(variant&& _initialOp) { RecursionGuard recursionGuard(*this); - FunctionCall ret; - if (holds_alternative(_initialOp)) - { - ret.functionName = std::move(std::get(_initialOp)); - ret.location = ret.functionName.location; - } - else if (holds_alternative(_initialOp)) - ret = std::move(std::get(_initialOp)); - else + if (!holds_alternative(_initialOp)) fatalParserError(9980_error, "Function name expected."); + FunctionCall ret; + ret.functionName = std::move(std::get(_initialOp)); + ret.location = ret.functionName.location; + expectToken(Token::LParen); if (currentToken() != Token::RParen) { diff --git a/libyul/AsmParser.h b/libyul/AsmParser.h index 705711b52..d1294b111 100644 --- a/libyul/AsmParser.h +++ b/libyul/AsmParser.h @@ -61,8 +61,6 @@ public: std::unique_ptr parse(std::shared_ptr const& _scanner, bool _reuseScanner); protected: - using ElementaryOperation = std::variant; - langutil::SourceLocation currentLocation() const override { return m_locationOverride ? *m_locationOverride : ParserBase::currentLocation(); @@ -84,10 +82,10 @@ protected: Expression parseExpression(); /// Parses an elementary operation, i.e. a literal, identifier, instruction or /// builtin functian call (only the name). - ElementaryOperation parseElementaryOperation(); + std::variant parseLiteralOrIdentifier(); VariableDeclaration parseVariableDeclaration(); FunctionDefinition parseFunctionDefinition(); - Expression parseCall(ElementaryOperation&& _initialOp); + FunctionCall parseCall(std::variant&& _initialOp); TypedName parseTypedName(); YulString expectAsmIdentifier(); diff --git a/scripts/error_codes.py b/scripts/error_codes.py index 23c1657a7..9b106d0c0 100755 --- a/scripts/error_codes.py +++ b/scripts/error_codes.py @@ -223,7 +223,7 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False): "1123", "1220", "1584", "1823", "1988", "2657", "2800", "3356", "3893", "3996", "4010", "4802", - "5073", "5272", "5622", "6272", "7128", + "5073", "5272", "5622", "7128", "7589", "7593", "7653", "8065", "8084", "8140", "8312", "8592", "9085", "9390" } diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol index 3296252ea..cb675ab29 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_from_opcode_like.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// ParserError 2314: (118-119): Expected '(' but got '}' +// ParserError 7104: (104-109): Builtin function "mload" must be called. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/assignment_to_opcode_like.sol b/test/libsolidity/syntaxTests/inlineAssembly/assignment_to_opcode_like.sol index 7a783b9fe..51028e50c 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/assignment_to_opcode_like.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/assignment_to_opcode_like.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// ParserError 2314: (101-103): Expected '(' but got ':=' +// ParserError 6272: (101-103): Cannot assign to builtin function "mload". diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol index a55586af9..87884efee 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/bare_instructions_disallowed.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// ParserError 2314: (95-98): Expected '(' but got identifier +// ParserError 6913: (95-98): Call or assignment expected. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol b/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol index 3f92beec2..80dd3a587 100644 --- a/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol +++ b/test/libsolidity/syntaxTests/inlineAssembly/invalid/unbalanced_negative_stack.sol @@ -6,4 +6,4 @@ contract test { } } // ---- -// ParserError 2314: (85-86): Expected '(' but got '}' +// ParserError 6913: (85-86): Call or assignment expected. diff --git a/test/libyul/yulSyntaxTests/builtin_identifier_3.yul b/test/libyul/yulSyntaxTests/builtin_identifier_3.yul index 283d64b49..c7969b8ef 100644 --- a/test/libyul/yulSyntaxTests/builtin_identifier_3.yul +++ b/test/libyul/yulSyntaxTests/builtin_identifier_3.yul @@ -2,4 +2,4 @@ function f(x) { f(add) } } // ---- -// ParserError 2314: (24-25): Expected '(' but got ')' +// ParserError 7104: (21-24): Builtin function "add" must be called. diff --git a/test/libyul/yulSyntaxTests/builtin_identifier_6.yul b/test/libyul/yulSyntaxTests/builtin_identifier_6.yul index 8f3395d79..e261354fc 100644 --- a/test/libyul/yulSyntaxTests/builtin_identifier_6.yul +++ b/test/libyul/yulSyntaxTests/builtin_identifier_6.yul @@ -1,6 +1,5 @@ { - // Test for the unreachable 6272_error add := 1 } // ---- -// ParserError 2314: (47-49): Expected '(' but got ':=' +// ParserError 6272: (7-9): Cannot assign to builtin function "add". diff --git a/test/libyul/yulSyntaxTests/builtin_identifier_7.yul b/test/libyul/yulSyntaxTests/builtin_identifier_7.yul index 391b190d9..c34da0363 100644 --- a/test/libyul/yulSyntaxTests/builtin_identifier_7.yul +++ b/test/libyul/yulSyntaxTests/builtin_identifier_7.yul @@ -1,7 +1,6 @@ { - // Test for the unreachable 6272_error function f() -> a, b {} add, mul := f() } // ---- -// ParserError 2314: (71-72): Expected '(' but got ',' +// ParserError 6272: (31-32): Cannot assign to builtin function "add". diff --git a/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul b/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul index acf9be847..5d739e81e 100644 --- a/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul +++ b/test/libyul/yulSyntaxTests/for_expr_invalid_5.yul @@ -2,4 +2,4 @@ for {} mload {} {} } // ---- -// ParserError 2314: (16-17): Expected '(' but got '{' +// ParserError 7104: (10-15): Builtin function "mload" must be called. diff --git a/test/libyul/yulSyntaxTests/functional_partial.yul b/test/libyul/yulSyntaxTests/functional_partial.yul index f66225658..ea28283d4 100644 --- a/test/libyul/yulSyntaxTests/functional_partial.yul +++ b/test/libyul/yulSyntaxTests/functional_partial.yul @@ -2,4 +2,4 @@ let x := byte } // ---- -// ParserError 2314: (20-21): Expected '(' but got '}' +// ParserError 7104: (15-19): Builtin function "byte" must be called. diff --git a/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul b/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul index 5f73fcf2a..0a4f33844 100644 --- a/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul +++ b/test/libyul/yulSyntaxTests/if_statement_invalid_1.yul @@ -2,4 +2,4 @@ if mload {} } // ---- -// ParserError 2314: (15-16): Expected '(' but got '{' +// ParserError 7104: (9-14): Builtin function "mload" must be called. diff --git a/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul b/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul index ed9deeda6..b84004a8d 100644 --- a/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul +++ b/test/libyul/yulSyntaxTests/if_statement_invalid_4.yul @@ -2,4 +2,4 @@ if calldatasize {} } // ---- -// ParserError 2314: (22-23): Expected '(' but got '{' +// ParserError 7104: (9-21): Builtin function "calldatasize" must be called. diff --git a/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul b/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul index 842fa02f3..9378297ca 100644 --- a/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul +++ b/test/libyul/yulSyntaxTests/switch_invalid_expr_2.yul @@ -4,4 +4,4 @@ default {} } // ---- -// ParserError 2314: (23-27): Expected '(' but got reserved keyword 'case' +// ParserError 7104: (13-18): Builtin function "mload" must be called.