Merge pull request #10212 from ethereum/testfileparser

Refactor and simplify TestFileParser
This commit is contained in:
chriseth 2020-11-10 13:15:35 +01:00 committed by GitHub
commit 3db94fbc48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 52 additions and 61 deletions

View File

@ -36,11 +36,9 @@
using namespace solidity; using namespace solidity;
using namespace solidity::util; using namespace solidity::util;
using namespace solidity::langutil;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::frontend::test; using namespace solidity::frontend::test;
using namespace std; using namespace std;
using namespace soltest;
bytes BytesUtils::alignLeft(bytes _bytes) bytes BytesUtils::alignLeft(bytes _bytes)
{ {

View File

@ -41,7 +41,6 @@ using namespace solidity::util;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::frontend::test; using namespace solidity::frontend::test;
using namespace std; using namespace std;
using namespace soltest;
namespace namespace
{ {

View File

@ -16,7 +16,6 @@
#include <libsolutil/AnsiColorized.h> #include <libsolutil/AnsiColorized.h>
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libsolidity/ast/Types.h>
namespace solidity::frontend::test namespace solidity::frontend::test
{ {

View File

@ -34,11 +34,11 @@
#include <stdexcept> #include <stdexcept>
using namespace solidity; using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::frontend; using namespace solidity::frontend;
using namespace solidity::frontend::test; using namespace solidity::frontend::test;
using namespace std; using namespace std;
using namespace soltest;
using Token = soltest::Token;
char TestFileParser::Scanner::peek() const noexcept char TestFileParser::Scanner::peek() const noexcept
{ {
@ -158,7 +158,7 @@ vector<solidity::frontend::test::FunctionCall> TestFileParser::parseFunctionCall
return calls; return calls;
} }
bool TestFileParser::accept(soltest::Token _token, bool const _expect) bool TestFileParser::accept(Token _token, bool const _expect)
{ {
if (m_scanner.currentToken() != _token) if (m_scanner.currentToken() != _token)
return false; return false;
@ -167,7 +167,7 @@ bool TestFileParser::accept(soltest::Token _token, bool const _expect)
return true; return true;
} }
bool TestFileParser::expect(soltest::Token _token, bool const _advance) bool TestFileParser::expect(Token _token, bool const _advance)
{ {
if (m_scanner.currentToken() != _token || m_scanner.currentToken() == Token::Invalid) if (m_scanner.currentToken() != _token || m_scanner.currentToken() == Token::Invalid)
throw TestParserError( throw TestParserError(
@ -484,31 +484,31 @@ void TestFileParser::Scanner::readStream(istream& _stream)
void TestFileParser::Scanner::scanNextToken() void TestFileParser::Scanner::scanNextToken()
{ {
using namespace langutil;
// Make code coverage happy. // Make code coverage happy.
assert(formatToken(Token::NUM_TOKENS) == ""); assert(formatToken(Token::NUM_TOKENS) == "");
auto detectKeyword = [](std::string const& _literal = "") -> TokenDesc { auto detectKeyword = [](std::string const& _literal = "") -> std::pair<Token, std::string> {
if (_literal == "true") return TokenDesc{Token::Boolean, _literal}; if (_literal == "true") return {Token::Boolean, "true"};
if (_literal == "false") return TokenDesc{Token::Boolean, _literal}; if (_literal == "false") return {Token::Boolean, "false"};
if (_literal == "ether") return TokenDesc{Token::Ether, _literal}; if (_literal == "ether") return {Token::Ether, ""};
if (_literal == "wei") return TokenDesc{Token::Wei, _literal}; if (_literal == "wei") return {Token::Wei, ""};
if (_literal == "left") return TokenDesc{Token::Left, _literal}; if (_literal == "left") return {Token::Left, ""};
if (_literal == "library") return TokenDesc{Token::Library, _literal}; if (_literal == "library") return {Token::Library, ""};
if (_literal == "right") return TokenDesc{Token::Right, _literal}; if (_literal == "right") return {Token::Right, ""};
if (_literal == "hex") return TokenDesc{Token::Hex, _literal}; if (_literal == "hex") return {Token::Hex, ""};
if (_literal == "FAILURE") return TokenDesc{Token::Failure, _literal}; if (_literal == "FAILURE") return {Token::Failure, ""};
if (_literal == "storage") return TokenDesc{Token::Storage, _literal}; if (_literal == "storage") return {Token::Storage, ""};
return TokenDesc{Token::Identifier, _literal}; return {Token::Identifier, _literal};
}; };
auto selectToken = [this](Token _token, std::optional<std::string> _literal = std::nullopt) -> TokenDesc { auto selectToken = [this](Token _token, std::string const& _literal = "") {
advance(); advance();
return make_pair(_token, _literal.has_value() ? *_literal : formatToken(_token)); m_currentToken = _token;
m_currentLiteral = _literal;
}; };
TokenDesc token = make_pair(Token::Unknown, ""); m_currentToken = Token::Unknown;
m_currentLiteral = "";
do do
{ {
switch(current()) switch(current())
@ -516,71 +516,73 @@ void TestFileParser::Scanner::scanNextToken()
case '/': case '/':
advance(); advance();
if (current() == '/') if (current() == '/')
token = selectToken(Token::Newline); selectToken(Token::Newline);
else else
token = selectToken(Token::Invalid); selectToken(Token::Invalid);
break; break;
case '-': case '-':
if (peek() == '>') if (peek() == '>')
{ {
advance(); advance();
token = selectToken(Token::Arrow); selectToken(Token::Arrow);
} }
else else
token = selectToken(Token::Sub); selectToken(Token::Sub);
break; break;
case ':': case ':':
token = selectToken(Token::Colon); selectToken(Token::Colon);
break; break;
case '#': case '#':
token = selectToken(Token::Comment, scanComment()); selectToken(Token::Comment, scanComment());
break; break;
case ',': case ',':
token = selectToken(Token::Comma); selectToken(Token::Comma);
break; break;
case '(': case '(':
token = selectToken(Token::LParen); selectToken(Token::LParen);
break; break;
case ')': case ')':
token = selectToken(Token::RParen); selectToken(Token::RParen);
break; break;
case '[': case '[':
token = selectToken(Token::LBrack); selectToken(Token::LBrack);
break; break;
case ']': case ']':
token = selectToken(Token::RBrack); selectToken(Token::RBrack);
break; break;
case '\"': case '\"':
token = selectToken(Token::String, scanString()); selectToken(Token::String, scanString());
break; break;
default: default:
if (isIdentifierStart(current())) if (langutil::isIdentifierStart(current()))
{ {
TokenDesc detectedToken = detectKeyword(scanIdentifierOrKeyword()); std::tie(m_currentToken, m_currentLiteral) = detectKeyword(scanIdentifierOrKeyword());
token = selectToken(detectedToken.first, detectedToken.second); advance();
} }
else if (isDecimalDigit(current())) else if (langutil::isDecimalDigit(current()))
{ {
if (current() == '0' && peek() == 'x') if (current() == '0' && peek() == 'x')
{ {
advance(); advance();
advance(); advance();
token = selectToken(Token::HexNumber, "0x" + scanHexNumber()); selectToken(Token::HexNumber, "0x" + scanHexNumber());
} }
else else
token = selectToken(Token::Number, scanDecimalNumber()); selectToken(Token::Number, scanDecimalNumber());
} }
else if (isWhiteSpace(current())) else if (langutil::isWhiteSpace(current()))
token = selectToken(Token::Whitespace); selectToken(Token::Whitespace);
else if (isEndOfLine()) else if (isEndOfLine())
token = make_pair(Token::EOS, "EOS"); {
m_currentToken = Token::EOS;
m_currentLiteral = "";
}
else else
throw TestParserError("Unexpected character: '" + string{current()} + "'"); throw TestParserError("Unexpected character: '" + string{current()} + "'");
break; break;
} }
} }
while (token.first == Token::Whitespace); while (m_currentToken == Token::Whitespace);
m_currentToken = token;
} }
string TestFileParser::Scanner::scanComment() string TestFileParser::Scanner::scanComment()

View File

@ -15,7 +15,6 @@
#pragma once #pragma once
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>
#include <libsolidity/ast/Types.h>
#include <liblangutil/Exceptions.h> #include <liblangutil/Exceptions.h>
#include <test/libsolidity/util/SoltestTypes.h> #include <test/libsolidity/util/SoltestTypes.h>
@ -64,7 +63,6 @@ public:
std::vector<FunctionCall> parseFunctionCalls(std::size_t _lineOffset); std::vector<FunctionCall> parseFunctionCalls(std::size_t _lineOffset);
private: private:
using Token = soltest::Token;
/** /**
* Token scanner that is used internally to abstract away character traversal. * Token scanner that is used internally to abstract away character traversal.
*/ */
@ -81,8 +79,8 @@ private:
/// Reads character stream and creates token. /// Reads character stream and creates token.
void scanNextToken(); void scanNextToken();
soltest::Token currentToken() { return m_currentToken.first; } soltest::Token currentToken() { return m_currentToken; }
std::string currentLiteral() { return m_currentToken.second; } std::string currentLiteral() { return m_currentLiteral; }
std::string scanComment(); std::string scanComment();
std::string scanIdentifierOrKeyword(); std::string scanIdentifierOrKeyword();
@ -92,8 +90,6 @@ private:
char scanHexPart(); char scanHexPart();
private: private:
using TokenDesc = std::pair<Token, std::string>;
/// Advances current position in the input stream. /// Advances current position in the input stream.
void advance(unsigned n = 1) void advance(unsigned n = 1)
{ {
@ -120,7 +116,8 @@ private:
std::string m_line; std::string m_line;
std::string::const_iterator m_char; std::string::const_iterator m_char;
TokenDesc m_currentToken; std::string m_currentLiteral;
soltest::Token m_currentToken = soltest::Token::Unknown;
}; };
bool accept(soltest::Token _token, bool const _expect = false); bool accept(soltest::Token _token, bool const _expect = false);

View File

@ -30,6 +30,8 @@ using namespace solidity::util;
using namespace solidity::frontend::test; using namespace solidity::frontend::test;
using namespace std; using namespace std;
using Token = soltest::Token;
string TestFunctionCall::format( string TestFunctionCall::format(
ErrorReporter& _errorReporter, ErrorReporter& _errorReporter,
string const& _linePrefix, string const& _linePrefix,
@ -37,9 +39,6 @@ string TestFunctionCall::format(
bool const _highlight bool const _highlight
) const ) const
{ {
using namespace soltest;
using Token = soltest::Token;
stringstream stream; stringstream stream;
bool highlight = !matchesExpectation() && _highlight; bool highlight = !matchesExpectation() && _highlight;
@ -279,8 +278,6 @@ string TestFunctionCall::formatFailure(
bool _highlight bool _highlight
) const ) const
{ {
using Token = soltest::Token;
stringstream os; stringstream os;
os << formatToken(Token::Failure); os << formatToken(Token::Failure);

View File

@ -17,7 +17,6 @@
#include <test/libsolidity/util/TestFileParser.h> #include <test/libsolidity/util/TestFileParser.h>
#include <test/libsolidity/util/SoltestErrors.h> #include <test/libsolidity/util/SoltestErrors.h>
#include <libsolidity/ast/Types.h>
#include <liblangutil/Exceptions.h> #include <liblangutil/Exceptions.h>
#include <libsolutil/AnsiColorized.h> #include <libsolutil/AnsiColorized.h>
#include <libsolutil/CommonData.h> #include <libsolutil/CommonData.h>