Do not emit Solidity-only tokens in the Scanner for Yul

And simplfiy AsmParser greatly.
This commit is contained in:
Alex Beregszaszi 2020-07-10 16:20:04 +01:00
parent bd7283ad22
commit caa329066e
10 changed files with 56 additions and 38 deletions

View File

@ -668,7 +668,7 @@ void Scanner::scanToken()
tie(token, m, n) = scanIdentifierOrKeyword();
// Special case for hexadecimal literals
if (token == Token::Hex)
if (token == Token::Hex && m_kind != ScannerKind::Yul)
{
// reset
m = 0;
@ -680,7 +680,7 @@ void Scanner::scanToken()
else
token = setError(ScannerError::IllegalToken);
}
else if (token == Token::Unicode)
else if (token == Token::Unicode && m_kind != ScannerKind::Yul)
{
// reset
m = 0;
@ -969,7 +969,14 @@ tuple<Token, unsigned, unsigned> Scanner::scanIdentifierOrKeyword()
while (isIdentifierPart(m_char) || (m_char == '.' && m_kind == ScannerKind::Yul))
addLiteralCharAndAdvance();
literal.complete();
return TokenTraits::fromIdentifierOrKeyword(m_tokens[NextNext].literal);
auto const token = TokenTraits::fromIdentifierOrKeyword(m_tokens[NextNext].literal);
if (m_kind == ScannerKind::Yul)
{
// Turn non-Yul keywords into identifiers.
if (!TokenTraits::isYulKeyword(std::get<0>(token)))
return std::make_tuple(Token::Identifier, 0, 0);
}
return token;
}
} // namespace solidity::langutil

View File

@ -317,6 +317,13 @@ namespace TokenTraits
constexpr bool isTimeSubdenomination(Token op) { return op == Token::SubSecond || op == Token::SubMinute || op == Token::SubHour || op == Token::SubDay || op == Token::SubWeek || op == Token::SubYear; }
constexpr bool isReservedKeyword(Token op) { return (Token::After <= op && op <= Token::Unchecked); }
constexpr bool isYulKeyword(Token tok)
{
return tok == Token::Function || tok == Token::Let || tok == Token::If || tok == Token::Switch || tok == Token::Case ||
tok == Token::Default || tok == Token::For || tok == Token::Break || tok == Token::Continue /* || tok == Token::Leave */ ||
tok == Token::TrueLiteral || tok == Token::FalseLiteral;
}
inline Token AssignmentToBinaryOp(Token op)
{
solAssert(isAssignmentOp(op) && op != Token::Assign, "");

View File

@ -284,12 +284,6 @@ Parser::ElementaryOperation Parser::parseElementaryOperation()
switch (currentToken())
{
case Token::Identifier:
case Token::Return:
case Token::Byte:
case Token::Bool:
case Token::Address:
case Token::Var:
case Token::In:
{
YulString literal{currentLiteral()};
if (m_dialect.builtin(literal))
@ -472,24 +466,10 @@ TypedName Parser::parseTypedName()
YulString Parser::expectAsmIdentifier()
{
YulString name{currentLiteral()};
switch (currentToken())
{
case Token::Return:
case Token::Byte:
case Token::Address:
case Token::Bool:
case Token::Identifier:
case Token::Var:
case Token::In:
break;
default:
expectToken(Token::Identifier);
break;
}
if (m_dialect.builtin(name))
if (currentToken() == Token::Identifier && m_dialect.builtin(name))
fatalParserError(5568_error, "Cannot use builtin function name \"" + name.str() + "\" as identifier name.");
advance();
// NOTE: We keep the expectation here to ensure the correct source location for the error above.
expectToken(Token::Identifier);
return name;
}

View File

@ -595,6 +595,11 @@ BOOST_AUTO_TEST_CASE(unicode_prefix_only)
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalToken);
scanner.reset(CharStream("{ unicode", ""));
scanner.setScannerMode(ScannerKind::Yul);
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.currentLiteral(), "unicode");
}
BOOST_AUTO_TEST_CASE(unicode_invalid_space)
@ -611,6 +616,13 @@ BOOST_AUTO_TEST_CASE(unicode_invalid_token)
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalToken);
scanner.reset(CharStream("{ unicode test", ""));
scanner.setScannerMode(ScannerKind::Yul);
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.currentLiteral(), "unicode");
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.currentLiteral(), "test");
}
BOOST_AUTO_TEST_CASE(valid_unicode_literal)
@ -638,6 +650,11 @@ BOOST_AUTO_TEST_CASE(hex_prefix_only)
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalToken);
scanner.reset(CharStream("{ hex", ""));
scanner.setScannerMode(ScannerKind::Yul);
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.currentLiteral(), "hex");
}
BOOST_AUTO_TEST_CASE(hex_invalid_space)
@ -654,6 +671,13 @@ BOOST_AUTO_TEST_CASE(hex_invalid_token)
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
BOOST_CHECK_EQUAL(scanner.next(), Token::Illegal);
BOOST_CHECK_EQUAL(scanner.currentError(), ScannerError::IllegalToken);
scanner.reset(CharStream("{ hex test", ""));
scanner.setScannerMode(ScannerKind::Yul);
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::LBrace);
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.currentLiteral(), "hex");
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.currentLiteral(), "test");
}
BOOST_AUTO_TEST_CASE(valid_hex_literal)
@ -839,12 +863,12 @@ BOOST_AUTO_TEST_CASE(solidity_keywords)
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
scanner.reset(CharStream(keywords, ""));
scanner.setScannerMode(ScannerKind::Yul);
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Return);
BOOST_CHECK_EQUAL(scanner.next(), Token::Byte);
BOOST_CHECK_EQUAL(scanner.next(), Token::Bool);
BOOST_CHECK_EQUAL(scanner.next(), Token::Address);
BOOST_CHECK_EQUAL(scanner.next(), Token::Var);
BOOST_CHECK_EQUAL(scanner.next(), Token::In);
BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);
BOOST_CHECK_EQUAL(scanner.next(), Token::TrueLiteral);
BOOST_CHECK_EQUAL(scanner.next(), Token::FalseLiteral);
BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier);

View File

@ -6,4 +6,4 @@ contract C {
}
}
// ----
// ParserError 1856: (72-81): Literal or identifier expected.
// ParserError 6913: (86-87): Call or assignment expected.

View File

@ -6,4 +6,4 @@ contract C {
}
}
// ----
// ParserError 1856: (67-76): Literal or identifier expected.
// ParserError 2314: (70-76): Expected ',' but got 'StringLiteral'

View File

@ -8,4 +8,4 @@ contract C {
}
}
// ----
// ParserError 1856: (92-99): Literal or identifier expected.
// ParserError 4805: (95-99): Literal expected.

View File

@ -2,4 +2,4 @@
let x := hex"0011"
}
// ----
// ParserError 1856: (15-24): Literal or identifier expected.
// ParserError 6913: (25-26): Call or assignment expected.

View File

@ -2,4 +2,4 @@
pop(hex"2233")
}
// ----
// ParserError 1856: (10-19): Literal or identifier expected.
// ParserError 2314: (13-19): Expected ',' but got 'StringLiteral'

View File

@ -4,4 +4,4 @@
case hex"1122" {}
}
// ----
// ParserError 1856: (33-40): Literal or identifier expected.
// ParserError 4805: (36-40): Literal expected.