Reimplemented major parts of parsing preconditions.
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
#include <pddlparse/detail/VariableStack.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
|
||||
namespace pddl
|
||||
@@ -13,16 +15,38 @@ namespace detail
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void VariableStack::push(ast::VariableDeclarations *variables)
|
||||
void VariableStack::push(ast::VariableDeclarations *layer)
|
||||
{
|
||||
m_variableStack.push_back(variables);
|
||||
m_layers.push_back(layer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void VariableStack::pop()
|
||||
{
|
||||
m_variableStack.pop_back();
|
||||
m_layers.pop_back();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::experimental::optional<ast::VariableDeclaration *> VariableStack::findVariableDeclaration(const std::string &variableName)
|
||||
{
|
||||
const auto variableDeclarationMatches =
|
||||
[&variableName](const auto &variableDeclaration)
|
||||
{
|
||||
return variableDeclaration->name == variableName;
|
||||
};
|
||||
|
||||
for (auto i = m_layers.rbegin(); i != m_layers.rend(); i++)
|
||||
{
|
||||
auto &layer = **i;
|
||||
const auto matchingVariableDeclaration = std::find_if(layer.begin(), layer.end(), variableDeclarationMatches);
|
||||
|
||||
if (matchingVariableDeclaration != layer.end())
|
||||
return matchingVariableDeclaration->get();
|
||||
}
|
||||
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -30,6 +30,7 @@ std::experimental::optional<ast::ConstantPointer> findConstant(const std::string
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: remove if unneeded
|
||||
ast::ConstantPointer parseConstant(Context &context, ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
@@ -45,6 +46,7 @@ ast::ConstantPointer parseConstant(Context &context, ast::Domain &domain)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: remove if unneeded
|
||||
ast::ConstantPointer parseConstant(Context &context, ast::Problem &problem)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
@@ -65,5 +67,25 @@ ast::ConstantPointer parseConstant(Context &context, ast::Problem &problem)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::ConstantPointer parseConstant(Context &context, ASTContext &astContext)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
const auto constantName = tokenizer.getIdentifier();
|
||||
|
||||
auto constant = findConstant(constantName, astContext.domain->constants);
|
||||
|
||||
if (constant)
|
||||
return std::move(constant.value());
|
||||
|
||||
constant = findConstant(constantName, astContext.problem.value()->objects);
|
||||
|
||||
if (constant)
|
||||
return std::move(constant.value());
|
||||
|
||||
throw ParserException(tokenizer.location(), "constant “" + constantName + "” used but never declared");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -51,7 +51,7 @@ ast::Description DescriptionParser::parse()
|
||||
// TODO: check consistency
|
||||
// * check typing requirement
|
||||
// * check that typing is used consistently
|
||||
// * check that constants, variables, and predicates aren't declared twice
|
||||
// * check that constants/objects, 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)};
|
||||
|
113
lib/pddlparse/src/pddlparse/detail/parsing/Precondition.cpp
Normal file
113
lib/pddlparse/src/pddlparse/detail/parsing/Precondition.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#include <pddlparse/detail/parsing/Precondition.h>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/detail/parsing/Expressions.h>
|
||||
#include <pddlparse/detail/parsing/Predicate.h>
|
||||
#include <pddlparse/detail/parsing/Unsupported.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Precondition
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::experimental::optional<ast::Precondition> parsePreconditionBody(Context &context, ASTContext &astContext, VariableStack &variableStack);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::experimental::optional<ast::Precondition> parsePrecondition(Context &context, ASTContext &astContext, VariableStack &variableStack)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
std::experimental::optional<ast::Precondition> precondition;
|
||||
|
||||
if ((precondition = parseAnd<ast::Precondition>(context, astContext, variableStack, parsePrecondition))
|
||||
|| (precondition = parseForAll<ast::Precondition>(context, astContext, variableStack, parsePrecondition)))
|
||||
{
|
||||
return std::move(precondition.value());
|
||||
}
|
||||
|
||||
const auto position = tokenizer.position();
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
|
||||
const auto expressionIdentifierPosition = tokenizer.position();
|
||||
|
||||
if (tokenizer.testIdentifierAndSkip("preference"))
|
||||
{
|
||||
// TODO: refactor
|
||||
tokenizer.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = tokenizer.getIdentifier();
|
||||
|
||||
tokenizer.seek(position);
|
||||
return parseUnsupported(context);
|
||||
}
|
||||
|
||||
tokenizer.seek(position);
|
||||
return parsePreconditionBody(context, astContext, variableStack);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::experimental::optional<ast::Precondition> parsePreconditionBody(Context &context, ASTContext &astContext, VariableStack &variableStack)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
std::experimental::optional<ast::Precondition> precondition;
|
||||
|
||||
if ((precondition = parseAnd<ast::Precondition>(context, astContext, variableStack, parsePrecondition))
|
||||
|| (precondition = parseOr<ast::Precondition>(context, astContext, variableStack, parsePrecondition))
|
||||
|| (precondition = parseExists<ast::Precondition>(context, astContext, variableStack, parsePrecondition))
|
||||
|| (precondition = parseForAll<ast::Precondition>(context, astContext, variableStack, parsePrecondition))
|
||||
|| (precondition = parseNot<ast::Precondition>(context, astContext, variableStack, parsePrecondition))
|
||||
|| (precondition = parseImply<ast::Precondition>(context, astContext, variableStack, parsePrecondition))
|
||||
|| (precondition = parsePredicate(context, astContext, variableStack)))
|
||||
{
|
||||
return std::move(precondition.value());
|
||||
}
|
||||
|
||||
const auto position = tokenizer.position();
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
|
||||
const auto expressionIdentifierPosition = tokenizer.position();
|
||||
|
||||
if (tokenizer.testIdentifierAndSkip("-")
|
||||
|| tokenizer.testIdentifierAndSkip("=")
|
||||
|| tokenizer.testIdentifierAndSkip("*")
|
||||
|| tokenizer.testIdentifierAndSkip("+")
|
||||
|| tokenizer.testIdentifierAndSkip("-")
|
||||
|| tokenizer.testIdentifierAndSkip("/")
|
||||
|| tokenizer.testIdentifierAndSkip(">")
|
||||
|| tokenizer.testIdentifierAndSkip("<")
|
||||
|| tokenizer.testIdentifierAndSkip("=")
|
||||
|| tokenizer.testIdentifierAndSkip(">=")
|
||||
|| tokenizer.testIdentifierAndSkip("<="))
|
||||
{
|
||||
tokenizer.seek(expressionIdentifierPosition);
|
||||
const auto expressionIdentifier = tokenizer.getIdentifier();
|
||||
|
||||
tokenizer.seek(position);
|
||||
return parseUnsupported(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");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
79
lib/pddlparse/src/pddlparse/detail/parsing/Predicate.cpp
Normal file
79
lib/pddlparse/src/pddlparse/detail/parsing/Predicate.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <pddlparse/detail/parsing/Predicate.h>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/detail/parsing/Constant.h>
|
||||
#include <pddlparse/detail/parsing/Variable.h>
|
||||
#include <pddlparse/detail/parsing/VariableDeclaration.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Predicate
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::experimental::optional<ast::PredicatePointer> parsePredicate(Context &context, ASTContext &astContext, VariableStack &variableStack)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
const auto position = tokenizer.position();
|
||||
|
||||
if (!tokenizer.testAndSkip<std::string>("("))
|
||||
{
|
||||
tokenizer.seek(position);
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
|
||||
const auto predicateName = tokenizer.getIdentifier();
|
||||
|
||||
ast::Predicate::Arguments arguments;
|
||||
|
||||
/*const auto matchingPredicate = std::find_if(predicates.cbegin(), predicates.cend(),
|
||||
[&](const auto &predicate)
|
||||
{
|
||||
return predicate->name() == predicateName;
|
||||
});
|
||||
|
||||
if (matchingPredicate == predicates.cend())
|
||||
{
|
||||
tokenizer.seek(position);
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
|
||||
auto predicate = PredicatePointer(new Predicate);
|
||||
|
||||
predicate->m_name = predicateName;*/
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
// Parse arguments
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
// Parse variables
|
||||
if (tokenizer.currentCharacter() == '?')
|
||||
arguments.emplace_back(parseVariable(context, variableStack));
|
||||
// Parse constants
|
||||
else
|
||||
arguments.emplace_back(parseConstant(context, astContext));
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
|
||||
//const auto &predicates = astContext.domain->predicates;
|
||||
|
||||
// TODO: check that signature matches one of the declared ones
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
|
||||
// TODO: add matching predicate declaration
|
||||
return std::make_unique<ast::Predicate>(std::move(arguments), nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
53
lib/pddlparse/src/pddlparse/detail/parsing/Type.cpp
Normal file
53
lib/pddlparse/src/pddlparse/detail/parsing/Type.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <pddlparse/detail/parsing/Type.h>
|
||||
|
||||
#include <pddlparse/ParserException.h>
|
||||
#include <pddlparse/detail/parsing/Expressions.h>
|
||||
#include <pddlparse/detail/parsing/PrimitiveType.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Type
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::Type parseType(Context &context, ast::Domain &domain)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
if (tokenizer.testAndReturn<char>('('))
|
||||
{
|
||||
// TODO: put into Type parsing unit
|
||||
// TODO: refactor
|
||||
auto p =
|
||||
[](auto &context, auto &astContext, auto &) -> std::experimental::optional<ast::PrimitiveTypePointer>
|
||||
{
|
||||
return parsePrimitiveType(context, *astContext.domain);
|
||||
};
|
||||
|
||||
// TODO: refactor
|
||||
ASTContext astContext(domain);
|
||||
VariableStack variableStack;
|
||||
|
||||
auto eitherType = parseEither<ast::PrimitiveTypePointer>(context, astContext, variableStack, p);
|
||||
|
||||
if (!eitherType)
|
||||
throw ParserException(tokenizer.location(), "expected primitive type or “either” expression");
|
||||
|
||||
return std::move(eitherType.value());
|
||||
}
|
||||
|
||||
// If existing, parse and store parent type
|
||||
return parsePrimitiveType(context, domain);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
35
lib/pddlparse/src/pddlparse/detail/parsing/Unsupported.cpp
Normal file
35
lib/pddlparse/src/pddlparse/detail/parsing/Unsupported.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <pddlparse/detail/parsing/Unsupported.h>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/detail/parsing/Utils.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Unsupported
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::UnsupportedPointer parseUnsupported(Context &context)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
|
||||
auto expressionType = tokenizer.getIdentifier();
|
||||
|
||||
context.warningCallback(tokenizer.location(), "expression type “" + expressionType + "” currently unsupported in this context");
|
||||
|
||||
skipSection(tokenizer);
|
||||
|
||||
return std::make_unique<ast::Unsupported>(std::move(expressionType));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
36
lib/pddlparse/src/pddlparse/detail/parsing/Variable.cpp
Normal file
36
lib/pddlparse/src/pddlparse/detail/parsing/Variable.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <pddlparse/detail/parsing/Variable.h>
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/ParserException.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Predicate
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::VariablePointer parseVariable(Context &context, VariableStack &variableStack)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
tokenizer.expect<std::string>("?");
|
||||
|
||||
const auto variableName = tokenizer.getIdentifier();
|
||||
|
||||
auto variableDeclaration = variableStack.findVariableDeclaration(variableName);
|
||||
|
||||
if (!variableDeclaration)
|
||||
throw ParserException(tokenizer.location(), "undeclared variable “" + variableName + "”");
|
||||
|
||||
return std::make_unique<ast::Variable>(variableDeclaration.value());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
@@ -3,7 +3,7 @@
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/ParserException.h>
|
||||
#include <pddlparse/detail/ASTCopy.h>
|
||||
#include <pddlparse/detail/parsing/PrimitiveType.h>
|
||||
#include <pddlparse/detail/parsing/Type.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
@@ -48,10 +48,8 @@ ast::VariableDeclarations parseVariableDeclarations(Context &context, ast::Domai
|
||||
if (!tokenizer.testAndSkip<char>('-'))
|
||||
continue;
|
||||
|
||||
// TODO: reimplement parsing “either” types
|
||||
|
||||
// If existing, parse and store parent type
|
||||
auto parentType = parsePrimitiveType(context, domain);
|
||||
auto parentType = parseType(context, domain);
|
||||
parentType = ast::deepCopy(parentType);
|
||||
|
||||
for (size_t i = inheritanceIndex; i < variableDeclarations.size(); i++)
|
||||
variableDeclarations[i]->type = ast::deepCopy(parentType);
|
||||
|
Reference in New Issue
Block a user