From 54b6739962ef45319777ce2aebafdf4b91412d84 Mon Sep 17 00:00:00 2001 From: chriseth Date: Fri, 8 Dec 2017 14:01:22 +0100 Subject: Separate expression and statement. --- libsolidity/inlineasm/AsmParser.cpp | 91 +++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 35 deletions(-) (limited to 'libsolidity/inlineasm/AsmParser.cpp') diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 4f8802a0..273e1d5c 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -77,9 +77,7 @@ assembly::Statement Parser::parseStatement() { assembly::If _if = createWithLocation(); m_scanner->next(); - _if.condition = make_shared(parseExpression()); - if (_if.condition->type() == typeid(assembly::Instruction)) - fatalParserError("Instructions are not supported as conditions for if - try to append \"()\"."); + _if.condition = make_shared(parseExpression()); _if.body = parseBlock(); return _if; } @@ -87,9 +85,7 @@ assembly::Statement Parser::parseStatement() { assembly::Switch _switch = createWithLocation(); m_scanner->next(); - _switch.expression = make_shared(parseExpression()); - if (_switch.expression->type() == typeid(assembly::Instruction)) - fatalParserError("Instructions are not supported as expressions for switch - try to append \"()\"."); + _switch.expression = make_shared(parseExpression()); while (m_scanner->currentToken() == Token::Case) _switch.cases.emplace_back(parseCase()); if (m_scanner->currentToken() == Token::Default) @@ -127,18 +123,21 @@ assembly::Statement Parser::parseStatement() // Simple instruction (might turn into functional), // literal, // identifier (might turn into label or functional assignment) - Statement statement(parseElementaryOperation(false)); + ElementaryOperation elementary(parseElementaryOperation(false)); switch (currentToken()) { case Token::LParen: - return parseCall(std::move(statement)); + { + Expression expr = parseCall(std::move(elementary)); + return ExpressionStatement{locationOf(expr), expr}; + } case Token::Comma: { // if a comma follows, a multiple assignment is assumed - if (statement.type() != typeid(assembly::Identifier)) + if (elementary.type() != typeid(assembly::Identifier)) fatalParserError("Label name / variable name must precede \",\" (multiple assignment)."); - assembly::Identifier const& identifier = boost::get(statement); + assembly::Identifier const& identifier = boost::get(elementary); Assignment assignment = createWithLocation(identifier.location); assignment.variableNames.emplace_back(identifier); @@ -146,25 +145,25 @@ assembly::Statement Parser::parseStatement() do { expectToken(Token::Comma); - statement = parseElementaryOperation(false); - if (statement.type() != typeid(assembly::Identifier)) + elementary = parseElementaryOperation(false); + if (elementary.type() != typeid(assembly::Identifier)) fatalParserError("Variable name expected in multiple assignemnt."); - assignment.variableNames.emplace_back(boost::get(statement)); + assignment.variableNames.emplace_back(boost::get(elementary)); } while (currentToken() == Token::Comma); expectToken(Token::Colon); expectToken(Token::Assign); - assignment.value.reset(new Statement(parseExpression())); + assignment.value.reset(new Expression(parseExpression())); assignment.location.end = locationOf(*assignment.value).end; return assignment; } case Token::Colon: { - if (statement.type() != typeid(assembly::Identifier)) + if (elementary.type() != typeid(assembly::Identifier)) fatalParserError("Label name / variable name must precede \":\"."); - assembly::Identifier const& identifier = boost::get(statement); + assembly::Identifier const& identifier = boost::get(elementary); advance(); // identifier:=: should be parsed as identifier: =: (i.e. a label), // while identifier:= (being followed by a non-colon) as identifier := (assignment). @@ -175,7 +174,7 @@ assembly::Statement Parser::parseStatement() fatalParserError("Cannot use instruction names for identifier names."); advance(); assignment.variableNames.emplace_back(identifier); - assignment.value.reset(new Statement(parseExpression())); + assignment.value.reset(new Expression(parseExpression())); assignment.location.end = locationOf(*assignment.value).end; return assignment; } @@ -194,7 +193,21 @@ assembly::Statement Parser::parseStatement() fatalParserError("Call or assignment expected."); break; } - return statement; + if (elementary.type() == typeid(assembly::Identifier)) + { + Expression expr = boost::get(elementary); + return ExpressionStatement{locationOf(expr), expr}; + } + else if (elementary.type() == typeid(assembly::Literal)) + { + Expression expr = boost::get(elementary); + return ExpressionStatement{locationOf(expr), expr}; + } + else + { + solAssert(elementary.type() == typeid(assembly::Instruction), "Invalid elementary operation."); + return boost::get(elementary); + } } assembly::Case Parser::parseCase() @@ -206,10 +219,10 @@ assembly::Case Parser::parseCase() else if (m_scanner->currentToken() == Token::Case) { m_scanner->next(); - assembly::Statement statement = parseElementaryOperation(); - if (statement.type() != typeid(assembly::Literal)) + ElementaryOperation literal = parseElementaryOperation(); + if (literal.type() != typeid(assembly::Literal)) fatalParserError("Literal expected."); - _case.value = make_shared(std::move(boost::get(statement))); + _case.value = make_shared(boost::get(std::move(literal))); } else fatalParserError("Case or default case expected."); @@ -224,19 +237,17 @@ assembly::ForLoop Parser::parseForLoop() ForLoop forLoop = createWithLocation(); expectToken(Token::For); forLoop.pre = parseBlock(); - forLoop.condition = make_shared(parseExpression()); - if (forLoop.condition->type() == typeid(assembly::Instruction)) - fatalParserError("Instructions are not supported as conditions for the for statement."); + forLoop.condition = make_shared(parseExpression()); forLoop.post = parseBlock(); forLoop.body = parseBlock(); forLoop.location.end = forLoop.body.location.end; return forLoop; } -assembly::Statement Parser::parseExpression() +assembly::Expression Parser::parseExpression() { RecursionGuard recursionGuard(*this); - Statement operation = parseElementaryOperation(true); + ElementaryOperation operation = parseElementaryOperation(true); if (operation.type() == typeid(Instruction)) { Instruction const& instr = boost::get(operation); @@ -252,8 +263,18 @@ assembly::Statement Parser::parseExpression() } if (currentToken() == Token::LParen) return parseCall(std::move(operation)); + else if (operation.type() == typeid(Instruction)) + { + Instruction& instr = boost::get(operation); + return FunctionalInstruction{std::move(instr.location), instr.instruction, {}}; + } + else if (operation.type() == typeid(assembly::Identifier)) + return boost::get(operation); else - return operation; + { + solAssert(operation.type() == typeid(assembly::Literal), ""); + return boost::get(operation); + } } std::map const& Parser::instructions() @@ -296,10 +317,10 @@ std::map const& Parser::instructionNames() return s_instructionNames; } -assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher) +Parser::ElementaryOperation Parser::parseElementaryOperation(bool _onlySinglePusher) { RecursionGuard recursionGuard(*this); - Statement ret; + ElementaryOperation ret; switch (currentToken()) { case Token::Identifier: @@ -402,7 +423,7 @@ assembly::VariableDeclaration Parser::parseVariableDeclaration() { expectToken(Token::Colon); expectToken(Token::Assign); - varDecl.value.reset(new Statement(parseExpression())); + varDecl.value.reset(new Expression(parseExpression())); varDecl.location.end = locationOf(*varDecl.value).end; } else @@ -442,13 +463,13 @@ assembly::FunctionDefinition Parser::parseFunctionDefinition() return funDef; } -assembly::Statement Parser::parseCall(assembly::Statement&& _instruction) +assembly::Expression Parser::parseCall(Parser::ElementaryOperation&& _initialOp) { RecursionGuard recursionGuard(*this); - if (_instruction.type() == typeid(Instruction)) + if (_initialOp.type() == typeid(Instruction)) { solAssert(!m_julia, "Instructions are invalid in JULIA"); - Instruction const& instruction = std::move(boost::get(_instruction)); + Instruction& instruction = boost::get(_initialOp); FunctionalInstruction ret; ret.instruction = instruction.instruction; ret.location = std::move(instruction.location); @@ -499,10 +520,10 @@ assembly::Statement Parser::parseCall(assembly::Statement&& _instruction) expectToken(Token::RParen); return ret; } - else if (_instruction.type() == typeid(Identifier)) + else if (_initialOp.type() == typeid(Identifier)) { FunctionCall ret; - ret.functionName = std::move(boost::get(_instruction)); + ret.functionName = std::move(boost::get(_initialOp)); ret.location = ret.functionName.location; expectToken(Token::LParen); while (currentToken() != Token::RParen) -- cgit