Parsing preconditions and recursion with Boost::Spirit

Viewed 242

I am trying to parse a PDDL file with Boost::Spirit and have some trouble with parsing preconditions into a struct. I am struggling to understand the Boost manual on how to get the condition into my struct and with recursion.

I give a snippet of the code below, that should illustrate the problem well. A string that looks like this has to be parsed:

:precondition
(and
  (at-pos ?r ?pos)
  (not (has-pos ?m ?pos))
)

My code so far looks like this, but I am almost sure I did not understand how at_c works having no experience with Boost::Phoenix yet.

predi_param = '?' >> name_type;
predi = '(' 
    >> name_type
    >> +predi_param
    >> ')';
literal = ( 
    ( '(' >> lit("not") >>
      predi       [at_c<0>(_val) = false]
      >> ')'
    )
    | predi       [at_c<0>(_val) = true]
  )
  >> ')';
pred_list = ( '(' >> lit("and") >> (*pred_list) >> ')')
  | literal;
preconditions = lit(":precondition") >> pred_list;

qi::rule<Iterator, std::string(), ascii::space_type> predi_param;
qi::rule<Iterator, Predicate(), ascii::space_type> predi;
qi::rule<Iterator, Literal(), ascii::space_type> literal;
qi::rule<Iterator, std::vector<Literal>(), ascii::space_type> preconditions, pred_list;

My AST looks like this:

struct Predicate
{
  std::string name;
  std::vector<std::string> predicate_params;
};  
struct Literal
{
  bool condition;
  Predicate predicate;
};

BOOST_FUSION_ADAPT_STRUCT(
    pddl_parser::Literal,
    (bool, condition)
    (pddl_parser::Predicate, predicate)
)

BOOST_FUSION_ADAPT_STRUCT(
    pddl_parser::Predicate,
    (std::string, name)
    (std::vector<std::string>, predicate_params)
)

Compiling this results in a compilation error:

parser.cpp:67:17:   required from ‘pddl_parser::domain_parser<Iterator>::domain_parser() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >]’
parser.cpp:136:10:   required from here
/usr/include/boost/spirit/home/qi/detail/assign_to.hpp:153:20: error: no matching function for call to ‘pddl_parser::Literal::Literal(const std::vector<pddl_parser::Literal>&)’
             attr = static_cast<Attribute>(val);
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from parser.cpp:11:0:
./pddlast.h:23:10: note: candidate: pddl_parser::Literal::Literal()
   struct Literal
          ^~~~~~~
./pddlast.h:23:10: note:   candidate expects 0 arguments, 1 provided
./pddlast.h:23:10: note: candidate: pddl_parser::Literal::Literal(const pddl_parser::Literal&)
./pddlast.h:23:10: note:   no known conversion for argument 1 from ‘const std::vector<pddl_parser::Literal>’ to ‘const pddl_parser::Literal&’
./pddlast.h:23:10: note: candidate: pddl_parser::Literal::Literal(pddl_parser::Literal&&)
./pddlast.h:23:10: note:   no known conversion for argument 1 from ‘const std::vector<pddl_parser::Literal>’ to ‘pddl_parser::Literal&&’

If I reformat the pred_list for test purposes into pred_list = ( '(' >> *literal) >> ')'); the code compiles but still yields no success, although I take the (and ) out. I have the impression I have something totally wrong, but cannot find anything. This is my first try using Boost::Spirit.

1 Answers
Related