Started reimplementing expression parsing.
This commit is contained in:
parent
fa9fd0935b
commit
62b9da844a
@ -1,127 +0,0 @@
|
||||
#ifndef __PDDL_PARSE__DETAIL__PARSING__AST_H
|
||||
#define __PDDL_PARSE__DETAIL__PARSING__AST_H
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/detail/parsing/Parser.h>
|
||||
#include <pddlparse/detail/parsing/Utils.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/*
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ParseAST
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Primitives
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct Parser<ast::Constant>
|
||||
{
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct Parser<ast::ConstantDeclaration>
|
||||
{
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct Parser<ast::PrimitiveType>
|
||||
{
|
||||
std::experimental::optional<ast::PrimitiveType> parse(Context &context, ASTContext &astContext)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
auto &types = astContext.description.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 ast::PrimitiveType(types.back());
|
||||
}
|
||||
else
|
||||
throw tokenize::TokenizerException(tokenizer.location(), "type “" + typeName + "” used but never declared");
|
||||
}
|
||||
|
||||
auto &type = *matchingType;
|
||||
|
||||
return ast::PrimitiveType(type);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct Parser<ast::PrimitiveTypeDeclaration>
|
||||
{
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<>
|
||||
struct Parser<ast::Unsupported>
|
||||
{
|
||||
std::experimental::optional<ast::Unsupported> parse(Context &context, ASTContext &)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
ast::Unsupported unsupported;
|
||||
|
||||
tokenizer.expect<std::string>("(");
|
||||
|
||||
unsupported.type = tokenizer.getIdentifier();
|
||||
|
||||
context.warningCallback(tokenizer.location(), "expression type “" + unsupported.type + "” currently unsupported in this context");
|
||||
|
||||
skipSection(tokenizer);
|
||||
|
||||
return unsupported;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Expressions
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Argument>
|
||||
struct Parser<ast::And<Argument>>
|
||||
{
|
||||
template<typename ArgumentParser>
|
||||
std::experimental::optional<ast::And<Argument>> parse(Context &context, ASTContext &astContext, ArgumentParser parseArgument)
|
||||
{
|
||||
return Parser<ast::NAry<ast::And<Argument>, Argument>>::parse(context, astContext, parseArgument);
|
||||
}
|
||||
};
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
206
lib/pddlparse/include/pddlparse/detail/parsing/Expressions.h
Normal file
206
lib/pddlparse/include/pddlparse/detail/parsing/Expressions.h
Normal file
@ -0,0 +1,206 @@
|
||||
#ifndef __PDDL_PARSE__DETAIL__PARSING__EXPRESSIONS_H
|
||||
#define __PDDL_PARSE__DETAIL__PARSING__EXPRESSIONS_H
|
||||
|
||||
#include <pddlparse/AST.h>
|
||||
#include <pddlparse/Context.h>
|
||||
#include <pddlparse/ParserException.h>
|
||||
#include <pddlparse/detail/ASTContext.h>
|
||||
#include <pddlparse/detail/VariableStack.h>
|
||||
#include <pddlparse/detail/parsing/VariableDeclaration.h>
|
||||
|
||||
namespace pddl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Expressions
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::AndPointer<Argument>> parseAnd(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument);
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::AtPointer<Argument>> parseAt(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument);
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::EitherPointer<Argument>> parseEither(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument);
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::ExistsPointer<Argument>> parseExists(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument);
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::ForAllPointer<Argument>> parseForAll(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument);
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::ImplyPointer<Argument>> parseImply(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument);
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::NotPointer<Argument>> parseNot(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument);
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::OrPointer<Argument>> parseOr(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument);
|
||||
template<typename ArgumentLeft, typename ArgumentRight, typename ArgumentParser>
|
||||
std::experimental::optional<ast::WhenPointer<ArgumentLeft, ArgumentRight>> parseWhen(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Expressions: Base Classes
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Derived, typename ArgumentParser>
|
||||
std::experimental::optional<std::unique_ptr<Derived>> parseBinary(Context &context,
|
||||
ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
const auto position = tokenizer.position();
|
||||
|
||||
if (!tokenizer.testAndSkip<std::string>("(")
|
||||
|| !tokenizer.testIdentifierAndSkip(Derived::Identifier))
|
||||
{
|
||||
tokenizer.seek(position);
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
// Parse arguments of the expression
|
||||
auto argumentLeft = parseArgument(context, astContext, variableStack);
|
||||
|
||||
if (!argumentLeft)
|
||||
throw ParserException(tokenizer.location(), "could not parse argument of “" + Derived::Identifier + "” expression");
|
||||
|
||||
auto argumentRight = parseArgument(context, astContext, variableStack);
|
||||
|
||||
if (!argumentRight)
|
||||
throw ParserException(tokenizer.location(), "could not parse argument of “" + Derived::Identifier + "” expression");
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
|
||||
return std::make_unique<Derived>(std::move(argumentLeft.value()), std::move(argumentRight.value()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Derived, typename ArgumentParser>
|
||||
std::experimental::optional<std::unique_ptr<Derived>> parseNAry(Context &context,
|
||||
ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
const auto position = tokenizer.position();
|
||||
|
||||
if (!tokenizer.testAndSkip<std::string>("(")
|
||||
|| !tokenizer.testIdentifierAndSkip(Derived::Identifier))
|
||||
{
|
||||
tokenizer.seek(position);
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
|
||||
typename Derived::Arguments arguments;
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
|
||||
// Parse arguments of the expression
|
||||
while (tokenizer.currentCharacter() != ')')
|
||||
{
|
||||
auto &argument = parseArgument(context, astContext, variableStack);
|
||||
|
||||
if (!argument)
|
||||
throw ParserException(tokenizer.location(), "could not parse argument of “" + Derived::Identifier + "” expression");
|
||||
|
||||
arguments.emplace_back(std::move(argument.value));
|
||||
|
||||
tokenizer.skipWhiteSpace();
|
||||
}
|
||||
|
||||
if (arguments.empty())
|
||||
context.warningCallback(tokenizer.location(), "“" + Derived::Identifier + "” expressions should not be empty");
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
|
||||
return std::make_unique<Derived>(std::move(arguments));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Derived, typename ArgumentParser>
|
||||
std::experimental::optional<std::unique_ptr<Derived>> parseQuantified(Context &context,
|
||||
ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument)
|
||||
{
|
||||
auto &tokenizer = context.tokenizer;
|
||||
|
||||
const auto position = tokenizer.position();
|
||||
|
||||
if (!tokenizer.testAndSkip<std::string>("(")
|
||||
|| !tokenizer.testIdentifierAndSkip(Derived::Identifier))
|
||||
{
|
||||
tokenizer.seek(position);
|
||||
return std::experimental::nullopt;
|
||||
}
|
||||
|
||||
// Parse variable list
|
||||
tokenizer.expect<std::string>("(");
|
||||
auto parameters = parseVariableDeclarations(context, *astContext.domain);
|
||||
tokenizer.expect<std::string>(")");
|
||||
|
||||
// Push newly parsed variables to the stack
|
||||
variableStack.push(¶meters);
|
||||
|
||||
// Parse argument of the expression
|
||||
auto argument = parseArgument(context, astContext, variableStack);
|
||||
|
||||
if (!argument)
|
||||
throw ParserException(tokenizer.location(), "could not parse argument of “" + Derived::Identifier + "” expression");
|
||||
|
||||
// Clean up variable stack
|
||||
variableStack.pop();
|
||||
|
||||
tokenizer.expect<std::string>(")");
|
||||
|
||||
return std::make_unique<Derived>(std::move(parameters), std::move(argument.value()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Expressions
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::AndPointer<Argument>> parseAnd(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument)
|
||||
{
|
||||
return parseNAry<ast::And<Argument>, ArgumentParser>(context, astContext, variableStack, parseArgument);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::EitherPointer<Argument>> parseEither(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument)
|
||||
{
|
||||
return parseNAry<ast::Either<Argument>, ArgumentParser>(context, astContext, variableStack, parseArgument);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::ImplyPointer<Argument>> parseImply(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument)
|
||||
{
|
||||
return parseBinary<ast::Imply<Argument>, ArgumentParser>(context, astContext, variableStack, parseArgument);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Argument, typename ArgumentParser>
|
||||
std::experimental::optional<ast::OrPointer<Argument>> parseOr(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument)
|
||||
{
|
||||
return parseNAry<ast::Or<Argument>, ArgumentParser>(context, astContext, variableStack, parseArgument);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ArgumentLeft, typename ArgumentRight, typename ArgumentParser>
|
||||
std::experimental::optional<ast::WhenPointer<ArgumentLeft, ArgumentRight>> parseImply(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument)
|
||||
{
|
||||
return parseBinary<ast::When<ArgumentLeft, ArgumentRight>, ArgumentParser>(context, astContext, variableStack, parseArgument);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -48,6 +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);
|
||||
|
||||
|
Reference in New Issue
Block a user