Major refactoring of underlying Parser class.
This commit is contained in:
@@ -5,10 +5,8 @@
|
||||
#include <plasp/pddl/Context.h>
|
||||
#include <plasp/pddl/Domain.h>
|
||||
#include <plasp/pddl/ExpressionContext.h>
|
||||
#include <plasp/pddl/Identifier.h>
|
||||
#include <plasp/pddl/expressions/Type.h>
|
||||
#include <plasp/utils/IO.h>
|
||||
#include <plasp/utils/ParserException.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -23,31 +21,33 @@ namespace pddl
|
||||
|
||||
void Action::parseDeclaration(Context &context, Domain &domain)
|
||||
{
|
||||
auto &parser = context.parser;
|
||||
|
||||
auto action = std::make_unique<Action>(Action());
|
||||
|
||||
action->m_name = context.parser.parseIdentifier(isIdentifier);
|
||||
action->m_name = parser.parseIdentifier();
|
||||
|
||||
context.parser.expect<std::string>(":parameters");
|
||||
context.parser.expect<std::string>("(");
|
||||
parser.expect<std::string>(":parameters");
|
||||
parser.expect<std::string>("(");
|
||||
|
||||
ExpressionContext expressionContext(domain, action->m_parameters);
|
||||
|
||||
// Read parameters
|
||||
expressions::Variable::parseTypedDeclarations(context, expressionContext);
|
||||
|
||||
context.parser.expect<std::string>(")");
|
||||
parser.expect<std::string>(")");
|
||||
|
||||
// Parse preconditions and effects
|
||||
while (context.parser.currentCharacter() != ')')
|
||||
while (!parser.testAndReturn(')'))
|
||||
{
|
||||
context.parser.expect<std::string>(":");
|
||||
parser.expect<std::string>(":");
|
||||
|
||||
if (context.parser.probeIdentifier("precondition", isIdentifier))
|
||||
if (parser.testIdentifierAndSkip("precondition"))
|
||||
action->m_precondition = parsePreconditionExpression(context, expressionContext);
|
||||
else if (context.parser.probeIdentifier("effect", isIdentifier))
|
||||
else if (parser.testIdentifierAndSkip("effect"))
|
||||
action->m_effect = parseEffectExpression(context, expressionContext);
|
||||
|
||||
context.parser.skipWhiteSpace();
|
||||
parser.skipWhiteSpace();
|
||||
}
|
||||
|
||||
// Store new action
|
||||
|
@@ -44,7 +44,7 @@ Description Description::fromStream(std::istream &istream)
|
||||
{
|
||||
Description description;
|
||||
|
||||
description.m_context.parser.readStream("std::cin", istream);
|
||||
description.m_context.parser.read("std::cin", istream);
|
||||
description.parse();
|
||||
|
||||
return description;
|
||||
@@ -56,7 +56,7 @@ Description Description::fromFile(const std::string &path)
|
||||
{
|
||||
Description description;
|
||||
|
||||
description.m_context.parser.readFile(path);
|
||||
description.m_context.parser.read(path);
|
||||
description.parse();
|
||||
|
||||
return description;
|
||||
@@ -73,7 +73,7 @@ Description Description::fromFiles(const std::vector<std::string> &paths)
|
||||
std::for_each(paths.cbegin(), paths.cend(),
|
||||
[&](const auto &path)
|
||||
{
|
||||
description.m_context.parser.readFile(path);
|
||||
description.m_context.parser.read(path);
|
||||
});
|
||||
|
||||
description.parse();
|
||||
@@ -126,7 +126,6 @@ void Description::parse()
|
||||
{
|
||||
auto &parser = m_context.parser;
|
||||
|
||||
parser.setCaseSensitive(false);
|
||||
parser.removeComments(";", "\n", false);
|
||||
|
||||
// First, determine the locations of domain and problem
|
||||
@@ -155,7 +154,7 @@ void Description::findSections()
|
||||
|
||||
parser.skipWhiteSpace();
|
||||
|
||||
while (!parser.atEndOfStream())
|
||||
while (!parser.atEnd())
|
||||
{
|
||||
const auto position = parser.position();
|
||||
|
||||
@@ -163,20 +162,20 @@ void Description::findSections()
|
||||
parser.expect<std::string>("define");
|
||||
parser.expect<std::string>("(");
|
||||
|
||||
if (parser.probe<std::string>("domain"))
|
||||
if (parser.testAndSkip<std::string>("domain"))
|
||||
{
|
||||
if (m_domainPosition != -1)
|
||||
throw utils::ParserException(parser, "PDDL description may not contain two domains");
|
||||
throw utils::ParserException(parser.coordinate(), "PDDL description may not contain two domains");
|
||||
|
||||
m_domainPosition = position;
|
||||
|
||||
parser.seek(position);
|
||||
m_domain->findSections();
|
||||
}
|
||||
else if (m_context.parser.probe<std::string>("problem"))
|
||||
else if (m_context.parser.testAndSkip<std::string>("problem"))
|
||||
{
|
||||
if (m_problemPosition != -1)
|
||||
throw utils::ParserException(parser, "PDDL description may currently not contain two problems");
|
||||
throw utils::ParserException(parser.coordinate(), "PDDL description may currently not contain two problems");
|
||||
|
||||
m_problem = std::make_unique<Problem>(Problem(m_context, *m_domain));
|
||||
|
||||
@@ -188,7 +187,7 @@ void Description::findSections()
|
||||
else
|
||||
{
|
||||
const auto sectionIdentifier = parser.parse<std::string>();
|
||||
throw utils::ParserException(parser, "unknown PDDL section “" + sectionIdentifier + "”");
|
||||
throw utils::ParserException(parser.coordinate(), "unknown PDDL section “" + sectionIdentifier + "”");
|
||||
}
|
||||
|
||||
m_context.parser.skipWhiteSpace();
|
||||
|
@@ -3,7 +3,6 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include <plasp/pddl/ConsistencyException.h>
|
||||
#include <plasp/pddl/Identifier.h>
|
||||
#include <plasp/pddl/IO.h>
|
||||
#include <plasp/pddl/expressions/Constant.h>
|
||||
#include <plasp/pddl/expressions/PredicateDeclaration.h>
|
||||
@@ -43,7 +42,7 @@ void Domain::findSections()
|
||||
parser.expect<std::string>("(");
|
||||
parser.expect<std::string>("domain");
|
||||
|
||||
m_name = m_context.parser.parseIdentifier(isIdentifier);
|
||||
m_name = m_context.parser.parseIdentifier();
|
||||
|
||||
parser.expect<std::string>(")");
|
||||
|
||||
@@ -53,7 +52,7 @@ void Domain::findSections()
|
||||
if (unique && sectionPosition != -1)
|
||||
{
|
||||
parser.seek(value);
|
||||
throw utils::ParserException(parser, "only one “:" + sectionName + "” section allowed");
|
||||
throw utils::ParserException(parser.coordinate(), "only one “:" + sectionName + "” section allowed");
|
||||
}
|
||||
|
||||
sectionPosition = value;
|
||||
@@ -72,38 +71,38 @@ void Domain::findSections()
|
||||
const auto sectionIdentifierPosition = parser.position();
|
||||
|
||||
// Save the parser position of the individual sections for later parsing
|
||||
if (parser.probeIdentifier("requirements", isIdentifier))
|
||||
if (parser.testIdentifierAndSkip("requirements"))
|
||||
setSectionPosition("requirements", m_requirementsPosition, position, true);
|
||||
else if (parser.probeIdentifier("types", isIdentifier))
|
||||
else if (parser.testIdentifierAndSkip("types"))
|
||||
setSectionPosition("types", m_typesPosition, position, true);
|
||||
else if (parser.probeIdentifier("constants", isIdentifier))
|
||||
else if (parser.testIdentifierAndSkip("constants"))
|
||||
setSectionPosition("constants", m_constantsPosition, position, true);
|
||||
else if (parser.probeIdentifier("predicates", isIdentifier))
|
||||
else if (parser.testIdentifierAndSkip("predicates"))
|
||||
setSectionPosition("predicates", m_predicatesPosition, position, true);
|
||||
else if (parser.probeIdentifier("action", isIdentifier))
|
||||
else if (parser.testIdentifierAndSkip("action"))
|
||||
{
|
||||
m_actionPositions.emplace_back(-1);
|
||||
setSectionPosition("action", m_actionPositions.back(), position);
|
||||
}
|
||||
else if (parser.probeIdentifier("functions", isIdentifier)
|
||||
|| parser.probeIdentifier("constraints", isIdentifier)
|
||||
|| parser.probeIdentifier("durative-action", isIdentifier)
|
||||
|| parser.probeIdentifier("derived", isIdentifier))
|
||||
else if (parser.testIdentifierAndSkip("functions")
|
||||
|| parser.testIdentifierAndSkip("constraints")
|
||||
|| parser.testIdentifierAndSkip("durative-action")
|
||||
|| parser.testIdentifierAndSkip("derived"))
|
||||
{
|
||||
parser.seek(sectionIdentifierPosition);
|
||||
|
||||
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto sectionIdentifier = parser.parseIdentifier();
|
||||
|
||||
m_context.logger.logWarning(parser, "section type “" + sectionIdentifier + "” currently unsupported");
|
||||
m_context.logger.logWarning(parser.coordinate(), "section type “" + sectionIdentifier + "” currently unsupported");
|
||||
|
||||
parser.seek(sectionIdentifierPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto sectionIdentifier = parser.parseIdentifier();
|
||||
|
||||
parser.seek(position);
|
||||
throw utils::ParserException(m_context.parser, "unknown domain section “" + sectionIdentifier + "”");
|
||||
throw utils::ParserException(parser.coordinate(), "unknown domain section “" + sectionIdentifier + "”");
|
||||
}
|
||||
|
||||
// Skip section for now and parse it later
|
||||
@@ -340,7 +339,7 @@ void Domain::parseTypeSection()
|
||||
while (parser.currentCharacter() != ')')
|
||||
{
|
||||
if (parser.currentCharacter() == '(')
|
||||
throw utils::ParserException(parser, "only primitive types are allowed in type section");
|
||||
throw utils::ParserException(parser.coordinate(), "only primitive types are allowed in type section");
|
||||
|
||||
expressions::PrimitiveType::parseTypedDeclaration(m_context, *this);
|
||||
|
||||
|
@@ -3,7 +3,6 @@
|
||||
#include <plasp/pddl/Context.h>
|
||||
#include <plasp/pddl/Domain.h>
|
||||
#include <plasp/pddl/ExpressionContext.h>
|
||||
#include <plasp/pddl/Identifier.h>
|
||||
#include <plasp/pddl/IO.h>
|
||||
#include <plasp/pddl/expressions/And.h>
|
||||
#include <plasp/pddl/expressions/Imply.h>
|
||||
@@ -49,12 +48,12 @@ ExpressionPointer parsePreconditionExpression(Context &context,
|
||||
|
||||
const auto expressionIdentifierPosition = parser.position();
|
||||
|
||||
if (parser.probeIdentifier("forall", isIdentifier)
|
||||
|| parser.probeIdentifier("preference", isIdentifier))
|
||||
if (parser.testIdentifierAndSkip("forall")
|
||||
|| parser.testIdentifierAndSkip("preference"))
|
||||
{
|
||||
// TODO: refactor
|
||||
parser.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto expressionIdentifier = parser.parseIdentifier();
|
||||
|
||||
parser.seek(position);
|
||||
return expressions::Unsupported::parse(context);
|
||||
@@ -89,32 +88,32 @@ ExpressionPointer parseExpression(Context &context, ExpressionContext &expressio
|
||||
|
||||
const auto expressionIdentifierPosition = parser.position();
|
||||
|
||||
if (parser.probeIdentifier("exists", isIdentifier)
|
||||
|| parser.probeIdentifier("forall", isIdentifier)
|
||||
|| parser.probeIdentifier("-", isIdentifier)
|
||||
|| parser.probeIdentifier("=", isIdentifier)
|
||||
|| parser.probeIdentifier("*", isIdentifier)
|
||||
|| parser.probeIdentifier("+", isIdentifier)
|
||||
|| parser.probeIdentifier("-", isIdentifier)
|
||||
|| parser.probeIdentifier("/", isIdentifier)
|
||||
|| parser.probeIdentifier(">", isIdentifier)
|
||||
|| parser.probeIdentifier("<", isIdentifier)
|
||||
|| parser.probeIdentifier("=", isIdentifier)
|
||||
|| parser.probeIdentifier(">=", isIdentifier)
|
||||
|| parser.probeIdentifier("<=", isIdentifier))
|
||||
if (parser.testIdentifierAndSkip("exists")
|
||||
|| parser.testIdentifierAndSkip("forall")
|
||||
|| parser.testIdentifierAndSkip("-")
|
||||
|| parser.testIdentifierAndSkip("=")
|
||||
|| parser.testIdentifierAndSkip("*")
|
||||
|| parser.testIdentifierAndSkip("+")
|
||||
|| parser.testIdentifierAndSkip("-")
|
||||
|| parser.testIdentifierAndSkip("/")
|
||||
|| parser.testIdentifierAndSkip(">")
|
||||
|| parser.testIdentifierAndSkip("<")
|
||||
|| parser.testIdentifierAndSkip("=")
|
||||
|| parser.testIdentifierAndSkip(">=")
|
||||
|| parser.testIdentifierAndSkip("<="))
|
||||
{
|
||||
parser.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto expressionIdentifier = parser.parseIdentifier();
|
||||
|
||||
parser.seek(position);
|
||||
return expressions::Unsupported::parse(context);
|
||||
}
|
||||
|
||||
parser.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto expressionIdentifier = parser.parseIdentifier();
|
||||
|
||||
parser.seek(position);
|
||||
throw utils::ParserException(context.parser, "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
|
||||
throw utils::ParserException(parser.coordinate(), "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -134,11 +133,11 @@ ExpressionPointer parseEffectExpression(Context &context, ExpressionContext &exp
|
||||
|
||||
const auto expressionIdentifierPosition = parser.position();
|
||||
|
||||
if (parser.probeIdentifier("forall", isIdentifier)
|
||||
|| parser.probeIdentifier("when", isIdentifier))
|
||||
if (parser.testIdentifierAndSkip("forall")
|
||||
|| parser.testIdentifierAndSkip("when"))
|
||||
{
|
||||
parser.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto expressionIdentifier = parser.parseIdentifier();
|
||||
|
||||
parser.seek(position);
|
||||
return expressions::Unsupported::parse(context);
|
||||
@@ -168,37 +167,39 @@ ExpressionPointer parseEffectBodyExpression(Context &context, ExpressionContext
|
||||
|
||||
const auto expressionIdentifierPosition = parser.position();
|
||||
|
||||
if (parser.probeIdentifier("=", isIdentifier)
|
||||
|| parser.probeIdentifier("assign", isIdentifier)
|
||||
|| parser.probeIdentifier("scale-up", isIdentifier)
|
||||
|| parser.probeIdentifier("scale-down", isIdentifier)
|
||||
|| parser.probeIdentifier("increase", isIdentifier)
|
||||
|| parser.probeIdentifier("decrease", isIdentifier))
|
||||
if (parser.testIdentifierAndSkip("=")
|
||||
|| parser.testIdentifierAndSkip("assign")
|
||||
|| parser.testIdentifierAndSkip("scale-up")
|
||||
|| parser.testIdentifierAndSkip("scale-down")
|
||||
|| parser.testIdentifierAndSkip("increase")
|
||||
|| parser.testIdentifierAndSkip("decrease"))
|
||||
{
|
||||
parser.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto expressionIdentifier = parser.parseIdentifier();
|
||||
|
||||
parser.seek(position);
|
||||
return expressions::Unsupported::parse(context);
|
||||
}
|
||||
|
||||
parser.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto expressionIdentifier = parser.parseIdentifier();
|
||||
|
||||
parser.seek(position);
|
||||
throw utils::ParserException(context.parser, "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
|
||||
throw utils::ParserException(parser.coordinate(), "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer parsePredicate(Context &context, ExpressionContext &expressionContext)
|
||||
{
|
||||
auto &parser = context.parser;
|
||||
|
||||
ExpressionPointer expression;
|
||||
|
||||
if ((expression = expressions::Predicate::parse(context, expressionContext)))
|
||||
return expression;
|
||||
|
||||
throw utils::ParserException(context.parser, "expected predicate");
|
||||
throw utils::ParserException(parser.coordinate(), "expected predicate");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -229,15 +230,15 @@ ExpressionPointer parseAtomicFormula(Context &context, ExpressionContext &expres
|
||||
|
||||
const auto position = parser.position();
|
||||
|
||||
if (!parser.probe<std::string>("("))
|
||||
if (!parser.testAndSkip<std::string>("("))
|
||||
return nullptr;
|
||||
|
||||
const auto expressionIdentifierPosition = parser.position();
|
||||
|
||||
if (parser.probeIdentifier("=", isIdentifier))
|
||||
if (parser.testIdentifierAndSkip("="))
|
||||
{
|
||||
parser.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto expressionIdentifier = parser.parseIdentifier();
|
||||
|
||||
parser.seek(position);
|
||||
return expressions::Unsupported::parse(context);
|
||||
|
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <plasp/pddl/Context.h>
|
||||
#include <plasp/pddl/ExpressionContext.h>
|
||||
#include <plasp/pddl/Identifier.h>
|
||||
#include <plasp/pddl/IO.h>
|
||||
#include <plasp/pddl/Problem.h>
|
||||
#include <plasp/pddl/expressions/At.h>
|
||||
@@ -46,20 +45,20 @@ std::unique_ptr<InitialState> InitialState::parseDeclaration(Context &context,
|
||||
|
||||
const auto expressionIdentifierPosition = parser.position();
|
||||
|
||||
if (parser.probeIdentifier("=", isIdentifier))
|
||||
if (parser.testIdentifierAndSkip("="))
|
||||
{
|
||||
parser.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto expressionIdentifier = parser.parseIdentifier();
|
||||
|
||||
parser.seek(position);
|
||||
return expressions::Unsupported::parse(context);
|
||||
}
|
||||
|
||||
parser.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto expressionIdentifier = parser.parseIdentifier();
|
||||
|
||||
parser.seek(position);
|
||||
throw utils::ParserException(parser, "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
|
||||
throw utils::ParserException(parser.coordinate(), "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
|
||||
};
|
||||
|
||||
parser.skipWhiteSpace();
|
||||
|
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <plasp/pddl/Domain.h>
|
||||
#include <plasp/pddl/ExpressionContext.h>
|
||||
#include <plasp/pddl/Identifier.h>
|
||||
#include <plasp/pddl/IO.h>
|
||||
#include <plasp/pddl/expressions/Constant.h>
|
||||
#include <plasp/utils/IO.h>
|
||||
@@ -43,7 +42,7 @@ void Problem::findSections()
|
||||
parser.expect<std::string>("(");
|
||||
parser.expect<std::string>("problem");
|
||||
|
||||
m_name = parser.parseIdentifier(isIdentifier);
|
||||
m_name = parser.parseIdentifier();
|
||||
|
||||
parser.expect<std::string>(")");
|
||||
|
||||
@@ -53,7 +52,7 @@ void Problem::findSections()
|
||||
if (unique && sectionPosition != -1)
|
||||
{
|
||||
parser.seek(value);
|
||||
throw utils::ParserException(parser, "only one “:" + sectionName + "” section allowed");
|
||||
throw utils::ParserException(parser.coordinate(), "only one “:" + sectionName + "” section allowed");
|
||||
}
|
||||
|
||||
sectionPosition = value;
|
||||
@@ -71,34 +70,34 @@ void Problem::findSections()
|
||||
const auto sectionIdentifierPosition = parser.position();
|
||||
|
||||
// TODO: check order of the sections
|
||||
if (parser.probeIdentifier("domain", isIdentifier))
|
||||
if (parser.testIdentifierAndSkip("domain"))
|
||||
setSectionPosition("domain", m_domainPosition, position, true);
|
||||
else if (parser.probeIdentifier("requirements", isIdentifier))
|
||||
else if (parser.testIdentifierAndSkip("requirements"))
|
||||
setSectionPosition("requirements", m_requirementsPosition, position, true);
|
||||
else if (parser.probeIdentifier("objects", isIdentifier))
|
||||
else if (parser.testIdentifierAndSkip("objects"))
|
||||
setSectionPosition("objects", m_objectsPosition, position, true);
|
||||
else if (parser.probeIdentifier("init", isIdentifier))
|
||||
else if (parser.testIdentifierAndSkip("init"))
|
||||
setSectionPosition("init", m_initialStatePosition, position, true);
|
||||
else if (parser.probeIdentifier("goal", isIdentifier))
|
||||
else if (parser.testIdentifierAndSkip("goal"))
|
||||
setSectionPosition("goal", m_goalPosition, position, true);
|
||||
else if (parser.probeIdentifier("constraints", isIdentifier)
|
||||
|| parser.probeIdentifier("metric", isIdentifier)
|
||||
|| parser.probeIdentifier("length", isIdentifier))
|
||||
else if (parser.testIdentifierAndSkip("constraints")
|
||||
|| parser.testIdentifierAndSkip("metric")
|
||||
|| parser.testIdentifierAndSkip("length"))
|
||||
{
|
||||
parser.seek(sectionIdentifierPosition);
|
||||
|
||||
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto sectionIdentifier = parser.parseIdentifier();
|
||||
|
||||
m_context.logger.logWarning(parser, "section type “" + sectionIdentifier + "” currently unsupported");
|
||||
m_context.logger.logWarning(parser.coordinate(), "section type “" + sectionIdentifier + "” currently unsupported");
|
||||
|
||||
parser.seek(sectionIdentifierPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
|
||||
const auto sectionIdentifier = parser.parseIdentifier();
|
||||
|
||||
parser.seek(position);
|
||||
throw utils::ParserException(m_context.parser, "unknown problem section “" + sectionIdentifier + "”");
|
||||
throw utils::ParserException(parser.coordinate(), "unknown problem section “" + sectionIdentifier + "”");
|
||||
}
|
||||
|
||||
// Skip section for now and parse it later
|
||||
@@ -201,10 +200,10 @@ void Problem::parseDomainSection()
|
||||
|
||||
parser.skipWhiteSpace();
|
||||
|
||||
const auto domainName = parser.parseIdentifier(isIdentifier);
|
||||
const auto domainName = parser.parseIdentifier();
|
||||
|
||||
if (m_domain.name() != domainName)
|
||||
throw utils::ParserException(parser, "domains do not match (“" + m_domain.name() + "” and “" + domainName + "”)");
|
||||
throw utils::ParserException(parser.coordinate(), "domains do not match (“" + m_domain.name() + "” and “" + domainName + "”)");
|
||||
|
||||
parser.expect<std::string>(")");
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/bimap.hpp>
|
||||
|
||||
#include <plasp/pddl/Identifier.h>
|
||||
#include <plasp/utils/IO.h>
|
||||
#include <plasp/utils/ParserException.h>
|
||||
|
||||
@@ -84,17 +83,19 @@ Requirement::Requirement(Requirement::Type type)
|
||||
|
||||
Requirement Requirement::parse(Context &context)
|
||||
{
|
||||
const auto requirementName = context.parser.parseIdentifier(isIdentifier);
|
||||
auto &parser = context.parser;
|
||||
|
||||
const auto requirementName = parser.parseIdentifier();
|
||||
|
||||
const auto match = requirementTypesToPDDL.right.find(requirementName);
|
||||
|
||||
if (match == requirementTypesToPDDL.right.end())
|
||||
throw utils::ParserException(context.parser, "unknown PDDL requirement “" + requirementName + "”");
|
||||
throw utils::ParserException(parser.coordinate(), "unknown PDDL requirement “" + requirementName + "”");
|
||||
|
||||
const auto requirementType = match->second;
|
||||
|
||||
if (requirementType == Requirement::Type::GoalUtilities)
|
||||
context.logger.logWarning(context.parser, "requirement “goal-utilities” is not part of the PDDL 3.1 specification");
|
||||
context.logger.logWarning(parser.coordinate(), "requirement “goal-utilities” is not part of the PDDL 3.1 specification");
|
||||
|
||||
return Requirement(match->second);
|
||||
}
|
||||
|
@@ -37,7 +37,7 @@ ConstantPointer Constant::parseDeclaration(Context &context)
|
||||
|
||||
auto constant = std::make_unique<Constant>(Constant());
|
||||
|
||||
constant->m_name = context.parser.parseIdentifier(isIdentifier);
|
||||
constant->m_name = context.parser.parseIdentifier();
|
||||
|
||||
BOOST_ASSERT(constant->m_name != "-");
|
||||
|
||||
@@ -71,7 +71,7 @@ void Constant::parseTypedDeclaration(Context &context, Domain &domain, Constants
|
||||
context.parser.skipWhiteSpace();
|
||||
|
||||
// Check for typing information
|
||||
if (!context.parser.probe('-'))
|
||||
if (!context.parser.testAndSkip<char>('-'))
|
||||
return;
|
||||
|
||||
// If existing, parse and store parent type
|
||||
@@ -113,7 +113,7 @@ void Constant::parseTypedDeclarations(Context &context, Domain &domain)
|
||||
domain.checkRequirement(Requirement::Type::Typing);
|
||||
// If no types are given, check that typing is not a requirement
|
||||
else if (domain.hasRequirement(Requirement::Type::Typing))
|
||||
throw utils::ParserException(parser, "constant has undeclared type");
|
||||
throw utils::ParserException(parser.coordinate(), "constant has undeclared type");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -140,32 +140,36 @@ void Constant::parseTypedDeclarations(Context &context, Problem &problem)
|
||||
problem.checkRequirement(Requirement::Type::Typing);
|
||||
// If no types are given, check that typing is not a requirement
|
||||
else if (problem.hasRequirement(Requirement::Type::Typing))
|
||||
throw utils::ParserException(context.parser, "constant has undeclared type");
|
||||
throw utils::ParserException(parser.coordinate(), "constant has undeclared type");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Constant *Constant::parseAndFind(Context &context, const Domain &domain)
|
||||
{
|
||||
context.parser.skipWhiteSpace();
|
||||
auto &parser = context.parser;
|
||||
|
||||
const auto constantName = context.parser.parseIdentifier(isIdentifier);
|
||||
parser.skipWhiteSpace();
|
||||
|
||||
const auto constantName = parser.parseIdentifier();
|
||||
|
||||
auto *constant = parseAndFind(constantName, domain.constants());
|
||||
|
||||
if (constant != nullptr)
|
||||
return constant;
|
||||
|
||||
throw utils::ParserException(context.parser, "constant “" + constantName + "” used but never declared");
|
||||
throw utils::ParserException(parser.coordinate(), "constant “" + constantName + "” used but never declared");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Constant *Constant::parseAndFind(Context &context, const Problem &problem)
|
||||
{
|
||||
context.parser.skipWhiteSpace();
|
||||
auto &parser = context.parser;
|
||||
|
||||
const auto constantName = context.parser.parseIdentifier(isIdentifier);
|
||||
parser.skipWhiteSpace();
|
||||
|
||||
const auto constantName = parser.parseIdentifier();
|
||||
|
||||
auto *constant = parseAndFind(constantName, problem.domain().constants());
|
||||
|
||||
@@ -177,7 +181,7 @@ Constant *Constant::parseAndFind(Context &context, const Problem &problem)
|
||||
if (constant)
|
||||
return constant;
|
||||
|
||||
throw utils::ParserException(context.parser, "constant “" + constantName + "” used but never declared");
|
||||
throw utils::ParserException(parser.coordinate(), "constant “" + constantName + "” used but never declared");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -13,6 +13,7 @@ namespace expressions
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: make static character string literal
|
||||
const std::string Imply::Identifier = "imply";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -3,7 +3,6 @@
|
||||
#include <plasp/pddl/Context.h>
|
||||
#include <plasp/pddl/Domain.h>
|
||||
#include <plasp/pddl/ExpressionContext.h>
|
||||
#include <plasp/pddl/Identifier.h>
|
||||
#include <plasp/pddl/Problem.h>
|
||||
#include <plasp/pddl/expressions/Constant.h>
|
||||
#include <plasp/pddl/expressions/Variable.h>
|
||||
@@ -34,13 +33,13 @@ PredicatePointer Predicate::parse(Context &context, ExpressionContext &expressio
|
||||
|
||||
const auto position = parser.position();
|
||||
|
||||
if (!parser.probe<std::string>("("))
|
||||
if (!parser.testAndSkip<std::string>("("))
|
||||
{
|
||||
parser.seek(position);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto predicateName = parser.parseIdentifier(isIdentifier);
|
||||
const auto predicateName = parser.parseIdentifier();
|
||||
const auto &predicates = expressionContext.domain.predicates();
|
||||
|
||||
const auto matchingPredicate = std::find_if(predicates.cbegin(), predicates.cend(),
|
||||
@@ -97,13 +96,13 @@ PredicatePointer Predicate::parse(Context &context, const Problem &problem)
|
||||
|
||||
const auto position = parser.position();
|
||||
|
||||
if (!parser.probe<std::string>("("))
|
||||
if (!parser.testAndSkip<std::string>("("))
|
||||
{
|
||||
parser.seek(position);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto predicateName = parser.parseIdentifier(isIdentifier);
|
||||
const auto predicateName = parser.parseIdentifier();
|
||||
const auto &predicates = problem.domain().predicates();
|
||||
|
||||
const auto matchingPredicate = std::find_if(predicates.cbegin(), predicates.cend(),
|
||||
@@ -122,12 +121,12 @@ PredicatePointer Predicate::parse(Context &context, const Problem &problem)
|
||||
|
||||
predicate->m_name = predicateName;
|
||||
|
||||
context.parser.skipWhiteSpace();
|
||||
parser.skipWhiteSpace();
|
||||
|
||||
while (context.parser.currentCharacter() != ')')
|
||||
while (parser.currentCharacter() != ')')
|
||||
{
|
||||
if (context.parser.currentCharacter() == '?')
|
||||
throw utils::ParserException(context.parser, "variables not allowed in this context");
|
||||
if (parser.currentCharacter() == '?')
|
||||
throw utils::ParserException(parser.coordinate(), "variables not allowed in this context");
|
||||
|
||||
// Parse objects and constants
|
||||
const auto *constant = Constant::parseAndFind(context, problem);
|
||||
|
@@ -3,7 +3,6 @@
|
||||
#include <plasp/pddl/Context.h>
|
||||
#include <plasp/pddl/Domain.h>
|
||||
#include <plasp/pddl/ExpressionContext.h>
|
||||
#include <plasp/pddl/Identifier.h>
|
||||
#include <plasp/pddl/expressions/Constant.h>
|
||||
#include <plasp/pddl/expressions/Variable.h>
|
||||
|
||||
@@ -33,7 +32,7 @@ void PredicateDeclaration::parse(Context &context, Domain &domain)
|
||||
|
||||
auto predicate = std::make_unique<PredicateDeclaration>(PredicateDeclaration());
|
||||
|
||||
predicate->m_name = context.parser.parseIdentifier(isIdentifier);
|
||||
predicate->m_name = context.parser.parseIdentifier();
|
||||
|
||||
// Flag predicate as correctly declared in the types section
|
||||
predicate->setDeclared();
|
||||
|
@@ -43,7 +43,7 @@ void PrimitiveType::parseDeclaration(Context &context, Domain &domain)
|
||||
|
||||
context.parser.skipWhiteSpace();
|
||||
|
||||
const auto typeName = context.parser.parseIdentifier(isIdentifier);
|
||||
const auto typeName = context.parser.parseIdentifier();
|
||||
|
||||
const auto match = std::find_if(types.cbegin(), types.cend(),
|
||||
[&](const auto &primitiveType)
|
||||
@@ -76,7 +76,7 @@ void PrimitiveType::parseTypedDeclaration(Context &context, Domain &domain)
|
||||
context.parser.skipWhiteSpace();
|
||||
|
||||
// Check for type inheritance
|
||||
if (!context.parser.probe('-'))
|
||||
if (!context.parser.testAndSkip<char>('-'))
|
||||
return;
|
||||
|
||||
domain.checkRequirement(Requirement::Type::Typing);
|
||||
@@ -102,14 +102,16 @@ void PrimitiveType::parseTypedDeclaration(Context &context, Domain &domain)
|
||||
|
||||
PrimitiveType *PrimitiveType::parseAndFind(Context &context, Domain &domain)
|
||||
{
|
||||
auto &parser = context.parser;
|
||||
|
||||
auto &types = domain.types();
|
||||
|
||||
context.parser.skipWhiteSpace();
|
||||
parser.skipWhiteSpace();
|
||||
|
||||
const auto typeName = context.parser.parseIdentifier(isIdentifier);
|
||||
const auto typeName = parser.parseIdentifier();
|
||||
|
||||
if (typeName.empty())
|
||||
throw utils::ParserException(context.parser, "no type supplied");
|
||||
throw utils::ParserException(parser.coordinate(), "no type supplied");
|
||||
|
||||
const auto match = std::find_if(types.cbegin(), types.cend(),
|
||||
[&](const auto &primitiveType)
|
||||
@@ -122,11 +124,11 @@ PrimitiveType *PrimitiveType::parseAndFind(Context &context, Domain &domain)
|
||||
// Only "object" is allowed as an implicit type
|
||||
if (typeName == "object" || typeName == "objects")
|
||||
{
|
||||
context.logger.logWarning(context.parser, "primitive type “" + typeName + "” should be declared");
|
||||
context.logger.logWarning(parser.coordinate(), "primitive type “" + typeName + "” should be declared");
|
||||
types.emplace_back(std::make_unique<expressions::PrimitiveType>(typeName));
|
||||
}
|
||||
else
|
||||
throw utils::ParserException(context.parser, "type “" + typeName + "” used but never declared");
|
||||
throw utils::ParserException(parser.coordinate(), "type “" + typeName + "” used but never declared");
|
||||
|
||||
return types.back().get();
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#include <plasp/pddl/expressions/Unsupported.h>
|
||||
|
||||
#include <plasp/pddl/Identifier.h>
|
||||
#include <plasp/pddl/IO.h>
|
||||
|
||||
namespace plasp
|
||||
@@ -24,9 +23,9 @@ UnsupportedPointer Unsupported::parse(Context &context)
|
||||
|
||||
parser.expect<std::string>("(");
|
||||
|
||||
expression->m_type = parser.parseIdentifier(isIdentifier);
|
||||
expression->m_type = parser.parseIdentifier();
|
||||
|
||||
context.logger.logWarning(context.parser, "expression type “" + expression->m_type + "” currently unsupported in this context");
|
||||
context.logger.logWarning(parser.coordinate(), "expression type “" + expression->m_type + "” currently unsupported in this context");
|
||||
|
||||
skipSection(parser);
|
||||
|
||||
|
@@ -7,7 +7,6 @@
|
||||
#include <plasp/pddl/Context.h>
|
||||
#include <plasp/pddl/Domain.h>
|
||||
#include <plasp/pddl/ExpressionContext.h>
|
||||
#include <plasp/pddl/Identifier.h>
|
||||
#include <plasp/pddl/expressions/Either.h>
|
||||
#include <plasp/pddl/expressions/PrimitiveType.h>
|
||||
#include <plasp/pddl/expressions/Type.h>
|
||||
@@ -36,13 +35,15 @@ Variable::Variable()
|
||||
|
||||
void Variable::parseDeclaration(Context &context, Variables ¶meters)
|
||||
{
|
||||
context.parser.skipWhiteSpace();
|
||||
auto &parser = context.parser;
|
||||
|
||||
context.parser.expect<std::string>("?");
|
||||
parser.skipWhiteSpace();
|
||||
|
||||
parser.expect<std::string>("?");
|
||||
|
||||
auto variable = std::make_unique<Variable>(Variable());
|
||||
|
||||
variable->m_name = context.parser.parseIdentifier(isIdentifier);
|
||||
variable->m_name = parser.parseIdentifier();
|
||||
|
||||
// Check if variable of that name already exists in the current scope
|
||||
const auto match = std::find_if(parameters.cbegin(), parameters.cend(),
|
||||
@@ -52,7 +53,7 @@ void Variable::parseDeclaration(Context &context, Variables ¶meters)
|
||||
});
|
||||
|
||||
if (match != parameters.cend())
|
||||
throw utils::ParserException(context.parser, "variable “" + variable->m_name + "” already declared in this scope");
|
||||
throw utils::ParserException(parser.coordinate(), "variable “" + variable->m_name + "” already declared in this scope");
|
||||
|
||||
// Flag variable for potentially upcoming type declaration
|
||||
variable->setDirty();
|
||||
@@ -75,7 +76,7 @@ void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expres
|
||||
parser.skipWhiteSpace();
|
||||
|
||||
// Check if the variable has a type declaration
|
||||
if (!parser.probe('-'))
|
||||
if (!parser.testAndSkip<char>('-'))
|
||||
return;
|
||||
|
||||
const auto setType =
|
||||
@@ -132,18 +133,20 @@ void Variable::parseTypedDeclarations(Context &context, ExpressionContext &expre
|
||||
expressionContext.checkRequirement(Requirement::Type::Typing);
|
||||
// If no types are given, check that typing is not a requirement
|
||||
else if (expressionContext.hasRequirement(Requirement::Type::Typing))
|
||||
throw utils::ParserException(parser, "variable has undeclared type");
|
||||
throw utils::ParserException(parser.coordinate(), "variable has undeclared type");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const Variable *Variable::parseAndFind(Context &context, const ExpressionContext &expressionContext)
|
||||
{
|
||||
context.parser.skipWhiteSpace();
|
||||
auto &parser = context.parser;
|
||||
|
||||
context.parser.expect<std::string>("?");
|
||||
parser.skipWhiteSpace();
|
||||
|
||||
const auto variableName = context.parser.parseIdentifier(isIdentifier);
|
||||
parser.expect<std::string>("?");
|
||||
|
||||
const auto variableName = parser.parseIdentifier();
|
||||
|
||||
const auto &variables = expressionContext.parameters;
|
||||
|
||||
@@ -154,7 +157,7 @@ const Variable *Variable::parseAndFind(Context &context, const ExpressionContext
|
||||
});
|
||||
|
||||
if (match == variables.cend())
|
||||
throw utils::ParserException(context.parser, "parameter “" + variableName + "” used but never declared");
|
||||
throw utils::ParserException(parser.coordinate(), "parameter “" + variableName + "” used but never declared");
|
||||
|
||||
return match->get();
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ AssignedVariable::AssignedVariable(const Variable &variable, const Value &value)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AssignedVariable AssignedVariable::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
AssignedVariable AssignedVariable::fromSAS(utils::Parser<> &parser, const Variables &variables)
|
||||
{
|
||||
AssignedVariable assignedVariable;
|
||||
|
||||
@@ -43,7 +43,7 @@ AssignedVariable AssignedVariable::fromSAS(utils::Parser &parser, const Variable
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AssignedVariable AssignedVariable::fromSAS(utils::Parser &parser, const Variable &variable)
|
||||
AssignedVariable AssignedVariable::fromSAS(utils::Parser<> &parser, const Variable &variable)
|
||||
{
|
||||
AssignedVariable assignedVariable;
|
||||
|
||||
|
@@ -23,7 +23,7 @@ AxiomRule::AxiomRule(AxiomRule::Conditions conditions, AxiomRule::Condition post
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AxiomRule AxiomRule::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
AxiomRule AxiomRule::fromSAS(utils::Parser<> &parser, const Variables &variables)
|
||||
{
|
||||
parser.expect<std::string>("begin_rule");
|
||||
|
||||
|
@@ -28,10 +28,8 @@ Description::Description()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Description Description::fromParser(utils::Parser &&parser)
|
||||
Description Description::fromParser(utils::Parser<> &&parser)
|
||||
{
|
||||
parser.setCaseSensitive(true);
|
||||
|
||||
Description description;
|
||||
description.parseContent(parser);
|
||||
|
||||
@@ -42,8 +40,8 @@ Description Description::fromParser(utils::Parser &&parser)
|
||||
|
||||
Description Description::fromStream(std::istream &istream)
|
||||
{
|
||||
utils::Parser parser;
|
||||
parser.readStream("std::cin", istream);
|
||||
utils::Parser<> parser;
|
||||
parser.read("std::cin", istream);
|
||||
|
||||
Description description;
|
||||
description.parseContent(parser);
|
||||
@@ -58,8 +56,8 @@ Description Description::fromFile(const boost::filesystem::path &path)
|
||||
if (!boost::filesystem::is_regular_file(path))
|
||||
throw std::runtime_error("File does not exist: “" + path.string() + "”");
|
||||
|
||||
utils::Parser parser;
|
||||
parser.readFile(path);
|
||||
utils::Parser<> parser;
|
||||
parser.read(path);
|
||||
|
||||
Description description;
|
||||
description.parseContent(parser);
|
||||
@@ -155,7 +153,7 @@ bool Description::usesConditionalEffects() const
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseContent(utils::Parser &parser)
|
||||
void Description::parseContent(utils::Parser<> &parser)
|
||||
{
|
||||
parseVersionSection(parser);
|
||||
parseMetricSection(parser);
|
||||
@@ -168,27 +166,27 @@ void Description::parseContent(utils::Parser &parser)
|
||||
|
||||
parser.skipWhiteSpace();
|
||||
|
||||
if (!parser.atEndOfStream())
|
||||
throw utils::ParserException(parser, "expected end of SAS description (perhaps, input contains two SAS descriptions?)");
|
||||
if (!parser.atEnd())
|
||||
throw utils::ParserException(parser.coordinate(), "expected end of SAS description (perhaps, input contains two SAS descriptions?)");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseVersionSection(utils::Parser &parser) const
|
||||
void Description::parseVersionSection(utils::Parser<> &parser) const
|
||||
{
|
||||
parser.expect<std::string>("begin_version");
|
||||
|
||||
const auto formatVersion = parser.parse<size_t>();
|
||||
|
||||
if (formatVersion != 3)
|
||||
throw utils::ParserException(parser, "unsupported SAS format version (" + std::to_string(formatVersion) + ")");
|
||||
throw utils::ParserException(parser.coordinate(), "unsupported SAS format version (" + std::to_string(formatVersion) + ")");
|
||||
|
||||
parser.expect<std::string>("end_version");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseMetricSection(utils::Parser &parser)
|
||||
void Description::parseMetricSection(utils::Parser<> &parser)
|
||||
{
|
||||
parser.expect<std::string>("begin_metric");
|
||||
|
||||
@@ -199,7 +197,7 @@ void Description::parseMetricSection(utils::Parser &parser)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseVariablesSection(utils::Parser &parser)
|
||||
void Description::parseVariablesSection(utils::Parser<> &parser)
|
||||
{
|
||||
const auto numberOfVariables = parser.parse<size_t>();
|
||||
m_variables.reserve(numberOfVariables);
|
||||
@@ -210,7 +208,7 @@ void Description::parseVariablesSection(utils::Parser &parser)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseMutexSection(utils::Parser &parser)
|
||||
void Description::parseMutexSection(utils::Parser<> &parser)
|
||||
{
|
||||
const auto numberOfMutexGroups = parser.parse<size_t>();
|
||||
m_mutexGroups.reserve(numberOfMutexGroups);
|
||||
@@ -221,21 +219,21 @@ void Description::parseMutexSection(utils::Parser &parser)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseInitialStateSection(utils::Parser &parser)
|
||||
void Description::parseInitialStateSection(utils::Parser<> &parser)
|
||||
{
|
||||
m_initialState = std::make_unique<InitialState>(InitialState::fromSAS(parser, m_variables));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseGoalSection(utils::Parser &parser)
|
||||
void Description::parseGoalSection(utils::Parser<> &parser)
|
||||
{
|
||||
m_goal = std::make_unique<Goal>(Goal::fromSAS(parser, m_variables));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseOperatorSection(utils::Parser &parser)
|
||||
void Description::parseOperatorSection(utils::Parser<> &parser)
|
||||
{
|
||||
const auto numberOfOperators = parser.parse<size_t>();
|
||||
m_operators.reserve(numberOfOperators);
|
||||
@@ -246,7 +244,7 @@ void Description::parseOperatorSection(utils::Parser &parser)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseAxiomSection(utils::Parser &parser)
|
||||
void Description::parseAxiomSection(utils::Parser<> &parser)
|
||||
{
|
||||
const auto numberOfAxiomRules = parser.parse<size_t>();
|
||||
m_axiomRules.reserve(numberOfAxiomRules);
|
||||
|
@@ -23,7 +23,7 @@ Effect::Effect(Conditions conditions, Condition postcondition)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Effect Effect::fromSAS(utils::Parser &parser, const Variables &variables, Conditions &preconditions)
|
||||
Effect Effect::fromSAS(utils::Parser<> &parser, const Variables &variables, Conditions &preconditions)
|
||||
{
|
||||
Effect::Conditions conditions;
|
||||
|
||||
|
@@ -13,7 +13,7 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Goal Goal::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
Goal Goal::fromSAS(utils::Parser<> &parser, const Variables &variables)
|
||||
{
|
||||
Goal goal;
|
||||
|
||||
|
@@ -11,7 +11,7 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
InitialState InitialState::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
InitialState InitialState::fromSAS(utils::Parser<> &parser, const Variables &variables)
|
||||
{
|
||||
InitialState initialState;
|
||||
|
||||
|
@@ -15,7 +15,7 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MutexGroup MutexGroup::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
MutexGroup MutexGroup::fromSAS(utils::Parser<> &parser, const Variables &variables)
|
||||
{
|
||||
MutexGroup mutexGroup;
|
||||
|
||||
@@ -29,7 +29,7 @@ MutexGroup MutexGroup::fromSAS(utils::Parser &parser, const Variables &variables
|
||||
mutexGroup.m_facts.emplace_back(Fact::fromSAS(parser, variables));
|
||||
|
||||
if (mutexGroup.m_facts[j].value() == Value::None)
|
||||
throw utils::ParserException(parser, "mutex groups must not contain <none of those> values");
|
||||
throw utils::ParserException(parser.coordinate(), "mutex groups must not contain <none of those> values");
|
||||
}
|
||||
|
||||
parser.expect<std::string>("end_mutex_group");
|
||||
|
@@ -17,7 +17,7 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Operator Operator::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
Operator Operator::fromSAS(utils::Parser<> &parser, const Variables &variables)
|
||||
{
|
||||
Operator operator_;
|
||||
|
||||
|
@@ -18,7 +18,7 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Predicate Predicate::fromSAS(utils::Parser &parser)
|
||||
Predicate Predicate::fromSAS(utils::Parser<> &parser)
|
||||
{
|
||||
Predicate predicate;
|
||||
|
||||
@@ -31,11 +31,12 @@ Predicate Predicate::fromSAS(utils::Parser &parser)
|
||||
while (true)
|
||||
{
|
||||
// Parse arguments until reaching newline
|
||||
parser.skipWhiteSpace(
|
||||
// TODO: reimplement
|
||||
/*parser.skipWhiteSpace(
|
||||
[&](const auto character)
|
||||
{
|
||||
return character != '\n' && std::isspace(character);
|
||||
});
|
||||
});*/
|
||||
|
||||
if (parser.currentCharacter() == '\n')
|
||||
break;
|
||||
@@ -46,7 +47,7 @@ Predicate Predicate::fromSAS(utils::Parser &parser)
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
throw utils::ParserException(parser, "could not parse operator predicate");
|
||||
throw utils::ParserException(parser.coordinate(), "could not parse operator predicate");
|
||||
}
|
||||
|
||||
return predicate;
|
||||
|
@@ -55,7 +55,7 @@ Value Value::negated() const
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Value Value::fromSAS(utils::Parser &parser)
|
||||
Value Value::fromSAS(utils::Parser<> &parser)
|
||||
{
|
||||
const auto sasSign = parser.parse<std::string>();
|
||||
|
||||
@@ -75,12 +75,12 @@ Value Value::fromSAS(utils::Parser &parser)
|
||||
else if (sasSign == "NegatedAtom")
|
||||
value.m_sign = Value::Sign::Negative;
|
||||
else
|
||||
throw utils::ParserException(parser, "invalid value sign “" + sasSign + "”");
|
||||
throw utils::ParserException(parser.coordinate(), "invalid value sign “" + sasSign + "”");
|
||||
|
||||
try
|
||||
{
|
||||
parser.skipWhiteSpace();
|
||||
value.m_name = parser.getLine();
|
||||
value.m_name = parser.parseLine();
|
||||
|
||||
// Remove trailing ()
|
||||
if (value.m_name.find("()") != std::string::npos)
|
||||
@@ -91,7 +91,7 @@ Value Value::fromSAS(utils::Parser &parser)
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
throw utils::ParserException(parser, std::string("could not parse variable value (") + e.what() + ")");
|
||||
throw utils::ParserException(parser.coordinate(), std::string("could not parse variable value (") + e.what() + ")");
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -99,7 +99,7 @@ Value Value::fromSAS(utils::Parser &parser)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const Value &Value::referenceFromSAS(utils::Parser &parser, const Variable &variable)
|
||||
const Value &Value::referenceFromSAS(utils::Parser<> &parser, const Variable &variable)
|
||||
{
|
||||
const auto valueID = parser.parse<int>();
|
||||
|
||||
@@ -107,7 +107,7 @@ const Value &Value::referenceFromSAS(utils::Parser &parser, const Variable &vari
|
||||
return Value::Any;
|
||||
|
||||
if (valueID < 0 || static_cast<size_t>(valueID) >= variable.values().size())
|
||||
throw utils::ParserException(parser, "value index out of range (variable " + variable.name() + ", index " + std::to_string(valueID) + ")");
|
||||
throw utils::ParserException(parser.coordinate(), "value index out of range (variable " + variable.name() + ", index " + std::to_string(valueID) + ")");
|
||||
|
||||
return variable.values()[valueID];
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ Variable::Variable()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Variable Variable::fromSAS(utils::Parser &parser)
|
||||
Variable Variable::fromSAS(utils::Parser<> &parser)
|
||||
{
|
||||
Variable variable;
|
||||
|
||||
@@ -42,7 +42,7 @@ Variable Variable::fromSAS(utils::Parser &parser)
|
||||
|
||||
// <none of those> values are only allowed at the end
|
||||
if (j < numberOfValues - 1 && variable.m_values[j] == Value::None)
|
||||
throw utils::ParserException(parser, "<none of those> value must be the last value of a variable");
|
||||
throw utils::ParserException(parser.coordinate(), "<none of those> value must be the last value of a variable");
|
||||
}
|
||||
|
||||
parser.expect<std::string>("end_variable");
|
||||
@@ -59,12 +59,12 @@ void Variable::printNameAsASPPredicate(utils::LogStream &outputStream) const
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const Variable &Variable::referenceFromSAS(utils::Parser &parser, const Variables &variables)
|
||||
const Variable &Variable::referenceFromSAS(utils::Parser<> &parser, const Variables &variables)
|
||||
{
|
||||
const auto variableID = parser.parse<size_t>();
|
||||
|
||||
if (variableID >= variables.size())
|
||||
throw utils::ParserException(parser, "variable index out of range (index " + std::to_string(variableID) + ")");
|
||||
throw utils::ParserException(parser.coordinate(), "variable index out of range (index " + std::to_string(variableID) + ")");
|
||||
|
||||
return variables[variableID];
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ VariableTransition::VariableTransition()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VariableTransition VariableTransition::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
VariableTransition VariableTransition::fromSAS(utils::Parser<> &parser, const Variables &variables)
|
||||
{
|
||||
VariableTransition variableTransition;
|
||||
|
||||
|
@@ -105,7 +105,7 @@ void Logger::logError(const std::string &message)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Logger::logError(const Parser::Coordinate &coordinate, const std::string &message)
|
||||
void Logger::logError(const StreamCoordinate &coordinate, const std::string &message)
|
||||
{
|
||||
m_errorStream
|
||||
<< Format(Color::White, FontWeight::Bold) << coordinate.sectionName << ":"
|
||||
@@ -119,15 +119,13 @@ void Logger::logError(const Parser::Coordinate &coordinate, const std::string &m
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Logger::logWarning(const Parser &parser, const std::string &message)
|
||||
void Logger::logWarning(const StreamCoordinate &coordinate, const std::string &message)
|
||||
{
|
||||
if (m_warningLevel == WarningLevel::Ignore)
|
||||
return;
|
||||
|
||||
if (m_warningLevel == WarningLevel::Error)
|
||||
throw ParserException(parser, message);
|
||||
|
||||
const auto coordinate = parser.coordinate();
|
||||
throw ParserException(coordinate, message);
|
||||
|
||||
m_errorStream
|
||||
<< Format(Color::White, FontWeight::Bold) << coordinate.sectionName << ":"
|
||||
|
@@ -1,628 +0,0 @@
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <plasp/utils/ParserException.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parser
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::istreambuf_iterator<char> Parser::EndOfFile = std::istreambuf_iterator<char>();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Parser::Parser()
|
||||
: m_isCaseSensitive{true}
|
||||
{
|
||||
std::setlocale(LC_NUMERIC, "C");
|
||||
|
||||
// Don’t skip whitespace
|
||||
m_stream.exceptions(std::istream::badbit);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Parser::Parser(std::string streamName, std::istream &istream)
|
||||
: Parser()
|
||||
{
|
||||
readStream(streamName, istream);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Parser::Parser(Parser &&other)
|
||||
: m_stream{std::move(other.m_stream)},
|
||||
m_streamDelimiters{std::move(other.m_streamDelimiters)},
|
||||
m_isCaseSensitive{other.m_isCaseSensitive}
|
||||
{
|
||||
other.m_isCaseSensitive = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Parser &Parser::operator=(Parser &&other)
|
||||
{
|
||||
m_stream = std::move(other.m_stream);
|
||||
m_streamDelimiters = std::move(other.m_streamDelimiters);
|
||||
m_isCaseSensitive = other.m_isCaseSensitive;
|
||||
|
||||
other.m_isCaseSensitive = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Parser::readStream(std::string streamName, std::istream &istream)
|
||||
{
|
||||
// Store position of new section
|
||||
const auto position = m_stream.tellp();
|
||||
|
||||
m_streamDelimiters.push_back({position, streamName});
|
||||
|
||||
m_stream << istream.rdbuf();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Parser::readFile(const boost::filesystem::path &path)
|
||||
{
|
||||
if (!boost::filesystem::is_regular_file(path))
|
||||
throw std::runtime_error("File does not exist: “" + path.string() + "”");
|
||||
|
||||
std::ifstream fileStream(path.string(), std::ios::in);
|
||||
|
||||
readStream(path.string(), fileStream);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Parser::reset()
|
||||
{
|
||||
m_stream.clear();
|
||||
seek(0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Parser::seek(Position position)
|
||||
{
|
||||
m_stream.clear();
|
||||
m_stream.seekg(position);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Parser::Position Parser::position() const
|
||||
{
|
||||
return m_stream.tellg();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Parser::Coordinate Parser::coordinate() const
|
||||
{
|
||||
const auto currentPosition = position();
|
||||
|
||||
// Find current section
|
||||
auto currentFile = std::find_if(m_streamDelimiters.crbegin(), m_streamDelimiters.crend(),
|
||||
[&](const auto &fileDelimiter)
|
||||
{
|
||||
return currentPosition >= fileDelimiter.position;
|
||||
});
|
||||
|
||||
// If the parser is at the end of the stream, still count from the beginning of the last section
|
||||
if (currentFile == m_streamDelimiters.crend())
|
||||
currentFile = m_streamDelimiters.crbegin();
|
||||
|
||||
// Go back to beginning of section
|
||||
m_stream.clear();
|
||||
m_stream.seekg(currentFile->position);
|
||||
|
||||
size_t row = 1;
|
||||
size_t column = 1;
|
||||
|
||||
// Compute the coordinate character by character
|
||||
while (true)
|
||||
{
|
||||
if (currentPosition == -1 && atEndOfStream())
|
||||
break;
|
||||
else if (currentPosition >= 0 && position() >= currentPosition)
|
||||
break;
|
||||
|
||||
const auto character = currentCharacter();
|
||||
|
||||
if (character == '\n')
|
||||
{
|
||||
row++;
|
||||
column = 1;
|
||||
}
|
||||
else if (std::isblank(character) || std::isprint(character))
|
||||
column++;
|
||||
|
||||
m_stream.ignore(1);
|
||||
}
|
||||
|
||||
return {currentFile->sectionName, row, column};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Parser::setCaseSensitive(bool isCaseSensitive)
|
||||
{
|
||||
m_isCaseSensitive = isCaseSensitive;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Parser::isCaseSensitive() const noexcept
|
||||
{
|
||||
return m_isCaseSensitive;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char Parser::currentCharacter() const
|
||||
{
|
||||
if (m_isCaseSensitive)
|
||||
return m_stream.peek();
|
||||
|
||||
return std::tolower(m_stream.peek());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Parser::atEndOfStream() const
|
||||
{
|
||||
return position() == -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Parser::checkStream() const
|
||||
{
|
||||
if (atEndOfStream())
|
||||
throw ParserException(*this, "reading past end of file");
|
||||
|
||||
if (m_stream.fail())
|
||||
throw ParserException(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Parser::advance()
|
||||
{
|
||||
checkStream();
|
||||
m_stream.ignore(1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Parser::skipWhiteSpace()
|
||||
{
|
||||
return skipWhiteSpace(
|
||||
[](const auto character)
|
||||
{
|
||||
return std::isspace(character);
|
||||
});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Parser::skipLine()
|
||||
{
|
||||
checkStream();
|
||||
|
||||
while (currentCharacter() != '\n')
|
||||
advance();
|
||||
|
||||
advance();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string Parser::getLine()
|
||||
{
|
||||
checkStream();
|
||||
|
||||
std::string value;
|
||||
|
||||
while (true)
|
||||
{
|
||||
const auto character = currentCharacter();
|
||||
|
||||
advance();
|
||||
|
||||
if (character == '\n')
|
||||
break;
|
||||
else if (character == '\r')
|
||||
continue;
|
||||
|
||||
value.push_back(character);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
std::string Parser::parse<std::string>()
|
||||
{
|
||||
skipWhiteSpace();
|
||||
|
||||
std::string value;
|
||||
|
||||
while (true)
|
||||
{
|
||||
const auto character = currentCharacter();
|
||||
|
||||
if (std::isspace(character))
|
||||
break;
|
||||
|
||||
value.push_back(character);
|
||||
advance();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
bool Parser::probe<std::string>(const std::string &expectedValue)
|
||||
{
|
||||
const auto previousPosition = position();
|
||||
|
||||
if (!std::iswspace(expectedValue.front()))
|
||||
skipWhiteSpace();
|
||||
|
||||
const auto match = std::find_if(expectedValue.cbegin(), expectedValue.cend(),
|
||||
[&](const auto &expectedCharacter)
|
||||
{
|
||||
const auto character = static_cast<char>(this->currentCharacter());
|
||||
|
||||
if (character != expectedCharacter)
|
||||
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, "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("expected “") + expectedValue + "”");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint64_t Parser::parseIntegerBody()
|
||||
{
|
||||
checkStream();
|
||||
|
||||
if (!std::isdigit(currentCharacter()))
|
||||
throw ParserException(*this, "could not parse integer value");
|
||||
|
||||
uint64_t value = 0;
|
||||
|
||||
while (!atEndOfStream())
|
||||
{
|
||||
const auto character = currentCharacter();
|
||||
|
||||
if (!std::isdigit(character))
|
||||
break;
|
||||
|
||||
value *= 10;
|
||||
value += character - '0';
|
||||
|
||||
advance();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
int64_t Parser::parse<int64_t>()
|
||||
{
|
||||
skipWhiteSpace();
|
||||
|
||||
bool positive = probe('+') || !probe('-');
|
||||
|
||||
const auto value = parseIntegerBody();
|
||||
|
||||
return (positive ? value : -value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
uint64_t Parser::parse<uint64_t>()
|
||||
{
|
||||
skipWhiteSpace();
|
||||
|
||||
if (currentCharacter() == '-')
|
||||
throw ParserException(*this, "expected unsigned integer, got signed one");
|
||||
|
||||
return parseIntegerBody();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
bool Parser::probe<int64_t>(const int64_t &expectedValue)
|
||||
{
|
||||
const auto previousPosition = position();
|
||||
const auto value = parse<int64_t>();
|
||||
|
||||
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, "expected “" + std::to_string(expectedValue) + "”");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
void Parser::expect<uint64_t>(const uint64_t &expectedValue)
|
||||
{
|
||||
if (!probe<uint64_t>(expectedValue))
|
||||
throw ParserException(*this, "expected “" + std::to_string(expectedValue) + "”");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
int32_t Parser::parse<int32_t>()
|
||||
{
|
||||
return static_cast<int32_t>(parse<int64_t>());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
uint32_t Parser::parse<uint32_t>()
|
||||
{
|
||||
return static_cast<uint32_t>(parse<uint64_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)
|
||||
{
|
||||
expect<int64_t>(static_cast<int64_t>(expectedValue));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
void Parser::expect<uint32_t>(const uint32_t &expectedValue)
|
||||
{
|
||||
expect<uint64_t>(static_cast<uint64_t>(expectedValue));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
bool Parser::parse<bool>()
|
||||
{
|
||||
skipWhiteSpace();
|
||||
|
||||
if (probe('0'))
|
||||
return false;
|
||||
|
||||
if (probe('1'))
|
||||
return true;
|
||||
|
||||
throw ParserException(*this, "could not parse Boolean value");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
void Parser::expect<bool>(const bool &expectedValue)
|
||||
{
|
||||
const auto value = parse<bool>();
|
||||
|
||||
if (value != expectedValue)
|
||||
throw ParserException(*this, "expected “" + std::to_string(expectedValue) + "”");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Parser::probeNumber()
|
||||
{
|
||||
const auto previousPosition = position();
|
||||
|
||||
skipWhiteSpace();
|
||||
|
||||
while (!std::iswspace(currentCharacter()))
|
||||
if (!std::isdigit(currentCharacter()))
|
||||
{
|
||||
seek(previousPosition);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Parser::removeComments(const std::string &startSequence, const std::string &endSequence, bool removeEnd)
|
||||
{
|
||||
const auto inPosition = m_stream.tellg();
|
||||
const auto outPosition = m_stream.tellp();
|
||||
|
||||
m_stream.seekg(0);
|
||||
|
||||
const auto removeRange =
|
||||
[&](const auto &start, const auto &end)
|
||||
{
|
||||
BOOST_ASSERT(start != -1);
|
||||
|
||||
m_stream.clear();
|
||||
m_stream.seekp(start);
|
||||
m_stream.seekg(start);
|
||||
|
||||
auto position = start;
|
||||
|
||||
while (end == -1 || position < end)
|
||||
{
|
||||
m_stream.ignore(1);
|
||||
|
||||
if (atEndOfStream())
|
||||
return;
|
||||
|
||||
m_stream.put(' ');
|
||||
position += static_cast<std::streamoff>(1);
|
||||
}
|
||||
};
|
||||
|
||||
while (!atEndOfStream())
|
||||
{
|
||||
Position startPosition = m_stream.tellg();
|
||||
|
||||
while (!atEndOfStream())
|
||||
{
|
||||
startPosition = m_stream.tellg();
|
||||
|
||||
if (probe(startSequence))
|
||||
break;
|
||||
|
||||
advance();
|
||||
}
|
||||
|
||||
Position endPosition = m_stream.tellg();
|
||||
|
||||
while (!atEndOfStream())
|
||||
{
|
||||
endPosition = m_stream.tellg();
|
||||
|
||||
if (probe(endSequence))
|
||||
break;
|
||||
|
||||
advance();
|
||||
}
|
||||
|
||||
if (removeEnd)
|
||||
endPosition = m_stream.tellg();
|
||||
|
||||
removeRange(startPosition, endPosition);
|
||||
}
|
||||
|
||||
m_stream.clear();
|
||||
|
||||
m_stream.seekg(inPosition);
|
||||
m_stream.seekp(outPosition);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
162
src/plasp/utils/Stream.cpp
Normal file
162
src/plasp/utils/Stream.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#include <plasp/utils/Stream.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace utils
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Stream
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Stream::Stream()
|
||||
{
|
||||
std::setlocale(LC_NUMERIC, "C");
|
||||
|
||||
// Don’t skip whitespace
|
||||
m_stream.exceptions(std::istream::badbit);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Stream::Stream(std::string streamName, std::istream &istream)
|
||||
{
|
||||
read(streamName, istream);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::read(std::string streamName, std::istream &istream)
|
||||
{
|
||||
// Store position of new section
|
||||
const auto position = m_stream.tellp();
|
||||
|
||||
m_delimiters.push_back({position, streamName});
|
||||
|
||||
m_stream << istream.rdbuf();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::read(const boost::filesystem::path &path)
|
||||
{
|
||||
if (!boost::filesystem::is_regular_file(path))
|
||||
throw std::runtime_error("File does not exist: “" + path.string() + "”");
|
||||
|
||||
std::ifstream fileStream(path.string(), std::ios::in);
|
||||
|
||||
read(path.string(), fileStream);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::reset()
|
||||
{
|
||||
m_stream.clear();
|
||||
seek(0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::seek(Position position)
|
||||
{
|
||||
m_stream.clear();
|
||||
m_stream.seekg(position);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typename Stream::Position Stream::position() const
|
||||
{
|
||||
return m_stream.tellg();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
StreamCoordinate Stream::coordinate() const
|
||||
{
|
||||
const auto currentPosition = position();
|
||||
|
||||
// Find current section
|
||||
auto currentFile = std::find_if(m_delimiters.crbegin(), m_delimiters.crend(),
|
||||
[&](const auto &fileDelimiter)
|
||||
{
|
||||
return currentPosition >= fileDelimiter.position;
|
||||
});
|
||||
|
||||
// If the parser is at the end of the stream, still count from the beginning of the last section
|
||||
if (currentFile == m_delimiters.crend())
|
||||
currentFile = m_delimiters.crbegin();
|
||||
|
||||
// Go back to beginning of section
|
||||
m_stream.clear();
|
||||
m_stream.seekg(currentFile->position);
|
||||
|
||||
size_t row = 1;
|
||||
size_t column = 1;
|
||||
|
||||
// Compute the coordinate character by character
|
||||
while (true)
|
||||
{
|
||||
if (currentPosition == -1 && atEnd())
|
||||
break;
|
||||
else if (currentPosition >= 0 && position() >= currentPosition)
|
||||
break;
|
||||
|
||||
const auto character = currentCharacter();
|
||||
|
||||
if (character == '\n')
|
||||
{
|
||||
row++;
|
||||
column = 1;
|
||||
}
|
||||
else if (std::isblank(character) || std::isprint(character))
|
||||
column++;
|
||||
|
||||
m_stream.ignore(1);
|
||||
}
|
||||
|
||||
return {currentFile->sectionName, row, column};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char Stream::currentCharacter() const
|
||||
{
|
||||
return m_stream.peek();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Stream::atEnd() const
|
||||
{
|
||||
return position() == -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::check() const
|
||||
{
|
||||
if (atEnd())
|
||||
throw ParserException(coordinate(), "reading past end of file");
|
||||
|
||||
if (m_stream.fail())
|
||||
throw ParserException(coordinate());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::advance()
|
||||
{
|
||||
check();
|
||||
m_stream.ignore(1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user