From 05779a999415ceb9e5241bb12640d40afc8b224d Mon Sep 17 00:00:00 2001 From: Dominik Drexler Date: Mon, 16 Oct 2023 09:46:27 +0200 Subject: [PATCH] some work on parsing --- include/dlplan/core.h | 3 + .../core/parsers/elements/stage_1/ast.hpp | 6 +- .../core/parsers/elements/stage_2/parser.hpp | 8 +- src/core/element_factory.cpp | 8 +- .../parsers/elements/stage_1/ast_adapted.hpp | 2 +- .../parsers/elements/stage_1/parser_def.hpp | 3 +- src/core/parsers/elements/stage_2/parser.cpp | 383 +++++++++++++++++- src/core/vocabulary_info.cpp | 10 + 8 files changed, 393 insertions(+), 30 deletions(-) diff --git a/include/dlplan/core.h b/include/dlplan/core.h index d41fac79..8aec929d 100644 --- a/include/dlplan/core.h +++ b/include/dlplan/core.h @@ -595,6 +595,9 @@ class VocabularyInfo { const Predicate& add_predicate(const std::string &name, int arity, bool is_static=false); const Constant& add_constant(const std::string& name); + const std::unordered_map get_predicates_mapping() const; + const std::unordered_map get_constants_mapping() const; + const std::vector& get_predicates() const; const std::vector& get_constants() const; diff --git a/include/dlplan/core/parsers/elements/stage_1/ast.hpp b/include/dlplan/core/parsers/elements/stage_1/ast.hpp index 73b2be2f..c1675729 100644 --- a/include/dlplan/core/parsers/elements/stage_1/ast.hpp +++ b/include/dlplan/core/parsers/elements/stage_1/ast.hpp @@ -40,9 +40,6 @@ namespace dlplan::core::parsers::elements::stage_1::ast struct SumConceptDistanceNumerical; struct SumRoleDistanceNumerical; struct AndRole; - struct Arg1Role; - struct Arg2Role; - struct Arg3Role; struct ComposeRole; struct DiffRole; struct IdentityRole; @@ -171,7 +168,8 @@ namespace dlplan::core::parsers::elements::stage_1::ast }; struct InclusionBoolean : x3::position_tagged { - ConceptOrRole element; + ConceptOrRole element_left; + ConceptOrRole element_right; }; struct NullaryBoolean : x3::position_tagged { diff --git a/include/dlplan/core/parsers/elements/stage_2/parser.hpp b/include/dlplan/core/parsers/elements/stage_2/parser.hpp index ac55993e..3dbce7f3 100644 --- a/include/dlplan/core/parsers/elements/stage_2/parser.hpp +++ b/include/dlplan/core/parsers/elements/stage_2/parser.hpp @@ -12,22 +12,22 @@ namespace dlplan::core::parsers::elements::stage_2::parser { -extern std::shared_ptr parse_boolean( +extern std::shared_ptr parse( const stage_1::ast::Boolean& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory); -extern std::shared_ptr parse_numerical( +extern std::shared_ptr parse( const stage_1::ast::Numerical& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory); -extern std::shared_ptr parse_concept( +extern std::shared_ptr parse( const stage_1::ast::Concept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory); -extern std::shared_ptr parse_role( +extern std::shared_ptr parse( const stage_1::ast::Role& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory); diff --git a/src/core/element_factory.cpp b/src/core/element_factory.cpp index 615dba1d..e74aabfe 100644 --- a/src/core/element_factory.cpp +++ b/src/core/element_factory.cpp @@ -94,7 +94,7 @@ std::shared_ptr SyntacticElementFactoryImpl::parse_concept(Syntac } /* Stage 2 parse */ - auto feature = parsers::elements::stage_2::parser::parse_concept(ast, error_handler, parent); + auto feature = parsers::elements::stage_2::parser::parse(ast, error_handler, parent); return feature; } @@ -135,7 +135,7 @@ std::shared_ptr SyntacticElementFactoryImpl::parse_role(SyntacticEle } /* Stage 2 parse */ - auto feature = parsers::elements::stage_2::parser::parse_role(ast, error_handler, parent); + auto feature = parsers::elements::stage_2::parser::parse(ast, error_handler, parent); return feature; } @@ -176,7 +176,7 @@ std::shared_ptr SyntacticElementFactoryImpl::parse_boolean(Syntac } /* Stage 2 parse */ - auto feature = parsers::elements::stage_2::parser::parse_boolean(ast, error_handler, parent); + auto feature = parsers::elements::stage_2::parser::parse(ast, error_handler, parent); return feature; } @@ -217,7 +217,7 @@ std::shared_ptr SyntacticElementFactoryImpl::parse_numerical(Sy } /* Stage 2 parse */ - auto feature = parsers::elements::stage_2::parser::parse_numerical(ast, error_handler, parent); + auto feature = parsers::elements::stage_2::parser::parse(ast, error_handler, parent); return feature; } diff --git a/src/core/parsers/elements/stage_1/ast_adapted.hpp b/src/core/parsers/elements/stage_1/ast_adapted.hpp index cdbcaf12..f7b1de50 100644 --- a/src/core/parsers/elements/stage_1/ast_adapted.hpp +++ b/src/core/parsers/elements/stage_1/ast_adapted.hpp @@ -20,7 +20,7 @@ BOOST_FUSION_ADAPT_STRUCT(dlplan::core::parsers::elements::stage_1::ast::Role, r BOOST_FUSION_ADAPT_STRUCT(dlplan::core::parsers::elements::stage_1::ast::Element, element) BOOST_FUSION_ADAPT_STRUCT(dlplan::core::parsers::elements::stage_1::ast::ConceptOrRole, inner) BOOST_FUSION_ADAPT_STRUCT(dlplan::core::parsers::elements::stage_1::ast::EmptyBoolean, element) -BOOST_FUSION_ADAPT_STRUCT(dlplan::core::parsers::elements::stage_1::ast::InclusionBoolean, element) +BOOST_FUSION_ADAPT_STRUCT(dlplan::core::parsers::elements::stage_1::ast::InclusionBoolean, element_left, element_right) BOOST_FUSION_ADAPT_STRUCT(dlplan::core::parsers::elements::stage_1::ast::NullaryBoolean, predicate) BOOST_FUSION_ADAPT_STRUCT(dlplan::core::parsers::elements::stage_1::ast::AllConcept, role, concept_) BOOST_FUSION_ADAPT_STRUCT(dlplan::core::parsers::elements::stage_1::ast::AndConcept, concept_left, concept_right) diff --git a/src/core/parsers/elements/stage_1/parser_def.hpp b/src/core/parsers/elements/stage_1/parser_def.hpp index 1c60d2dc..e48f6298 100644 --- a/src/core/parsers/elements/stage_1/parser_def.hpp +++ b/src/core/parsers/elements/stage_1/parser_def.hpp @@ -239,7 +239,8 @@ namespace dlplan::core::parsers::elements::stage_1::parser const auto empty_boolean_def = lit("b_empty") > lit('(') > concept_or_role > lit(')'); - const auto inclusion_boolean_def = lit("b_inclusion") > lit('(') > concept_or_role > lit(')'); + // could change this to two_concept_or_two_role to produce more verbose error + const auto inclusion_boolean_def = lit("b_inclusion") > lit('(') > concept_or_role > lit(',') > concept_or_role > lit(')'); const auto nullary_boolean_def = lit("b_nullary") > lit('(') > predicate > lit(')'); diff --git a/src/core/parsers/elements/stage_2/parser.cpp b/src/core/parsers/elements/stage_2/parser.cpp index 88a18e33..da440c6b 100644 --- a/src/core/parsers/elements/stage_2/parser.cpp +++ b/src/core/parsers/elements/stage_2/parser.cpp @@ -5,32 +5,383 @@ namespace dlplan::core::parsers::elements::stage_2::parser { -std::shared_ptr parse_boolean( - const stage_1::ast::Boolean& node, - const error_handler_type& error_handler, - SyntacticElementFactory& element_factory) { +// forward declarations +static boost::variant, std::shared_ptr> +parse(const stage_1::ast::ConceptOrRole& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory); + + +static std::string +parse(const stage_1::ast::Name& node, const error_handler_type&, SyntacticElementFactory&) { + std::stringstream ss; + ss << node.alphabetical << node.suffix; + return ss.str(); +} + +static core::Constant +parse(const stage_1::ast::Constant& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + const auto name = parse(node.name, error_handler, element_factory); + const auto& constants_mapping = element_factory.get_vocabulary_info()->get_constants_mapping(); + auto it = constants_mapping.find(name); + if (it == constants_mapping.end()) { + error_handler(node, "undefined constant"); + } + return element_factory.get_vocabulary_info()->get_constant(name); +} + +static core::Predicate +parse(const stage_1::ast::Predicate& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + const auto name = parse(node.name, error_handler, element_factory); + const auto& predicates_mapping = element_factory.get_vocabulary_info()->get_predicates_mapping(); + auto it = predicates_mapping.find(name); + if (it == predicates_mapping.end()) { + error_handler(node, "undefined predicate"); + } + return element_factory.get_vocabulary_info()->get_predicate(name); +} + +static int +parse(const stage_1::ast::Position& node, const error_handler_type&, SyntacticElementFactory&) { + return node.value; +} + +class ConceptVisitor { +private: + const error_handler_type& error_handler; + SyntacticElementFactory& element_factory; + +public: + ConceptVisitor(const error_handler_type& error_handler, SyntacticElementFactory& element_factory) + : error_handler(error_handler), element_factory(element_factory) { } + + std::shared_ptr result; + + void operator()(const std::shared_ptr& concept) { + result = concept; + } + + void operator()(const std::shared_ptr&) { } +}; + +class RoleVisitor { +private: + const error_handler_type& error_handler; + SyntacticElementFactory& element_factory; + +public: + RoleVisitor(const error_handler_type& error_handler, SyntacticElementFactory& element_factory) + : error_handler(error_handler), element_factory(element_factory) { } + + std::shared_ptr result; + + void operator()(const std::shared_ptr&) { } + + void operator()(const std::shared_ptr& role) { + result = role; + } +}; + + +static std::shared_ptr +parse(const stage_1::ast::EmptyBoolean& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + auto concept_or_role = parse(node.element, error_handler, element_factory); + ConceptVisitor concept_visitor(error_handler, element_factory); + boost::apply_visitor(concept_visitor, concept_or_role); + if (concept_visitor.result != nullptr) return element_factory.make_empty_boolean(concept_visitor.result); + RoleVisitor role_visitor(error_handler, element_factory); + boost::apply_visitor(role_visitor, concept_or_role); + if (role_visitor.result != nullptr) return element_factory.make_empty_boolean(role_visitor.result); + error_handler(node, "expected two concepts or two roles"); + throw std::runtime_error("Failed parse"); +} + +static std::shared_ptr +parse(const stage_1::ast::InclusionBoolean& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + auto concept_or_role_left = parse(node.element_left, error_handler, element_factory); + auto concept_or_role_right = parse(node.element_right, error_handler, element_factory); + ConceptVisitor concept_visitor_left(error_handler, element_factory); + ConceptVisitor concept_visitor_right(error_handler, element_factory); + boost::apply_visitor(concept_visitor_left, concept_or_role_left); + boost::apply_visitor(concept_visitor_right, concept_or_role_right); + if (concept_visitor_left.result != nullptr && concept_visitor_right.result != nullptr) { + return element_factory.make_inclusion_boolean(concept_visitor_left.result, concept_visitor_right.result); + } + RoleVisitor role_visitor_left(error_handler, element_factory); + RoleVisitor role_visitor_right(error_handler, element_factory); + boost::apply_visitor(role_visitor_left, concept_or_role_left); + boost::apply_visitor(role_visitor_right, concept_or_role_right); + if (role_visitor_left.result != nullptr && role_visitor_right.result != nullptr) { + return element_factory.make_inclusion_boolean(role_visitor_left.result, role_visitor_right.result); + } + error_handler(node, "expected two concepts or two roles"); + throw std::runtime_error("Failed parse"); +} + +static std::shared_ptr +parse(const stage_1::ast::NullaryBoolean& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_nullary_boolean(parse(node.predicate, error_handler, element_factory)); +} + +static std::shared_ptr +parse(const stage_1::ast::AllConcept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_all_concept( + parse(node.role, error_handler, element_factory), + parse(node.concept_, error_handler, element_factory)); +} + +static std::shared_ptr +parse(const stage_1::ast::AndConcept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_and_concept( + parse(node.concept_left, error_handler, element_factory), + parse(node.concept_right, error_handler, element_factory)); +} + +static std::shared_ptr +parse(const stage_1::ast::BotConcept&, const error_handler_type&, SyntacticElementFactory& element_factory) { + return element_factory.make_bot_concept(); +} + +static std::shared_ptr +parse(const stage_1::ast::DiffConcept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_diff_concept( + parse(node.concept_left, error_handler, element_factory), + parse(node.concept_right, error_handler, element_factory)); +} + +static std::shared_ptr +parse(const stage_1::ast::EqualConcept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_equal_concept( + parse(node.role_left, error_handler, element_factory), + parse(node.role_right, error_handler, element_factory)); +} + +static std::shared_ptr +parse(const stage_1::ast::NotConcept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_not_concept( + parse(node.concept_, error_handler, element_factory)); +} + +static std::shared_ptr +parse(const stage_1::ast::OneOfConcept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_one_of_concept( + parse(node.constant, error_handler, element_factory)); +} + +static std::shared_ptr +parse(const stage_1::ast::OrConcept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_or_concept( + parse(node.concept_left, error_handler, element_factory), + parse(node.concept_right, error_handler, element_factory)); +} + +static std::shared_ptr +parse(const stage_1::ast::PrimitiveConcept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_primitive_concept( + parse(node.predicate, error_handler, element_factory), + parse(node.pos, error_handler, element_factory)); } -std::shared_ptr parse_numerical( - const stage_1::ast::Numerical& node, - const error_handler_type& error_handler, - SyntacticElementFactory& element_factory) { +static std::shared_ptr +parse(const stage_1::ast::ProjectionConcept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_projection_concept( + parse(node.role, error_handler, element_factory), + parse(node.pos, error_handler, element_factory)); +} + +static std::shared_ptr +parse(const stage_1::ast::SomeConcept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_some_concept( + parse(node.role, error_handler, element_factory), + parse(node.concept_, error_handler, element_factory)); +} + +static std::shared_ptr +parse(const stage_1::ast::SubsetConcept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return element_factory.make_subset_concept( + parse(node.role_left, error_handler, element_factory), + parse(node.role_right, error_handler, element_factory)); +} + +static std::shared_ptr +parse(const stage_1::ast::TopConcept&, const error_handler_type&, SyntacticElementFactory& element_factory) { + return element_factory.make_top_concept(); +} + +struct ConceptDistanceNumerical; + +static std::shared_ptr +parse(const stage_1::ast::CountNumerical& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + auto concept_or_role = parse(node.element, error_handler, element_factory); + ConceptVisitor concept_visitor(error_handler, element_factory); + boost::apply_visitor(concept_visitor, concept_or_role); + if (concept_visitor.result != nullptr) return element_factory.make_count_numerical(concept_visitor.result); + RoleVisitor role_visitor(error_handler, element_factory); + boost::apply_visitor(role_visitor, concept_or_role); + if (role_visitor.result != nullptr) return element_factory.make_count_numerical(role_visitor.result); + error_handler(node, "expected two concepts or two roles"); + throw std::runtime_error("Failed parse"); +} + +struct RoleDistanceNumerical; +struct SumConceptDistanceNumerical; +struct SumRoleDistanceNumerical; +struct AndRole; +struct ComposeRole; +struct DiffRole; +struct IdentityRole; +struct InverseRole; +struct NotRole; +struct OrRole; +struct PrimitiveRole; +struct RestrictRole; +struct TopRole; +struct TransitiveClosureRole; +struct TransitiveReflexiveClosureRole; + + +class ConceptInnerVisitor { +private: + const error_handler_type& error_handler; + SyntacticElementFactory& element_factory; + +public: + ConceptInnerVisitor( + const error_handler_type& error_handler, SyntacticElementFactory& element_factory) + : error_handler(error_handler), element_factory(element_factory) { } + + std::shared_ptr result; + + template + void operator()(const Node& node) { + result = parse(node, error_handler, element_factory); + } +}; + +static std::shared_ptr +parse(const stage_1::ast::ConceptInner& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + ConceptInnerVisitor visitor(error_handler, element_factory); + boost::apply_visitor(visitor, node); + return visitor.result; } -std::shared_ptr parse_concept( - const stage_1::ast::Concept& node, - const error_handler_type& error_handler, - SyntacticElementFactory& element_factory) { +class RoleInnerVisitor { +private: + const error_handler_type& error_handler; + SyntacticElementFactory& element_factory; +public: + RoleInnerVisitor( + const error_handler_type& error_handler, SyntacticElementFactory& element_factory) + : error_handler(error_handler), element_factory(element_factory) { } + + std::shared_ptr result; + + template + void operator()(const Node& node) { + result = parse(node, error_handler, element_factory); + } +}; + +static std::shared_ptr +parse(const stage_1::ast::RoleInner& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + RoleInnerVisitor visitor(error_handler, element_factory); + boost::apply_visitor(visitor, node); + return visitor.result; } -std::shared_ptr parse_role( - const stage_1::ast::Role& node, - const error_handler_type& error_handler, - SyntacticElementFactory& element_factory) { +class BooleanInnerVisitor { +private: + const error_handler_type& error_handler; + SyntacticElementFactory& element_factory; + +public: + BooleanInnerVisitor( + const error_handler_type& error_handler, SyntacticElementFactory& element_factory) + : error_handler(error_handler), element_factory(element_factory) { } + + std::shared_ptr result; + + template + void operator()(const Node& node) { + result = parse(node, error_handler, element_factory); + } +}; + +static std::shared_ptr +parse(const stage_1::ast::BooleanInner& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + BooleanInnerVisitor visitor(error_handler, element_factory); + boost::apply_visitor(visitor, node); + return visitor.result; +} + +class NumericalInnerVisitor { +private: + const error_handler_type& error_handler; + SyntacticElementFactory& element_factory; + +public: + NumericalInnerVisitor( + const error_handler_type& error_handler, SyntacticElementFactory& element_factory) + : error_handler(error_handler), element_factory(element_factory) { } + + std::shared_ptr result; + + template + void operator()(const Node& node) { + result = parse(node, error_handler, element_factory); + } +}; + +static std::shared_ptr +parse(const stage_1::ast::NumericalInner& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + NumericalInnerVisitor visitor(error_handler, element_factory); + boost::apply_visitor(visitor, node); + return visitor.result; +} + +class ConceptOrRoleInnerVisitor { +private: + const error_handler_type& error_handler; + SyntacticElementFactory& element_factory; + +public: + ConceptOrRoleInnerVisitor(const error_handler_type& error_handler, SyntacticElementFactory& element_factory) + : error_handler(error_handler), element_factory(element_factory) { } + + boost::variant, std::shared_ptr> result; + + template + void operator()(const Node& node) { + result = parse(node, error_handler, element_factory); + } +}; + +static boost::variant, std::shared_ptr> +parse(const stage_1::ast::ConceptOrRole& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + ConceptOrRoleInnerVisitor visitor(error_handler, element_factory); + boost::apply_visitor(visitor, node.inner); + return visitor.result; +} + +std::shared_ptr +parse(const stage_1::ast::Concept& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return parse(node.concept, error_handler, element_factory); +} + +std::shared_ptr +parse(const stage_1::ast::Role& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return parse(node.role, error_handler, element_factory); +} + +std::shared_ptr +parse(const stage_1::ast::Boolean& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return parse(node.boolean, error_handler, element_factory); +} +std::shared_ptr +parse(const stage_1::ast::Numerical& node, const error_handler_type& error_handler, SyntacticElementFactory& element_factory) { + return parse(node.numerical, error_handler, element_factory); } } \ No newline at end of file diff --git a/src/core/vocabulary_info.cpp b/src/core/vocabulary_info.cpp index 7dc7b6a8..62905730 100644 --- a/src/core/vocabulary_info.cpp +++ b/src/core/vocabulary_info.cpp @@ -46,6 +46,16 @@ const Constant& VocabularyInfo::add_constant(const std::string& constant_name) { return m_constants.back(); } +const std::unordered_map +VocabularyInfo::get_predicates_mapping() const { + return m_predicate_name_to_index; +} + +const std::unordered_map +VocabularyInfo::get_constants_mapping() const { + return m_constant_name_to_index; +} + const std::vector& VocabularyInfo::get_predicates() const { return m_predicates; }