Fawkes API  Fawkes Development Version
pddl_grammar.h
1 
2 /***************************************************************************
3  * grammar.h
4  *
5  * Created: Fri 19 May 2017 14:07:29 CEST
6  * Copyright 2017 Matthias Loebach
7  * Till Hofmann
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #ifndef PLUGINS_PDDL_GRAMMAR_H_
24 #define PLUGINS_PDDL_GRAMMAR_H_
25 
26 #include "pddl_ast.h"
27 #include "pddl_semantics.h"
28 
29 #include <boost/spirit/include/phoenix.hpp>
30 #include <boost/spirit/include/qi.hpp>
31 #include <boost/spirit/include/qi_expect.hpp>
32 #include <boost/spirit/repository/include/qi_iter_pos.hpp>
33 
34 namespace px = boost::phoenix;
35 namespace qr = boost::spirit::repository::qi;
36 
37 namespace pddl_parser {
38 namespace grammar {
39 /** @class pddl_skipper
40  * A skipper for PDDL files.
41  * This skipper skips spaces and comments starting with ';'
42  */
43 template <typename Iterator>
44 struct pddl_skipper : public qi::grammar<Iterator>
45 {
46  pddl_skipper() : pddl_skipper::base_type(skip, "PDDL")
47  {
48  skip = ascii::space | (';' >> *(qi::char_ - qi::eol));
49  }
50  /** The actual skipping rule. */
51  qi::rule<Iterator> skip;
52 };
53 
54 /** @class domain_parser
55  * A Boost QI parser for a PDDL domain.
56  */
57 template <typename Iterator, typename Skipper = pddl_skipper<Iterator>>
58 struct domain_parser : qi::grammar<Iterator, Domain(), Skipper>
59 {
60  domain_parser() : domain_parser::base_type(domain)
61  {
62  using namespace qi;
63  using ascii::alnum;
64  using ascii::blank;
65  using ascii::char_;
66 
67  name_type = lexeme[alnum > *(alnum | char_('-') | char_('_'))];
68 
69  domain_name = lit("define") > '(' > lit("domain") > +(char_ - ')') > ')';
70 
71  requirements = '(' > lit(":requirements") > *(':' > name_type) > ')';
72 
73  // _r1: domain, _r2: parent list of pairs _val is parsed into
74  type_pair =
75  (qr::iter_pos
76  >> qi::as<pair_strings_type>()[+name_type
77  > -('-' >> (qi::as<std::vector<std::string>>()[name_type]
78  | ('(' > lit("either") > *name_type > ')')))])
79  [_val = type_semantics_(qi::_1, param_transformer_(qi::_1, qi::_2, qi::_r2), qi::_r1)];
80  // _r1: domain
81  types = '(' >> lit(":types") > +type_pair(qi::_r1, qi::_val) > ')';
82 
83  constant_value_list = +name_type;
84  // _r1: parent list of pairs _val is parsed into
85  constant_multi_pair =
86  (qr::iter_pos >> qi::as<pair_multi_const>()[(constant_value_list > -('-' > name_type))])
87  [_val =
88  constant_semantics_(qi::_1, qi::_2, qi::_r1, px::bind(&domain_parser::warnings, this))];
89  // _r1: domain
90  constants = '(' >> lit(":constants") > +constant_multi_pair(qi::_r1) > ')';
91 
92  // _r1: parent list of pairs _val is parsed into
93  param_pair =
94  (qr::iter_pos
95  >> qi::as<pair_strings_type>()[+('?' > name_type)
96  > -('-' >> (qi::as<std::vector<std::string>>()[name_type]
97  | ('(' > lit("either") > *name_type > ')')))])
98  [_val = param_transformer_(qi::_1, qi::_2, qi::_r1)];
99  param_pairs = +param_pair(qi::_val);
100  pred = '(' > name_type > -param_pairs > ')';
101  predicates = '(' > lit(":predicates") > +pred > ')';
102 
103  function = '(' >> name_type > -param_pairs > ')' >> -("-" > lit("number"));
104  functions = '(' >> lit(":functions") > *function > ')';
105 
106  atom = +(graph - '(' - ')');
107  bool_op = qi::string("and") | qi::string("or") | qi::string("not");
108  comparison_op =
109  qi::string("<") | qi::string(">") | qi::string("=") | qi::string("<=") | qi::string(">=");
110  numerical_op = qi::string("+") | qi::string("-") | qi::string("/") | qi::string("*")
111  | qi::string("=") | string("increase") | string("decrease");
112 
113  // no expectation parsing to allow proper backtracking
114  value_expression = attr(ExpressionType::VALUE) >> qi::as_string[qi::raw[qi::float_]];
115  numeric_expression =
116  attr(ExpressionType::NUMERIC)
117  >> qi::as<Predicate>()[atom >> *(hold[attr(ExpressionType::ATOM) >> atom])];
118  pred_expression = attr(ExpressionType::PREDICATE)
119  >> qi::as<Predicate>()[atom >> *(hold[attr(ExpressionType::ATOM) >> atom])];
120  bool_expression = attr(ExpressionType::BOOL) >> qi::as<Predicate>()[(bool_op >> +expression)];
121  quantified_expression =
122  attr(ExpressionType::QUANTIFIED)
123  >> qi::as<QuantifiedFormula>()[(qi::string("exists") | qi::string("forall")) > '('
124  > param_pairs > ')' > expression];
125  cond_effect_expression = attr(ExpressionType::COND_EFFECT)
126  >> qi::as<Predicate>()[qi::string("when") > expression > expression];
127  durative_expression = attr(ExpressionType::DURATIVE)
128  >> qi::as<Predicate>()[(qi::string("at start") | qi::string("at end")
129  | qi::string("over all"))
130  > expression];
131  unknown_expression =
132  attr(ExpressionType::UNKNOWN) >> atom >> *(hold[attr(ExpressionType::ATOM) >> atom]);
133  function_expression = attr(ExpressionType::NUMERIC_COMP)
134  >> qi::as<Predicate>()[qi::as<Atom>()[comparison_op]
135  > (hold[expression >> value_expression]
136  | hold[value_expression >> expression]
137  | hold[expression >> expression]
138  | +(hold[attr(ExpressionType::ATOM) >> atom]))];
139  function_change_expression =
140  attr(ExpressionType::NUMERIC_CHANGE)
141  >> qi::as<Predicate>()[numerical_op > (hold[expression >> value_expression]
142  | hold[value_expression >> expression]
143  | hold[expression >> expression])];
144 
145  // hold to backtrack the ExpressionType
146  expression =
147  '('
148  >> hold[(hold[bool_expression] | hold[function_expression] | hold[function_change_expression]
149  | hold[durative_expression] | hold[quantified_expression]
150  | hold[cond_effect_expression] | hold[pred_expression] | hold[unknown_expression])]
151  >> ')';
152  temp_breakup = lit(":temporal-breakup") > expression;
153  cond_breakup = lit(":conditional-breakup") > expression;
154  effects = lit(":effect") > expression;
155  preconditions = (lit(":precondition") | lit(":condition")) > expression;
156  duration = lit(":duration") > '(' > '=' > lit("?duration")
157  > (value_expression
158  | ('(' > (hold[function_change_expression] | hold[pred_expression]) > ')'))
159  > ')';
160  action_params = lit(":parameters") > '(' > *param_pair(qi::_val) > ')';
161 
162  // validate action semantics after parsing
163  // _r1: domain
164  action =
165  ('(' >> qr::iter_pos
166  >> qi::as<Action>()[(lit(":durative-action") | lit(":action")) > name_type > action_params
167  > -duration > preconditions > effects > -cond_breakup > -temp_breakup
168  > ')'])[_val = action_semantics_(qi::_1, qi::_2, qi::_r1)];
169  // pass down the domain for semantics check
170  // _r1: domain
171  actions = +(action(qi::_r1));
172 
173  domain = '(' > domain_name > requirements > -types(qi::_val) > -constants(qi::_val) > predicates
174  > -functions > actions(qi::_val) // pass down the domain for semantic check
175  // make closing parenthesis optional to stay backwards compatible
176  > -lit(")");
177  }
178 
179 private:
180  /** Semantic checks for each parsed type. */
181  px::function<pddl_parser::TypeSemantics> type_semantics_;
182  /** Transforms pair<vector<string>,vector<string>> to separate pair<string,string> entries in the parent vector */
183  px::function<pddl_parser::ParamTransformer> param_transformer_;
184  /** Semantic checks for each parsed action. */
185  px::function<pddl_parser::ActionSemantics> action_semantics_;
186  /** Semantic checks for each parsed constants. */
187  px::function<pddl_parser::ConstantSemantics> constant_semantics_;
188  std::vector<std::string> warnings;
189  /** Named placeholder for parsing a name. */
190  qi::rule<Iterator, std::string(), Skipper> name_type;
191 
192  /** Named placeholder for parsing a domain name. */
193  qi::rule<Iterator, std::string(), Skipper> domain_name;
194 
195  /** Named placeholder for parsing requirements. */
196  qi::rule<Iterator, std::vector<std::string>(), Skipper> requirements;
197 
198  /** Named placeholder for parsing types. Pass the domain for semantic checks. */
199  qi::rule<Iterator, pairs_type(const Domain &), Skipper> types;
200  /** Named placeholder for parsing type pairs. Pass the domain for semantic checks. */
201  qi::rule<Iterator, pair_type(const Domain &, string_pairs_type &), Skipper> type_pair;
202 
203  /** Named placeholder for parsing a list of constant values. */
204  qi::rule<Iterator, type_list(), Skipper> constant_value_list;
205  /** Named placeholder for parsing a list of predicate parameters. */
206  qi::rule<Iterator, type_list(), Skipper> predicate_params;
207  /** Named placeholder for parsing a list of typed constants. Pass the domain for semantic checks. */
208  qi::rule<Iterator, pair_multi_const(const Domain &), Skipper> constant_multi_pair;
209  /** Named placeholder for parsing a list of constants. Pass the domain for semantic checks. */
210  qi::rule<Iterator, pairs_multi_consts(const Domain &), Skipper> constants;
211 
212  /** Named placeholder for parsing a parameter pair. */
213  qi::rule<Iterator, string_pair_type(string_pairs_type &), Skipper> param_pair;
214  /** Named placeholder for parsing a list of parameter pairs. */
215  qi::rule<Iterator, string_pairs_type(), Skipper> param_pairs;
216  /** Named placeholder for parsing a predicate type. */
217  qi::rule<Iterator, predicate_type(), Skipper> pred;
218  /** Named placeholder for parsing a list of predicate types. */
219  qi::rule<Iterator, std::vector<predicate_type>(), Skipper> predicates;
220 
221  /** Named placeholder for parsing any atom. */
222  qi::rule<Iterator, Atom()> atom;
223  /** Named placeholder for parsing an atom that is a logical operator. */
224  qi::rule<Iterator, Atom()> bool_op;
225  /** Named placeholder for parsing an atom that is a comparison operator. */
226  qi::rule<Iterator, Atom()> comparison_op;
227  /** Named placeholder for parsing an atom that is a numerical operator. */
228  qi::rule<Iterator, Atom()> numerical_op;
229  /** Named placeholder for parsing a predicate. */
230  qi::rule<Iterator, Predicate(), Skipper> predicate;
231  /** Named placeholder for parsing a PDDL predicate expression. */
232  qi::rule<Iterator, Expression(), Skipper> pred_expression;
233  /** Named placeholder for parsing a PDDL value expression. */
234  qi::rule<Iterator, Expression(), Skipper> value_expression;
235  /** Named placeholder for parsing a PDDL numeric expression. */
236  qi::rule<Iterator, Expression(), Skipper> numeric_expression;
237  /** Named placeholder for parsing a PDDL function expression. */
238  qi::rule<Iterator, Expression(), Skipper> function_expression;
239  /** Named placeholder for parsing a PDDL function changing expression. */
240  qi::rule<Iterator, Expression(), Skipper> function_change_expression;
241  /** Named placeholder for parsing a PDDL bool expression. */
242  qi::rule<Iterator, Expression(), Skipper> bool_expression;
243  /** Named placeholder for parsing a PDDL durative expression. */
244  qi::rule<Iterator, Expression(), Skipper> durative_expression;
245  /** Named placeholder for parsing a PDDL quantified expression. */
246  qi::rule<Iterator, Expression(), Skipper> quantified_expression;
247  /** Named placeholder for parsing a PDDL conditional effect expression. */
248  qi::rule<Iterator, Expression(), Skipper> cond_effect_expression;
249  /** Named placeholder for parsing an arbitrary PDDL expression, where no semantic checks can be performed. */
250  qi::rule<Iterator, Expression(), Skipper> unknown_expression;
251  /** Named placeholder for parsing a PDDL expression. */
252  qi::rule<Iterator, Expression(), Skipper> expression;
253  /** Named placeholder for parsing a PDDL precondition. */
254  qi::rule<Iterator, Expression(), Skipper> preconditions;
255  /** Named placeholder for parsing a PDDL effect. */
256  qi::rule<Iterator, Expression(), Skipper> effects;
257  /** Named placeholder for parsing a temporal breakup. */
258  qi::rule<Iterator, Expression(), Skipper> temp_breakup;
259  /** Named placeholder for parsing a conditional breakup. */
260  qi::rule<Iterator, Expression(), Skipper> cond_breakup;
261  /** Named placeholder for parsing an action duration. */
262  qi::rule<Iterator, Expression(), Skipper> duration;
263  /** Named placeholder for parsing action parameters. */
264  qi::rule<Iterator, string_pairs_type(), Skipper> action_params;
265  /** Named placeholder for parsing an action. Inherits a domain. */
266  qi::rule<Iterator, Action(const Domain &), Skipper> action;
267  /** Named placeholder for parsing a function type. */
268  qi::rule<Iterator, Function(), Skipper> function;
269  /** Named placeholder for parsing a list of functions. */
270  qi::rule<Iterator, std::vector<Function>(), Skipper> functions;
271  /** Named placeholder for parsing a list of actions. */
272  qi::rule<Iterator, std::vector<Action>(const Domain &), Skipper> actions;
273 
274  /** Named placeholder for parsing a domain. */
275  qi::rule<Iterator, Domain(), Skipper> domain;
276 };
277 
278 /** @class problem_parser
279  * A Boost QI parser for a PDDL problem.
280  */
281 template <typename Iterator, typename Skipper = pddl_skipper<Iterator>>
282 struct problem_parser : qi::grammar<Iterator, Problem(), Skipper>
283 {
284  problem_parser() : problem_parser::base_type(problem)
285  {
286  using namespace qi;
287  using ascii::alnum;
288  using ascii::blank;
289  using ascii::char_;
290 
291  name_type = lexeme[alnum > *(alnum | char_('-') | char_('_'))];
292 
293  problem_name = '(' > lit("define") > '(' > lit("problem") > name_type > ')';
294 
295  domain_name = '(' > lit(":domain") > name_type > ')';
296 
297  constant_value_list = +name_type;
298  constant_multi_pair = constant_value_list > -('-' > name_type);
299  objects = '(' > lit(":objects") > +constant_multi_pair > ')';
300 
301  atom = +(graph - '(' - ')');
302  predicate = '(' > atom > *expression > ')';
303  expression = attr(ExpressionType::PREDICATE) > predicate;
304  init = '(' > lit(":init") > +expression > ')';
305 
306  goal = '(' > lit(":goal") > expression > ')';
307 
308  problem = problem_name > domain_name > objects > init > goal;
309  }
310 
311  /** Named placeholder for parsing a name. */
312  qi::rule<Iterator, std::string(), Skipper> name_type;
313 
314  /** Named placeholder for parsing a problem name. */
315  qi::rule<Iterator, std::string(), Skipper> problem_name;
316  /** Named placeholder for parsing a domain name. */
317  qi::rule<Iterator, std::string(), Skipper> domain_name;
318 
319  /** Named placeholder for parsing a list of constant values. */
320  qi::rule<Iterator, type_list(), Skipper> constant_value_list;
321  /** Named placeholder for parsing a list of predicate parameters. */
322  qi::rule<Iterator, type_list(), Skipper> predicate_params;
323  /** Named placeholder for parsing a list of typed constants. */
324  qi::rule<Iterator, pair_multi_const(), Skipper> constant_multi_pair;
325  /** Named placeholder for parsing a list of domain objects. */
326  qi::rule<Iterator, pairs_multi_consts(), Skipper> objects;
327 
328  /** Named placeholder for parsing an atom. */
329  qi::rule<Iterator, Atom()> atom;
330  /** Named placeholder for parsing a predicate. */
331  qi::rule<Iterator, Predicate(), Skipper> predicate;
332  /** Named placeholder for parsing a PDDL expression. */
333  qi::rule<Iterator, Expression(), Skipper> expression;
334  /** Named placeholder for parsing a PDDL goal. */
335  qi::rule<Iterator, Expression(), Skipper> goal;
336  /** Named placeholder for parsing the initial state. */
337  qi::rule<Iterator, std::vector<Expression>(), Skipper> init;
338 
339  /** Named placeholder for parsing a PDDL problem. */
340  qi::rule<Iterator, Problem(), Skipper> problem;
341 };
342 
343 } // namespace grammar
344 } // namespace pddl_parser
345 
346 #endif
A structured representation of a PDDL action.
Definition: pddl_ast.h:133
A structured representation of a PDDL domain.
Definition: pddl_ast.h:157
A PDDL Expression.
Definition: pddl_ast.h:78
A structured representation of a PDDL function.
Definition: pddl_ast.h:122
A PDDL formula (either part of a precondition or an effect(.
Definition: pddl_ast.h:107
A structured representation of a PDDL problem.
Definition: pddl_ast.h:180
A Boost QI parser for a PDDL domain.
Definition: pddl_grammar.h:59
A skipper for PDDL files.
Definition: pddl_grammar.h:45
qi::rule< Iterator > skip
The actual skipping rule.
Definition: pddl_grammar.h:51
A Boost QI parser for a PDDL problem.
Definition: pddl_grammar.h:283
qi::rule< Iterator, std::vector< Expression >), Skipper > init
Named placeholder for parsing the initial state.
Definition: pddl_grammar.h:337
qi::rule< Iterator, type_list(), Skipper > constant_value_list
Named placeholder for parsing a list of constant values.
Definition: pddl_grammar.h:320
qi::rule< Iterator, std::string(), Skipper > name_type
Named placeholder for parsing a name.
Definition: pddl_grammar.h:312
qi::rule< Iterator, std::string(), Skipper > domain_name
Named placeholder for parsing a domain name.
Definition: pddl_grammar.h:317
qi::rule< Iterator, Problem(), Skipper > problem
Named placeholder for parsing a PDDL problem.
Definition: pddl_grammar.h:340
qi::rule< Iterator, Expression(), Skipper > goal
Named placeholder for parsing a PDDL goal.
Definition: pddl_grammar.h:335
qi::rule< Iterator, std::string(), Skipper > problem_name
Named placeholder for parsing a problem name.
Definition: pddl_grammar.h:315
qi::rule< Iterator, Expression(), Skipper > expression
Named placeholder for parsing a PDDL expression.
Definition: pddl_grammar.h:333
qi::rule< Iterator, Predicate(), Skipper > predicate
Named placeholder for parsing a predicate.
Definition: pddl_grammar.h:331
qi::rule< Iterator, pair_multi_const(), Skipper > constant_multi_pair
Named placeholder for parsing a list of typed constants.
Definition: pddl_grammar.h:324
qi::rule< Iterator, Atom()> atom
Named placeholder for parsing an atom.
Definition: pddl_grammar.h:329
qi::rule< Iterator, pairs_multi_consts(), Skipper > objects
Named placeholder for parsing a list of domain objects.
Definition: pddl_grammar.h:326
qi::rule< Iterator, type_list(), Skipper > predicate_params
Named placeholder for parsing a list of predicate parameters.
Definition: pddl_grammar.h:322