Added efficient probing functions to Parser.

This commit is contained in:
Patrick Lühne 2016-06-08 00:02:40 +02:00
parent 78889e18c6
commit 69ff84eecc
5 changed files with 119 additions and 95 deletions

View File

@ -53,7 +53,6 @@ class Parser
char currentCharacter() const;
void advance();
bool advanceIf(char expectedCharacter);
bool atEndOfStream() const;
template<typename Type>
@ -65,6 +64,9 @@ class Parser
template<class CharacterPredicate>
std::string parseIdentifier(CharacterPredicate characterPredicate);
template<typename Type>
bool probe(const Type &expectedValue);
template<typename Type>
void expect(const Type &expectedValue);

View File

@ -80,7 +80,7 @@ void Constant::parseTypedDeclaration(Context &context, Domain &domain, Constants
context.parser.skipWhiteSpace();
// Check for typing information
if (!context.parser.advanceIf('-'))
if (!context.parser.probe('-'))
return;
// If existing, parse and store parent type

View File

@ -82,7 +82,7 @@ void PrimitiveType::parseTypedDeclaration(Context &context, Domain &domain)
context.parser.skipWhiteSpace();
// Check for type inheritance
if (!context.parser.advanceIf('-'))
if (!context.parser.probe('-'))
return;
// If existing, parse and store parent type

View File

@ -64,7 +64,7 @@ void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expres
context.parser.skipWhiteSpace();
// Check if the variable has a type declaration
if (!context.parser.advanceIf('-'))
if (!context.parser.probe('-'))
return;
// TODO: do not allow nested either expressions

View File

@ -179,20 +179,6 @@ void Parser::advance()
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Parser::advanceIf(char expectedCharacter)
{
checkStream();
if (currentCharacter() != expectedCharacter)
return false;
advance();
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::skipWhiteSpace()
{
return skipWhiteSpace(
@ -265,22 +251,78 @@ std::string Parser::parse<std::string>()
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<std::string>(const std::string &expectedValue)
bool Parser::probe<std::string>(const std::string &expectedValue)
{
BOOST_ASSERT(!std::isspace(expectedValue[0]));
skipWhiteSpace();
std::for_each(expectedValue.cbegin(), expectedValue.cend(),
const auto previousPosition = position();
const auto match = std::find_if(expectedValue.cbegin(), expectedValue.cend(),
[&](const auto &expectedCharacter)
{
const auto character = static_cast<char>(this->currentCharacter());
if (character != expectedCharacter)
throw ParserException(*this, "Unexpected string, expected \"" + expectedValue + "\" (expected character '" + expectedCharacter + "', got '" + character + "')");
return true;
this->advance();
return false;
});
const auto differs = (match != expectedValue.cend());
if (!differs)
return true;
seek(previousPosition);
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<std::string>(const std::string &expectedValue)
{
if (!probe<std::string>(expectedValue))
throw ParserException(*this, "Unexpected value, expected \"" + expectedValue + "\"");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
char Parser::parse<char>()
{
const auto value = currentCharacter();
advance();
return value;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::probe<char>(const char &expectedValue)
{
if (currentCharacter() != expectedValue)
return false;
advance();
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<char>(const char &expectedValue)
{
if (!probe<char>(expectedValue))
throw ParserException(*this, std::string("Unexpected value, expected \"") + expectedValue + "\"");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -317,7 +359,7 @@ int64_t Parser::parse<int64_t>()
{
skipWhiteSpace();
bool positive = advanceIf('+') || !advanceIf('-');
bool positive = probe('+') || !probe('-');
const auto value = parseIntegerBody();
@ -340,12 +382,42 @@ uint64_t Parser::parse<uint64_t>()
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<int64_t>(const int64_t &expectedValue)
bool Parser::probe<int64_t>(const int64_t &expectedValue)
{
const auto previousPosition = position();
const auto value = parse<int64_t>();
if (value != expectedValue)
throw ParserException(*this, "Unexpected value " + std::to_string(value) + ", expected " + std::to_string(expectedValue));
if (value == expectedValue)
return true;
seek(previousPosition);
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::probe<uint64_t>(const uint64_t &expectedValue)
{
const auto previousPosition = position();
const auto value = parse<uint64_t>();
if (value == expectedValue)
return true;
seek(previousPosition);
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<int64_t>(const int64_t &expectedValue)
{
if (!probe<int64_t>(expectedValue))
throw ParserException(*this, "Unexpected value, expected \"" + std::to_string(expectedValue) + "\"");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -353,10 +425,8 @@ void Parser::expect<int64_t>(const int64_t &expectedValue)
template<>
void Parser::expect<uint64_t>(const uint64_t &expectedValue)
{
const auto value = parse<uint64_t>();
if (value != expectedValue)
throw ParserException(*this, "Unexpected value " + std::to_string(value) + ", expected " + std::to_string(expectedValue));
if (!probe<uint64_t>(expectedValue))
throw ParserException(*this, "Unexpected value, expected \"" + std::to_string(expectedValue) + "\"");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -377,6 +447,22 @@ uint32_t Parser::parse<uint32_t>()
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::probe<int32_t>(const int32_t &expectedValue)
{
return probe<int64_t>(static_cast<int64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::probe<uint32_t>(const uint32_t &expectedValue)
{
return probe<uint64_t>(static_cast<uint64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<int32_t>(const int32_t &expectedValue)
{
@ -393,79 +479,15 @@ void Parser::expect<uint32_t>(const uint32_t &expectedValue)
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
int16_t Parser::parse<int16_t>()
{
return static_cast<int16_t>(parse<int64_t>());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
uint16_t Parser::parse<uint16_t>()
{
return static_cast<uint16_t>(parse<uint64_t>());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<int16_t>(const int16_t &expectedValue)
{
expect<int64_t>(static_cast<int64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<uint16_t>(const uint16_t &expectedValue)
{
expect<uint64_t>(static_cast<uint64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
int8_t Parser::parse<int8_t>()
{
return static_cast<int8_t>(parse<int64_t>());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
uint8_t Parser::parse<uint8_t>()
{
return static_cast<uint8_t>(parse<uint64_t>());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<int8_t>(const int8_t &expectedValue)
{
expect<int64_t>(static_cast<int64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<uint8_t>(const uint8_t &expectedValue)
{
expect<uint64_t>(static_cast<uint64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::parse<bool>()
{
skipWhiteSpace();
if (advanceIf('0'))
if (probe('0'))
return false;
if (advanceIf('1'))
if (probe('1'))
return true;
throw ParserException(*this, "Could not parse Boolean value");