aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/inlineasm/AsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/inlineasm/AsmParser.cpp')
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp92
1 files changed, 59 insertions, 33 deletions
diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp
index 33c8efa0..7d0157d3 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -35,7 +35,7 @@ shared_ptr<assembly::Block> Parser::parse(std::shared_ptr<Scanner> const& _scann
try
{
m_scanner = _scanner;
- return make_shared<assembly::Block>(parseBlock());
+ return make_shared<Block>(parseBlock());
}
catch (FatalError const&)
{
@@ -47,10 +47,11 @@ shared_ptr<assembly::Block> Parser::parse(std::shared_ptr<Scanner> const& _scann
assembly::Block Parser::parseBlock()
{
+ assembly::Block block = createWithLocation<Block>();
expectToken(Token::LBrace);
- Block block;
while (m_scanner->currentToken() != Token::RBrace)
block.statements.emplace_back(parseStatement());
+ block.location.end = endPosition();
m_scanner->next();
return block;
}
@@ -65,11 +66,14 @@ assembly::Statement Parser::parseStatement()
return parseBlock();
case Token::Assign:
{
+ assembly::Assignment assignment = createWithLocation<assembly::Assignment>();
m_scanner->next();
expectToken(Token::Colon);
- string name = m_scanner->currentLiteral();
+ assignment.variableName.location = location();
+ assignment.variableName.name = m_scanner->currentLiteral();
+ assignment.location.end = endPosition();
expectToken(Token::Identifier);
- return assembly::Assignment{assembly::Identifier{name}};
+ return assignment;
}
case Token::Return: // opcode
case Token::Byte: // opcode
@@ -84,24 +88,30 @@ assembly::Statement Parser::parseStatement()
switch (m_scanner->currentToken())
{
case Token::LParen:
- return parseFunctionalInstruction(statement);
+ return parseFunctionalInstruction(std::move(statement));
case Token::Colon:
{
if (statement.type() != typeid(assembly::Identifier))
fatalParserError("Label name / variable name must precede \":\".");
- string const& name = boost::get<assembly::Identifier>(statement).name;
+ assembly::Identifier const& identifier = boost::get<assembly::Identifier>(statement);
m_scanner->next();
if (m_scanner->currentToken() == Token::Assign)
{
// functional assignment
+ FunctionalAssignment funAss = createWithLocation<FunctionalAssignment>(identifier.location);
m_scanner->next();
- unique_ptr<Statement> value;
- value.reset(new Statement(parseExpression()));
- return FunctionalAssignment{{std::move(name)}, std::move(value)};
+ funAss.variableName = identifier;
+ funAss.value.reset(new Statement(parseExpression()));
+ funAss.location.end = locationOf(*funAss.value).end;
+ return funAss;
}
else
+ {
// label
- return Label{name};
+ Label label = createWithLocation<Label>(identifier.location);
+ label.name = identifier.name;
+ return label;
+ }
}
default:
break;
@@ -113,7 +123,7 @@ assembly::Statement Parser::parseExpression()
{
Statement operation = parseElementaryOperation(true);
if (m_scanner->currentToken() == Token::LParen)
- return parseFunctionalInstruction(operation);
+ return parseFunctionalInstruction(std::move(operation));
else
return operation;
}
@@ -137,8 +147,7 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
s_instructions[name] = instruction.second;
}
- //@TODO track location
-
+ Statement ret;
switch (m_scanner->currentToken())
{
case Token::Identifier:
@@ -162,48 +171,50 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
if (info.ret != 1)
fatalParserError("Instruction " + info.name + " not allowed in this context.");
}
- m_scanner->next();
- return Instruction{instr};
+ ret = Instruction{location(), instr};
}
else
- m_scanner->next();
- return Identifier{literal};
+ ret = Identifier{location(), literal};
break;
}
case Token::StringLiteral:
case Token::Number:
{
- Literal literal{
+ ret = Literal{
+ location(),
m_scanner->currentToken() == Token::Number,
m_scanner->currentLiteral()
};
- m_scanner->next();
- return literal;
+ break;
}
default:
- break;
+ fatalParserError("Expected elementary inline assembly operation.");
}
- fatalParserError("Expected elementary inline assembly operation.");
- return {};
+ m_scanner->next();
+ return ret;
}
assembly::VariableDeclaration Parser::parseVariableDeclaration()
{
+ VariableDeclaration varDecl = createWithLocation<VariableDeclaration>();
expectToken(Token::Let);
- string name = m_scanner->currentLiteral();
+ varDecl.name = m_scanner->currentLiteral();
expectToken(Token::Identifier);
expectToken(Token::Colon);
expectToken(Token::Assign);
- unique_ptr<Statement> value;
- value.reset(new Statement(parseExpression()));
- return VariableDeclaration{name, std::move(value)};
+ varDecl.value.reset(new Statement(parseExpression()));
+ varDecl.location.end = locationOf(*varDecl.value).end;
+ return varDecl;
}
-FunctionalInstruction Parser::parseFunctionalInstruction(assembly::Statement const& _instruction)
+FunctionalInstruction Parser::parseFunctionalInstruction(Statement&& _instruction)
{
if (_instruction.type() != typeid(Instruction))
fatalParserError("Assembly instruction required in front of \"(\")");
- solidity::Instruction instr = boost::get<solidity::assembly::Instruction>(_instruction).instruction;
+ FunctionalInstruction ret;
+ ret.instruction = std::move(boost::get<Instruction>(_instruction));
+ ret.location = ret.instruction.location;
+ solidity::Instruction instr = ret.instruction.instruction;
InstructionInfo instrInfo = instructionInfo(instr);
if (solidity::Instruction::DUP1 <= instr && instr <= solidity::Instruction::DUP16)
fatalParserError("DUPi instructions not allowed for functional notation");
@@ -211,14 +222,29 @@ FunctionalInstruction Parser::parseFunctionalInstruction(assembly::Statement con
fatalParserError("SWAPi instructions not allowed for functional notation");
expectToken(Token::LParen);
- vector<Statement> arguments;
unsigned args = unsigned(instrInfo.args);
for (unsigned i = 0; i < args; ++i)
{
- arguments.push_back(parseExpression());
+ ret.arguments.emplace_back(parseExpression());
if (i != args - 1)
- expectToken(Token::Comma);
+ {
+ if (m_scanner->currentToken() != Token::Comma)
+ fatalParserError(string(
+ "Expected comma (" +
+ instrInfo.name +
+ " expects " +
+ boost::lexical_cast<string>(args) +
+ " arguments)"
+ ));
+ else
+ m_scanner->next();
+ }
}
+ ret.location.end = endPosition();
+ if (m_scanner->currentToken() == Token::Comma)
+ fatalParserError(
+ string("Expected ')' (" + instrInfo.name + " expects " + boost::lexical_cast<string>(args) + " arguments)")
+ );
expectToken(Token::RParen);
- return FunctionalInstruction{{instr}, std::move(arguments)};
+ return ret;
}