Started reimplementing problem parser.
This commit is contained in:
@@ -12,6 +12,7 @@ file(GLOB detail_parsing_headers "../include/pddlparse/detail/parsing/*.h")
|
||||
set(includes
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
${PROJECT_SOURCE_DIR}/../../lib/tokenize/include
|
||||
${PROJECT_SOURCE_DIR}/../../lib/variant/include
|
||||
)
|
||||
|
||||
set(sources
|
||||
|
22
lib/pddlparse/src/pddlparse/Parse.cpp
Normal file
22
lib/pddlparse/src/pddlparse/Parse.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <pddlparse/Parse.h>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/detail/parsing/Description.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parse
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::Description parseDescription(Context &context)
|
||||
{
|
||||
return detail::DescriptionParser(context).parse();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
92
lib/pddlparse/src/pddlparse/detail/Requirements.cpp
Normal file
92
lib/pddlparse/src/pddlparse/detail/Requirements.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <pddlparse/detail/Requirements.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <pddlparse/detail/parsing/Requirement.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Requirements
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool hasRequirement(const ast::Domain &domain, ast::Requirement requirement)
|
||||
{
|
||||
const auto match = std::find_if(domain.requirements.cbegin(), domain.requirements.cend(),
|
||||
[&](const auto &declaredRequirement)
|
||||
{
|
||||
return declaredRequirement == requirement;
|
||||
});
|
||||
|
||||
return match != domain.requirements.cend();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool hasRequirement(const ast::Problem &problem, ast::Requirement requirement)
|
||||
{
|
||||
const auto match = std::find_if(problem.requirements.cbegin(), problem.requirements.cend(),
|
||||
[&](const auto &declaredRequirement)
|
||||
{
|
||||
return declaredRequirement == requirement;
|
||||
});
|
||||
|
||||
if (match != problem.requirements.cend())
|
||||
return true;
|
||||
|
||||
return hasRequirement(problem.domain, requirement);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool hasRequirement(const ASTContext &astContext, ast::Requirement requirement)
|
||||
{
|
||||
if (astContext.problem)
|
||||
return hasRequirement(*astContext.problem.value(), requirement);
|
||||
|
||||
return hasRequirement(*astContext.domain, requirement);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void checkRequirement(ast::Domain &domain, ast::Requirement requirement, Context &context)
|
||||
{
|
||||
if (hasRequirement(domain, requirement))
|
||||
return;
|
||||
|
||||
context.warningCallback(context.tokenizer.location(), "requirement “" + std::string(toString(requirement)) + "” used but never declared");
|
||||
|
||||
domain.requirements.push_back(requirement);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void checkRequirement(ast::Problem &problem, ast::Requirement requirement, Context &context)
|
||||
{
|
||||
if (hasRequirement(problem, requirement))
|
||||
return;
|
||||
|
||||
context.warningCallback(context.tokenizer.location(), "requirement “" + std::string(toString(requirement)) + "” used but never declared");
|
||||
|
||||
problem.requirements.push_back(requirement);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void checkRequirement(ASTContext &astContext, ast::Requirement requirement, Context &context)
|
||||
{
|
||||
if (astContext.problem)
|
||||
checkRequirement(*astContext.problem.value(), requirement, context);
|
||||
else
|
||||
checkRequirement(*astContext.domain, requirement, context);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
68
lib/pddlparse/src/pddlparse/detail/parsing/Action.cpp
Normal file
68
lib/pddlparse/src/pddlparse/detail/parsing/Action.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <pddlparse/detail/parsing/Action.h>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
// TODO: remove
|
||||
#include <pddlparse/detail/parsing/Utils.h>
|
||||
#include <pddlparse/detail/parsing/VariableDeclaration.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Action
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void parseAndAddAction(Context &context, ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
tokenizer.expect<std::string>("action");
|
||||
|
||||
auto action = std::make_unique<ast::Action>();
|
||||
action->name = tokenizer.getIdentifier();
|
||||
|
||||
tokenizer.expect<std::string>(":parameters");
|
||||
tokenizer.expect<std::string>("(");
|
||||
|
||||
// Read parameters
|
||||
action->parameters = parseVariableDeclarations(context, domain);
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
|
||||
// TODO: reimplement
|
||||
skipSection(tokenizer);
|
||||
|
||||
/*
|
||||
// Parse preconditions and effects
|
||||
while (!tokenizer.testAndReturn(')'))
|
||||
{
|
||||
tokenizer.expect<std::string>(":");
|
||||
|
||||
if (tokenizer.testIdentifierAndSkip("precondition"))
|
||||
// TODO: reimplement
|
||||
//action->precondition = parsePreconditionExpression(context, expressionContext);
|
||||
skipSection(tokenizer);
|
||||
else if (tokenizer.testIdentifierAndSkip("effect"))
|
||||
// TODO: reimplement
|
||||
//action->effect = parseEffectExpression(context, expressionContext);
|
||||
skipSection(tokenizer);
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}*/
|
||||
|
||||
// Store new action
|
||||
domain.actions.emplace_back(std::move(action));
|
||||
|
||||
//tokenizer.expect<std::string>(")");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
69
lib/pddlparse/src/pddlparse/detail/parsing/Constant.cpp
Normal file
69
lib/pddlparse/src/pddlparse/detail/parsing/Constant.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include <pddlparse/detail/parsing/Constant.h>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/ParserException.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Constant
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::experimental::optional<ast::ConstantPointer> findConstant(const std::string &constantName, ast::ConstantDeclarations &constantDeclarations)
|
||||
{
|
||||
const auto matchingConstant = std::find_if(constantDeclarations.begin(), constantDeclarations.end(),
|
||||
[&](const auto &constantDeclaration)
|
||||
{
|
||||
return constantDeclaration->name == constantName;
|
||||
});
|
||||
|
||||
if (matchingConstant == constantDeclarations.end())
|
||||
return std::experimental::nullopt;
|
||||
|
||||
return std::make_unique<ast::Constant>(matchingConstant->get());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::ConstantPointer parseConstant(Context &context, ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
const auto constantName = tokenizer.getIdentifier();
|
||||
|
||||
auto constant = findConstant(constantName, domain.constants);
|
||||
|
||||
if (constant)
|
||||
return std::move(constant.value());
|
||||
|
||||
throw ParserException(tokenizer.location(), "constant “" + constantName + "” used but never declared");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::ConstantPointer parseConstant(Context &context, ast::Problem &problem)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
const auto constantName = tokenizer.getIdentifier();
|
||||
|
||||
auto constant = findConstant(constantName, problem.domain->constants);
|
||||
|
||||
if (constant)
|
||||
return std::move(constant.value());
|
||||
|
||||
auto object = findConstant(constantName, problem.objects);
|
||||
|
||||
if (object)
|
||||
return std::move(object.value());
|
||||
|
||||
throw ParserException(tokenizer.location(), "constant “" + constantName + "” used but never declared");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
#include <pddlparse/detail/parsing/ConstantDeclaration.h>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/ParserException.h>
|
||||
#include <pddlparse/detail/ASTCopy.h>
|
||||
#include <pddlparse/detail/parsing/PrimitiveType.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ConstantDeclaration
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void parseAndAddUntypedConstantDeclaration(Context &context, ast::ConstantDeclarations &constantDeclarations)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
auto constantName = tokenizer.getIdentifier();
|
||||
|
||||
assert(constantName != "-");
|
||||
|
||||
constantDeclarations.emplace_back(std::make_unique<ast::ConstantDeclaration>(std::move(constantName)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void parseAndAddConstantDeclarations(Context &context, ast::Domain &domain, ast::ConstantDeclarations &constantDeclarations)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
// Index on the first element of the current inheritance list
|
||||
size_t inheritanceIndex = 0;
|
||||
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
parseAndAddUntypedConstantDeclaration(context, constantDeclarations);
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
if (!tokenizer.testAndSkip<char>('-'))
|
||||
continue;
|
||||
|
||||
// If existing, parse and store parent type
|
||||
auto parentType = parsePrimitiveType(context, domain);
|
||||
|
||||
for (size_t i = inheritanceIndex; i < constantDeclarations.size(); i++)
|
||||
constantDeclarations[i]->type = ast::deepCopy(parentType);
|
||||
|
||||
// All types up to now are labeled with their parent types
|
||||
inheritanceIndex = constantDeclarations.size() + 1;
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void parseAndAddConstantDeclarations(Context &context, ast::Domain &domain)
|
||||
{
|
||||
parseAndAddConstantDeclarations(context, domain, domain.constants);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void parseAndAddConstantDeclarations(Context &context, ast::Problem &problem)
|
||||
{
|
||||
parseAndAddConstantDeclarations(context, *problem.domain, problem.objects);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
107
lib/pddlparse/src/pddlparse/detail/parsing/Description.cpp
Normal file
107
lib/pddlparse/src/pddlparse/detail/parsing/Description.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <pddlparse/detail/parsing/Description.h>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/ParserException.h>
|
||||
#include <pddlparse/detail/parsing/Domain.h>
|
||||
#include <pddlparse/detail/parsing/Problem.h>
|
||||
#include <pddlparse/detail/parsing/Utils.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Description
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DescriptionParser::DescriptionParser(Context &context)
|
||||
: m_context{context},
|
||||
m_domainPosition{-1},
|
||||
m_problemPosition{-1}
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::Description DescriptionParser::parse()
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
tokenizer.removeComments(";", "\n", false);
|
||||
|
||||
findSections();
|
||||
|
||||
if (m_domainPosition == -1)
|
||||
throw ParserException("no PDDL domain specified");
|
||||
|
||||
tokenizer.seek(m_domainPosition);
|
||||
|
||||
auto domain = DomainParser(m_context).parse();
|
||||
|
||||
// If no problem is given, return just the domain
|
||||
if (m_problemPosition == -1)
|
||||
return {std::move(domain), std::experimental::nullopt};
|
||||
|
||||
tokenizer.seek(m_problemPosition);
|
||||
|
||||
auto problem = ProblemParser(m_context, *domain).parse();
|
||||
|
||||
// TODO: check consistency
|
||||
// * check typing requirement
|
||||
// * check that typing is used consistently
|
||||
// * check that constants, variables, and predicates aren't declared twice
|
||||
// * check section order
|
||||
// * check that preconditions and effects are well-formed
|
||||
return {std::move(domain), std::move(problem)};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DescriptionParser::findSections()
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
while (!tokenizer.atEnd())
|
||||
{
|
||||
const auto position = tokenizer.position();
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>("define");
|
||||
tokenizer.expect<std::string>("(");
|
||||
|
||||
if (tokenizer.testAndSkip<std::string>("domain"))
|
||||
{
|
||||
if (m_domainPosition != -1)
|
||||
throw ParserException(tokenizer.location(), "PDDL description may not contain two domains");
|
||||
|
||||
m_domainPosition = position;
|
||||
skipSection(tokenizer);
|
||||
skipSection(tokenizer);
|
||||
}
|
||||
else if (m_context.tokenizer.testAndSkip<std::string>("problem"))
|
||||
{
|
||||
if (m_problemPosition != -1)
|
||||
throw ParserException("PDDL description may not contain two problems currently");
|
||||
|
||||
m_problemPosition = position;
|
||||
skipSection(tokenizer);
|
||||
skipSection(tokenizer);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto sectionIdentifier = tokenizer.get<std::string>();
|
||||
throw ParserException(tokenizer.location(), "unknown PDDL section “" + sectionIdentifier + "”");
|
||||
}
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
300
lib/pddlparse/src/pddlparse/detail/parsing/Domain.cpp
Normal file
300
lib/pddlparse/src/pddlparse/detail/parsing/Domain.cpp
Normal file
@@ -0,0 +1,300 @@
|
||||
#include <pddlparse/detail/parsing/Domain.h>
|
||||
|
||||
#include <pddlparse/ParserException.h>
|
||||
#include <pddlparse/detail/Requirements.h>
|
||||
#include <pddlparse/detail/parsing/Action.h>
|
||||
#include <pddlparse/detail/parsing/ConstantDeclaration.h>
|
||||
#include <pddlparse/detail/parsing/PredicateDeclaration.h>
|
||||
#include <pddlparse/detail/parsing/PrimitiveTypeDeclaration.h>
|
||||
#include <pddlparse/detail/parsing/Requirement.h>
|
||||
#include <pddlparse/detail/parsing/Utils.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Domain
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DomainParser::DomainParser(Context &context)
|
||||
: m_context{context},
|
||||
m_requirementsPosition{-1},
|
||||
m_typesPosition{-1},
|
||||
m_constantsPosition{-1},
|
||||
m_predicatesPosition{-1}
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::DomainPointer DomainParser::parse()
|
||||
{
|
||||
auto domain = std::make_unique<ast::Domain>();
|
||||
|
||||
findSections(*domain);
|
||||
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
if (m_requirementsPosition != -1)
|
||||
{
|
||||
tokenizer.seek(m_requirementsPosition);
|
||||
parseRequirementSection(*domain);
|
||||
}
|
||||
|
||||
if (m_typesPosition != -1)
|
||||
{
|
||||
tokenizer.seek(m_typesPosition);
|
||||
parseTypeSection(*domain);
|
||||
}
|
||||
|
||||
if (m_constantsPosition != -1)
|
||||
{
|
||||
tokenizer.seek(m_constantsPosition);
|
||||
parseConstantSection(*domain);
|
||||
}
|
||||
|
||||
if (m_predicatesPosition != -1)
|
||||
{
|
||||
tokenizer.seek(m_predicatesPosition);
|
||||
parsePredicateSection(*domain);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_actionPositions.size(); i++)
|
||||
if (m_actionPositions[i] != -1)
|
||||
{
|
||||
tokenizer.seek(m_actionPositions[i]);
|
||||
parseActionSection(*domain);
|
||||
}
|
||||
|
||||
computeDerivedRequirements(*domain);
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DomainParser::findSections(ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>("define");
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>("domain");
|
||||
|
||||
domain.name = tokenizer.getIdentifier();
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
|
||||
const auto setSectionPosition =
|
||||
[&](const std::string §ionName, auto §ionPosition, const auto value, bool unique = false)
|
||||
{
|
||||
if (unique && sectionPosition != -1)
|
||||
{
|
||||
tokenizer.seek(value);
|
||||
throw tokenize::TokenizerException(tokenizer.location(), "only one “:" + sectionName + "” section allowed");
|
||||
}
|
||||
|
||||
sectionPosition = value;
|
||||
};
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
// Find sections
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
const auto position = tokenizer.position();
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
|
||||
const auto sectionIdentifierPosition = tokenizer.position();
|
||||
|
||||
// Save the parser position of the individual sections for later parsing
|
||||
if (tokenizer.testIdentifierAndSkip("requirements"))
|
||||
setSectionPosition("requirements", m_requirementsPosition, position, true);
|
||||
else if (tokenizer.testIdentifierAndSkip("types"))
|
||||
setSectionPosition("types", m_typesPosition, position, true);
|
||||
else if (tokenizer.testIdentifierAndSkip("constants"))
|
||||
setSectionPosition("constants", m_constantsPosition, position, true);
|
||||
else if (tokenizer.testIdentifierAndSkip("predicates"))
|
||||
setSectionPosition("predicates", m_predicatesPosition, position, true);
|
||||
else if (tokenizer.testIdentifierAndSkip("action"))
|
||||
{
|
||||
m_actionPositions.emplace_back(-1);
|
||||
setSectionPosition("action", m_actionPositions.back(), position);
|
||||
}
|
||||
else if (tokenizer.testIdentifierAndSkip("functions")
|
||||
|| tokenizer.testIdentifierAndSkip("constraints")
|
||||
|| tokenizer.testIdentifierAndSkip("durative-action")
|
||||
|| tokenizer.testIdentifierAndSkip("derived"))
|
||||
{
|
||||
tokenizer.seek(sectionIdentifierPosition);
|
||||
|
||||
const auto sectionIdentifier = tokenizer.getIdentifier();
|
||||
|
||||
m_context.warningCallback(tokenizer.location(), "section type “" + sectionIdentifier + "” currently unsupported");
|
||||
|
||||
tokenizer.seek(sectionIdentifierPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto sectionIdentifier = tokenizer.getIdentifier();
|
||||
|
||||
tokenizer.seek(position);
|
||||
throw tokenize::TokenizerException(tokenizer.location(), "unknown domain section “" + sectionIdentifier + "”");
|
||||
}
|
||||
|
||||
// Skip section for now and parse it later
|
||||
skipSection(tokenizer);
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DomainParser::parseRequirementSection(ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
tokenizer.expect<std::string>("requirements");
|
||||
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
tokenizer.expect<std::string>(":");
|
||||
|
||||
domain.requirements.emplace_back(parseRequirement(m_context));
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
|
||||
// TODO: do this check only once the problem is parsed
|
||||
// If no requirements are specified, assume STRIPS
|
||||
if (domain.requirements.empty())
|
||||
domain.requirements.emplace_back(ast::Requirement::STRIPS);
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DomainParser::computeDerivedRequirements(ast::Domain &domain)
|
||||
{
|
||||
const auto addRequirementUnique =
|
||||
[&](auto requirement)
|
||||
{
|
||||
if (hasRequirement(domain, requirement))
|
||||
return;
|
||||
|
||||
domain.requirements.push_back(requirement);
|
||||
};
|
||||
|
||||
if (hasRequirement(domain, ast::Requirement::ADL))
|
||||
{
|
||||
addRequirementUnique(ast::Requirement::STRIPS);
|
||||
addRequirementUnique(ast::Requirement::Typing);
|
||||
addRequirementUnique(ast::Requirement::NegativePreconditions);
|
||||
addRequirementUnique(ast::Requirement::DisjunctivePreconditions);
|
||||
addRequirementUnique(ast::Requirement::Equality);
|
||||
addRequirementUnique(ast::Requirement::QuantifiedPreconditions);
|
||||
addRequirementUnique(ast::Requirement::ConditionalEffects);
|
||||
}
|
||||
|
||||
if (hasRequirement(domain, ast::Requirement::QuantifiedPreconditions))
|
||||
{
|
||||
addRequirementUnique(ast::Requirement::ExistentialPreconditions);
|
||||
addRequirementUnique(ast::Requirement::UniversalPreconditions);
|
||||
}
|
||||
|
||||
if (hasRequirement(domain, ast::Requirement::Fluents))
|
||||
{
|
||||
addRequirementUnique(ast::Requirement::NumericFluents);
|
||||
addRequirementUnique(ast::Requirement::ObjectFluents);
|
||||
}
|
||||
|
||||
if (hasRequirement(domain, ast::Requirement::TimedInitialLiterals))
|
||||
addRequirementUnique(ast::Requirement::DurativeActions);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DomainParser::parseTypeSection(ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
tokenizer.expect<std::string>("types");
|
||||
|
||||
checkRequirement(domain, ast::Requirement::Typing, m_context);
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
// Store types and their parent types
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
if (tokenizer.currentCharacter() == '(')
|
||||
throw ParserException(tokenizer.location(), "only primitive types are allowed in type section");
|
||||
|
||||
parseAndAddPrimitiveTypeDeclarations(m_context, domain);
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DomainParser::parseConstantSection(ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
tokenizer.expect<std::string>("constants");
|
||||
|
||||
// Store constants
|
||||
parseAndAddConstantDeclarations(m_context, domain);
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DomainParser::parsePredicateSection(ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
tokenizer.expect<std::string>("predicates");
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
// Store predicates
|
||||
parseAndAddPredicateDeclarations(m_context, domain);
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DomainParser::parseActionSection(ast::Domain &domain)
|
||||
{
|
||||
parseAndAddAction(m_context, domain);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
79
lib/pddlparse/src/pddlparse/detail/parsing/InitialState.cpp
Normal file
79
lib/pddlparse/src/pddlparse/detail/parsing/InitialState.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <pddlparse/detail/parsing/InitialState.h>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
// TODO: remove
|
||||
#include <pddlparse/detail/parsing/Utils.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// InitialState
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::InitialState parseInitialState(Context &context, ASTContext &)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
ast::InitialState initialState;
|
||||
|
||||
// TODO: reimplement
|
||||
/*const auto parseInitialStateElement =
|
||||
[&]() -> ExpressionPointer
|
||||
{
|
||||
ExpressionPointer expression;
|
||||
|
||||
// TODO: do not allow negative initial state literals
|
||||
if ((expression = parseLiteral(context, expressionContext))
|
||||
|| (expression = expressions::At::parse(context, expressionContext, parseLiteral)))
|
||||
{
|
||||
return expression;
|
||||
}
|
||||
|
||||
const auto position = tokenizer.position();
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
|
||||
const auto expressionIdentifierPosition = tokenizer.position();
|
||||
|
||||
if (tokenizer.testIdentifierAndSkip("="))
|
||||
{
|
||||
tokenizer.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = tokenizer.getIdentifier();
|
||||
|
||||
tokenizer.seek(position);
|
||||
return expressions::Unsupported::parse(context);
|
||||
}
|
||||
|
||||
tokenizer.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = tokenizer.getIdentifier();
|
||||
|
||||
tokenizer.seek(position);
|
||||
throw tokenize::TokenizerException(tokenizer.location(), "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
|
||||
};
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
ast::Expression expression;
|
||||
|
||||
if ((expression = parseInitialStateElement()))
|
||||
initialState->m_facts.emplace_back(std::move(expression));
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}*/
|
||||
|
||||
skipSection(tokenizer);
|
||||
|
||||
return initialState;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
#include <pddlparse/detail/parsing/PredicateDeclaration.h>
|
||||
|
||||
#include <pddlparse/ParserException.h>
|
||||
#include <pddlparse/detail/ASTContext.h>
|
||||
#include <pddlparse/detail/parsing/VariableDeclaration.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PredicateDeclaration
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void parseAndAddPredicateDeclaration(Context &context, ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
tokenizer.expect<std::string>("(");
|
||||
|
||||
auto name = tokenizer.getIdentifier();
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
// Parse parameters
|
||||
auto parameters = parseVariableDeclarations(context, domain);
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
|
||||
domain.predicates.emplace_back(std::make_unique<ast::PredicateDeclaration>(std::move(name), std::move(parameters)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void parseAndAddPredicateDeclarations(Context &context, ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
parseAndAddPredicateDeclaration(context, domain);
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
55
lib/pddlparse/src/pddlparse/detail/parsing/PrimitiveType.cpp
Normal file
55
lib/pddlparse/src/pddlparse/detail/parsing/PrimitiveType.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#include <pddlparse/detail/parsing/PrimitiveType.h>
|
||||
|
||||
#include <pddlparse/ParserException.h>
|
||||
#include <pddlparse/detail/Requirements.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PrimitiveType
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::PrimitiveTypePointer parsePrimitiveType(Context &context, ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
auto &types = domain.types;
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
auto typeName = tokenizer.getIdentifier();
|
||||
|
||||
if (typeName.empty())
|
||||
throw tokenize::TokenizerException(tokenizer.location(), "no type supplied");
|
||||
|
||||
auto matchingType = std::find_if(types.begin(), types.end(),
|
||||
[&](auto &primitiveTypeDeclaration)
|
||||
{
|
||||
return primitiveTypeDeclaration->name == typeName;
|
||||
});
|
||||
|
||||
if (matchingType == types.end())
|
||||
{
|
||||
// Only “object” is allowed as an implicit type
|
||||
if (typeName == "object" || typeName == "objects")
|
||||
{
|
||||
context.warningCallback(tokenizer.location(), "primitive type “" + typeName + "” should be declared");
|
||||
types.emplace_back(std::make_unique<ast::PrimitiveTypeDeclaration>(std::move(typeName)));
|
||||
|
||||
return std::make_unique<ast::PrimitiveType>(types.back().get());
|
||||
}
|
||||
else
|
||||
throw tokenize::TokenizerException(tokenizer.location(), "type “" + typeName + "” used but never declared");
|
||||
}
|
||||
|
||||
return std::make_unique<ast::PrimitiveType>(matchingType->get());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,77 @@
|
||||
#include <pddlparse/detail/parsing/PrimitiveTypeDeclaration.h>
|
||||
|
||||
#include <pddlparse/ParserException.h>
|
||||
#include <pddlparse/detail/ASTCopy.h>
|
||||
#include <pddlparse/detail/parsing/PrimitiveType.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PrimitiveTypeDeclaration
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::PrimitiveTypeDeclarationPointer &parseAndAddUntypedPrimitiveTypeDeclaration(Context &context, ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
auto typeName = tokenizer.getIdentifier();
|
||||
|
||||
auto &types = domain.types;
|
||||
|
||||
const auto matchingPrimitiveType = std::find_if(types.begin(), types.end(),
|
||||
[&](const auto &primitiveType)
|
||||
{
|
||||
return primitiveType->name == typeName;
|
||||
});
|
||||
|
||||
// Return existing primitive type
|
||||
if (matchingPrimitiveType != types.cend())
|
||||
return *matchingPrimitiveType;
|
||||
|
||||
types.emplace_back(std::make_unique<ast::PrimitiveTypeDeclaration>(std::move(typeName)));
|
||||
|
||||
return types.back();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void parseAndAddPrimitiveTypeDeclarations(Context &context, ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
// Index on the first element of the current inheritance list
|
||||
size_t inheritanceIndex = 0;
|
||||
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
parseAndAddUntypedPrimitiveTypeDeclaration(context, domain);
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
if (!tokenizer.testAndSkip<char>('-'))
|
||||
continue;
|
||||
|
||||
// If existing, parse and store parent type
|
||||
auto parentType = parsePrimitiveType(context, domain);
|
||||
|
||||
auto &types = domain.types;
|
||||
|
||||
for (size_t i = inheritanceIndex; i < types.size(); i++)
|
||||
types[i]->parentTypes.emplace_back(ast::deepCopy(parentType));
|
||||
|
||||
// All types up to now are labeled with their parent types
|
||||
inheritanceIndex = types.size() + 1;
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
297
lib/pddlparse/src/pddlparse/detail/parsing/Problem.cpp
Normal file
297
lib/pddlparse/src/pddlparse/detail/parsing/Problem.cpp
Normal file
@@ -0,0 +1,297 @@
|
||||
#include <pddlparse/detail/parsing/Problem.h>
|
||||
|
||||
#include <pddlparse/ParserException.h>
|
||||
#include <pddlparse/detail/Requirements.h>
|
||||
#include <pddlparse/detail/parsing/ConstantDeclaration.h>
|
||||
#include <pddlparse/detail/parsing/InitialState.h>
|
||||
#include <pddlparse/detail/parsing/Requirement.h>
|
||||
#include <pddlparse/detail/parsing/Utils.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Problem
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ProblemParser::ProblemParser(Context &context, ast::Domain &domain)
|
||||
: m_context{context},
|
||||
m_domain{domain},
|
||||
m_domainPosition{-1},
|
||||
m_requirementsPosition{-1},
|
||||
m_objectsPosition{-1},
|
||||
m_initialStatePosition{-1},
|
||||
m_goalPosition{-1}
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::ProblemPointer ProblemParser::parse()
|
||||
{
|
||||
auto problem = std::make_unique<ast::Problem>(&m_domain);
|
||||
|
||||
findSections(*problem);
|
||||
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
if (m_domainPosition == -1)
|
||||
throw ParserException(tokenizer.location(), "problem description does not specify a corresponding domain");
|
||||
|
||||
tokenizer.seek(m_domainPosition);
|
||||
parseDomainSection(*problem);
|
||||
|
||||
if (m_requirementsPosition != -1)
|
||||
{
|
||||
tokenizer.seek(m_requirementsPosition);
|
||||
parseRequirementSection(*problem);
|
||||
}
|
||||
|
||||
if (m_objectsPosition != -1)
|
||||
{
|
||||
tokenizer.seek(m_objectsPosition);
|
||||
parseObjectSection(*problem);
|
||||
}
|
||||
|
||||
if (m_initialStatePosition == -1)
|
||||
throw ParserException(tokenizer.location(), "problem description does not specify an initial state");
|
||||
|
||||
tokenizer.seek(m_initialStatePosition);
|
||||
parseInitialStateSection(*problem);
|
||||
|
||||
if (m_goalPosition == -1)
|
||||
throw ParserException(tokenizer.location(), "problem description does not specify a goal");
|
||||
|
||||
tokenizer.seek(m_goalPosition);
|
||||
parseGoalSection(*problem);
|
||||
|
||||
return problem;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProblemParser::findSections(ast::Problem &problem)
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>("define");
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>("problem");
|
||||
|
||||
problem.name = tokenizer.getIdentifier();
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
|
||||
const auto setSectionPosition =
|
||||
[&](const std::string §ionName, auto §ionPosition, const auto value, bool unique = false)
|
||||
{
|
||||
if (unique && sectionPosition != -1)
|
||||
{
|
||||
tokenizer.seek(value);
|
||||
throw tokenize::TokenizerException(tokenizer.location(), "only one “:" + sectionName + "” section allowed");
|
||||
}
|
||||
|
||||
sectionPosition = value;
|
||||
};
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
const auto position = tokenizer.position();
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
|
||||
const auto sectionIdentifierPosition = tokenizer.position();
|
||||
|
||||
if (tokenizer.testIdentifierAndSkip("domain"))
|
||||
setSectionPosition("domain", m_domainPosition, position, true);
|
||||
else if (tokenizer.testIdentifierAndSkip("requirements"))
|
||||
setSectionPosition("requirements", m_requirementsPosition, position, true);
|
||||
else if (tokenizer.testIdentifierAndSkip("objects"))
|
||||
setSectionPosition("objects", m_objectsPosition, position, true);
|
||||
else if (tokenizer.testIdentifierAndSkip("init"))
|
||||
setSectionPosition("init", m_initialStatePosition, position, true);
|
||||
else if (tokenizer.testIdentifierAndSkip("goal"))
|
||||
setSectionPosition("goal", m_goalPosition, position, true);
|
||||
else if (tokenizer.testIdentifierAndSkip("constraints")
|
||||
|| tokenizer.testIdentifierAndSkip("metric")
|
||||
|| tokenizer.testIdentifierAndSkip("length"))
|
||||
{
|
||||
tokenizer.seek(sectionIdentifierPosition);
|
||||
|
||||
const auto sectionIdentifier = tokenizer.getIdentifier();
|
||||
|
||||
m_context.warningCallback(tokenizer.location(), "section type “" + sectionIdentifier + "” currently unsupported");
|
||||
|
||||
tokenizer.seek(sectionIdentifierPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto sectionIdentifier = tokenizer.getIdentifier();
|
||||
|
||||
tokenizer.seek(position);
|
||||
throw tokenize::TokenizerException(tokenizer.location(), "unknown problem section “" + sectionIdentifier + "”");
|
||||
}
|
||||
|
||||
// Skip section for now and parse it later
|
||||
skipSection(tokenizer);
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProblemParser::parseDomainSection(ast::Problem &problem)
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
tokenizer.expect<std::string>("domain");
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
const auto domainName = tokenizer.getIdentifier();
|
||||
|
||||
if (problem.domain->name != domainName)
|
||||
throw tokenize::TokenizerException(tokenizer.location(), "domains do not match (“" + problem.domain->name + "” and “" + domainName + "”)");
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProblemParser::parseRequirementSection(ast::Problem &problem)
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
tokenizer.expect<std::string>("requirements");
|
||||
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
tokenizer.expect<std::string>(":");
|
||||
|
||||
problem.requirements.emplace_back(parseRequirement(m_context));
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
|
||||
// TODO: do this check only once the problem is parsed
|
||||
// If no requirements are specified, assume STRIPS
|
||||
if (problem.requirements.empty())
|
||||
problem.requirements.emplace_back(ast::Requirement::STRIPS);
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: refactor, exists identically in DomainParser
|
||||
void ProblemParser::computeDerivedRequirements(ast::Problem &problem)
|
||||
{
|
||||
const auto addRequirementUnique =
|
||||
[&](const auto requirement)
|
||||
{
|
||||
if (hasRequirement(problem, requirement))
|
||||
return;
|
||||
|
||||
problem.requirements.push_back(ast::Requirement(requirement));
|
||||
};
|
||||
|
||||
if (hasRequirement(problem, ast::Requirement::ADL))
|
||||
{
|
||||
addRequirementUnique(ast::Requirement::STRIPS);
|
||||
addRequirementUnique(ast::Requirement::Typing);
|
||||
addRequirementUnique(ast::Requirement::NegativePreconditions);
|
||||
addRequirementUnique(ast::Requirement::DisjunctivePreconditions);
|
||||
addRequirementUnique(ast::Requirement::Equality);
|
||||
addRequirementUnique(ast::Requirement::QuantifiedPreconditions);
|
||||
addRequirementUnique(ast::Requirement::ConditionalEffects);
|
||||
}
|
||||
|
||||
if (hasRequirement(problem, ast::Requirement::QuantifiedPreconditions))
|
||||
{
|
||||
addRequirementUnique(ast::Requirement::ExistentialPreconditions);
|
||||
addRequirementUnique(ast::Requirement::UniversalPreconditions);
|
||||
}
|
||||
|
||||
if (hasRequirement(problem, ast::Requirement::Fluents))
|
||||
{
|
||||
addRequirementUnique(ast::Requirement::NumericFluents);
|
||||
addRequirementUnique(ast::Requirement::ObjectFluents);
|
||||
}
|
||||
|
||||
if (hasRequirement(problem, ast::Requirement::TimedInitialLiterals))
|
||||
addRequirementUnique(ast::Requirement::DurativeActions);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProblemParser::parseObjectSection(ast::Problem &problem)
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
tokenizer.expect<std::string>("objects");
|
||||
|
||||
// Store constants
|
||||
parseAndAddConstantDeclarations(m_context, problem);
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProblemParser::parseInitialStateSection(ast::Problem &problem)
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
tokenizer.expect<std::string>("init");
|
||||
|
||||
ASTContext astContext(problem);
|
||||
|
||||
// TODO: reimplement
|
||||
//problem.initialState = parseInitialState(m_context, astContext);
|
||||
//tokenizer.expect<std::string>(")");
|
||||
|
||||
skipSection(tokenizer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ProblemParser::parseGoalSection(ast::Problem &problem)
|
||||
{
|
||||
auto &tokenizer = m_context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
tokenizer.expect<std::string>(":");
|
||||
tokenizer.expect<std::string>("goal");
|
||||
|
||||
ASTContext expressionContext(problem);
|
||||
|
||||
// TODO: reimplement
|
||||
//problem.goal = parsePreconditionExpression(m_context, expressionContext);
|
||||
//tokenizer.expect<std::string>(")");
|
||||
|
||||
skipSection(tokenizer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
102
lib/pddlparse/src/pddlparse/detail/parsing/Requirement.cpp
Normal file
102
lib/pddlparse/src/pddlparse/detail/parsing/Requirement.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#include <pddlparse/detail/parsing/Requirement.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/ParserException.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Requirement
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct CompareStrings
|
||||
{
|
||||
bool operator()(const char *lhs, const char *rhs) const
|
||||
{
|
||||
return std::strcmp(lhs, rhs) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
using RequirementNameMap = std::map<const char *, ast::Requirement, CompareStrings>;
|
||||
static const RequirementNameMap requirementNameMap =
|
||||
{
|
||||
{"strips", ast::Requirement::STRIPS},
|
||||
{"typing", ast::Requirement::Typing},
|
||||
{"negative-preconditions", ast::Requirement::NegativePreconditions},
|
||||
{"disjunctive-preconditions", ast::Requirement::DisjunctivePreconditions},
|
||||
{"equality", ast::Requirement::Equality},
|
||||
{"existential-preconditions", ast::Requirement::ExistentialPreconditions},
|
||||
{"universal-preconditions", ast::Requirement::UniversalPreconditions},
|
||||
{"quantified-preconditions", ast::Requirement::QuantifiedPreconditions},
|
||||
{"conditional-effects", ast::Requirement::ConditionalEffects},
|
||||
{"fluents", ast::Requirement::Fluents},
|
||||
{"numeric-fluents", ast::Requirement::NumericFluents},
|
||||
{"object-fluents", ast::Requirement::ObjectFluents},
|
||||
{"adl", ast::Requirement::ADL},
|
||||
{"durative-actions", ast::Requirement::DurativeActions},
|
||||
{"duration-inequalities", ast::Requirement::DurationInequalities},
|
||||
{"continuous-effects", ast::Requirement::ContinuousEffects},
|
||||
{"derived-predicates", ast::Requirement::DerivedPredicates},
|
||||
{"timed-initial-literals", ast::Requirement::TimedInitialLiterals},
|
||||
{"preferences", ast::Requirement::Preferences},
|
||||
{"constraints", ast::Requirement::Constraints},
|
||||
{"action-costs", ast::Requirement::ActionCosts},
|
||||
{"goal-utilities", ast::Requirement::GoalUtilities},
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::Requirement parseRequirement(Tokenizer &tokenizer)
|
||||
{
|
||||
const auto requirementName = tokenizer.getIdentifier();
|
||||
const auto matchingRequirement = requirementNameMap.find(requirementName.c_str());
|
||||
|
||||
if (matchingRequirement == requirementNameMap.cend())
|
||||
throw ParserException(tokenizer.location(), "unknown PDDL requirement “" + requirementName + "”");
|
||||
|
||||
return matchingRequirement->second;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::Requirement parseRequirement(Context &context)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
auto requirement = parseRequirement(tokenizer);
|
||||
|
||||
if (requirement == ast::Requirement::GoalUtilities)
|
||||
context.warningCallback(tokenizer.location(), "requirement “goal-utilities” is not part of the PDDL 3.1 specification");
|
||||
|
||||
return requirement;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const char *toString(const ast::Requirement &requirement)
|
||||
{
|
||||
const auto matchingRequirement = std::find_if(requirementNameMap.cbegin(), requirementNameMap.cend(),
|
||||
[&](const auto &requirementNamePair)
|
||||
{
|
||||
return requirementNamePair.second == requirement;
|
||||
});
|
||||
|
||||
assert(matchingRequirement != requirementNameMap.cend());
|
||||
|
||||
return matchingRequirement->first;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
#include <pddlparse/detail/parsing/VariableDeclaration.h>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/ParserException.h>
|
||||
#include <pddlparse/detail/ASTCopy.h>
|
||||
#include <pddlparse/detail/parsing/PrimitiveType.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// VariableDeclaration
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void parseAndAddUntypedVariableDeclaration(Context &context, ast::VariableDeclarations &variableDeclarations)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
tokenizer.expect<std::string>("?");
|
||||
auto variableName = tokenizer.getIdentifier();
|
||||
|
||||
assert(variableName != "-");
|
||||
|
||||
variableDeclarations.emplace_back(std::make_unique<ast::VariableDeclaration>(std::move(variableName)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::VariableDeclarations parseVariableDeclarations(Context &context, ast::Domain &domain)
|
||||
{
|
||||
ast::VariableDeclarations variableDeclarations;
|
||||
|
||||
auto &tokenizer = context.tokenizer;
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
// Index on the first element of the current inheritance list
|
||||
size_t inheritanceIndex = 0;
|
||||
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
parseAndAddUntypedVariableDeclaration(context, variableDeclarations);
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
if (!tokenizer.testAndSkip<char>('-'))
|
||||
continue;
|
||||
|
||||
// If existing, parse and store parent type
|
||||
auto parentType = parsePrimitiveType(context, domain);
|
||||
|
||||
for (size_t i = inheritanceIndex; i < variableDeclarations.size(); i++)
|
||||
variableDeclarations[i]->type = ast::deepCopy(parentType);
|
||||
|
||||
// All types up to now are labeled with their parent types
|
||||
inheritanceIndex = variableDeclarations.size() + 1;
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
|
||||
return variableDeclarations;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user