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
34namespace px = boost::phoenix;
35namespace qr = boost::spirit::repository::qi;
36
37namespace pddl_parser {
38namespace grammar {
39/** @class pddl_skipper
40 * A skipper for PDDL files.
41 * This skipper skips spaces and comments starting with ';'
42 */
43template <typename Iterator>
44struct 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 */
57template <typename Iterator, typename Skipper = pddl_skipper<Iterator>>
58struct 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
179private:
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 */
281template <typename Iterator, typename Skipper = pddl_skipper<Iterator>>
282struct 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
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
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, 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, std::vector< Expression >(), Skipper > init
Named placeholder for parsing the initial state.
Definition: pddl_grammar.h:337
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