Introduce experimental analysis basic infrastructure

This commit is contained in:
Matheus Aguiar
2023-09-11 12:29:44 -03:00
parent 34c86d90be
commit 14aed39261
16 changed files with 329 additions and 157 deletions
+14 -1
View File
@@ -1019,15 +1019,28 @@ std::tuple<Token, unsigned, unsigned> Scanner::scanIdentifierOrKeyword()
while (isIdentifierPart(m_char) || (m_char == '.' && m_kind == ScannerKind::Yul))
addLiteralCharAndAdvance();
literal.complete();
auto const token = TokenTraits::fromIdentifierOrKeyword(m_tokens[NextNext].literal);
if (m_kind == ScannerKind::Yul)
switch (m_kind)
{
case ScannerKind::Solidity:
// Turn experimental Solidity keywords that are not keywords in legacy Solidity into identifiers.
if (TokenTraits::isExperimentalSolidityOnlyKeyword(std::get<0>(token)))
return std::make_tuple(Token::Identifier, 0, 0);
break;
case ScannerKind::Yul:
// Turn Solidity identifier into a Yul keyword
if (m_tokens[NextNext].literal == "leave")
return std::make_tuple(Token::Leave, 0, 0);
// Turn non-Yul keywords into identifiers.
if (!TokenTraits::isYulKeyword(std::get<0>(token)))
return std::make_tuple(Token::Identifier, 0, 0);
break;
case ScannerKind::ExperimentalSolidity:
// Turn legacy Solidity keywords that are not keywords in experimental Solidity into identifiers.
if (!TokenTraits::isExperimentalSolidityKeyword(std::get<0>(token)))
return std::make_tuple(Token::Identifier, 0, 0);
break;
}
return token;
}
+2 -1
View File
@@ -69,7 +69,8 @@ class ParserRecorder;
enum class ScannerKind
{
Solidity,
Yul
Yul,
ExperimentalSolidity
};
enum class ScannerError
+35
View File
@@ -268,6 +268,8 @@ namespace solidity::langutil
/* Yul-specific tokens, but not keywords. */ \
T(Leave, "leave", 0) \
\
T(NonExperimentalEnd, nullptr, 0) /* used as non-experimental enum end marker */ \
T(ExperimentalEnd, nullptr, 0) /* used as experimental enum end marker */ \
/* Illegal token - not able to scan. */ \
T(Illegal, "ILLEGAL", 0) \
\
@@ -323,6 +325,39 @@ namespace TokenTraits
tok == Token::TrueLiteral || tok == Token::FalseLiteral || tok == Token::HexStringLiteral || tok == Token::Hex;
}
constexpr bool isExperimentalSolidityKeyword(Token token)
{
return
token == Token::Assembly ||
token == Token::Contract ||
token == Token::External ||
token == Token::Fallback ||
token == Token::Pragma ||
token == Token::Import ||
token == Token::As ||
token == Token::Function ||
token == Token::Let ||
token == Token::Return ||
token == Token::Type ||
token == Token::If ||
token == Token::Else ||
token == Token::Do ||
token == Token::While ||
token == Token::For ||
token == Token::Continue ||
token == Token::Break;
// TODO: see isExperimentalSolidityKeyword below
// || (token > Token::NonExperimentalEnd && token < Token::ExperimentalEnd);
}
constexpr bool isExperimentalSolidityOnlyKeyword(Token)
{
// TODO: use token > Token::NonExperimentalEnd && token < Token::ExperimentalEnd
// as soon as other experimental tokens are added. For now the comparison generates
// a warning from clang because it is always false.
return false;
}
bool isYulKeyword(std::string const& _literal);
Token AssignmentToBinaryOp(Token op);