diff --git a/lib/pddlparse/include/pddlparse/detail/parsing/AST.h b/lib/pddlparse/include/pddlparse/detail/parsing/AST.h deleted file mode 100644 index e6e12a6..0000000 --- a/lib/pddlparse/include/pddlparse/detail/parsing/AST.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef __PDDL_PARSE__DETAIL__PARSING__AST_H -#define __PDDL_PARSE__DETAIL__PARSING__AST_H - -#include -#include -#include - -namespace pddl -{ -namespace detail -{ -/* -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// ParseAST -// -//////////////////////////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Primitives -//////////////////////////////////////////////////////////////////////////////////////////////////// - -template<> -struct Parser -{ -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -template<> -struct Parser -{ -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -template<> -struct Parser -{ - std::experimental::optional 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(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 -{ -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -template<> -struct Parser -{ - std::experimental::optional parse(Context &context, ASTContext &) - { - auto &tokenizer = context.tokenizer; - - ast::Unsupported unsupported; - - tokenizer.expect("("); - - unsupported.type = tokenizer.getIdentifier(); - - context.warningCallback(tokenizer.location(), "expression type “" + unsupported.type + "” currently unsupported in this context"); - - skipSection(tokenizer); - - return unsupported; - } -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Expressions -//////////////////////////////////////////////////////////////////////////////////////////////////// - -template -struct Parser> -{ - template - std::experimental::optional> parse(Context &context, ASTContext &astContext, ArgumentParser parseArgument) - { - return Parser, Argument>>::parse(context, astContext, parseArgument); - } -}; -*/ -//////////////////////////////////////////////////////////////////////////////////////////////////// - -} -} - -#endif diff --git a/lib/pddlparse/include/pddlparse/detail/parsing/Expressions.h b/lib/pddlparse/include/pddlparse/detail/parsing/Expressions.h new file mode 100644 index 0000000..e4c17d9 --- /dev/null +++ b/lib/pddlparse/include/pddlparse/detail/parsing/Expressions.h @@ -0,0 +1,206 @@ +#ifndef __PDDL_PARSE__DETAIL__PARSING__EXPRESSIONS_H +#define __PDDL_PARSE__DETAIL__PARSING__EXPRESSIONS_H + +#include +#include +#include +#include +#include +#include + +namespace pddl +{ +namespace detail +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Expressions +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +std::experimental::optional> parseAnd(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument); +template +std::experimental::optional> parseAt(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument); +template +std::experimental::optional> parseEither(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument); +template +std::experimental::optional> parseExists(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument); +template +std::experimental::optional> parseForAll(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument); +template +std::experimental::optional> parseImply(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument); +template +std::experimental::optional> parseNot(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument); +template +std::experimental::optional> parseOr(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument); +template +std::experimental::optional> parseWhen(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument); + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Expressions: Base Classes +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +std::experimental::optional> parseBinary(Context &context, + ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument) +{ + auto &tokenizer = context.tokenizer; + + const auto position = tokenizer.position(); + + if (!tokenizer.testAndSkip("(") + || !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(")"); + + return std::make_unique(std::move(argumentLeft.value()), std::move(argumentRight.value())); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +std::experimental::optional> parseNAry(Context &context, + ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument) +{ + auto &tokenizer = context.tokenizer; + + const auto position = tokenizer.position(); + + if (!tokenizer.testAndSkip("(") + || !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(")"); + + return std::make_unique(std::move(arguments)); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +std::experimental::optional> parseQuantified(Context &context, + ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument) +{ + auto &tokenizer = context.tokenizer; + + const auto position = tokenizer.position(); + + if (!tokenizer.testAndSkip("(") + || !tokenizer.testIdentifierAndSkip(Derived::Identifier)) + { + tokenizer.seek(position); + return std::experimental::nullopt; + } + + // Parse variable list + tokenizer.expect("("); + auto parameters = parseVariableDeclarations(context, *astContext.domain); + tokenizer.expect(")"); + + // 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(")"); + + return std::make_unique(std::move(parameters), std::move(argument.value())); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Expressions +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +std::experimental::optional> parseAnd(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument) +{ + return parseNAry, ArgumentParser>(context, astContext, variableStack, parseArgument); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +std::experimental::optional> parseEither(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument) +{ + return parseNAry, ArgumentParser>(context, astContext, variableStack, parseArgument); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +std::experimental::optional> parseImply(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument) +{ + return parseBinary, ArgumentParser>(context, astContext, variableStack, parseArgument); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +std::experimental::optional> parseOr(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument) +{ + return parseNAry, ArgumentParser>(context, astContext, variableStack, parseArgument); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +std::experimental::optional> parseImply(Context &context, ASTContext &astContext, VariableStack &variableStack, ArgumentParser parseArgument) +{ + return parseBinary, ArgumentParser>(context, astContext, variableStack, parseArgument); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} + +#endif diff --git a/lib/pddlparse/src/pddlparse/detail/parsing/VariableDeclaration.cpp b/lib/pddlparse/src/pddlparse/detail/parsing/VariableDeclaration.cpp index 811b233..c9eb972 100644 --- a/lib/pddlparse/src/pddlparse/detail/parsing/VariableDeclaration.cpp +++ b/lib/pddlparse/src/pddlparse/detail/parsing/VariableDeclaration.cpp @@ -48,6 +48,8 @@ ast::VariableDeclarations parseVariableDeclarations(Context &context, ast::Domai if (!tokenizer.testAndSkip('-')) continue; + // TODO: reimplement parsing “either” types + // If existing, parse and store parent type auto parentType = parsePrimitiveType(context, domain);