Added efficient probing functions to Parser.
This commit is contained in:
parent
78889e18c6
commit
69ff84eecc
@ -53,7 +53,6 @@ class Parser
|
|||||||
|
|
||||||
char currentCharacter() const;
|
char currentCharacter() const;
|
||||||
void advance();
|
void advance();
|
||||||
bool advanceIf(char expectedCharacter);
|
|
||||||
bool atEndOfStream() const;
|
bool atEndOfStream() const;
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
@ -65,6 +64,9 @@ class Parser
|
|||||||
template<class CharacterPredicate>
|
template<class CharacterPredicate>
|
||||||
std::string parseIdentifier(CharacterPredicate characterPredicate);
|
std::string parseIdentifier(CharacterPredicate characterPredicate);
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
bool probe(const Type &expectedValue);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
void expect(const Type &expectedValue);
|
void expect(const Type &expectedValue);
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ void Constant::parseTypedDeclaration(Context &context, Domain &domain, Constants
|
|||||||
context.parser.skipWhiteSpace();
|
context.parser.skipWhiteSpace();
|
||||||
|
|
||||||
// Check for typing information
|
// Check for typing information
|
||||||
if (!context.parser.advanceIf('-'))
|
if (!context.parser.probe('-'))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If existing, parse and store parent type
|
// If existing, parse and store parent type
|
||||||
|
@ -82,7 +82,7 @@ void PrimitiveType::parseTypedDeclaration(Context &context, Domain &domain)
|
|||||||
context.parser.skipWhiteSpace();
|
context.parser.skipWhiteSpace();
|
||||||
|
|
||||||
// Check for type inheritance
|
// Check for type inheritance
|
||||||
if (!context.parser.advanceIf('-'))
|
if (!context.parser.probe('-'))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If existing, parse and store parent type
|
// If existing, parse and store parent type
|
||||||
|
@ -64,7 +64,7 @@ void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expres
|
|||||||
context.parser.skipWhiteSpace();
|
context.parser.skipWhiteSpace();
|
||||||
|
|
||||||
// Check if the variable has a type declaration
|
// Check if the variable has a type declaration
|
||||||
if (!context.parser.advanceIf('-'))
|
if (!context.parser.probe('-'))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: do not allow nested either expressions
|
// TODO: do not allow nested either expressions
|
||||||
|
@ -179,20 +179,6 @@ void Parser::advance()
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool Parser::advanceIf(char expectedCharacter)
|
|
||||||
{
|
|
||||||
checkStream();
|
|
||||||
|
|
||||||
if (currentCharacter() != expectedCharacter)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
advance();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void Parser::skipWhiteSpace()
|
void Parser::skipWhiteSpace()
|
||||||
{
|
{
|
||||||
return skipWhiteSpace(
|
return skipWhiteSpace(
|
||||||
@ -265,22 +251,78 @@ std::string Parser::parse<std::string>()
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<>
|
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]));
|
BOOST_ASSERT(!std::isspace(expectedValue[0]));
|
||||||
|
|
||||||
skipWhiteSpace();
|
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 &expectedCharacter)
|
||||||
{
|
{
|
||||||
const auto character = static_cast<char>(this->currentCharacter());
|
const auto character = static_cast<char>(this->currentCharacter());
|
||||||
|
|
||||||
if (character != expectedCharacter)
|
if (character != expectedCharacter)
|
||||||
throw ParserException(*this, "Unexpected string, expected \"" + expectedValue + "\" (expected character '" + expectedCharacter + "', got '" + character + "')");
|
return true;
|
||||||
|
|
||||||
this->advance();
|
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();
|
skipWhiteSpace();
|
||||||
|
|
||||||
bool positive = advanceIf('+') || !advanceIf('-');
|
bool positive = probe('+') || !probe('-');
|
||||||
|
|
||||||
const auto value = parseIntegerBody();
|
const auto value = parseIntegerBody();
|
||||||
|
|
||||||
@ -340,12 +382,42 @@ uint64_t Parser::parse<uint64_t>()
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<>
|
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>();
|
const auto value = parse<int64_t>();
|
||||||
|
|
||||||
if (value != expectedValue)
|
if (value == expectedValue)
|
||||||
throw ParserException(*this, "Unexpected value " + std::to_string(value) + ", expected " + std::to_string(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<>
|
template<>
|
||||||
void Parser::expect<uint64_t>(const uint64_t &expectedValue)
|
void Parser::expect<uint64_t>(const uint64_t &expectedValue)
|
||||||
{
|
{
|
||||||
const auto value = parse<uint64_t>();
|
if (!probe<uint64_t>(expectedValue))
|
||||||
|
throw ParserException(*this, "Unexpected value, expected \"" + std::to_string(expectedValue) + "\"");
|
||||||
if (value != expectedValue)
|
|
||||||
throw ParserException(*this, "Unexpected value " + std::to_string(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<>
|
template<>
|
||||||
void Parser::expect<int32_t>(const int32_t &expectedValue)
|
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<>
|
template<>
|
||||||
bool Parser::parse<bool>()
|
bool Parser::parse<bool>()
|
||||||
{
|
{
|
||||||
skipWhiteSpace();
|
skipWhiteSpace();
|
||||||
|
|
||||||
if (advanceIf('0'))
|
if (probe('0'))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (advanceIf('1'))
|
if (probe('1'))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
throw ParserException(*this, "Could not parse Boolean value");
|
throw ParserException(*this, "Could not parse Boolean value");
|
||||||
|
Reference in New Issue
Block a user