#include #include #include #include #include #include #include namespace pddl { namespace detail { //////////////////////////////////////////////////////////////////////////////////////////////////// // // Effect // //////////////////////////////////////////////////////////////////////////////////////////////////// std::experimental::optional parseEffectBody(Context &context, ASTContext &astContext, VariableStack &variableStack); std::experimental::optional parseConditionalEffect(Context &context, ASTContext &astContext, VariableStack &variableStack); std::experimental::optional parseConditionalEffectBody(Context &context, ASTContext &astContext, VariableStack &variableStack); //////////////////////////////////////////////////////////////////////////////////////////////////// std::experimental::optional parseEffect(Context &context, ASTContext &astContext, VariableStack &variableStack) { auto &tokenizer = context.tokenizer; tokenizer.skipWhiteSpace(); std::experimental::optional effect; if ((effect = parseAnd(context, astContext, variableStack, parseEffect)) || (effect = parseForAll(context, astContext, variableStack, parseEffect)) || (effect = parseWhen(context, astContext, variableStack, parsePreconditionBody, parseConditionalEffect))) { return std::move(effect.value()); } return parseEffectBody(context, astContext, variableStack); } //////////////////////////////////////////////////////////////////////////////////////////////////// std::experimental::optional parseEffectBody(Context &context, ASTContext &astContext, VariableStack &variableStack) { auto &tokenizer = context.tokenizer; tokenizer.skipWhiteSpace(); // Test unsupported expressions first const auto position = tokenizer.position(); tokenizer.expect("("); tokenizer.skipWhiteSpace(); const auto expressionIdentifierPosition = tokenizer.position(); if (tokenizer.testIdentifierAndReturn("assign") || tokenizer.testIdentifierAndReturn("scale-up") || tokenizer.testIdentifierAndReturn("scale-down") || tokenizer.testIdentifierAndReturn("increase") || tokenizer.testIdentifierAndReturn("decrease")) { throw exceptUnsupportedExpression(position, context); } tokenizer.seek(position); // Now, test supported expressions std::experimental::optional effect; if ((effect = parseNot(context, astContext, variableStack, parseAtomicFormula)) || (effect = parseAtomicFormula(context, astContext, variableStack))) { return std::move(effect.value()); } tokenizer.seek(expressionIdentifierPosition); const auto expressionIdentifier = tokenizer.getIdentifier(); tokenizer.seek(position); throw ParserException(tokenizer.location(), "expression type “" + expressionIdentifier + "” unknown or not allowed in effect body"); } //////////////////////////////////////////////////////////////////////////////////////////////////// std::experimental::optional parseConditionalEffect(Context &context, ASTContext &astContext, VariableStack &variableStack) { auto &tokenizer = context.tokenizer; tokenizer.skipWhiteSpace(); std::experimental::optional conditionalEffect; if ((conditionalEffect = parseAnd(context, astContext, variableStack, parseConditionalEffectBody))) return std::move(conditionalEffect.value()); return parseConditionalEffectBody(context, astContext, variableStack); } //////////////////////////////////////////////////////////////////////////////////////////////////// std::experimental::optional parseConditionalEffectBody(Context &context, ASTContext &astContext, VariableStack &variableStack) { auto &tokenizer = context.tokenizer; tokenizer.skipWhiteSpace(); // Test unsupported expressions first const auto position = tokenizer.position(); tokenizer.expect("("); tokenizer.skipWhiteSpace(); const auto expressionIdentifierPosition = tokenizer.position(); if (tokenizer.testIdentifierAndReturn("=") || tokenizer.testIdentifierAndReturn("assign") || tokenizer.testIdentifierAndReturn("scale-up") || tokenizer.testIdentifierAndReturn("scale-down") || tokenizer.testIdentifierAndReturn("increase") || tokenizer.testIdentifierAndReturn("decrease")) { throw exceptUnsupportedExpression(position, context); } tokenizer.seek(position); // Now, test supported expressions std::experimental::optional literal; if ((literal = parseNot(context, astContext, variableStack, parseAtomicFormula)) || (literal = parseAtomicFormula(context, astContext, variableStack))) { return std::move(literal.value()); } tokenizer.seek(expressionIdentifierPosition); const auto expressionIdentifier = tokenizer.getIdentifier(); tokenizer.seek(position); throw ParserException(tokenizer.location(), "expression type “" + expressionIdentifier + "” unknown or not allowed in conditional effect body"); } //////////////////////////////////////////////////////////////////////////////////////////////////// } }