diff --git a/liblangutil/Scanner.cpp b/liblangutil/Scanner.cpp index 2d5607607..bc4bc2788 100644 --- a/liblangutil/Scanner.cpp +++ b/liblangutil/Scanner.cpp @@ -1019,15 +1019,28 @@ std::tuple 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 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; } diff --git a/liblangutil/Scanner.h b/liblangutil/Scanner.h index c45a2ec24..eaa2b3b54 100644 --- a/liblangutil/Scanner.h +++ b/liblangutil/Scanner.h @@ -69,7 +69,8 @@ class ParserRecorder; enum class ScannerKind { Solidity, - Yul + Yul, + ExperimentalSolidity }; enum class ScannerError diff --git a/liblangutil/Token.h b/liblangutil/Token.h index ef0c7f6af..cca90be20 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -322,6 +322,14 @@ namespace TokenTraits tok == Token::Default || tok == Token::For || tok == Token::Break || tok == Token::Continue || tok == Token::Leave || tok == Token::TrueLiteral || tok == Token::FalseLiteral || tok == Token::HexStringLiteral || tok == Token::Hex; } + constexpr bool isExperimentalSolidityKeyword(Token tok) + { + return tok == Token::Assembly || tok == Token::Contract || tok == Token::External || tok == Token::Fallback; + } + constexpr bool isExperimentalSolidityOnlyKeyword(Token) + { + return false; + } bool isYulKeyword(std::string const& _literal); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 84ff5bdbe..ae0dbb631 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -503,6 +503,7 @@ private: std::map m_libraries; ImportRemapper m_importRemapper; std::map m_sources; + std::optional m_maxAstId; std::vector m_unhandledSMTLib2Queries; std::map m_smtlib2Responses; std::shared_ptr m_globalContext; diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 1f5611a2f..e7d46892a 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -100,6 +100,9 @@ ASTPointer Parser::parse(CharStream& _charStream) while (m_scanner->currentToken() == Token::Pragma) nodes.push_back(parsePragmaDirective(false)); + if (m_experimentalSolidityEnabledInCurrentSourceUnit) + m_scanner->setScannerMode(ScannerKind::ExperimentalSolidity); + while (m_scanner->currentToken() != Token::EOS) { switch (m_scanner->currentToken()) diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 5f2a1213d..df282cb99 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -197,6 +197,8 @@ private: /// Returns the next AST node ID int64_t nextID() { return ++m_currentNodeID; } + /// Returns the maximal AST node ID assigned so far + int64_t maxID() const { return m_currentNodeID; } std::pair tryParseIndexAccessedPath(); /// Performs limited look-ahead to distinguish between variable declaration and expression statement.