From 03cd0e16a20f9fe3f3442b1d96969a75d1a1ab88 Mon Sep 17 00:00:00 2001 From: Dominik Drexler Date: Mon, 1 Jan 2024 16:15:55 +0100 Subject: [PATCH] refactored type parsng --- include/domain/pddl/exceptions.hpp | 5 ++ src/domain/pddl/exceptions.cpp | 4 + src/domain/pddl/parser/constants.cpp | 2 +- src/domain/pddl/parser/predicates.cpp | 4 +- src/domain/pddl/parser/types.cpp | 108 ++++++++++++++------------ src/problem/pddl/parser/objects.cpp | 2 +- 6 files changed, 69 insertions(+), 56 deletions(-) diff --git a/include/domain/pddl/exceptions.hpp b/include/domain/pddl/exceptions.hpp index c64addfb..5df12413 100644 --- a/include/domain/pddl/exceptions.hpp +++ b/include/domain/pddl/exceptions.hpp @@ -29,6 +29,11 @@ namespace loki { /* Type */ +class ReservedTypeError : public SemanticParserError { +public: + ReservedTypeError(const std::string& name, const std::string& error_handler_output); +}; + class UnusedTypeError : public SemanticParserError { public: UnusedTypeError(const std::string& name, const std::string& error_handler_output); diff --git a/src/domain/pddl/exceptions.cpp b/src/domain/pddl/exceptions.cpp index 193004d1..ff11c6df 100644 --- a/src/domain/pddl/exceptions.cpp +++ b/src/domain/pddl/exceptions.cpp @@ -24,6 +24,10 @@ namespace loki { /* Type */ +ReservedTypeError::ReservedTypeError(const std::string& name, const std::string& error_handler_output) + : SemanticParserError( + "Unexpected type name \"" + name + "\". It is a reserved type name", error_handler_output) { } + UnusedTypeError::UnusedTypeError(const std::string& name, const std::string& error_handler_output) : SemanticParserError( "The type with name \"" + name + "\" was never referred to.", error_handler_output) { } diff --git a/src/domain/pddl/parser/constants.cpp b/src/domain/pddl/parser/constants.cpp index 269513d4..cce86826 100644 --- a/src/domain/pddl/parser/constants.cpp +++ b/src/domain/pddl/parser/constants.cpp @@ -91,7 +91,7 @@ pddl::ObjectList ConstantListVisitor::operator()(const ast::TypedListOfNamesRecu // A non-visited vector of names has user defined base types auto constant_list = parse_constant_definitions(typed_list_of_names_recursively_node.names, type_list, context); // Recursively add objects. - auto additional_objects = boost::apply_visitor(ConstantListVisitor(context), typed_list_of_names_recursively_node.typed_list_of_names.get()); + auto additional_objects = boost::apply_visitor(*this, typed_list_of_names_recursively_node.typed_list_of_names.get()); constant_list.insert(constant_list.end(), additional_objects.begin(), additional_objects.end()); return constant_list; } diff --git a/src/domain/pddl/parser/predicates.cpp b/src/domain/pddl/parser/predicates.cpp index 38d02ef1..e279ae7d 100644 --- a/src/domain/pddl/parser/predicates.cpp +++ b/src/domain/pddl/parser/predicates.cpp @@ -33,8 +33,6 @@ static void test_multiple_definition(const pddl::Predicate& predicate, const dom const auto& [_predicate, position, error_handler] = binding.value(); if (position.has_value()) { message_2 = error_handler(position.value(), "First defined here:"); - } else { - // Reserved type error? } throw MultiDefinitionPredicateError(predicate_name, message_1 + message_2); } @@ -43,7 +41,7 @@ static void test_multiple_definition(const pddl::Predicate& predicate, const dom static void insert_context_information(const pddl::Predicate& predicate, const domain::ast::Predicate& node, Context& context) { context.positions.push_back(predicate, node); - context.scopes.insert(predicate->get_name(), predicate, node); + context.scopes.insert(predicate->get_name(), predicate, node); context.references.track(predicate); } diff --git a/src/domain/pddl/parser/types.cpp b/src/domain/pddl/parser/types.cpp index 7a7d4cc8..0e5d739c 100644 --- a/src/domain/pddl/parser/types.cpp +++ b/src/domain/pddl/parser/types.cpp @@ -83,34 +83,67 @@ pddl::TypeList TypeReferenceTypeVisitor::operator()(const ast::TypeEither& eithe } /* TypeDeclarationTypedListOfNamesVisitor */ +static void test_multiple_definition(const pddl::Type& type, const domain::ast::Name& node, const Context& context) { + const auto type_name = type->get_name(); + const auto binding = context.scopes.get(type_name); + if (binding.has_value()) { + const auto message_1 = context.scopes.get_error_handler()(node, "Defined here:"); + auto message_2 = std::string(""); + const auto& [_type, position, error_handler] = binding.value(); + if (position.has_value()) { + message_2 = error_handler(position.value(), "First defined here:"); + } + throw MultiDefinitionTypeError(type_name, message_1 + message_2); + } +} + + +static void test_reserved_type(const pddl::Type& type, const domain::ast::Name& node, const Context& context) { + if (type->get_name() == "object") { + throw ReservedTypeError("object", context.scopes.get_error_handler()(node, "")); + } + // We also reserve type name number although PDDL specification allows it. + // However, this allows using regular types as function types for simplicity. + if (type->get_name() == "number") { + throw ReservedTypeError("number", context.scopes.get_error_handler()(node, "")); + } +} + + +static void insert_context_information(const pddl::Type& type, const domain::ast::Name& node, Context& context) { + context.positions.push_back(type, node); + context.scopes.insert(type->get_name(), type, node); + context.references.track(type); +} + + +static pddl::Type parse_type_definition(const domain::ast::Name& node, const pddl::TypeList& type_list, Context& context) { + const auto name = parse(node); + const auto type = context.factories.types.get_or_create(name, type_list); + test_reserved_type(type, node, context); + test_multiple_definition(type, node, context); + insert_context_information(type, node, context); + return type; +} + + +static pddl::TypeList parse_type_definitions(const std::vector& nodes, const pddl::TypeList& parent_type_list, Context& context) { + auto type_list = pddl::TypeList(); + for (const auto& node : nodes) { + type_list.push_back(parse_type_definition(node, parent_type_list, context)); + } + return type_list; +} + TypeDeclarationTypedListOfNamesVisitor::TypeDeclarationTypedListOfNamesVisitor(Context& context_) : context(context_) { } pddl::TypeList TypeDeclarationTypedListOfNamesVisitor::operator()(const std::vector& name_nodes) { // A visited vector of name has single base type "object" - auto type_list = pddl::TypeList(); assert(context.scopes.get("object").has_value()); const auto& [type_object, _position, _error_handler] = context.scopes.get("object").value(); - for (const auto& name_node : name_nodes) { - const auto name = parse(name_node); - const auto binding = context.scopes.get(name); - if (binding.has_value()) { - const auto message_1 = context.scopes.get_error_handler()(name_node, "Defined here:"); - auto message_2 = std::string(""); - const auto& [_type, position, error_handler] = binding.value(); - if (position.has_value()) { - message_2 = error_handler(position.value(), "First defined here:"); - } else { - // Reserved type? - } - throw MultiDefinitionTypeError(name, message_1 + message_2); - } - const auto type = context.factories.types.get_or_create(name, pddl::TypeList{type_object}); - type_list.push_back(type); - context.positions.push_back(type, name_node); - context.scopes.insert(name, type, name_node); - } + const auto type_list = parse_type_definitions(name_nodes, pddl::TypeList{type_object}, context); return type_list; } @@ -120,39 +153,12 @@ pddl::TypeList TypeDeclarationTypedListOfNamesVisitor::operator()(const ast::Typ throw UndefinedRequirementError(pddl::RequirementEnum::TYPING, context.scopes.get_error_handler()(typed_list_of_names_recursively_node, "")); } context.references.untrack(pddl::RequirementEnum::TYPING); - auto type_list = pddl::TypeList(); - const auto types = boost::apply_visitor(TypeDeclarationTypeVisitor(context), - typed_list_of_names_recursively_node.type); // A non-visited vector of names has user defined base types. - for (const auto& name_node : typed_list_of_names_recursively_node.names) { - const auto name = parse(name_node); - if (name == "object") { - throw SemanticParserError("Unexpected type name \"object\". It is a reserved type name.", context.scopes.get_error_handler()(name_node, "")); - } - // We also reserve type name number although PDDL specification allows it. - // However, this allows using regular types as function types for simplicity. - if (name == "number") { - throw SemanticParserError("Unexpected type name \"number\". It is a reserved type name.", context.scopes.get_error_handler()(name_node, "")); - } - const auto binding = context.scopes.get(name); - if (binding.has_value()) { - const auto message_1 = context.scopes.get_error_handler()(name_node, "Defined here:"); - auto message_2 = std::string(""); - const auto& [_type, position, error_handler] = binding.value(); - if (position.has_value()) { - message_2 = error_handler(position.value(), "First defined here:"); - } else { - // Reserved type? - } - throw MultiDefinitionTypeError(name, message_1 + message_2); - } - const auto type = context.factories.types.get_or_create(name, types); - context.positions.push_back(type, name_node); - type_list.push_back(type); - context.scopes.insert(name, type, name_node); - } + const auto parent_type_list = boost::apply_visitor(TypeDeclarationTypeVisitor(context), + typed_list_of_names_recursively_node.type); + auto type_list = parse_type_definitions(typed_list_of_names_recursively_node.names, parent_type_list, context); // Recursively add types. - auto additional_types = boost::apply_visitor(TypeDeclarationTypedListOfNamesVisitor(context), typed_list_of_names_recursively_node.typed_list_of_names.get()); + const auto additional_types = boost::apply_visitor(*this, typed_list_of_names_recursively_node.typed_list_of_names.get()); type_list.insert(type_list.end(), additional_types.begin(), additional_types.end()); return type_list; } diff --git a/src/problem/pddl/parser/objects.cpp b/src/problem/pddl/parser/objects.cpp index f633d880..90a35f84 100644 --- a/src/problem/pddl/parser/objects.cpp +++ b/src/problem/pddl/parser/objects.cpp @@ -96,7 +96,7 @@ pddl::ObjectList ObjectListVisitor::operator()(const domain::ast::TypedListOfNam // A non-visited vector of names has user defined base types auto object_list = parse_object_definitions(node.names, type_list, context); // Recursively add objects. - auto additional_objects = boost::apply_visitor(ObjectListVisitor(context), node.typed_list_of_names.get()); + auto additional_objects = boost::apply_visitor(*this, node.typed_list_of_names.get()); object_list.insert(object_list.end(), additional_objects.begin(), additional_objects.end()); return object_list; }