331 Commits

Author SHA1 Message Date
4a2882711d Version bump for release 3.0.2 RC 1. 2016-08-14 17:36:59 +02:00
08113c961a Continuously incrementing effect IDs, with a special identifier for unconditional effects. 2016-08-14 17:21:41 +02:00
e2da46e20a Updated change log with documentation of output format. 2016-08-14 16:37:31 +02:00
0cf44da917 Minor formatting. 2016-08-14 16:35:38 +02:00
d03638919a Added more detail to the command-line interface documentation. 2016-08-14 16:34:39 +02:00
f5d342a442 Minor formatting. 2016-08-14 16:33:11 +02:00
06cab2f098 Put command-line interface documentation in a separate documentation file. 2016-08-14 16:31:23 +02:00
9d67ae800d Put building instructions in a separate documentation file. 2016-08-14 16:27:43 +02:00
d2a1030320 Added link to output format to the readme file. 2016-08-14 16:23:28 +02:00
5c17d23606 Added list of supported feature requirements. 2016-08-14 16:15:43 +02:00
bc1759aedf Minor formatting. 2016-08-14 16:09:36 +02:00
b9aef10db3 Documented axiom rules. 2016-08-14 16:07:45 +02:00
bdb6ac9fba Changed output format of axiom rules. 2016-08-14 16:02:28 +02:00
4d5f935e82 Minor formatting. 2016-08-14 16:01:39 +02:00
d604e44dff Documented mutex groups. 2016-08-14 16:00:31 +02:00
2c37da4cb4 Clarification about variables’ value uniqueness. 2016-08-14 16:00:09 +02:00
741078c4fd Minor formatting. 2016-08-14 15:50:49 +02:00
e101cf2aab Documented action costs. 2016-08-14 15:49:34 +02:00
3dfae74468 Documented goal. 2016-08-14 15:47:49 +02:00
2363f42bc9 Minor clarification in the documentation concerning action sequences. 2016-08-14 15:46:12 +02:00
491454ca3c Extended introduction to the documentation. 2016-08-14 15:44:14 +02:00
562b2296e5 Documented initial state. 2016-08-14 15:39:25 +02:00
3535afb1e1 Minor clarification concerning constants and objects. 2016-08-14 15:31:23 +02:00
7a63e4abb9 Documented constants and objects. 2016-08-14 15:29:27 +02:00
2281cd1cd4 Documented actions. 2016-08-14 15:14:27 +02:00
4037b339e4 Changed keyword for conditions of conditional effects. 2016-08-14 15:14:13 +02:00
00c3140f3b Restructured output format documentation once more and documented variables. 2016-08-14 14:58:04 +02:00
0fb282d153 Changed output format of feature requirements. 2016-08-14 14:55:46 +02:00
7a73f99581 Updated change log with recent fixes in SAS output formatting. 2016-08-13 19:14:04 +02:00
bdd68f04e1 Minor cleanup in documentation. 2016-08-13 19:02:05 +02:00
a5a300b150 Documented constants and objects. 2016-08-13 18:59:11 +02:00
197cec923e Added introductory example to output format documentation. 2016-08-13 18:47:01 +02:00
c391a1f566 Removed unwanted newline in SAS output. 2016-08-13 18:44:18 +02:00
1727113a8b Documented types. 2016-08-13 18:07:17 +02:00
18ac959970 Restructured documentation of feature requirements and added an example. 2016-08-13 17:52:27 +02:00
d00c5bb753 Minor rephrasing in documentation. 2016-08-13 17:42:02 +02:00
ffcf07b935 Documented feature requirements. 2016-08-13 17:39:39 +02:00
042531abc3 Started documenting the unified output format. 2016-08-13 13:35:30 +02:00
4fc7355fba Removed unwanted newline. 2016-08-13 13:21:00 +02:00
c12be088c6 Updated change log with unified output format. 2016-08-13 11:12:38 +02:00
9c3cfe8f7b Dropped »meta« prefix of encoding file because there will only be meta encodings. 2016-08-13 11:10:29 +02:00
d4c168af30 Unified SAS and PDDL meta encodings. 2016-08-13 11:09:35 +02:00
f2d3aee662 Updated PDDL meta encoding to recent changes of output format. 2016-08-13 11:09:35 +02:00
340db244f6 Fixed bug in output format. 2016-08-13 04:04:28 +02:00
8969364f73 Fixed syntax error in output format. 2016-08-13 03:27:37 +02:00
b67168134b Made initial state definition consistent with unified output format. 2016-08-13 03:22:25 +02:00
97d33da686 Added effect ID as a placeholder (for conditional effects) for consistency with unified output format. 2016-08-13 03:17:48 +02:00
1f35bda3d2 Wrapped translated PDDL action definitions for usability in meta encodings. 2016-08-13 03:11:38 +02:00
6960e8a8c7 Wrapped translated PDDL constant definitions for usability in meta encodings. 2016-08-13 03:09:14 +02:00
b30cecd297 Turning translated PDDL predicates into unified variable format in rest of output format. 2016-08-13 03:08:05 +02:00
99fc6988a3 Renamed heading to »variables«. 2016-08-13 02:50:07 +02:00
cf022f9959 Started turning translated PDDL predicates into unified variable format. 2016-08-13 02:48:30 +02:00
0a1044743e Renamed meta predicate for simplicity. 2016-08-13 02:33:28 +02:00
94b204615b Wrapped translated PDDL type definitions for usability in meta encodings. 2016-08-13 02:32:27 +02:00
230c6dfc15 Made order of sections of translated SAS more uniform with PDDL. 2016-08-13 02:29:48 +02:00
8be67e7065 Updated SAS meta encoding to recent changes of output format. 2016-08-13 01:49:00 +02:00
378b2ae673 Wrapped translated SAS axiom rule definitions for usability in meta encodings. 2016-08-13 01:44:45 +02:00
36e517bd80 Wrapped translated SAS mutex group definitions for usability in meta encodings. 2016-08-13 01:42:18 +02:00
569b3d0c97 Wrapped translated SAS action definitions for usability in meta encodings. 2016-08-13 01:40:31 +02:00
daf68d24ab Added highlighting of variable names. 2016-08-13 01:39:49 +02:00
8a82f52100 Wrapped translated SAS variable definitions for usability in meta encodings. 2016-08-13 01:36:08 +02:00
d0864b9efe Extended parser tests. 2016-08-08 12:40:02 +02:00
18bd606262 Extended parser tests. 2016-08-07 16:46:48 +02:00
252f50108b Removed unnecessary file. 2016-08-07 16:22:26 +02:00
015c34fc2b Minor refactoring. 2016-08-03 00:33:20 +02:00
d7b47797df Made Stream members protected again. 2016-08-03 00:28:22 +02:00
544d4e0635 Major refactoring of underlying Parser class. 2016-08-02 20:33:49 +02:00
73c9d6c1f3 Checking that Parser initially is case-sensitive. 2016-06-22 09:14:01 +01:00
d9578b6f1c Testing Parser position with seek and advance. 2016-06-22 09:07:19 +01:00
b5e325cbee Testing Parser’s reset method. 2016-06-22 09:02:46 +01:00
234938349c Fixed incorrect seek positions. 2016-06-22 08:59:18 +01:00
9ed7277ec9 Fixed minor formatting issue with axiom rules. 2016-06-22 08:45:48 +01:00
dc87c09442 Merge branch 'master' of github.com:potassco/plasp into develop 2016-06-15 00:57:01 +02:00
00688765fd Fixed typos in readme file. 2016-06-15 00:56:17 +02:00
3702b72feb Version bump after release 3.0.1. 2016-06-15 00:18:09 +02:00
9af383d2f6 Version bump for release 3.0.1. 2016-06-14 19:26:41 +02:00
d3039d55e5 Fixed typo in PDDL translation output. 2016-06-14 19:21:27 +02:00
6b5c8df03a Fixed issues with color output. 2016-06-14 19:14:26 +02:00
8084fe5574 Merge branch 'develop' of github.com:potassco/plasp 2016-06-14 18:54:43 +02:00
3d661cd1f4 Fixed unescaped ASP identifier. 2016-06-14 18:53:50 +02:00
853d7471c2 Added error message when using command-line options incorrectly. 2016-06-14 18:47:02 +02:00
0a205680fe Made default color policy autodetection again. 2016-06-14 18:46:47 +02:00
52fee6a4c1 Made the language command-line option lowercase for consistency. 2016-06-14 18:42:29 +02:00
fcdd3bba2b Added command-line options to readme file. 2016-06-14 18:40:40 +02:00
b491efa9f4 Minor rephrasing. 2016-06-14 18:30:06 +02:00
401cf79cf6 Fixed incorrect usage information in help message. 2016-06-14 18:28:45 +02:00
44a20ca7e3 Updated usage information in the readme file. 2016-06-14 18:25:24 +02:00
5bda1c2245 Reordered change log items. 2016-06-14 18:08:32 +02:00
eb3d91f085 Added command-line option to autodetect, enable, or disable color output. 2016-06-14 18:02:59 +02:00
aff396d919 Colorizing numbers in translated SAS output. 2016-06-14 17:41:41 +02:00
f7cd24b67a Colorized output for SAS translator. 2016-06-14 17:35:32 +02:00
1e21457efb Refactored color output of headings. 2016-06-14 17:11:45 +02:00
583ec78eef Removed deleted methods. 2016-06-14 17:06:07 +02:00
9969281b11 Refactored color output of variables and keywords. 2016-06-14 17:05:41 +02:00
6fec1cc409 Made all error and warning messages lowercase consistently. 2016-06-14 16:53:48 +02:00
2984da773d Fixed errors with gcc. 2016-06-14 16:47:11 +02:00
1b83708a6d Colorized PDDL translator output. 2016-06-14 16:38:41 +02:00
0de2489440 Using LogStreams in the PDDL translator. 2016-06-14 16:14:39 +02:00
fd5416c94e Removed template from LogStream. 2016-06-14 16:09:47 +02:00
48137ec24d Fixed an issue with gcc 5. 2016-06-14 15:59:16 +02:00
febef4bed4 Made output and error streams members of the logger. 2016-06-14 15:56:35 +02:00
b599670572 Added LogStream class for uniform color output handling. 2016-06-14 15:53:53 +02:00
57e9de6b05 Renamed method to »logWarning.« 2016-06-14 15:12:45 +02:00
9679706a08 Removed ParserWarning class. 2016-06-14 15:09:39 +02:00
777c9839a1 Removed error message prefixes. 2016-06-14 15:06:43 +02:00
a6c9434590 Fixed missing error message prefix. 2016-06-14 15:00:56 +02:00
fd77b65226 Merge branch 'master' of github.com:potassco/plasp into colored-output 2016-06-14 14:59:23 +02:00
a23063fd4f Minor formatting. 2016-06-14 14:22:41 +02:00
a7cf696357 Minor formatting. 2016-06-14 14:18:38 +02:00
94d448d438 Minor formatting. 2016-06-14 14:05:38 +02:00
c62f3f88f1 Handling untyped variables as variables of type »object« in PDDL translator for simplicity. 2016-06-14 13:53:09 +02:00
39a32a6e0a Handling untyped variables correctly in the PDDL translator. 2016-06-14 13:21:41 +02:00
342a346fce Started implementing colored output. 2016-06-14 12:47:39 +02:00
e0dd9833a3 Made unsupported expressions a separate type for disambiguation to fix issues with unsupported features. 2016-06-14 01:31:22 +02:00
591d3fcafd Correctly terminate plasp with failure exit code when unhandled exceptions are caught. 2016-06-14 00:32:26 +02:00
22f294493e Removed bloated translation feature support checks and replaced them with inline ones. 2016-06-13 19:20:00 +02:00
5d3496fa41 Fixed missing assignment of member variable in At expression parser. 2016-06-13 19:19:17 +02:00
4b500e4bf6 Implemented At expressions. 2016-06-13 19:02:15 +02:00
da85e5dd9b Checking whether variables have types before accessing them in the PDDL translator. 2016-06-13 16:37:35 +02:00
2b55d156ae Fixed performance issue caused by skipping over unsupported sections multiple times. 2016-06-13 16:17:55 +02:00
f24491cd5a Updated help message with PDDL support. 2016-06-13 15:01:23 +02:00
268bee3c5f Updated change log with new command-line option --warning-level. 2016-06-13 14:46:30 +02:00
5c3ea28e48 Added command-line option for treating warnings as errors or completely ignoring them. 2016-06-13 14:45:31 +02:00
fdbcb261df Avoiding empty arguments in n-ary expressions. 2016-06-13 14:04:12 +02:00
2c3481d027 Initializing PDDL problem description only if available. 2016-06-13 13:37:18 +02:00
1c2ad0ceec Updated change log with addition of basic PDDL translation. 2016-06-13 03:59:48 +02:00
7899d3e262 Added simple encoding for translated PDDL instances. 2016-06-13 03:48:04 +02:00
6b88cb7926 Renamed SAS → ASP encoding for clarity. 2016-06-13 03:32:58 +02:00
421125fee6 Escaping PDDL identifiers for use with ASP. 2016-06-13 03:31:41 +02:00
8563011939 Minor formatting. 2016-06-13 03:22:48 +02:00
e07672ffe6 Added transitive deduction of object types to PDDL translation. 2016-06-13 03:22:19 +02:00
23f6f9b26b Added translation of a PDDL problem’s goal. 2016-06-13 03:19:24 +02:00
e9c464b319 Added translation of a PDDL problem’s initial state. 2016-06-13 02:59:43 +02:00
d3dc9101dd Added translation of objects in PDDL problems. 2016-06-13 02:48:16 +02:00
e018cdbc91 Added translation of effects of PDDL actions. 2016-06-13 02:41:23 +02:00
e2b8fd2880 Added translation for preconditions of PDDL actions. 2016-06-13 02:38:56 +02:00
680206b40b Removed Reference expressions. 2016-06-13 01:38:56 +02:00
1c8af793c2 Made PDDL action preconditions and effects optional. 2016-06-12 23:51:45 +02:00
46351b2fe7 Ensuring that input contains only predicates, negations, and conjunctions for the time being. 2016-06-12 23:38:44 +02:00
30cfa1b45e Fixes lambda issue with gcc. 2016-06-12 22:58:17 +02:00
0756d63769 Put translation of PDDL variable lists into separate method. 2016-06-12 22:55:35 +02:00
87ca54a253 Translating names of PDDL actions. 2016-06-12 22:47:39 +02:00
9c2f49e4a0 Put PDDL translation sections into separate methods. 2016-06-12 22:39:04 +02:00
49002ac52d Made output stream a member of the SAS translator for convenience. 2016-06-12 22:35:31 +02:00
b70e62ff3b Made output stream a member of the PDDL translator for convenience. 2016-06-12 22:31:31 +02:00
046f803538 Implemented translation of PDDL predicates (with primitive types only). 2016-06-12 22:25:12 +02:00
639b7646c9 Making sure that PDDL predicates contain only primitive types for the time being. 2016-06-12 22:19:55 +02:00
89bb54a3ec Hiding translated PDDL sections if empty. 2016-06-12 22:19:24 +02:00
979d9509c1 Added function for escaping ASP variables. 2016-06-12 22:12:43 +02:00
e9d48bcb7d Removing visitor pattern and replacing it with CRTP. 2016-06-12 22:12:09 +02:00
318bd8297c Disambiguation of parser and translation errors in plasp binary. 2016-06-12 22:09:47 +02:00
0513b3aa0c Implemented translation of PDDL domain constants. 2016-06-10 17:52:19 +02:00
458dbd723c Restructured translated PDDL type output. 2016-06-10 17:48:17 +02:00
8f0f4bfa65 Implemented translation of PDDL domain types. 2016-06-10 17:40:32 +02:00
da71d4947b Added method for checking whether PDDL description contains problem. 2016-06-10 17:26:36 +02:00
6a83147ac0 Moved TranslatorException class to utils directory. 2016-06-10 17:21:56 +02:00
f6cfc55e21 Put exception handling back into plasp binary for convenient use. 2016-06-10 17:12:23 +02:00
34a413cf05 Clarified error message. 2016-06-10 17:12:08 +02:00
854ade5fa9 Ensuring input to contain only one SAS description. 2016-06-10 17:09:06 +02:00
be09230410 Added test for PDDL comment parsing. 2016-06-10 16:50:08 +02:00
20b40d3e1c Allowing primitive type »objects« for compatibility. 2016-06-10 16:46:02 +02:00
9f0e784a4a Implemented recognition of comments in PDDL. 2016-06-10 16:40:43 +02:00
168fcc874e Added PDDL-related changes to change log. 2016-06-10 01:30:30 +02:00
d446c192cf Made plasp’s help message more precise. 2016-06-10 01:28:13 +02:00
eb5a120286 Fixed wrong comparison for language detection. 2016-06-10 01:25:51 +02:00
2e1a011dcf Implemented automatic language detection for plasp application. 2016-06-10 01:23:41 +02:00
8ef874eb22 Simplified plasp application by initializing parser externally. 2016-06-10 00:59:44 +02:00
c6dc84f27f Removed now unnecessary check for number of files with SAS parser. 2016-06-10 00:51:31 +02:00
8bb25e9b90 Implemented construction of SAS and PDDL Descriptions from Parser object. 2016-06-10 00:46:40 +02:00
c6bdfe3f38 Renamed issue checking test. 2016-06-09 23:35:57 +02:00
d1063b345d Renamed error detection tests. 2016-06-09 23:31:12 +02:00
dea879199a Removed debug output. 2016-06-09 23:26:00 +02:00
9a034cb556 Testing goal for Storage problem. 2016-06-09 23:21:05 +02:00
5cd22d284b Testing goal for Blocks World problem. 2016-06-09 23:19:20 +02:00
f8fc1865a2 Added to-do. 2016-06-09 22:55:16 +02:00
85444f235b Parsing goal section of PDDL problem specifications. 2016-06-09 22:54:39 +02:00
15061f75a9 Added test covering last issue. 2016-06-09 18:48:16 +02:00
d138e869fc Fixed further white space issue with empty n-ary predicates. 2016-06-09 18:46:06 +02:00
23170e170a Added test covering last two issues. 2016-06-09 18:32:55 +02:00
156dfd88c2 Fixed issue with parsing unsupported sections. 2016-06-09 18:30:34 +02:00
730a9b7e63 Fixed whitespace issues when parsing constants. 2016-06-09 18:26:04 +02:00
3041b6a278 Testing initial state for Storage problem. 2016-06-09 18:16:51 +02:00
2da5be548a Testing initial state for Blocks World problem. 2016-06-09 18:13:19 +02:00
6f1b38cdb7 Fixed parsing issue with predicates in problem description. 2016-06-09 18:04:24 +02:00
a8e4ef7234 Added missing implementation of facts accessor of InitialState. 2016-06-09 18:03:43 +02:00
c7405e054f Minor formatting. 2016-06-09 18:03:32 +02:00
9506dcb31e Refactored parsing of expressions, all classes parse from opening to closing parenthesis now. 2016-06-09 17:51:10 +02:00
04aac10f1d Allowing empty and expressions for compatibility and added a warning if used. 2016-06-09 15:56:14 +02:00
bbb6379907 Added goal-utilities requirement with a warning if used for compatibility. 2016-06-09 15:52:57 +02:00
26d7e216a6 Fixed issue with invalid suffixes on section names. 2016-06-09 15:33:09 +02:00
d629f50661 Added many PDDL syntax error tests. 2016-06-09 15:19:01 +02:00
2245422d0f Made parser exception message more meaningful. 2016-06-09 15:18:36 +02:00
87889f5efe Implemented two-pass parsing for PDDL problems. 2016-06-09 14:39:03 +02:00
fb15a131ac Enabling tests by default. 2016-06-09 01:25:50 +02:00
8428c20bd4 Parsing domains in two passes and continued working on parsing the initial state. 2016-06-09 01:25:18 +02:00
ff7a6b8c8f Removed unnecessary include. 2016-06-08 16:52:44 +02:00
d92a3e9239 Started testing PDDL problem parsing for a Storage problem. 2016-06-08 13:57:01 +02:00
d23ec14e9d Started testing PDDL problem parsing for a Blocks World problem. 2016-06-08 13:52:36 +02:00
ad23c89266 Refactored PDDL tests. 2016-06-08 13:41:17 +02:00
1c8958ad9d Check that variables are not declared multiple times. 2016-06-08 13:35:10 +02:00
c99b7018c6 Checking that type declarations are not missing. 2016-06-08 13:34:41 +02:00
f2089f48b8 Fixed typo. 2016-06-08 12:56:50 +02:00
75e51c856e Implemented early checking for typing requirement in Variables and Constants. 2016-06-08 12:51:39 +02:00
e60af33f75 Added functions for checking PDDL requirements. 2016-06-08 12:22:31 +02:00
993d14d409 Implemented type requirement checking for problem objects. 2016-06-08 01:51:45 +02:00
bf0e636d57 Fixed PDDL problem header parsing. 2016-06-08 01:51:21 +02:00
374ac3b07f Removed unneeded temporary object. 2016-06-08 01:44:06 +02:00
183b0c954e Fixed debug output. 2016-06-08 01:41:21 +02:00
42559fd601 Minor refactoring removing unnecessary temporary variable. 2016-06-08 01:31:14 +02:00
069ad4ca99 To-dos and formatting. 2016-06-08 01:19:49 +02:00
8db4b5a53e Implemented constant type checking. 2016-06-08 01:14:39 +02:00
32883910bb Fixed typo. 2016-06-08 01:12:29 +02:00
9b3f78559e Implemented primitive type declaration check. 2016-06-08 01:08:22 +02:00
7bd2782fc8 Implemented variable type requirement checking. 2016-06-08 01:05:36 +02:00
75fbb5fb48 Checking type requirement. 2016-06-08 00:48:33 +02:00
af2f9290c6 Removed obsolete functionality. 2016-06-08 00:36:48 +02:00
31fb8ba79b Started parsing in a two-pass approach. 2016-06-08 00:34:59 +02:00
ee9626e4d2 Made the section skipping function a proper function. 2016-06-08 00:14:43 +02:00
9360f4295a Extracted function for skipping entire sections. 2016-06-08 00:13:53 +02:00
abfa3b3ca1 Added -Wextra compiler flag. 2016-06-08 00:13:07 +02:00
a1b93624d6 Fixed accepting std::cin input when omitting input file arguments. 2016-06-08 00:06:54 +02:00
69ff84eecc Added efficient probing functions to Parser. 2016-06-08 00:02:40 +02:00
78889e18c6 Fixed accidentally removed std::cin support. 2016-06-07 23:31:09 +02:00
fa178d5ee1 Fixed SAS file input bug. 2016-06-07 20:59:02 +02:00
eea3272c56 Made Parser seekable for easier maintenance. 2016-06-07 18:41:01 +02:00
27e76fc035 Added check that typing requirement is not added by PDDL problem. 2016-06-07 16:34:15 +02:00
188165bc4d Added fix for gcc. 2016-06-07 16:14:35 +02:00
e6ddad5960 Checking that all variables in predicates have types if and only if typing is enabled. 2016-06-07 16:11:12 +02:00
4228ca01dc Implemented multi-file input. 2016-06-07 15:54:01 +02:00
64190ba55a Added more tests for PDDL actions. 2016-06-07 14:07:17 +02:00
c489c7fd5a Added tests for PDDL actions. 2016-06-07 14:00:29 +02:00
acc063822e Minor formatting in PDDL parser tests. 2016-06-07 13:40:01 +02:00
b612122180 Refactoring to make parsing expressions consistent across PDDL domains and problems. 2016-06-07 13:26:19 +02:00
d5fa00a4a4 Started parsing initial state and object sections. 2016-06-06 15:18:06 +02:00
e607ca4e8e Refactored PDDL parser to make all input case-insensitive. 2016-06-04 18:28:43 +02:00
d64c68f754 Improved error message. 2016-06-04 18:21:42 +02:00
e5bf7d754f Refactored expression parsing. 2016-06-04 18:12:41 +02:00
0e739755b7 Making References transparent by forwarding visitors to their referee. 2016-06-04 18:08:34 +02:00
f8eab1cbb6 Removed unnecessary includes. 2016-06-04 18:07:57 +02:00
0f2c81f894 Added to-dos. 2016-06-04 17:55:17 +02:00
e481732fae Started implementation of PDDL problem parser. 2016-06-04 17:53:42 +02:00
ee597c805e Added to-do. 2016-06-04 17:52:37 +02:00
e561c55f73 Made Action section parsing case-insensitive. 2016-06-04 17:51:21 +02:00
2870bc6434 Made section identifier parsing case-insensitive. 2016-06-04 17:47:41 +02:00
7e60631840 Refactored Requirement parsing. 2016-06-04 17:47:01 +02:00
f2a1528ea9 Fixed determination of default requirement (STRIPS). 2016-06-04 17:28:52 +02:00
21af7e9983 Removed unnecessary include. 2016-06-04 17:22:57 +02:00
4ae37603f4 Added support for Imply expression. 2016-06-04 17:20:25 +02:00
30b4a1f614 Made include guards consistent. 2016-06-04 17:10:50 +02:00
2797b58646 Added missing ParserWarning file. 2016-06-04 16:45:14 +02:00
837612bb8d Made type warnings non-fatal by default. 2016-06-04 16:42:41 +02:00
813fecbf15 Removed now unnecessary Parser function arguments. 2016-06-04 16:24:10 +02:00
a776fc9e06 Put Parser into Context. 2016-06-04 16:10:11 +02:00
08eb14e400 Made section parsing function names consistent. 2016-06-04 15:07:18 +02:00
60c072a2b3 Clean-up. 2016-06-04 15:06:04 +02:00
feedb95295 Turned exception about undeclared types into a consistency warning. 2016-06-04 15:04:18 +02:00
c93661f44e Finished refactoring of expressions. 2016-06-04 14:46:05 +02:00
daa063c338 Big refactoring (build still broken). 2016-06-03 17:12:39 +02:00
5abf1f8a84 Removed obsolete Variable class. 2016-06-03 13:37:23 +02:00
133aa051eb Shortened Expression class names. 2016-06-03 13:33:05 +02:00
d334b4150b Started refactoring Variables as expressions. 2016-06-03 13:21:02 +02:00
36e28994ee Updated change log. 2016-06-03 00:19:05 +02:00
01908c52f8 Merge branch 'master' of github.com:potassco/plasp into develop 2016-06-03 00:15:40 +02:00
f9463d629a Added Travis badge for develop branch to readme file. 2016-06-03 00:14:51 +02:00
50315f5fae Relaxing white space requirements. 2016-06-02 23:41:40 +02:00
8817a3f226 Fixed whitespace parsing issue. 2016-06-02 22:47:25 +02:00
fcde9c9b6b Finished basic support for action parsing. 2016-06-02 22:31:02 +02:00
fb5a5a71a5 Removed unnecessary include. 2016-06-02 21:56:40 +02:00
8134c6af80 Started parsing action effects. 2016-06-02 21:53:10 +02:00
7271a5e52b Implemented predicate expressions. 2016-06-02 18:31:47 +02:00
7baf15d9f0 Implemented And expressions. 2016-06-02 17:35:01 +02:00
d070b5be9e Added expression visitor base class. 2016-06-02 16:29:17 +02:00
63d74e3524 Replaced tabs with spaces in test file to get more accurate parser positions in errors. 2016-06-02 16:28:26 +02:00
a07019801c Refactored expressions to inherit from base class. 2016-06-02 16:28:08 +02:00
97ab22461c Started implementing parsing of action preconditions. 2016-06-02 16:06:11 +02:00
138db460a9 Merge branch 'master' of github.com:potassco/plasp into pddl-parser 2016-06-01 22:54:49 +02:00
a9c0431ded Changed Travis configuration to use 3 threads for building. 2016-06-01 22:49:59 +02:00
7e4a05e1db Assuming parent types to be declared properly. 2016-06-01 18:09:40 +02:00
0a4541a401 Put parsing of typed variables into Variables class. 2016-06-01 17:20:34 +02:00
79773ba634 Removed unnecessary include. 2016-06-01 17:06:23 +02:00
b249e1cbf8 Put generic Type parsing in separate function. 2016-06-01 17:02:35 +02:00
25cf7c8ae8 Implemented parsing of PDDL constants. 2016-06-01 16:47:34 +02:00
3c97ced486 Implemented predicate parsing and refactored context storage. 2016-06-01 14:11:13 +02:00
44482ae438 Renamed TypePrimitive to PrimitiveType and made Type hash map contain PrimitiveTypes only. 2016-06-01 01:54:43 +02:00
f597b3ab80 Moved include to the right location. 2016-06-01 01:32:49 +02:00
b8223b42bd Removed unnecessary include. 2016-06-01 01:31:14 +02:00
ced1fd0038 Started refactoring Types with variants. 2016-06-01 01:29:46 +02:00
2654a6ff23 Started implementing predicate parsing. 2016-05-31 16:43:25 +02:00
5f763e90fc Refactored Requirement to be a proper class. 2016-05-31 14:11:21 +02:00
cf1c66a085 Refactored interface for parsing Types. 2016-05-31 14:01:18 +02:00
1395b62e60 Added checks that used types are correctly declared previously. 2016-05-31 13:50:30 +02:00
85da5024ea Refactored type parsing. 2016-05-31 01:06:57 +02:00
a989f5f86e Started implementing PDDL type parsing. 2016-05-30 20:43:36 +02:00
1c4c035acc Added missing test file for PDDL parser tests. 2016-05-30 15:47:57 +02:00
d26ff2df77 Implemented computation of derived requirements. 2016-05-30 15:44:13 +02:00
5c37026ec7 Parsing PDDL requirements. 2016-05-30 15:06:04 +02:00
8aa419b5c2 Implemented requirement parsing. 2016-05-30 14:34:17 +02:00
c191b418f2 Added PDDL requirements enum. 2016-05-30 13:36:47 +02:00
0eb2714c9e Removed incorrect parentheses check. 2016-05-30 13:22:17 +02:00
0b33ac0e7d Minor formatting. 2016-05-30 13:06:10 +02:00
f55e366b17 Removed unnecessary statement. 2016-05-30 13:03:18 +02:00
b89b1708c3 Additional line-skipping tests for Parser. 2016-05-30 13:00:55 +02:00
f9c5a830e1 Additional assertions in Parser test cases. 2016-05-30 12:58:10 +02:00
348bd98de8 Extended Parser tests with whitespace handling check. 2016-05-30 12:56:30 +02:00
4d984d32c3 Refactoring of Parser class with std::istreambuf_iterator. 2016-05-30 12:54:56 +02:00
8d879344f2 Merge branch 'pddl-parser' of github.com:potassco/plasp into pddl-parser 2016-05-30 12:54:41 +02:00
40547691a0 Started implementing PDDL domain parser. 2016-05-30 12:51:00 +02:00
8f705b0737 Added test for Parser’s cursor position. 2016-05-30 12:32:13 +02:00
67c9e2148d Started implementing PDDL domain parser. 2016-05-29 16:55:43 +02:00
42fda5925d Simplified Parser interface. 2016-05-29 15:08:10 +02:00
2c564f47d3 Refactored predicate argument parsing. 2016-05-28 14:21:05 +02:00
b4bc347006 Removed unnecessary include. 2016-05-28 14:18:51 +02:00
f81fd1a1b4 Introduced alias for parser’s underlying character type. 2016-05-27 19:25:59 +02:00
a1b334a302 Made Parser constructor explicit. 2016-05-27 19:08:31 +02:00
ff420fbe57 Minor formatting. 2016-05-27 18:39:43 +02:00
07eb23b312 Refactored basic parsing. 2016-05-27 03:58:59 +02:00
6017cfe3d5 Removed version numbers from contributors to earlier versions. 2016-05-26 13:01:46 +02:00
8eb0a4847f Refactoring of TranslatorASP class. 2016-05-26 12:59:18 +02:00
47f269782e Reduced the number of boost dependencies with Travis. 2016-05-26 00:23:30 +02:00
d9a40af3f0 Using unsigned constants in tests to avoid warnings with Google Test. 2016-05-26 00:17:55 +02:00
2281967176 Added info about running the tests to the readme file. 2016-05-26 00:11:32 +02:00
6b38b55c58 Merge branch 'master' of github.com:potassco/plasp 2016-05-25 23:50:38 +02:00
12ffbb4d80 Ignoring configuration files for exporting the repository. 2016-05-25 23:49:58 +02:00
045239b620 Fixed wrong operator in debug output. 2016-05-25 23:22:25 +02:00
dda81e9011 Merge branch 'master' of github.com:potassco/plasp 2016-05-25 23:02:17 +02:00
98a15bbf8e Removed gtest package from Travis configuration to properly use the git submodule instead. 2016-05-25 23:01:42 +02:00
7a8b562173 Fixed URLs in readme file. 2016-05-25 18:11:00 +02:00
0cbb3453bd Added version badge to readme file. 2016-05-25 18:04:49 +02:00
062a04233f Changed license to Markdown format. 2016-05-25 12:44:28 +02:00
75c841e3c5 Added change log. 2016-05-25 12:42:31 +02:00
441b8b0154 Added support for input from std::cin. 2016-05-25 12:36:45 +02:00
150 changed files with 11488 additions and 490 deletions

5
.gitattributes vendored
View File

@@ -1 +1,6 @@
.gitignore export-ignore
.gitattributes export-ignore
.gitmodules export-ignore
.travis.yml export-ignore
tests/data/* linguist-documentation

View File

@@ -11,11 +11,15 @@ matrix:
- boost-latest
packages:
- g++-5
- libboost1.55-all-dev
- libgtest-dev
- libboost-program-options1.55-dev
- libboost-iostreams1.55-dev
- libboost-system1.55-dev
- libboost-filesystem1.55-dev
env: COMPILER=g++-5
script:
- git submodule init
- git submodule update
- mkdir build
- cd build
- cmake .. -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON -DCMAKE_CXX_COMPILER=$COMPILER
- make && make run-tests
- make -j3 && make -j3 run-tests

36
CHANGELOG.md Normal file
View File

@@ -0,0 +1,36 @@
# Change Log
## (unreleased)
Features:
* unified translation format for SAS and PDDL files
* documentation of `plasp`s output format
Bug Fixes:
* fixes minor formatting issues in SAS translation
## 3.0.1 (2016-06-14)
Features:
* basic support for parsing PDDL 3.1 domains and problems
* limited support for translating PDDL 3.1 domains and problems to ASP facts
* automatic language detection for PDDL and SAS
* supports input from `std::cin`
* supports colorized output
* new command-line option `--language` to explicitly specify input language
* new command-line option `--warning-level` to treat warnings as errors or to ignore warnings
* new command-line option `--color` to autodetect, enable, or disable color output
Bug Fixes:
* fixes bug in translation of SAS axiom rules
## 3.0.0 (2016-05-24)
Features:
* parses [SAS](http://www.fast-downward.org/TranslatorOutputFormat) files created with [Fast Downward](http://www.fast-downward.org/)
* experimental translation from SAS to ASP facts

View File

@@ -3,11 +3,11 @@ project(plasp CXX)
find_package(Boost 1.55.0 COMPONENTS program_options iostreams system filesystem REQUIRED)
set(CMAKE_CXX_FLAGS "-Wall -Wpedantic")
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wpedantic")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
add_definitions(-std=c++14)
option(BUILD_TESTS "Build unit tests" OFF)
option(BUILD_TESTS "Build unit tests" ON)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
# The MIT License (MIT)
Copyright (c) 2016 Patrick Lühne
Copyright © 2016 Patrick Lühne
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,50 +1,70 @@
# plasp—Translate PDDL to ASP
[![Build Status](https://travis-ci.org/potassco/plasp.svg?branch=master)](https://travis-ci.org/potassco/plasp)
[![GitHub Release](https://img.shields.io/github/release/potassco/plasp.svg?maxAge=3600)](https://github.com/potassco/plasp/releases)
[![Build Status](https://img.shields.io/travis/potassco/plasp/develop.svg?maxAge=3600&label=build (master))](https://travis-ci.org/potassco/plasp?branch=master)
[![Build Status](https://img.shields.io/travis/potassco/plasp/develop.svg?maxAge=3600&label=build (develop))](https://travis-ci.org/potassco/plasp?branch=develop)
`plasp` 3 is in early development and not intended for productive use yet.
As of now, `plasp` 3 experimentally supports the full [SAS Format](http://www.fast-downward.org/TranslatorOutputFormat) (as of version 3) used by [Fast Downward](http://www.fast-downward.org/).
`plasp` translates planning problem instances to ASP facts.
`plasp` 3 supports the input languages [PDDL 3.1](https://helios.hud.ac.uk/scommv/IPC-14/software.html) (only basic features currently) and [SAS](http://www.fast-downward.org/TranslatorOutputFormat) (full support of SAS 3), which is used by [Fast Downward](http://www.fast-downward.org/).
Please get in touch with [Patrick Lühne](https://www.luehne.de) if you have any suggestions.
## Usage
To translate an SAS file into ASP facts, call:
### Translating PDDL to ASP Facts
PDDL instances are translated to ASP facts as follows:
```bash
$ plasp file.sas
$ plasp domain.pddl problem.pddl
```
For instance, a PDDL instance can be solved as follows.
First, use [Fast Downward](http://www.fast-downward.org/) to translate the files from PDDL to SAS:
Alternatively, PDDL instances may first be translated to SAS, the output format of [Fast Downward](http://www.fast-downward.org/).
```bash
$ ./fast-downward.py --translate --build=release64 domain.pddl instance.pddl
$ ./fast-downward.py --translate --build=release64 domain.pddl problem.pddl
```
This creates the file `output.sas`.
The translated SAS instance can now be solved incrementally with `clingo` and the meta encoding `meta-sequential-incremental.lp`:
This creates a file called `output.sas`, which may now be translated by `plasp`.
```bash
$ plasp output.sas > instance.lp
$ clingo encodings/meta-sequential-incremental.lp instance.lp
$ plasp output.sas
```
### Solving the Translated Instance
The translated instance can finally be solved incrementally with `clingo` and a meta encoding, for instance, `pddl-meta-sequential-incremental.lp`:
```bash
$ plasp domain.pddl problem.pddl > instance.lp
$ clingo encodings/pddl-meta-sequential-incremental.lp instance.lp
```
## Command-Line Interface
```bash
$ plasp [files] [options]
```
`plasp` automatically detects the language of the input program.
See [command-line interface](doc/command-line-interface.md) for more detail.
## Output Format
`plasp` provides a uniform output format for SAS and PDDL input problems.
See [output format](doc/output-format.md) for more detail.
If you want to write your own meta encoding for `plasp`s output, this [simple example encoding](encodings/sequential-incremental.lp) gets you started.
## Building
`plasp` requires a C++14 compiler (preferrably GCC ≥ 6.1), the `boost` libraries (≥ 1.55), and CMake for building.
`plasp` requires `boost` and is built via CMake and a C++ compiler.
```bash
$ git clone https://github.com/potassco/plasp.git
$ cd plasp
$ mkdir -p build/release
$ cd build/release
$ cmake ../.. -DCMAKE_BUILD_TYPE=Release
$ make
```
The built `plasp` binary is then located at `plasp/build/release/bin/plasp`.
See [building instructions](doc/building-instructions.md) for more detail.
## Contributors
@@ -52,5 +72,5 @@ The built `plasp` binary is then located at `plasp/build/release/bin/plasp`.
### Earlier Versions
* René Knaebel (`plasp` 2)
* Murat Knecht (`plasp`)
* René Knaebel
* Murat Knecht

View File

@@ -1,9 +1,16 @@
#include <algorithm>
#include <iostream>
#include <string>
#include <boost/program_options.hpp>
#include <plasp/LanguageDetection.h>
#include <plasp/pddl/Description.h>
#include <plasp/pddl/TranslatorASP.h>
#include <plasp/sas/Description.h>
#include <plasp/sas/TranslatorASP.h>
#include <plasp/utils/LogStream.h>
#include <plasp/utils/TranslatorException.h>
int main(int argc, char **argv)
{
@@ -13,7 +20,10 @@ int main(int argc, char **argv)
description.add_options()
("help,h", "Display this help message.")
("version,v", "Display version information.")
("input,i", po::value<std::string>(), "Specify the SAS input file.");
("input,i", po::value<std::vector<std::string>>(), "Specify the PDDL or SAS input file.")
("language,l", po::value<std::string>(), "Specify the input language (sas or pddl). Omit for automatic detection.")
("warning-level", po::value<std::string>()->default_value("normal"), "Specify whether to output warnings normally (normal), to treat them as critical errors (error), or to ignore them (ignore).")
("color", po::value<std::string>()->default_value("auto"), "Specify whether to colorize the output (always, never, or auto).");
po::positional_options_description positionalOptionsDescription;
positionalOptionsDescription.add("input", -1);
@@ -23,12 +33,14 @@ int main(int argc, char **argv)
const auto printHelp =
[&]()
{
std::cout << "Usage: plasp file [options]" << std::endl;
std::cout << "Usage: plasp [files] [options]" << std::endl;
std::cout << "Translate PDDL instances to ASP facts." << std::endl << std::endl;
std::cout << description;
};
plasp::utils::Logger logger;
try
{
po::store(po::command_line_parser(argc, argv)
@@ -40,7 +52,8 @@ int main(int argc, char **argv)
}
catch (const po::error &e)
{
std::cerr << "Error: " << e.what() << std::endl << std::endl;
logger.logError(e.what());
std::cout << std::endl;
printHelp();
return EXIT_FAILURE;
}
@@ -53,27 +66,108 @@ int main(int argc, char **argv)
if (variablesMap.count("version"))
{
std::cout << "plasp version 3.0.0" << std::endl;
std::cout << "plasp version 3.0.2-rc.1" << std::endl;
return EXIT_SUCCESS;
}
if (!variablesMap.count("input"))
const auto warningLevel = variablesMap["warning-level"].as<std::string>();
if (warningLevel == "error")
logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Error);
else if (warningLevel == "ignore")
logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Ignore);
else if (warningLevel == "normal")
logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Normal);
else
{
std::cerr << "Error: No input file specified" << std::endl << std::endl;
logger.logError("unknown warning level “" + warningLevel + "");
std::cout << std::endl;
printHelp();
return EXIT_FAILURE;
}
const auto colorPolicy = variablesMap["color"].as<std::string>();
if (colorPolicy == "auto")
logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Auto);
else if (colorPolicy == "never")
logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Never);
else if (colorPolicy == "always")
logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Always);
else
{
logger.logError("unknown color policy “" + colorPolicy + "");
std::cout << std::endl;
printHelp();
return EXIT_FAILURE;
}
try
{
const auto sasDescription = plasp::sas::Description::fromFile(variablesMap["input"].as<std::string>());
const auto sasTranslator = plasp::sas::TranslatorASP(sasDescription);
sasTranslator.translate(std::cout);
plasp::utils::Parser<plasp::utils::CaseInsensitiveParserPolicy> parser;
if (variablesMap.count("input"))
{
const auto &inputFiles = variablesMap["input"].as<std::vector<std::string>>();
std::for_each(inputFiles.cbegin(), inputFiles.cend(),
[&](const auto &inputFile)
{
parser.read(inputFile);
});
}
else
parser.read("std::cin", std::cin);
const auto detectLanguage =
[&]()
{
if (variablesMap.count("language") == 0)
return plasp::detectLanguage(parser);
const auto languageName = variablesMap["language"].as<std::string>();
return plasp::Language::fromString(languageName);
};
const auto language = detectLanguage();
if (language == plasp::Language::Type::Unknown)
{
logger.logError("unknown input language");
std::cout << std::endl;
printHelp();
return EXIT_FAILURE;
}
if (language == plasp::Language::Type::PDDL)
{
auto pddlLogger = logger;
auto context = plasp::pddl::Context(std::move(parser), std::move(pddlLogger));
auto description = plasp::pddl::Description::fromContext(std::move(context));
const auto translator = plasp::pddl::TranslatorASP(description, description.context().logger.outputStream());
translator.translate();
}
else if (language == plasp::Language::Type::SAS)
{
const auto description = plasp::sas::Description::fromParser(std::move(parser));
const auto translator = plasp::sas::TranslatorASP(description, logger.outputStream());
translator.translate();
}
}
catch (const plasp::utils::ParserException &e)
{
logger.logError(e.coordinate(), e.message());
return EXIT_FAILURE;
}
catch (const plasp::utils::TranslatorException &e)
{
logger.logError(e.what());
return EXIT_FAILURE;
}
catch (const std::exception &e)
{
std::cerr << "Error: " << e.what() << std::endl << std::endl;
printHelp();
logger.logError(e.what());
return EXIT_FAILURE;
}

View File

@@ -0,0 +1,40 @@
# Building Instructions
`plasp` requires a C++14 compiler (preferrably GCC ≥ 6.1 or clang ≥ 3.8), the `boost` libraries (≥ 1.55), and CMake for building.
```bash
$ git clone https://github.com/potassco/plasp.git
$ cd plasp
$ mkdir -p build/release
$ cd build/release
$ cmake ../.. -DCMAKE_BUILD_TYPE=Release
$ make
```
The built `plasp` binary is then located at `plasp/build/release/bin/plasp`.
To update `plasp` to the most recent version, perform the following steps:
```bash
$ cd plasp
$ git pull
$ cd build/release
$ cmake .
$ make
```
## Running the Tests
`plasp` provides unit tests written using the [Google Test](https://github.com/google/googletest) framework.
Before building and running the tests, make sure you have fetched the Google Test git submodule:
```bash
$ git submodule init
$ git submodule update
```
Afterward, build and run the tests as follows:
```bash
$ make run-tests
```

View File

@@ -0,0 +1,18 @@
# Command-Line Interface
```bash
$ plasp [files] [options]
```
`plasp` automatically detects the language of the input files.
Multiple files may be provided in an arbitrary order.
`[files]` may also be omitted, in which case the input is read from `std::cin`.
`plasp` supports the following options:
| **option** | **explanation** |
|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
| `-l` [ `--language` ] | Specify the input language (`sas` or `pddl`). Omit for automatic detection. |
| `--warning-level` arg (=`normal`) | Specify whether to output warnings normally (`normal`), to treat them as critical errors (`error`), or to ignore them (`ignore`). |
| `--color` arg (=`auto`) | Specify whether to colorize the output (`always`, `never`, or `auto`). |

View File

@@ -0,0 +1,22 @@
# Feature Requirements
Feature requirements are part of `plasp`s [output format](output-format.md).
Currently, `plasp` detects feature requirements only for SAS problems.
`plasp` supports the following feature requirements:
SAS feature | description
------------|------------
`actionCosts` | actions have associated costs (see [action costs](output-format.md#action-costs))
`axiomRules` | immediate actions are used, which are executed as soon as the preconditions are satisfied (see [axiom rules](output-format.md#axiom-rules))
`conditionalEffects` | some effects of an action may have additional conditions (see [actions](output-format.md#actions))
## Example
The following specifies that the input problem has the two requirements `actionCosts` and `conditionalEffects`.
```prolog
% requirements
requiresFeature(actionCosts).
requiresFeature(conditionalEffects).
```

202
doc/output-format.md Normal file
View File

@@ -0,0 +1,202 @@
# Output Format
`plasp` 3 translates SAS and PDDL files into a uniform ASP fact format.
## Overview
Essentially, `plasp`s output format consists of [state variables](#variables) that are modified by [actions](#actions) if their preconditions are fulfilled.
Variables reference [entities](#constants-objects) that are affected by the actions.
As with PDDL, the objective is to achieve a specific [goal](#goal) starting from an [initial state](#initial-state) by executing a sequence of actions.
`plasp`s variables correspond to the multivalued variables in SAS.
PDDL predicates are turned into Boolean variables to make the output format consistent.
Actions are modeled exactly as PDDL actions and SAS operators.
## In a Nutshell
The following illustrates `plasp`s output format for the problem of turning switches on and off.
```prolog
% declares the type "type(switch)"
type(type(switch)).
% introduces a switch "constant(a)"
constant(constant(a)).
has(constant(a), type(switch)).
% declares a variable "variable(on(X))" for switches X
variable(variable(on(X))) :- has(X, type(switch)).
% the variable may be true or false
contains(variable(on(X)), value(on(X)), true)) :- has(X, type(switch)).
contains(variable(on(X)), value(on(X)), false)) :- has(X, type(switch)).
% declares the action "action(turnOn(X))", which requires switch X to be off and then turns it on
action(action(turnOn(X))) :- has(X, type(switch)).
precondition(action(turnOn(X)), variable(on(X)), value(on(X), false)) :- has(X, type(switch)).
postcondition(action(turnOn(X)), effect(0), variable(on(X)), value(on(X), true)) :- has(X, type(switch)).
% initially, the switch is off
initialState(variable(on(constant(a))), value(on(constant(a)), false)).
% in the end, the switch should be on
goal(variable(on(constant(a))), value(on(constant(a)), true)).
```
## Syntax and Semantics
`plasp` structures the translated ASP facts into multiple sections, which are explained in the following.
### Feature Requirements
```prolog
% declares a required feature
requires(feature(<name>)).
```
`plasp` recognizes and declares advanced features used by the input problem, such as conditional effects, [mutex groups](#mutex-groups) and [axiom rules](#axiom-rules) (currently only SAS).
See the [full list of supported features](feature-requirements.md) for more information.
The feature requirement predicates may be used in meta encodings to warn about unsupported features.
### Types
```prolog
% declares a <type>
type(type(<name>)).
% specifies <constant> to be of type type(<name>)
has(<constant>, type(<name>)).
```
[Variables](#variables), [constants](#constants-objects), and [objects](#constants-objects) may be typed. Types are only available with PDDL and if typing is enabled.
### Variables
```prolog
% declares a <variable>
variable(variable(<name>)).
% adds a <value> to the domain of a <variable>
contains(<variable>, <value>).
```
`plasp`s variables represent the current state of the planning problem.
Variables are linked to the problem's [objects](#constants-objects) and [constants](#constants-objects).
`plasp`s variables are multivalued, and each variable has exactly one value at each point in time.
With SAS, variable names are numbers starting at 0, `variable(<number>)`.
SAS variables are inherently multivalued, which results in two or more values of the form `value(<SAS predicate>, <bool>)` for each variable.
With PDDL, Boolean variables are created from the PDDL predicates.
Variables ared named after the PDDL predicates, `variable(<PDDL predicate>).`
Each variable contains exactly two values (one `true`, one `false`) of the form `value(<PDDL predicate>, <bool>)`.
Note that with PDDL, variables and values are named identically.
### Actions
```prolog
% declares an <action>
action(action(<name>)).
% defines that as a precondition to <action>, <variable> must have value <value>
precondition(<action>, <variable>, <value>).
% defines that after applying <action>, <variable> is assigned <value>
postcondition(<action>, effect(<number>), <variable>, <value>).
% defines the condition of a conditional effect
precondition(effect(<number>), <variable>, <value>).
% specifies the costs of applying <action>
costs(<action>, <number>).
```
Actions may require certain variables to have specific values in order to be executed.
After applying an action, variables get new values according to the action's postconditions.
Actions may have *conditional effects*, that is, certain postconditions are only applied if additional conditions are satisfied.
For this reason, each conditional effect is uniquely identified with a predicate `effect(<number>)` as the second argument of the `postcondition` facts.
The conditions of conditional effects are given by additional `precondition` facts that take the respective `effect(<number>)` predicates as the first argument.
Unconditional effects are identified with `effect(unconditional)`.
Conditional effects are currently only supported with SAS input problems.
Actions may also have *action costs* required to apply them. Action costs are currently supported for SAS only.
### Constants/Objects
```prolog
% declares a <constant> or object
constant(constant(<name>)).
% specifies <constant> to be of type type(<name>)
has(<constant>, <type>).
```
Constants and objects are the entities that are affected by [actions](#actions), for instance, the blocks in a Blocks World problem.
Constants are global for a domain, while objects are problem-specific.
`plasp` does not distinguish between the two (modeling both as constants), as both are identically used static identifiers.
### Initial State
```prolog
% initializes <variable> with a specific <value>
initialState(<variable>, <value>).
```
The initial state contains all [variable](#variables) assignments that hold before executing any [actions](#actions).
Note that with PDDL, the initial state might not assign values to all variables. Instead, unassigned values have to be assigned `false` manually.
### Goal
```prolog
% specifies that <variable> shall obtain <value> in the end
goal(<variable>, <value>).
```
The goal specifies all variable assignments that have to be fulfilled after executing the plan.
### Mutex Groups
```prolog
% declares a <mutex group>
mutexGroup(mutexGroup(<number>)).
% adds the assignment of <variable> to <value> to a <mutex group>
contains(<mutex group>, <variable>, <value>).
```
SAS contains information about mutually exclusive [variable](#variables) assignments.
That is, *at most one* variable assignment of each mutex group must be satisfied at all times.
Mutex group facts are only present with SAS input programs and not PDDL.
Mutex groups contain essential information in order to find plans correctly.
That is, if mutex groups are present in `plasp`s output, they have to be accounted for appropriately.
### Axiom Rules
```prolog
% declares an <axiom rule>
axiomRule(axiomRule(<number>)).
% defines that as a precondition to <axiom rule>, <variable> must have value <value>
precondition(<axiom rule>, <variable>, <value>).
% defines that after applying <axiom rule>, <variable> is assigned <value>
postcondition(<axiom rule>, <variable>, <value>).
```
Axiom rules are similar to [actions](#actions) in that they modify [variables](#variables) if certain preconditions are satisfied.
However, axiom rules must be applied *immediately* as soon as their preconditions are satisfied.
Axiom rule facts are only present with SAS input programs and not PDDL.
Axiom rules contain essential information in order to find plans correctly.
That is, if axiom rules are present in `plasp`s output, they have to be accounted for appropriately.

View File

@@ -1,40 +0,0 @@
#include <incmode>.
% Check feature requirements
:- requiresFeature(actionCosts).
:- requiresFeature(axiomRules).
:- requiresFeature(conditionalEffects).
#program base.
% Establish initial state
holds(Var, Val, 0) :- initialState(Var, Val).
#program step(t).
% Perform actions
1 {occurs(action(A), t) : action(A)} 1.
% Check preconditions
:- occurs(A, t), precondition(A, Var, Val), not holds(Var, Val, t - 1).
% Apply effects
caused(Var, Val, t) :- occurs(A, t), postcondition(A, _, Var, Val).
modified(Var, t) :- caused(Var, Val, t).
holds(Var, Val, t) :- caused(Var, Val, t).
holds(Var, Val, t) :- holds(Var, Val, t - 1), not modified(Var, t).
% Check that variables have unique values
:- variable(X), Var = variable(X), not 1 {holds(Var, Val, t) : contains(Var, Val)} 1.
% Check mutexes
:- mutexGroup(X), M = mutexGroup(X), not {holds(Var, Val, t) : contains(M, Var, Val)} 1.
#program check(t).
% Verify that goal is met
:- query(t), goal(Var, Val), not holds(Var, Val, t).
#show query/1.
#show occurs/2.

View File

@@ -0,0 +1,43 @@
#include <incmode>.
% Check feature requirements
:- requiresFeature(actionCosts).
:- requiresFeature(axiomRules).
:- requiresFeature(conditionalEffects).
#program base.
% Establish initial state
holds(Variable, Value, 0) :- initialState(Variable, Value).
% Make unspecified initial state variables false by default (for PDDL)
holds(variable(Variable), value(Variable, false), 0) :- variable(variable(Variable)), {initialState(variable(Variable), _)} 0.
#program step(t).
% Perform actions
1 {occurs(Action, t) : action(Action)} 1.
% Check preconditions
:- occurs(Action, t), precondition(Action, Variable, Value), not holds(Variable, Value, t - 1).
% Apply effects
caused(Variable, Value, t) :- occurs(Action, t), postcondition(Action, _, Variable, Value).
modified(Variable, t) :- caused(Variable, Value, t).
holds(Variable, Value, t) :- caused(Variable, Value, t).
holds(Variable, Value, t) :- holds(Variable, Value, t - 1), not modified(Variable, t).
% Check that variables have unique values
:- variable(Variable), not 1 {holds(Variable, Value, t) : contains(Variable, Value)} 1.
% Check mutexes
:- mutexGroup(MutexGroup), not {holds(Variable, Value, t) : contains(MutexGroup, Variable, Value)} 1.
#program check(t).
% Verify that goal is met
:- query(t), goal(Variable, Value), not holds(Variable, Value, t).
#show query/1.
#show occurs/2.

36
include/plasp/Language.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef __PLASP__LANGUAGE_H
#define __PLASP__LANGUAGE_H
#include <plasp/utils/Parser.h>
namespace plasp
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Language
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Language
{
public:
enum class Type
{
Unknown,
PDDL,
SAS
};
static std::string toString(Type language);
static Language::Type fromString(const std::string &languageName);
public:
Language() = delete;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
#endif

View File

@@ -0,0 +1,49 @@
#ifndef __PLASP__LANGUAGE_DETECTION_H
#define __PLASP__LANGUAGE_DETECTION_H
#include <plasp/Language.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// LanguageDetection
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Language::Type detectLanguage(utils::Parser<utils::CaseInsensitiveParserPolicy> &parser)
{
parser.skipWhiteSpace();
// SAS begins with "begin_version"
if (parser.testAndSkip<std::string>("begin"))
{
parser.seek(0);
return Language::Type::SAS;
}
// Skip potential PDDL comments
while (parser.currentCharacter() == ';')
{
parser.skipLine();
parser.skipWhiteSpace();
}
// PDDL contains sections starting with "(define"
if (parser.testAndSkip<std::string>("(") && parser.testAndSkip<std::string>("define"))
{
parser.seek(std::ios::beg);
return Language::Type::PDDL;
}
parser.seek(std::ios::beg);
return Language::Type::Unknown;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
#endif

View File

@@ -0,0 +1,48 @@
#ifndef __PLASP__PDDL__ACTION_H
#define __PLASP__PDDL__ACTION_H
#include <vector>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/expressions/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Action
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Action
{
public:
static void parseDeclaration(Context &context, Domain &domain);
public:
const std::string &name() const;
const expressions::Variables &parameters() const;
const Expression *precondition() const;
const Expression *effect() const;
private:
Action() = default;
std::string m_name;
expressions::Variables m_parameters;
std::unique_ptr<Expression> m_precondition;
std::unique_ptr<Expression> m_effect;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,57 @@
#ifndef __PLASP__PDDL__CONSISTENCY_EXCEPTION_H
#define __PLASP__PDDL__CONSISTENCY_EXCEPTION_H
#include <exception>
#include <string>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ConsistencyException
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class ConsistencyException: public std::exception
{
public:
explicit ConsistencyException()
: ConsistencyException("unspecified consistency error")
{
}
explicit ConsistencyException(const char *message)
: ConsistencyException(static_cast<std::string>(message))
{
}
explicit ConsistencyException(const std::string &message)
: m_message{message}
{
}
~ConsistencyException() throw()
{
}
const char *what() const throw()
{
if (m_message.empty())
return "unspecified consistency error";
return m_message.c_str();
}
private:
std::string m_message;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,70 @@
#ifndef __PLASP__PDDL__CONTEXT_H
#define __PLASP__PDDL__CONTEXT_H
#include <memory>
#include <unordered_map>
#include <vector>
#include <plasp/pddl/Parser.h>
#include <plasp/utils/Logger.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Context
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Context
{
public:
Context() = default;
~Context() = default;
explicit Context(Parser &&otherParser)
: parser{std::move(otherParser)}
{
}
explicit Context(utils::Logger &&otherLogger)
: logger{std::move(otherLogger)}
{
}
explicit Context(Parser &&otherParser, utils::Logger &&otherLogger)
: parser{std::move(otherParser)},
logger{std::move(otherLogger)}
{
}
Context(const Context &other) = delete;
Context &operator=(const Context &other) = delete;
Context(Context &&other)
: parser(std::move(other.parser)),
logger(std::move(other.logger))
{
}
Context &operator=(Context &&other)
{
parser = std::move(other.parser);
logger = std::move(other.logger);
return *this;
}
Parser parser;
utils::Logger logger;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,59 @@
#ifndef __PLASP__PDDL__DESCRIPTION_H
#define __PLASP__PDDL__DESCRIPTION_H
#include <boost/filesystem/path.hpp>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/Problem.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Description
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Description
{
public:
static Description fromContext(Context &&context);
static Description fromStream(std::istream &istream);
static Description fromFile(const std::string &path);
static Description fromFiles(const std::vector<std::string> &paths);
public:
Context &context();
const Context &context() const;
const Domain &domain() const;
bool containsProblem() const;
const Problem &problem() const;
private:
Description();
void parse();
void findSections();
void checkConsistency();
Context m_context;
utils::Stream::Position m_domainPosition;
std::unique_ptr<Domain> m_domain;
utils::Stream::Position m_problemPosition;
std::unique_ptr<Problem> m_problem;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,93 @@
#ifndef __PLASP__PDDL__DOMAIN_H
#define __PLASP__PDDL__DOMAIN_H
#include <plasp/pddl/Action.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Parser.h>
#include <plasp/pddl/Requirement.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Domain
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Domain
{
public:
Domain(Context &context);
public:
void findSections();
void parse();
void setName(std::string name);
const std::string &name() const;
const Requirements &requirements() const;
bool hasRequirement(Requirement::Type requirementType) const;
void checkRequirement(Requirement::Type requirementType) const;
expressions::PrimitiveTypes &types();
const expressions::PrimitiveTypes &types() const;
expressions::Constants &constants();
const expressions::Constants &constants() const;
expressions::PredicateDeclarations &predicates();
const expressions::PredicateDeclarations &predicates() const;
std::vector<std::unique_ptr<Action>> &actions();
const std::vector<std::unique_ptr<Action>> &actions() const;
void checkConsistency();
private:
void parseSection();
void parseRequirementSection();
void computeDerivedRequirements();
void parseTypeSection();
void parseConstantSection();
void parsePredicateSection();
void parseActionSection();
Context &m_context;
std::string m_name;
utils::Stream::Position m_requirementsPosition;
Requirements m_requirements;
utils::Stream::Position m_typesPosition;
expressions::PrimitiveTypes m_types;
utils::Stream::Position m_constantsPosition;
expressions::Constants m_constants;
utils::Stream::Position m_predicatesPosition;
expressions::PredicateDeclarations m_predicates;
std::vector<utils::Stream::Position> m_actionPositions;
std::vector<std::unique_ptr<Action>> m_actions;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,130 @@
#ifndef __PLASP__PDDL__EXPRESSION_H
#define __PLASP__PDDL__EXPRESSION_H
#include <memory>
#include <plasp/utils/Parser.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Expression
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Context;
class Domain;
class ExpressionContext;
class ExpressionVisitor;
class Problem;
class Expression;
using ExpressionPointer = std::unique_ptr<Expression>;
using Expressions = std::vector<ExpressionPointer>;
namespace expressions
{
class And;
using AndPointer = std::unique_ptr<And>;
class At;
using AtPointer = std::unique_ptr<At>;
class Constant;
using ConstantPointer = std::unique_ptr<Constant>;
using Constants = std::vector<ConstantPointer>;
class Either;
using EitherPointer = std::unique_ptr<Either>;
class Imply;
using ImplyPointer = std::unique_ptr<Imply>;
class Not;
using NotPointer = std::unique_ptr<Not>;
class Or;
using OrPointer = std::unique_ptr<Or>;
class Predicate;
using PredicatePointer = std::unique_ptr<Predicate>;
using Predicates = std::vector<PredicatePointer>;
class PredicateDeclaration;
using PredicateDeclarationPointer = std::unique_ptr<PredicateDeclaration>;
using PredicateDeclarations = std::vector<PredicateDeclarationPointer>;
class PrimitiveType;
using PrimitiveTypePointer = std::unique_ptr<PrimitiveType>;
using PrimitiveTypes = std::vector<PrimitiveTypePointer>;
class Unsupported;
using UnsupportedPointer = std::unique_ptr<Unsupported>;
class Variable;
using VariablePointer = std::unique_ptr<Variable>;
using Variables = std::vector<VariablePointer>;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
class Expression
{
public:
enum class Type
{
And,
At,
Binary,
Constant,
Either,
Imply,
Not,
Or,
PredicateDeclaration,
Predicate,
PrimitiveType,
Unsupported,
Variable
};
public:
virtual ~Expression() = default;
virtual Type expressionType() const = 0;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
class ExpressionCRTP: public Expression
{
public:
Type expressionType() const override final
{
return Derived::ExpressionType;
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseLiteral(Context &context, ExpressionContext &expressionContext);
ExpressionPointer parseAtomicFormula(Context &context, ExpressionContext &expressionContext);
ExpressionPointer parsePreconditionExpression(Context &context,
ExpressionContext &expressionContext);
ExpressionPointer parseExpression(Context &context, ExpressionContext &expressionContext);
ExpressionPointer parseEffectExpression(Context &context,
ExpressionContext &expressionContext);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,38 @@
#ifndef __PLASP__PDDL__EXPRESSION_CONTEXT_H
#define __PLASP__PDDL__EXPRESSION_CONTEXT_H
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Requirement.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ExpressionContext
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class ExpressionContext
{
public:
ExpressionContext(Domain &domain, expressions::Variables &parameters);
ExpressionContext(Domain &domain, Problem *problem, expressions::Variables &parameters);
bool hasRequirement(Requirement::Type requirementType) const;
void checkRequirement(Requirement::Type requirementType) const;
Domain &domain;
Problem *problem;
expressions::Variables &parameters;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

45
include/plasp/pddl/IO.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef __PLASP__PDDL__IO_H
#define __PLASP__PDDL__IO_H
#include <iostream>
#include <plasp/pddl/Parser.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// IO
//
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void skipSection(Parser &parser)
{
size_t openParentheses = 1;
while (true)
{
const auto character = parser.currentCharacter();
parser.advance();
if (character == '(')
openParentheses++;
else if (character == ')')
{
openParentheses--;
if (openParentheses == 0)
return;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,35 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__INITIAL_STATE_H
#define __PLASP__PDDL__EXPRESSIONS__INITIAL_STATE_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// InitialState
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class InitialState
{
public:
static std::unique_ptr<InitialState> parseDeclaration(Context &context,
ExpressionContext &expressionContext);
public:
const Expressions &facts() const;
private:
Expressions m_facts;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,49 @@
#ifndef __PLASP__PDDL__PARSER_H
#define __PLASP__PDDL__PARSER_H
#include <plasp/utils/Parser.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Parser
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class PDDLParserPolicy
{
public:
static char transformCharacter(char c) noexcept
{
return std::tolower(c);
}
static bool isWhiteSpaceCharacter(char c)
{
return std::iswspace(c);
}
static bool isIdentifierCharacter(char c)
{
return c != '?'
&& c != '('
&& c != ')'
&& c != ';'
&& std::isgraph(c);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
using Parser = utils::Parser<PDDLParserPolicy>;
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,85 @@
#ifndef __PLASP__PDDL__PROBLEM_H
#define __PLASP__PDDL__PROBLEM_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/InitialState.h>
#include <plasp/pddl/Parser.h>
#include <plasp/pddl/Requirement.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Problem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Problem
{
public:
Problem(Context &context, Domain &domain);
void findSections();
void parse();
Domain &domain();
const Domain &domain() const;
const std::string &name() const;
const Requirements &requirements() const;
bool hasRequirement(Requirement::Type requirementType) const;
void checkRequirement(Requirement::Type requirementType) const;
expressions::Constants &objects();
const expressions::Constants &objects() const;
InitialState &initialState();
const InitialState &initialState() const;
const Expression &goal() const;
void checkConsistency();
private:
void parseRequirementSection();
void computeDerivedRequirements();
void parseDomainSection();
void parseObjectSection();
void parseInitialStateSection();
void parseGoalSection();
Context &m_context;
Domain &m_domain;
std::string m_name;
utils::Stream::Position m_domainPosition;
utils::Stream::Position m_requirementsPosition;
Requirements m_requirements;
utils::Stream::Position m_objectsPosition;
expressions::Constants m_objects;
utils::Stream::Position m_initialStatePosition;
std::unique_ptr<InitialState> m_initialState;
utils::Stream::Position m_goalPosition;
ExpressionPointer m_goal;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,72 @@
#ifndef __PLASP__PDDL__REQUIREMENT_H
#define __PLASP__PDDL__REQUIREMENT_H
#include <vector>
#include <plasp/pddl/Context.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Requirement
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Requirement;
using Requirements = std::vector<Requirement>;
////////////////////////////////////////////////////////////////////////////////////////////////////
class Requirement
{
public:
enum class Type
{
STRIPS,
Typing,
NegativePreconditions,
DisjunctivePreconditions,
Equality,
ExistentialPreconditions,
UniversalPreconditions,
QuantifiedPreconditions,
ConditionalEffects,
Fluents,
NumericFluents,
ObjectFluents,
ADL,
DurativeActions,
DurationInequalities,
ContinuousEffects,
DerivedPredicates,
TimedInitialLiterals,
Preferences,
Constraints,
ActionCosts,
GoalUtilities
};
static Requirement parse(Context &context);
public:
Requirement(Type type);
Type type() const;
std::string toPDDL() const;
std::string toASP() const;
private:
Type m_type;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,51 @@
#ifndef __PLASP__PDDL__TRANSLATOR_ASP_H
#define __PLASP__PDDL__TRANSLATOR_ASP_H
#include <plasp/pddl/Description.h>
#include <iosfwd>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// TranslatorASP
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class TranslatorASP
{
public:
explicit TranslatorASP(const Description &description, utils::LogStream &outputStream);
void translate() const;
private:
void translateDomain() const;
void translateTypes() const;
void translatePredicates() const;
void translateActions() const;
void translateProblem() const;
void translateInitialState() const;
void translateGoal() const;
void translateConstants(const std::string &heading, const expressions::Constants &constants) const;
void translateVariablesHead(const expressions::Variables &variables) const;
void translateVariablesBody(const expressions::Variables &variables) const;
void translateLiteral(const Expression &literal) const;
void translatePredicate(const expressions::Predicate &predicate) const;
const Description &m_description;
utils::LogStream &m_outputStream;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,33 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__AND_H
#define __PLASP__PDDL__EXPRESSIONS__AND_H
#include <plasp/pddl/expressions/NAry.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// And
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class And: public NAry<And>
{
public:
static const Expression::Type ExpressionType = Expression::Type::And;
static const std::string Identifier;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,105 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__AT_H
#define __PLASP__PDDL__EXPRESSIONS__AT_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// At
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class At: public ExpressionCRTP<At>
{
public:
static const Expression::Type ExpressionType = Expression::Type::At;
template<typename ExpressionParser>
static AtPointer parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
static const size_t TimePointStart = std::numeric_limits<size_t>::max();
static const size_t TimePointEnd = std::numeric_limits<size_t>::max() - 1;
public:
At();
size_t timePoint() const;
const Expression *argument() const;
private:
void setArgument(const Expression *argument);
void setArgument(ExpressionPointer &&argument);
size_t m_timePoint;
const Expression *m_argument;
ExpressionPointer m_argumentStorage;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
AtPointer At::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto &parser = context.parser;
const auto position = parser.position();
if (!parser.testAndSkip<std::string>("(")
|| !parser.testIdentifierAndSkip("at"))
{
parser.seek(position);
return nullptr;
}
size_t timePoint;
const auto timePointPosition = parser.position();
if (parser.testIdentifierAndSkip("start"))
timePoint = TimePointStart;
else if (parser.testIdentifierAndSkip("end"))
timePoint = TimePointEnd;
else if (parser.probeNumber())
{
parser.seek(timePointPosition);
timePoint = parser.parse<size_t>();
}
else
{
parser.seek(position);
return nullptr;
}
auto expression = std::make_unique<At>(At());
expression->m_timePoint = timePoint;
context.parser.skipWhiteSpace();
// Parse argument
expression->setArgument(parseExpression(context, expressionContext));
parser.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,111 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__BINARY_H
#define __PLASP__PDDL__EXPRESSIONS__BINARY_H
#include <plasp/pddl/ConsistencyException.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/expressions/Variable.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Binary
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
class Binary: public ExpressionCRTP<Derived>
{
public:
template<typename ExpressionParser>
static std::unique_ptr<Derived> parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression);
public:
const std::array<const Expression *, 2> &arguments() const;
private:
template<size_t i>
void setArgument(const Expression *argument);
template<size_t i>
void setArgument(ExpressionPointer &&argument);
std::array<const Expression *, 2> m_arguments;
std::array<ExpressionPointer, 2> m_argumentStorage;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
template<typename ExpressionParser>
std::unique_ptr<Derived> Binary<Derived>::parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression)
{
auto &parser = context.parser;
const auto position = parser.position();
if (!parser.testAndSkip<std::string>("(")
|| !parser.testIdentifierAndSkip(Derived::Identifier))
{
parser.seek(position);
return nullptr;
}
auto expression = std::make_unique<Derived>();
// Assume that expression identifier (imply, exists, etc.) is already parsed
// Parse arguments of the expression
expression->Binary<Derived>::setArgument<0>(parseExpression(context, expressionContext));
expression->Binary<Derived>::setArgument<1>(parseExpression(context, expressionContext));
parser.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
template<size_t i>
void Binary<Derived>::setArgument(const Expression *expression)
{
static_assert(i <= 2, "Index out of range");
m_argumentStorage[i] = nullptr;
m_arguments[i] = expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
template<size_t i>
void Binary<Derived>::setArgument(ExpressionPointer &&expression)
{
static_assert(i <= 2, "Index out of range");
m_argumentStorage[i] = std::move(expression);
m_arguments[i] = m_argumentStorage[i].get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
const std::array<const Expression *, 2> &Binary<Derived>::arguments() const
{
return m_arguments;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,64 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__CONSTANT_H
#define __PLASP__PDDL__EXPRESSIONS__CONSTANT_H
#include <plasp/pddl/Expression.h>
#include <plasp/utils/Parser.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constant
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Constant: public ExpressionCRTP<Constant>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Constant;
static void parseTypedDeclaration(Context &context, Domain &domain);
static void parseTypedDeclarations(Context &context, Domain &domain);
static void parseTypedDeclaration(Context &context, Problem &problem);
static void parseTypedDeclarations(Context &context, Problem &problem);
static Constant *parseAndFind(Context &context, const Domain &domain);
static Constant *parseAndFind(Context &context, const Problem &problem);
public:
const std::string &name() const;
const PrimitiveType *type() const;
private:
static ConstantPointer parseDeclaration(Context &context);
static void parseTypedDeclaration(Context &context, Domain &domain, Constants &constants);
static Constant *parseAndFind(const std::string &constantName, const Constants &constants);
Constant();
void setDirty(bool isDirty = true);
bool isDirty() const;
void setType(const PrimitiveType *parentType);
bool m_isDirty;
std::string m_name;
const PrimitiveType *m_type;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,33 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__EITHER_H
#define __PLASP__PDDL__EXPRESSIONS__EITHER_H
#include <plasp/pddl/expressions/NAry.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Either
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Either: public NAry<Either>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Either;
static const std::string Identifier;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,33 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__IMPLY_H
#define __PLASP__PDDL__EXPRESSIONS__IMPLY_H
#include <plasp/pddl/expressions/Binary.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Imply
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Imply: public Binary<Imply>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Imply;
static const std::string Identifier;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,117 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__N_ARY_H
#define __PLASP__PDDL__EXPRESSIONS__N_ARY_H
#include <plasp/pddl/ConsistencyException.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/expressions/Variable.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// NAry
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
class NAry: public ExpressionCRTP<Derived>
{
public:
template<typename ExpressionParser>
static std::unique_ptr<Derived> parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression);
public:
const std::vector<const Expression *> &arguments() const;
private:
void addArgument(const Expression *argument);
void addArgument(ExpressionPointer &&argument);
std::vector<const Expression *> m_arguments;
Expressions m_argumentStorage;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
template<typename ExpressionParser>
std::unique_ptr<Derived> NAry<Derived>::parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression)
{
auto &parser = context.parser;
const auto position = parser.position();
if (!parser.testAndSkip<std::string>("(")
|| !parser.testIdentifierAndSkip(Derived::Identifier))
{
parser.seek(position);
return nullptr;
}
auto expression = std::make_unique<Derived>();
parser.skipWhiteSpace();
// Assume that expression identifier (and, or, etc.) is already parsed
// Parse arguments of the expression
while (parser.currentCharacter() != ')')
{
expression->addArgument(parseExpression(context, expressionContext));
parser.skipWhiteSpace();
}
if (expression->m_arguments.empty())
context.logger.logWarning(parser.coordinate(), "" + Derived::Identifier + "” expressions should not be empty");
parser.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
void NAry<Derived>::addArgument(const Expression *argument)
{
if (!argument)
return;
m_arguments.emplace_back(argument);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
void NAry<Derived>::addArgument(ExpressionPointer &&argument)
{
if (!argument)
return;
m_argumentStorage.emplace_back(std::move(argument));
m_arguments.emplace_back(m_argumentStorage.back().get());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
const std::vector<const Expression *> &NAry<Derived>::arguments() const
{
return m_arguments;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,77 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__NOT_H
#define __PLASP__PDDL__EXPRESSIONS__NOT_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Not
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Not: public ExpressionCRTP<Not>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Not;
template<typename ExpressionParser>
static NotPointer parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
public:
Not();
const Expression *argument() const;
private:
void setArgument(const Expression *argument);
void setArgument(ExpressionPointer &&argument);
const Expression *m_argument;
ExpressionPointer m_argumentStorage;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
NotPointer Not::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto &parser = context.parser;
const auto position = parser.position();
if (!parser.testAndSkip<std::string>("(")
|| !parser.testIdentifierAndSkip("not"))
{
parser.seek(position);
return nullptr;
}
auto expression = std::make_unique<Not>(Not());
context.parser.skipWhiteSpace();
// Parse argument
expression->setArgument(parseExpression(context, expressionContext));
parser.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,33 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__OR_H
#define __PLASP__PDDL__EXPRESSIONS__OR_H
#include <plasp/pddl/expressions/NAry.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Or
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Or: public NAry<Or>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Or;
static const std::string Identifier;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,50 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__PREDICATE_H
#define __PLASP__PDDL__EXPRESSIONS__PREDICATE_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Predicate
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Predicate: public ExpressionCRTP<Predicate>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Predicate;
static PredicatePointer parse(Context &context, ExpressionContext &expressionContext);
static PredicatePointer parse(Context &context, const Problem &problem);
public:
const std::string &name() const;
const std::vector<const Expression *> &arguments() const;
bool isDeclared() const;
private:
Predicate();
void setDeclared();
bool m_isDeclared;
std::string m_name;
std::vector<const Expression *> m_arguments;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,49 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__PREDICATE_DECLARATION_H
#define __PLASP__PDDL__EXPRESSIONS__PREDICATE_DECLARATION_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PredicateDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class PredicateDeclaration: public ExpressionCRTP<PredicateDeclaration>
{
public:
static const Expression::Type ExpressionType = Expression::Type::PredicateDeclaration;
static void parse(Context &context, Domain &domain);
public:
const std::string &name() const;
const Variables &arguments() const;
bool isDeclared() const;
private:
PredicateDeclaration();
void setDeclared();
bool m_isDeclared;
std::string m_name;
Variables m_parameters;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,55 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__PRIMITIVE_TYPE_H
#define __PLASP__PDDL__EXPRESSIONS__PRIMITIVE_TYPE_H
#include <plasp/pddl/ConsistencyException.h>
#include <plasp/pddl/Expression.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PrimitiveType
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class PrimitiveType: public ExpressionCRTP<PrimitiveType>
{
public:
static const Expression::Type ExpressionType = Expression::Type::PrimitiveType;
static void parseDeclaration(Context &context, Domain &domain);
static void parseTypedDeclaration(Context &context, Domain &domain);
static PrimitiveType *parseAndFind(Context &context, Domain &domain);
public:
PrimitiveType();
PrimitiveType(std::string name);
const std::string &name() const;
const std::vector<const PrimitiveType *> &parentTypes() const;
private:
void setDirty(bool isDirty = true);
bool isDirty() const;
bool m_isDirty;
std::string m_name;
std::vector<const PrimitiveType *> m_parentTypes;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,28 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__TYPE_H
#define __PLASP__PDDL__EXPRESSIONS__TYPE_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Type
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression *parseExistingPrimitiveType(Context &context,
ExpressionContext &expressionContext);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,40 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__UNSUPPORTED_H
#define __PLASP__PDDL__EXPRESSIONS__UNSUPPORTED_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Unsupported
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Unsupported: public ExpressionCRTP<Unsupported>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Unsupported;
static UnsupportedPointer parse(Context &context);
public:
const std::string &type() const;
private:
std::string m_type;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -0,0 +1,61 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__VARIABLE_H
#define __PLASP__PDDL__EXPRESSIONS__VARIABLE_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Variable
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Variable: public ExpressionCRTP<Variable>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Variable;
static void parseTypedDeclaration(Context &context, ExpressionContext &expressionContext);
static void parseTypedDeclarations(Context &context, ExpressionContext &expressionContext);
static const Variable *parseAndFind(Context &context,
const ExpressionContext &expressionContext);
public:
const std::string &name() const;
const Expression *type() const;
void setDirty(bool isDirty = true);
bool isDirty() const;
void setType(const Expression *type);
private:
static void parseDeclaration(Context &context, Variables &parameters);
private:
Variable();
bool m_isDirty;
std::string m_name;
const Expression *m_type;
// Stores "either" expression if necessary
ExpressionPointer m_eitherExpression;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@@ -6,6 +6,7 @@
#include <plasp/sas/Value.h>
#include <plasp/sas/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
@@ -26,8 +27,8 @@ using AssignedVariables = std::vector<AssignedVariable>;
class AssignedVariable
{
public:
static AssignedVariable fromSAS(std::istream &istream, const Variables &variables);
static AssignedVariable fromSAS(std::istream &istream, const Variable &variable);
static AssignedVariable fromSAS(utils::Parser<> &parser, const Variables &variables);
static AssignedVariable fromSAS(utils::Parser<> &parser, const Variable &variable);
public:
explicit AssignedVariable(const Variable &variable, const Value &value);

View File

@@ -5,6 +5,7 @@
#include <plasp/sas/AssignedVariable.h>
#include <plasp/sas/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
@@ -28,7 +29,7 @@ class AxiomRule
using Condition = AssignedVariable;
using Conditions = AssignedVariables;
static AxiomRule fromSAS(std::istream &istream, const Variables &variables);
static AxiomRule fromSAS(utils::Parser<> &parser, const Variables &variables);
public:
const Conditions &conditions() const;

View File

@@ -16,7 +16,7 @@ namespace sas
//
////////////////////////////////////////////////////////////////////////////////////////////////////
std::ostream &operator >>(std::ostream &ostream, const Description &description);
utils::LogStream &operator<<(utils::LogStream &ostream, const Description &description);
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -13,6 +13,7 @@
#include <plasp/sas/MutexGroup.h>
#include <plasp/sas/Operator.h>
#include <plasp/sas/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
@@ -28,6 +29,7 @@ namespace sas
class Description
{
public:
static Description fromParser(utils::Parser<> &&parser);
static Description fromStream(std::istream &istream);
static Description fromFile(const boost::filesystem::path &path);
@@ -43,17 +45,21 @@ class Description
bool usesAxiomRules() const;
bool usesConditionalEffects() const;
bool hasRequirements() const;
private:
Description();
void parseVersionSection(std::istream &istream) const;
void parseMetricSection(std::istream &istream);
void parseVariablesSection(std::istream &istream);
void parseMutexSection(std::istream &istream);
void parseInitialStateSection(std::istream &istream);
void parseGoalSection(std::istream &istream);
void parseOperatorSection(std::istream &istream);
void parseAxiomSection(std::istream &istream);
void parseContent(utils::Parser<> &parser);
void parseVersionSection(utils::Parser<> &parser) const;
void parseMetricSection(utils::Parser<> &parser);
void parseVariablesSection(utils::Parser<> &parser);
void parseMutexSection(utils::Parser<> &parser);
void parseInitialStateSection(utils::Parser<> &parser);
void parseGoalSection(utils::Parser<> &parser);
void parseOperatorSection(utils::Parser<> &parser);
void parseAxiomSection(utils::Parser<> &parser);
bool m_usesActionCosts;

View File

@@ -5,6 +5,7 @@
#include <plasp/sas/AssignedVariable.h>
#include <plasp/sas/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
@@ -28,7 +29,7 @@ class Effect
using Condition = AssignedVariable;
using Conditions = AssignedVariables;
static Effect fromSAS(std::istream &istream, const Variables &variables, Conditions &preconditions);
static Effect fromSAS(utils::Parser<> &parser, const Variables &variables, Conditions &preconditions);
public:
const Conditions &conditions() const;

View File

@@ -2,6 +2,7 @@
#define __PLASP__SAS__GOAL_H
#include <plasp/sas/AssignedVariable.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
@@ -20,7 +21,7 @@ class Goal
using Fact = AssignedVariable;
using Facts = AssignedVariables;
static Goal fromSAS(std::istream &istream, const Variables &variables);
static Goal fromSAS(utils::Parser<> &parser, const Variables &variables);
public:
const Facts &facts() const;

View File

@@ -2,6 +2,7 @@
#define __PLASP__SAS__INITIAL_STATE_H
#include <plasp/sas/AssignedVariable.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
@@ -20,7 +21,7 @@ class InitialState
using Fact = AssignedVariable;
using Facts = AssignedVariables;
static InitialState fromSAS(std::istream &istream, const Variables &variables);
static InitialState fromSAS(utils::Parser<> &parser, const Variables &variables);
public:
const Facts &facts() const;

View File

@@ -4,6 +4,7 @@
#include <vector>
#include <plasp/sas/AssignedVariable.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
@@ -27,7 +28,7 @@ class MutexGroup
using Fact = AssignedVariable;
using Facts = AssignedVariables;
static MutexGroup fromSAS(std::istream &istream, const Variables &variables);
static MutexGroup fromSAS(utils::Parser<> &parser, const Variables &variables);
public:
const Facts &facts() const;

View File

@@ -8,6 +8,8 @@
#include <plasp/sas/Effect.h>
#include <plasp/sas/Predicate.h>
#include <plasp/sas/Variable.h>
#include <plasp/utils/LogStream.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
@@ -31,10 +33,10 @@ class Operator
using Condition = AssignedVariable;
using Conditions = AssignedVariables;
static Operator fromSAS(std::istream &istream, const Variables &variables);
static Operator fromSAS(utils::Parser<> &parser, const Variables &variables);
public:
void printPredicateAsASP(std::ostream &ostream) const;
void printPredicateAsASP(utils::LogStream &ostream) const;
const Predicate &predicate() const;
const Conditions &preconditions() const;

View File

@@ -5,6 +5,9 @@
#include <string>
#include <vector>
#include <plasp/utils/LogStream.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
namespace sas
@@ -19,13 +22,13 @@ namespace sas
class Predicate
{
public:
static Predicate fromSAS(std::istream &istream);
static Predicate fromSAS(utils::Parser<> &parser);
using Arguments = std::vector<std::string>;
public:
void printAsSAS(std::ostream &ostream) const;
void printAsASP(std::ostream &ostream) const;
void printAsSAS(utils::LogStream &outputStream) const;
void printAsASP(utils::LogStream &outputStream) const;
const std::string &name() const;
const Arguments &arguments() const;

View File

@@ -2,6 +2,7 @@
#define __PLASP__SAS__TRANSLATOR_ASP_H
#include <plasp/sas/Description.h>
#include <plasp/utils/LogStream.h>
#include <iosfwd>
@@ -19,12 +20,21 @@ namespace sas
class TranslatorASP
{
public:
explicit TranslatorASP(const Description &description);
explicit TranslatorASP(const Description &description, utils::LogStream &outputStream);
void translate(std::ostream &ostream) const;
void translate() const;
private:
void translateRequirements() const;
void translateInitialState() const;
void translateGoal() const;
void translateVariables() const;
void translateActions() const;
void translateMutexes() const;
void translateAxiomRules() const;
const Description &m_description;
utils::LogStream &m_outputStream;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -5,6 +5,9 @@
#include <string>
#include <vector>
#include <plasp/utils/LogStream.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
namespace sas
@@ -36,15 +39,15 @@ struct Value
static const Value Any;
static const Value None;
static Value fromSAS(std::istream &istream);
static const Value &referenceFromSAS(std::istream &istream, const Variable &variable);
static Value fromSAS(utils::Parser<> &parser);
static const Value &referenceFromSAS(utils::Parser<> &parser, const Variable &variable);
public:
Value negated() const;
void printAsSAS(std::ostream &ostream) const;
void printAsASP(std::ostream &ostream) const;
void printAsASPPredicate(std::ostream &ostream) const;
void printAsSAS(utils::LogStream &outputStream) const;
void printAsASP(utils::LogStream &outputStream) const;
void printAsASPPredicate(utils::LogStream &outputStream) const;
Sign sign() const;
const std::string &name() const;

View File

@@ -6,6 +6,8 @@
#include <vector>
#include <plasp/sas/Value.h>
#include <plasp/utils/LogStream.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
@@ -26,11 +28,11 @@ using Variables = std::vector<Variable>;
class Variable
{
public:
static Variable fromSAS(std::istream &istream);
static const Variable &referenceFromSAS(std::istream &istream, const Variables &variables);
static Variable fromSAS(utils::Parser<> &parser);
static const Variable &referenceFromSAS(utils::Parser<> &parser, const Variables &variables);
public:
void printNameAsASPPredicate(std::ostream &ostream) const;
void printNameAsASPPredicate(utils::LogStream &outputStream) const;
const std::string &name() const;
int axiomLayer() const;

View File

@@ -5,6 +5,7 @@
#include <plasp/sas/Value.h>
#include <plasp/sas/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
@@ -25,7 +26,7 @@ using VariableTransitions = std::vector<VariableTransition>;
class VariableTransition
{
public:
static VariableTransition fromSAS(std::istream &istream, const Variables &variables);
static VariableTransition fromSAS(utils::Parser<> &parser, const Variables &variables);
public:
const Variable &variable() const;

View File

@@ -0,0 +1,203 @@
#ifndef __PLASP__UTILS__FORMATTING_H
#define __PLASP__UTILS__FORMATTING_H
#include <iostream>
#include <plasp/utils/LogStream.h>
namespace plasp
{
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Formatting
//
////////////////////////////////////////////////////////////////////////////////////////////////////
enum class Color
{
Black = 0,
Red = 1,
Green = 2,
Yellow = 3,
Blue = 4,
Magenta = 5,
Cyan = 6,
White = 7
};
////////////////////////////////////////////////////////////////////////////////////////////////////
enum class FontWeight
{
Normal = 0,
Bold = 1
};
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Format
{
Format(Color color, FontWeight fontWeight = FontWeight::Normal)
: m_color{color},
m_fontWeight{fontWeight}
{
}
Color m_color;
FontWeight m_fontWeight;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
inline LogStream &operator<<(LogStream &stream, const Format &format)
{
if (!stream.supportsColor())
return stream;
const auto fontWeightCode = static_cast<size_t>(format.m_fontWeight);
const auto colorCode = 30 + static_cast<size_t>(format.m_color);
return (stream << "\033[" << fontWeightCode << ";" << colorCode << "m");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
struct ResetFormat
{
};
////////////////////////////////////////////////////////////////////////////////////////////////////
inline LogStream &operator<<(LogStream &stream, const ResetFormat &)
{
if (!stream.supportsColor())
return stream;
return (stream << "\033[0m");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Token
{
Token(const std::string &name)
: name(name)
{
}
const std::string &name;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Keyword: public Token
{
Keyword(const std::string &name)
: Token(name)
{
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
inline LogStream &operator<<(LogStream &stream, const Keyword &keyword)
{
return (stream
<< utils::Format(utils::Color::White, utils::FontWeight::Bold)
<< keyword.name
<< utils::ResetFormat());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Number: public Token
{
Number(const std::string &name)
: Token(name)
{
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
inline LogStream &operator<<(LogStream &stream, const Number &number)
{
return (stream
<< utils::Format(utils::Color::Yellow, utils::FontWeight::Bold)
<< number.name
<< utils::ResetFormat());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Variable: public Token
{
Variable(const std::string &name)
: Token(name)
{
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
inline LogStream &operator<<(LogStream &stream, const Variable &variable)
{
return (stream
<< utils::Format(utils::Color::Green, utils::FontWeight::Bold)
<< variable.name
<< utils::ResetFormat());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Heading1: public Token
{
Heading1(const std::string &name)
: Token(name)
{
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
inline LogStream &operator<<(LogStream &stream, const Heading1 &heading1)
{
return (stream
<< utils::Format(utils::Color::Blue, utils::FontWeight::Bold)
<< "%---------------------------------------" << std::endl
<< "% " << heading1.name << std::endl
<< "%---------------------------------------"
<< utils::ResetFormat()
<< std::endl);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
struct Heading2: public Token
{
Heading2(const std::string &name)
: Token(name)
{
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
inline LogStream &operator<<(LogStream &stream, const Heading2 &heading2)
{
return (stream
<< utils::Format(utils::Color::Blue, utils::FontWeight::Bold)
<< "% " << heading2.name
<< utils::ResetFormat());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -1,17 +1,8 @@
#ifndef __PLASP__UTILS__PARSING_H
#define __PLASP__UTILS__PARSING_H
#include <algorithm>
#include <exception>
#include <iosfwd>
#include <sstream>
#include <string>
#include <typeinfo>
#ifndef __PLASP__UTILS__IO_H
#define __PLASP__UTILS__IO_H
#include <boost/algorithm/string/replace.hpp>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace utils
@@ -19,46 +10,10 @@ namespace utils
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Parsing
// IO
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
T parse(std::istream &istream)
{
T value;
try
{
istream >> value;
}
catch (const std::exception &e)
{
throw ParserException(std::string("Could not parse value of type ") + typeid(T).name() + " (" + e.what() + ")");
}
return value;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
void parseExpected(std::istream &istream, const T &expectedValue)
{
const auto value = parse<T>(istream);
if (value == expectedValue)
return;
std::stringstream errorStream;
errorStream << "Invalid format, expected " << expectedValue << ", got " + value;
throw utils::ParserException(errorStream.str());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline std::string escapeASP(const std::string &string)
{
auto escaped = string;
@@ -85,6 +40,17 @@ inline std::string unescapeASP(const std::string &string)
////////////////////////////////////////////////////////////////////////////////////////////////////
inline std::string escapeASPVariable(const std::string &string)
{
auto escaped = escapeASP(string);
escaped.front() = std::toupper(escaped.front());
return escaped;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@@ -0,0 +1,289 @@
#ifndef __PLASP__UTILS__LOG_STREAM_H
#define __PLASP__UTILS__LOG_STREAM_H
#include <iostream>
#include <unistd.h>
namespace plasp
{
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// LogStream
//
////////////////////////////////////////////////////////////////////////////////////////////////////
enum class StandardStream
{
Out,
Err
};
////////////////////////////////////////////////////////////////////////////////////////////////////
class LogStream
{
public:
enum class ColorPolicy
{
Never,
Auto,
Always
};
private:
using CharacterType = std::ostream::char_type;
using TraitsType = std::ostream::traits_type;
public:
LogStream(StandardStream standardStream)
: m_standardStream{standardStream},
m_colorPolicy{ColorPolicy::Auto}
{
}
LogStream(const LogStream &other)
: m_standardStream{other.m_standardStream},
m_colorPolicy{other.m_colorPolicy}
{
}
LogStream &operator=(const LogStream &other)
{
m_standardStream = other.m_standardStream;
m_colorPolicy = other.m_colorPolicy;
return *this;
}
LogStream(LogStream &&other)
: m_standardStream{other.m_standardStream},
m_colorPolicy{other.m_colorPolicy}
{
other.m_colorPolicy = ColorPolicy::Auto;
}
LogStream &operator=(LogStream &&other)
{
m_standardStream = other.m_standardStream;
m_colorPolicy = other.m_colorPolicy;
other.m_colorPolicy = ColorPolicy::Auto;
return *this;
}
void setColorPolicy(ColorPolicy colorPolicy)
{
m_colorPolicy = colorPolicy;
}
bool supportsColor() const
{
if (m_colorPolicy == ColorPolicy::Never)
return false;
if (m_colorPolicy == ColorPolicy::Always)
return true;
// Autodetect by checking whether output goes to a terminal
const auto fileDescriptor =
(m_standardStream == utils::StandardStream::Out)
? STDOUT_FILENO
: STDERR_FILENO;
return isatty(fileDescriptor);
}
std::ostream &ostream()
{
return (m_standardStream == utils::StandardStream::Out)
? std::cout
: std::cerr;
}
inline LogStream &operator<<(short value);
inline LogStream &operator<<(unsigned short value);
inline LogStream &operator<<(int value);
inline LogStream &operator<<(unsigned int value);
inline LogStream &operator<<(long value);
inline LogStream &operator<<(unsigned long value);
inline LogStream &operator<<(long long value);
inline LogStream &operator<<(unsigned long long value);
inline LogStream &operator<<(float value);
inline LogStream &operator<<(double value);
inline LogStream &operator<<(long double value);
inline LogStream &operator<<(bool value);
inline LogStream &operator<<(const void *value);
inline LogStream &operator<<(const char *value);
inline LogStream &operator<<(std::basic_streambuf<CharacterType, TraitsType> *sb);
inline LogStream &operator<<(std::ios_base &(*func)(std::ios_base &));
inline LogStream &operator<<(std::basic_ios<CharacterType, TraitsType> &(*func)(std::basic_ios<CharacterType, TraitsType> &));
inline LogStream &operator<<(std::basic_ostream<CharacterType, TraitsType> &(*func)(std::basic_ostream<CharacterType, TraitsType> &));
private:
StandardStream m_standardStream;
ColorPolicy m_colorPolicy;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(short value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(unsigned short value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(int value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(unsigned int value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(long value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(unsigned long value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(long long value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(unsigned long long value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(float value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(double value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(long double value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(bool value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(const void *value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(const char *value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(std::basic_streambuf<CharacterType, TraitsType>* sb)
{
ostream() << sb;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(std::ios_base &(*func)(std::ios_base &))
{
ostream() << func;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(std::basic_ios<CharacterType, TraitsType> &(*func)(std::basic_ios<CharacterType, TraitsType> &))
{
ostream() << func;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &LogStream::operator<<(std::basic_ostream<CharacterType, TraitsType> &(*func)(std::basic_ostream<CharacterType, TraitsType> &))
{
ostream() << func;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class CharacterType, class Traits, class Allocator>
inline LogStream &operator<<(LogStream &stream, const std::basic_string<CharacterType, Traits, Allocator> &string)
{
stream.ostream() << string;
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,62 @@
#ifndef __PLASP__UTILS__LOGGER_H
#define __PLASP__UTILS__LOGGER_H
#include <string>
#include <plasp/utils/LogStream.h>
#include <plasp/utils/ParserException.h>
#include <plasp/utils/StreamCoordinate.h>
namespace plasp
{
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Logger
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Logger
{
public:
enum class WarningLevel
{
Normal,
Error,
Ignore
};
public:
Logger();
Logger(const Logger &other);
Logger &operator=(const Logger &other);
Logger(Logger &&other);
Logger &operator=(Logger &&other);
LogStream &outputStream();
LogStream &errorStream();
void setWarningLevel(WarningLevel warningLevel);
void setColorPolicy(LogStream::ColorPolicy colorPolicy);
void logError(const std::string &message);
void logError(const StreamCoordinate &coordinate, const std::string &message);
void logWarning(const StreamCoordinate &parserCoordinate, const std::string &message);
private:
LogStream m_outputStream;
LogStream m_errorStream;
WarningLevel m_warningLevel;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,559 @@
#ifndef __PLASP__UTILS__PARSER_H
#define __PLASP__UTILS__PARSER_H
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
#include <boost/filesystem.hpp>
#include <plasp/utils/ParserException.h>
#include <plasp/utils/ParserPolicy.h>
#include <plasp/utils/Stream.h>
#include <plasp/utils/StreamCoordinate.h>
namespace plasp
{
namespace utils
{
template<typename Type>
struct Tag
{
};
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Parser
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy = CaseSensitiveParserPolicy>
class Parser: public Stream, public ParserPolicy
{
template<class OtherParserPolicy>
friend class Parser;
public:
explicit Parser();
explicit Parser(std::string streamName, std::istream &istream);
template<class OtherParser>
Parser(OtherParser &&otherParser)
{
m_stream = std::move(otherParser.m_stream);
m_delimiters = std::move(otherParser.m_delimiters);
}
void removeComments(const std::string &startSequence, const std::string &endSequence, bool removeEnd);
char currentCharacter() const;
template<typename Type>
Type parse();
template<typename Type>
bool testAndReturn(const Type &expectedValue);
template<typename Type>
bool testAndSkip(const Type &expectedValue);
template<typename Type>
void expect(const Type &expectedValue);
std::string parseIdentifier();
bool testIdentifierAndReturn(const std::string &identifier);
bool testIdentifierAndSkip(const std::string &identifier);
// TODO: remove
bool probeNumber();
std::string parseLine();
void skipWhiteSpace();
void skipLine();
private:
std::string parseImpl(Tag<std::string>);
char parseImpl(Tag<char>);
uint64_t parseImpl(Tag<uint64_t>);
int64_t parseImpl(Tag<int64_t>);
uint32_t parseImpl(Tag<uint32_t>);
int32_t parseImpl(Tag<int32_t>);
bool parseImpl(Tag<bool>);
bool testImpl(const std::string &expectedValue);
bool testImpl(char expectedValue);
bool testImpl(uint64_t expectedValue);
bool testImpl(int64_t expectedValue);
bool testImpl(uint32_t expectedValue);
bool testImpl(int32_t expectedValue);
bool testImpl(bool expectedValue);
uint64_t parseIntegerBody();
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
Parser<ParserPolicy>::Parser()
: Stream()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
Parser<ParserPolicy>::Parser(std::string streamName, std::istream &istream)
: Stream(streamName, istream)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
void Parser<ParserPolicy>::skipWhiteSpace()
{
check();
while (!atEnd() && ParserPolicy::isWhiteSpaceCharacter(currentCharacter()))
advance();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
void Parser<ParserPolicy>::skipLine()
{
check();
while (currentCharacter() != '\n')
advance();
advance();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
template<typename Type>
Type Parser<ParserPolicy>::parse()
{
return parseImpl(Tag<Type>());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
template<typename Type>
bool Parser<ParserPolicy>::testAndReturn(const Type &expectedValue)
{
const auto previousPosition = position();
const auto result = testImpl(expectedValue);
seek(previousPosition);
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
template<typename Type>
bool Parser<ParserPolicy>::testAndSkip(const Type &expectedValue)
{
const auto previousPosition = position();
const auto result = testImpl(expectedValue);
if (result == false)
seek(previousPosition);
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
template<typename Type>
void Parser<ParserPolicy>::expect(const Type &expectedValue)
{
if (testAndSkip(expectedValue))
return;
std::stringstream message;
message << "unexpected value, expected “" << expectedValue << "";
throw ParserException(coordinate(), message.str());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
std::string Parser<ParserPolicy>::parseIdentifier()
{
skipWhiteSpace();
std::string value;
while (true)
{
const auto character = currentCharacter();
if (!ParserPolicy::isIdentifierCharacter(character))
return value;
value.push_back(character);
advance();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
bool Parser<ParserPolicy>::testIdentifierAndSkip(const std::string &expectedValue)
{
return testAndSkip(expectedValue) && !ParserPolicy::isIdentifierCharacter(currentCharacter());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
bool Parser<ParserPolicy>::probeNumber()
{
const auto previousPosition = position();
skipWhiteSpace();
while (!ParserPolicy::isWhiteSpaceCharacter(currentCharacter()))
if (!std::isdigit(currentCharacter()))
{
seek(previousPosition);
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
std::string Parser<ParserPolicy>::parseLine()
{
std::string value;
while (true)
{
const auto character = currentCharacter();
advance();
if (character == '\n')
break;
else if (character == '\r')
continue;
value.push_back(character);
}
return value;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
void Parser<ParserPolicy>::removeComments(const std::string &startSequence, const std::string &endSequence, bool removeEnd)
{
const auto inPosition = m_stream.tellg();
const auto outPosition = m_stream.tellp();
m_stream.seekg(0);
const auto removeRange =
[&](const auto &start, const auto &end)
{
BOOST_ASSERT(start != -1);
m_stream.clear();
m_stream.seekp(start);
m_stream.seekg(start);
auto position = start;
while (end == -1 || position < end)
{
m_stream.ignore(1);
if (atEnd())
return;
m_stream.put(' ');
position += static_cast<std::streamoff>(1);
}
};
while (!atEnd())
{
Position startPosition = m_stream.tellg();
while (!atEnd())
{
startPosition = m_stream.tellg();
if (testAndSkip(startSequence))
break;
advance();
}
Position endPosition = m_stream.tellg();
while (!atEnd())
{
endPosition = m_stream.tellg();
if (testAndSkip(endSequence))
break;
advance();
}
if (removeEnd)
endPosition = m_stream.tellg();
removeRange(startPosition, endPosition);
}
m_stream.clear();
m_stream.seekg(inPosition);
m_stream.seekp(outPosition);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
char Parser<ParserPolicy>::currentCharacter() const
{
return ParserPolicy::transformCharacter(Stream::currentCharacter());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
std::string Parser<ParserPolicy>::parseImpl(Tag<std::string>)
{
skipWhiteSpace();
const auto startPosition = position();
while (!ParserPolicy::isWhiteSpaceCharacter(currentCharacter()))
advance();
const auto endPosition = position();
const auto length = static_cast<size_t>(endPosition - startPosition);
std::string value;
value.reserve(length);
seek(startPosition);
for (size_t i = 0; i < length; i++)
{
value.push_back(currentCharacter());
advance();
}
return value;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
char Parser<ParserPolicy>::parseImpl(Tag<char>)
{
const auto value = currentCharacter();
advance();
return value;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
uint64_t Parser<ParserPolicy>::parseIntegerBody()
{
check();
if (!std::isdigit(currentCharacter()))
throw ParserException(coordinate(), "could not parse integer value");
uint64_t value = 0;
while (!atEnd())
{
const auto character = currentCharacter();
if (!std::isdigit(character))
break;
value *= 10;
value += character - '0';
advance();
}
return value;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
int64_t Parser<ParserPolicy>::parseImpl(Tag<int64_t>)
{
skipWhiteSpace();
bool positive = testAndSkip<char>('+') || !testAndSkip<char>('-');
const auto value = parseIntegerBody();
return (positive ? value : -value);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
uint64_t Parser<ParserPolicy>::parseImpl(Tag<uint64_t>)
{
skipWhiteSpace();
if (currentCharacter() == '-')
throw ParserException(coordinate(), "expected unsigned integer, got signed one");
return parseIntegerBody();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
int32_t Parser<ParserPolicy>::parseImpl(Tag<int32_t>)
{
return static_cast<int32_t>(parseImpl(Tag<int64_t>()));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
uint32_t Parser<ParserPolicy>::parseImpl(Tag<uint32_t>)
{
return static_cast<uint32_t>(parseImpl(Tag<uint64_t>()));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
bool Parser<ParserPolicy>::parseImpl(Tag<bool>)
{
skipWhiteSpace();
if (testAndSkip<char>('0'))
return false;
if (testAndSkip<char>('1'))
return true;
throw ParserException(coordinate(), "could not parse Boolean value");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
bool Parser<ParserPolicy>::testImpl(const std::string &expectedValue)
{
if (!ParserPolicy::isWhiteSpaceCharacter(expectedValue.front()))
skipWhiteSpace();
const auto match = std::find_if(expectedValue.cbegin(), expectedValue.cend(),
[&](const auto &expectedCharacter)
{
const auto character = static_cast<char>(this->currentCharacter());
if (character != expectedCharacter)
return true;
this->advance();
return false;
});
return (match == expectedValue.cend());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
bool Parser<ParserPolicy>::testImpl(char expectedValue)
{
const auto result = (currentCharacter() == expectedValue);
advance();
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
bool Parser<ParserPolicy>::testImpl(int64_t expectedValue)
{
const auto value = parseImpl(Tag<int64_t>());
return (value == expectedValue);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
bool Parser<ParserPolicy>::testImpl(uint64_t expectedValue)
{
const auto value = parseImpl(Tag<uint64_t>());
return (value == expectedValue);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
bool Parser<ParserPolicy>::testImpl(int32_t expectedValue)
{
return testImpl(static_cast<int64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
bool Parser<ParserPolicy>::testImpl(uint32_t expectedValue)
{
return testImpl(static_cast<uint64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ParserPolicy>
bool Parser<ParserPolicy>::testImpl(bool expectedValue)
{
const auto value = parseImpl(Tag<bool>());
return (value == expectedValue);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -4,6 +4,8 @@
#include <exception>
#include <string>
#include <plasp/utils/StreamCoordinate.h>
namespace plasp
{
namespace utils
@@ -18,17 +20,21 @@ namespace utils
class ParserException: public std::exception
{
public:
explicit ParserException()
explicit ParserException(const StreamCoordinate &coordinate)
: ParserException(coordinate, "unspecified parser error")
{
}
explicit ParserException(const char *message)
: m_message(message)
explicit ParserException(const StreamCoordinate &coordinate, const char *message)
: ParserException(coordinate, static_cast<std::string>(message))
{
}
explicit ParserException(const std::string &message)
: m_message(message)
explicit ParserException(const StreamCoordinate &coordinate, const std::string &message)
: m_coordinate{coordinate},
m_message{message},
m_plainMessage{m_coordinate.sectionName + ":" + std::to_string(m_coordinate.row)
+ ":" + std::to_string(m_coordinate.column) + " " + m_message}
{
}
@@ -38,14 +44,23 @@ class ParserException: public std::exception
const char *what() const throw()
{
if (m_message.empty())
return "Unspecified error while parsing SAS description file";
return m_plainMessage.c_str();
}
return m_message.c_str();
const StreamCoordinate &coordinate() const
{
return m_coordinate;
}
const std::string &message() const
{
return m_message;
}
private:
StreamCoordinate m_coordinate;
std::string m_message;
std::string m_plainMessage;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,62 @@
#ifndef __PLASP__UTILS__PARSER_POLICY_H
#define __PLASP__UTILS__PARSER_POLICY_H
#include <iostream>
namespace plasp
{
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ParserPolicy
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class CaseSensitiveParserPolicy
{
public:
static constexpr char transformCharacter(char c) noexcept
{
return c;
}
static bool isWhiteSpaceCharacter(char c)
{
return std::iswspace(c);
}
static bool isIdentifierCharacter(char c)
{
return std::isgraph(c);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
class CaseInsensitiveParserPolicy
{
public:
static char transformCharacter(char c) noexcept
{
return std::tolower(c);
}
static bool isWhiteSpaceCharacter(char c)
{
return std::iswspace(c);
}
static bool isIdentifierCharacter(char c)
{
return std::isgraph(c);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,84 @@
#ifndef __PLASP__UTILS__STREAM_H
#define __PLASP__UTILS__STREAM_H
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
#include <boost/filesystem.hpp>
#include <plasp/utils/ParserException.h>
#include <plasp/utils/StreamCoordinate.h>
namespace plasp
{
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Stream
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Stream
{
public:
using Position = std::stringstream::pos_type;
struct Delimiter
{
Position position;
std::string sectionName;
};
public:
explicit Stream();
explicit Stream(std::string streamName, std::istream &istream);
Stream(const Stream &other) = delete;
Stream &operator=(const Stream &other) = delete;
Stream(Stream &&other)
: m_stream{std::move(other.m_stream)},
m_delimiters{std::move(other.m_delimiters)}
{
}
Stream &operator=(Stream &&other)
{
m_stream = std::move(other.m_stream);
m_delimiters = std::move(other.m_delimiters);
return *this;
}
~Stream() = default;
void read(std::string streamName, std::istream &istream);
void read(const boost::filesystem::path &path);
void reset();
void seek(Position position);
Position position() const;
StreamCoordinate coordinate() const;
char currentCharacter() const;
void advance();
bool atEnd() const;
void check() const;
protected:
mutable std::stringstream m_stream;
std::vector<Delimiter> m_delimiters;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,29 @@
#ifndef __PLASP__UTILS__STREAM_COORDINATE_H
#define __PLASP__UTILS__STREAM_COORDINATE_H
#include <string>
namespace plasp
{
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// StreamCoordinate
//
////////////////////////////////////////////////////////////////////////////////////////////////////
struct StreamCoordinate
{
std::string sectionName;
size_t row;
size_t column;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -1,12 +1,12 @@
#ifndef __PLASP__SAS__TRANSLATOR_EXCEPTION_H
#define __PLASP__SAS__TRANSLATOR_EXCEPTION_H
#ifndef __PLASP__UTILS__TRANSLATOR_EXCEPTION_H
#define __PLASP__UTILS__TRANSLATOR_EXCEPTION_H
#include <exception>
#include <string>
namespace plasp
{
namespace sas
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -39,7 +39,7 @@ class TranslatorException: public std::exception
const char *what() const throw()
{
if (m_message.empty())
return "Unspecified error while translating SAS description";
return "Unspecified error while translating description";
return m_message.c_str();
}

View File

@@ -3,6 +3,12 @@ set(target plasp)
file(GLOB core_sources "plasp/*.cpp")
file(GLOB core_headers "../include/plasp/*.h")
file(GLOB pddl_sources "plasp/pddl/*.cpp")
file(GLOB pddl_headers "../include/plasp/pddl/*.h")
file(GLOB pddl_expressions_sources "plasp/pddl/expressions/*.cpp")
file(GLOB pddl_expressions_headers "../include/plasp/pddl/expressions/*.h")
file(GLOB sas_sources "plasp/sas/*.cpp")
file(GLOB sas_headers "../include/plasp/sas/*.h")
@@ -21,6 +27,12 @@ set(sources
${core_sources}
${core_headers}
${pddl_sources}
${pddl_headers}
${pddl_expressions_sources}
${pddl_expressions_headers}
${sas_sources}
${sas_headers}

50
src/plasp/Language.cpp Normal file
View File

@@ -0,0 +1,50 @@
#include <plasp/Language.h>
#include <boost/assign.hpp>
#include <boost/bimap.hpp>
namespace plasp
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Language
//
////////////////////////////////////////////////////////////////////////////////////////////////////
using LanguageNames = boost::bimap<Language::Type, std::string>;
////////////////////////////////////////////////////////////////////////////////////////////////////
const LanguageNames languageNames = boost::assign::list_of<LanguageNames::relation>
(Language::Type::PDDL, "pddl")
(Language::Type::SAS, "sas")
(Language::Type::Unknown, "unknown");
////////////////////////////////////////////////////////////////////////////////////////////////////
std::string Language::toString(Language::Type language)
{
const auto match = languageNames.left.find(language);
if (match == languageNames.left.end())
return "unknown";
return match->second;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Language::Type Language::fromString(const std::string &languageName)
{
const auto match = languageNames.right.find(languageName);
if (match == languageNames.right.end())
return Language::Type::Unknown;
return match->second;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}

92
src/plasp/pddl/Action.cpp Normal file
View File

@@ -0,0 +1,92 @@
#include <plasp/pddl/Action.h>
#include <algorithm>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/expressions/Type.h>
#include <plasp/utils/IO.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Action
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void Action::parseDeclaration(Context &context, Domain &domain)
{
auto &parser = context.parser;
auto action = std::make_unique<Action>(Action());
action->m_name = parser.parseIdentifier();
parser.expect<std::string>(":parameters");
parser.expect<std::string>("(");
ExpressionContext expressionContext(domain, action->m_parameters);
// Read parameters
expressions::Variable::parseTypedDeclarations(context, expressionContext);
parser.expect<std::string>(")");
// Parse preconditions and effects
while (!parser.testAndReturn(')'))
{
parser.expect<std::string>(":");
if (parser.testIdentifierAndSkip("precondition"))
action->m_precondition = parsePreconditionExpression(context, expressionContext);
else if (parser.testIdentifierAndSkip("effect"))
action->m_effect = parseEffectExpression(context, expressionContext);
parser.skipWhiteSpace();
}
// Store new action
expressionContext.domain.actions().emplace_back(std::move(action));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Action::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::Variables &Action::parameters() const
{
return m_parameters;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression *Action::precondition() const
{
BOOST_ASSERT(m_precondition);
return m_precondition.get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression *Action::effect() const
{
BOOST_ASSERT(m_effect);
return m_effect.get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@@ -0,0 +1,208 @@
#include <plasp/pddl/Description.h>
#include <fstream>
#include <sstream>
#include <boost/filesystem.hpp>
#include <plasp/pddl/IO.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Description
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Description::Description()
: m_domainPosition{-1},
m_domain{std::make_unique<Domain>(Domain(m_context))},
m_problemPosition{-1}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromContext(Context &&context)
{
Description description;
description.m_context = std::move(context);
description.parse();
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromStream(std::istream &istream)
{
Description description;
description.m_context.parser.read("std::cin", istream);
description.parse();
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromFile(const std::string &path)
{
Description description;
description.m_context.parser.read(path);
description.parse();
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromFiles(const std::vector<std::string> &paths)
{
BOOST_ASSERT(!paths.empty());
Description description;
std::for_each(paths.cbegin(), paths.cend(),
[&](const auto &path)
{
description.m_context.parser.read(path);
});
description.parse();
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Context &Description::context()
{
return m_context;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Context &Description::context() const
{
return m_context;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Domain &Description::domain() const
{
BOOST_ASSERT(m_domain);
return *m_domain;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Description::containsProblem() const
{
return m_problem.get() != nullptr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Problem &Description::problem() const
{
BOOST_ASSERT(m_problem);
return *m_problem;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parse()
{
auto &parser = m_context.parser;
parser.removeComments(";", "\n", false);
// First, determine the locations of domain and problem
findSections();
if (m_domainPosition == -1)
throw ConsistencyException("no PDDL domain specified");
parser.seek(m_domainPosition);
m_domain->parse();
if (m_problemPosition != -1)
{
parser.seek(m_problemPosition);
m_problem->parse();
}
checkConsistency();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::findSections()
{
auto &parser = m_context.parser;
parser.skipWhiteSpace();
while (!parser.atEnd())
{
const auto position = parser.position();
parser.expect<std::string>("(");
parser.expect<std::string>("define");
parser.expect<std::string>("(");
if (parser.testAndSkip<std::string>("domain"))
{
if (m_domainPosition != -1)
throw utils::ParserException(parser.coordinate(), "PDDL description may not contain two domains");
m_domainPosition = position;
parser.seek(position);
m_domain->findSections();
}
else if (m_context.parser.testAndSkip<std::string>("problem"))
{
if (m_problemPosition != -1)
throw utils::ParserException(parser.coordinate(), "PDDL description may currently not contain two problems");
m_problem = std::make_unique<Problem>(Problem(m_context, *m_domain));
m_problemPosition = position;
parser.seek(position);
m_problem->findSections();
}
else
{
const auto sectionIdentifier = parser.parse<std::string>();
throw utils::ParserException(parser.coordinate(), "unknown PDDL section “" + sectionIdentifier + "");
}
m_context.parser.skipWhiteSpace();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::checkConsistency()
{
m_domain->checkConsistency();
m_problem->checkConsistency();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

418
src/plasp/pddl/Domain.cpp Normal file
View File

@@ -0,0 +1,418 @@
#include <plasp/pddl/Domain.h>
#include <algorithm>
#include <plasp/pddl/ConsistencyException.h>
#include <plasp/pddl/IO.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <plasp/pddl/expressions/Variable.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Domain
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Domain::Domain(Context &context)
: m_context(context),
m_requirementsPosition{-1},
m_typesPosition{-1},
m_constantsPosition{-1},
m_predicatesPosition{-1}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::findSections()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>("define");
parser.expect<std::string>("(");
parser.expect<std::string>("domain");
m_name = m_context.parser.parseIdentifier();
parser.expect<std::string>(")");
const auto setSectionPosition =
[&](const std::string &sectionName, auto &sectionPosition, const auto value, bool unique = false)
{
if (unique && sectionPosition != -1)
{
parser.seek(value);
throw utils::ParserException(parser.coordinate(), "only one “:" + sectionName + "” section allowed");
}
sectionPosition = value;
};
parser.skipWhiteSpace();
// Find sections
while (parser.currentCharacter() != ')')
{
const auto position = parser.position();
parser.expect<std::string>("(");
parser.expect<std::string>(":");
const auto sectionIdentifierPosition = parser.position();
// Save the parser position of the individual sections for later parsing
if (parser.testIdentifierAndSkip("requirements"))
setSectionPosition("requirements", m_requirementsPosition, position, true);
else if (parser.testIdentifierAndSkip("types"))
setSectionPosition("types", m_typesPosition, position, true);
else if (parser.testIdentifierAndSkip("constants"))
setSectionPosition("constants", m_constantsPosition, position, true);
else if (parser.testIdentifierAndSkip("predicates"))
setSectionPosition("predicates", m_predicatesPosition, position, true);
else if (parser.testIdentifierAndSkip("action"))
{
m_actionPositions.emplace_back(-1);
setSectionPosition("action", m_actionPositions.back(), position);
}
else if (parser.testIdentifierAndSkip("functions")
|| parser.testIdentifierAndSkip("constraints")
|| parser.testIdentifierAndSkip("durative-action")
|| parser.testIdentifierAndSkip("derived"))
{
parser.seek(sectionIdentifierPosition);
const auto sectionIdentifier = parser.parseIdentifier();
m_context.logger.logWarning(parser.coordinate(), "section type “" + sectionIdentifier + "” currently unsupported");
parser.seek(sectionIdentifierPosition);
}
else
{
const auto sectionIdentifier = parser.parseIdentifier();
parser.seek(position);
throw utils::ParserException(parser.coordinate(), "unknown domain section “" + sectionIdentifier + "");
}
// Skip section for now and parse it later
skipSection(parser);
parser.skipWhiteSpace();
}
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parse()
{
auto &parser = m_context.parser;
if (m_requirementsPosition != -1)
{
parser.seek(m_requirementsPosition);
parseRequirementSection();
}
if (m_typesPosition != -1)
{
parser.seek(m_typesPosition);
parseTypeSection();
}
if (m_constantsPosition != -1)
{
parser.seek(m_constantsPosition);
parseConstantSection();
}
if (m_predicatesPosition != -1)
{
parser.seek(m_predicatesPosition);
parsePredicateSection();
}
for (size_t i = 0; i < m_actionPositions.size(); i++)
if (m_actionPositions[i] != -1)
{
parser.seek(m_actionPositions[i]);
parseActionSection();
}
computeDerivedRequirements();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::setName(std::string name)
{
m_name = name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Domain::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Requirements &Domain::requirements() const
{
return m_requirements;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::PrimitiveTypes &Domain::types()
{
return m_types;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::PrimitiveTypes &Domain::types() const
{
return m_types;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::Constants &Domain::constants()
{
return m_constants;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::Constants &Domain::constants() const
{
return m_constants;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::PredicateDeclarations &Domain::predicates()
{
return m_predicates;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::PredicateDeclarations &Domain::predicates() const
{
return m_predicates;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<std::unique_ptr<Action>> &Domain::actions()
{
return m_actions;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::vector<std::unique_ptr<Action>> &Domain::actions() const
{
return m_actions;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parseRequirementSection()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("requirements");
while (parser.currentCharacter() != ')')
{
parser.expect<std::string>(":");
m_requirements.emplace_back(Requirement::parse(m_context));
parser.skipWhiteSpace();
}
// TODO: do this check only once the problem is parsed
// If no requirements are specified, assume STRIPS
if (m_requirements.empty())
m_requirements.emplace_back(Requirement::Type::STRIPS);
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Domain::hasRequirement(Requirement::Type requirementType) const
{
const auto match = std::find_if(m_requirements.cbegin(), m_requirements.cend(),
[&](const auto &requirement)
{
return requirement.type() == requirementType;
});
return match != m_requirements.cend();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::checkRequirement(Requirement::Type requirementType) const
{
if (hasRequirement(requirementType))
return;
throw ConsistencyException("requirement “" + Requirement(requirementType).toPDDL() + "” used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::computeDerivedRequirements()
{
const auto addRequirementUnique =
[&](const auto requirement)
{
if (hasRequirement(requirement))
return;
m_requirements.push_back(Requirement(requirement));
};
if (hasRequirement(Requirement::Type::ADL))
{
addRequirementUnique(Requirement::Type::STRIPS);
addRequirementUnique(Requirement::Type::Typing);
addRequirementUnique(Requirement::Type::NegativePreconditions);
addRequirementUnique(Requirement::Type::DisjunctivePreconditions);
addRequirementUnique(Requirement::Type::Equality);
addRequirementUnique(Requirement::Type::QuantifiedPreconditions);
addRequirementUnique(Requirement::Type::ConditionalEffects);
}
if (hasRequirement(Requirement::Type::QuantifiedPreconditions))
{
addRequirementUnique(Requirement::Type::ExistentialPreconditions);
addRequirementUnique(Requirement::Type::UniversalPreconditions);
}
if (hasRequirement(Requirement::Type::Fluents))
{
addRequirementUnique(Requirement::Type::NumericFluents);
addRequirementUnique(Requirement::Type::ObjectFluents);
}
if (hasRequirement(Requirement::Type::TimedInitialLiterals))
addRequirementUnique(Requirement::Type::DurativeActions);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parseTypeSection()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("types");
checkRequirement(Requirement::Type::Typing);
parser.skipWhiteSpace();
// Store types and their parent types
while (parser.currentCharacter() != ')')
{
if (parser.currentCharacter() == '(')
throw utils::ParserException(parser.coordinate(), "only primitive types are allowed in type section");
expressions::PrimitiveType::parseTypedDeclaration(m_context, *this);
parser.skipWhiteSpace();
}
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parseConstantSection()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("constants");
// Store constants
expressions::Constant::parseTypedDeclarations(m_context, *this);
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parsePredicateSection()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("predicates");
parser.skipWhiteSpace();
// Store predicates and their arguments
while (parser.currentCharacter() != ')')
{
expressions::PredicateDeclaration::parse(m_context, *this);
parser.skipWhiteSpace();
}
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parseActionSection()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("action");
Action::parseDeclaration(m_context, *this);
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::checkConsistency()
{
// Verify that constants are unique
// Verify that all primitive types are unique
// Check for case-sensitivity issues
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@@ -0,0 +1,254 @@
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/IO.h>
#include <plasp/pddl/expressions/And.h>
#include <plasp/pddl/expressions/Imply.h>
#include <plasp/pddl/expressions/Not.h>
#include <plasp/pddl/expressions/Or.h>
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/expressions/Unsupported.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Expression
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseEffectBodyExpression(Context &context, ExpressionContext &expressionContext);
ExpressionPointer parsePredicate(Context &context, ExpressionContext &expressionContext);
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parsePreconditionExpression(Context &context,
ExpressionContext &expressionContext)
{
auto &parser = context.parser;
parser.skipWhiteSpace();
ExpressionPointer expression;
if ((expression = expressions::And::parse(context, expressionContext, parsePreconditionExpression)))
return expression;
const auto position = parser.position();
parser.expect<std::string>("(");
const auto expressionIdentifierPosition = parser.position();
if (parser.testIdentifierAndSkip("forall")
|| parser.testIdentifierAndSkip("preference"))
{
// TODO: refactor
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier();
parser.seek(position);
return expressions::Unsupported::parse(context);
}
parser.seek(position);
return parseExpression(context, expressionContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseExpression(Context &context, ExpressionContext &expressionContext)
{
auto &parser = context.parser;
parser.skipWhiteSpace();
ExpressionPointer expression;
if ((expression = expressions::And::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Or::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Not::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Imply::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Predicate::parse(context, expressionContext)))
{
return expression;
}
const auto position = parser.position();
parser.expect<std::string>("(");
const auto expressionIdentifierPosition = parser.position();
if (parser.testIdentifierAndSkip("exists")
|| parser.testIdentifierAndSkip("forall")
|| parser.testIdentifierAndSkip("-")
|| parser.testIdentifierAndSkip("=")
|| parser.testIdentifierAndSkip("*")
|| parser.testIdentifierAndSkip("+")
|| parser.testIdentifierAndSkip("-")
|| parser.testIdentifierAndSkip("/")
|| parser.testIdentifierAndSkip(">")
|| parser.testIdentifierAndSkip("<")
|| parser.testIdentifierAndSkip("=")
|| parser.testIdentifierAndSkip(">=")
|| parser.testIdentifierAndSkip("<="))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier();
parser.seek(position);
return expressions::Unsupported::parse(context);
}
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier();
parser.seek(position);
throw utils::ParserException(parser.coordinate(), "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseEffectExpression(Context &context, ExpressionContext &expressionContext)
{
auto &parser = context.parser;
ExpressionPointer expression;
if ((expression = expressions::And::parse(context, expressionContext, parseEffectExpression)))
return expression;
const auto position = parser.position();
parser.expect<std::string>("(");
const auto expressionIdentifierPosition = parser.position();
if (parser.testIdentifierAndSkip("forall")
|| parser.testIdentifierAndSkip("when"))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier();
parser.seek(position);
return expressions::Unsupported::parse(context);
}
parser.seek(position);
return parseEffectBodyExpression(context, expressionContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseEffectBodyExpression(Context &context, ExpressionContext &expressionContext)
{
auto &parser = context.parser;
ExpressionPointer expression;
if ((expression = expressions::Not::parse(context, expressionContext, parsePredicate))
|| (expression = expressions::Predicate::parse(context, expressionContext)))
{
return expression;
}
const auto position = parser.position();
parser.expect<std::string>("(");
const auto expressionIdentifierPosition = parser.position();
if (parser.testIdentifierAndSkip("=")
|| parser.testIdentifierAndSkip("assign")
|| parser.testIdentifierAndSkip("scale-up")
|| parser.testIdentifierAndSkip("scale-down")
|| parser.testIdentifierAndSkip("increase")
|| parser.testIdentifierAndSkip("decrease"))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier();
parser.seek(position);
return expressions::Unsupported::parse(context);
}
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier();
parser.seek(position);
throw utils::ParserException(parser.coordinate(), "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parsePredicate(Context &context, ExpressionContext &expressionContext)
{
auto &parser = context.parser;
ExpressionPointer expression;
if ((expression = expressions::Predicate::parse(context, expressionContext)))
return expression;
throw utils::ParserException(parser.coordinate(), "expected predicate");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseLiteral(Context &context, ExpressionContext &expressionContext)
{
ExpressionPointer expression;
if ((expression = parseAtomicFormula(context, expressionContext))
|| (expression = expressions::Not::parse(context, expressionContext, parseAtomicFormula)))
{
return expression;
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseAtomicFormula(Context &context, ExpressionContext &expressionContext)
{
auto &parser = context.parser;
ExpressionPointer expression;
if ((expression = expressions::Predicate::parse(context, expressionContext)))
return expression;
const auto position = parser.position();
if (!parser.testAndSkip<std::string>("("))
return nullptr;
const auto expressionIdentifierPosition = parser.position();
if (parser.testIdentifierAndSkip("="))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier();
parser.seek(position);
return expressions::Unsupported::parse(context);
}
parser.seek(position);
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@@ -0,0 +1,56 @@
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/Problem.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ExpressionContext
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionContext::ExpressionContext(Domain &domain, expressions::Variables &parameters)
: domain(domain),
problem(nullptr),
parameters(parameters)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionContext::ExpressionContext(Domain &domain, Problem *problem, expressions::Variables &parameters)
: domain(domain),
problem{problem},
parameters(parameters)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool ExpressionContext::hasRequirement(Requirement::Type requirementType) const
{
if (problem != nullptr)
return problem->hasRequirement(requirementType);
return domain.hasRequirement(requirementType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ExpressionContext::checkRequirement(Requirement::Type requirementType) const
{
if (problem != nullptr)
problem->checkRequirement(requirementType);
else
domain.checkRequirement(requirementType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@@ -0,0 +1,89 @@
#include <plasp/pddl/InitialState.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/IO.h>
#include <plasp/pddl/Problem.h>
#include <plasp/pddl/expressions/At.h>
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/expressions/Unsupported.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// InitialState
//
////////////////////////////////////////////////////////////////////////////////////////////////////
std::unique_ptr<InitialState> InitialState::parseDeclaration(Context &context,
ExpressionContext &expressionContext)
{
auto &parser = context.parser;
auto initialState = std::make_unique<InitialState>(InitialState());
const auto parseInitialStateElement =
[&]() -> ExpressionPointer
{
ExpressionPointer expression;
// TODO: do not allow negative initial state literals
if ((expression = parseLiteral(context, expressionContext))
|| (expression = expressions::At::parse(context, expressionContext, parseLiteral)))
{
return expression;
}
const auto position = parser.position();
parser.expect<std::string>("(");
const auto expressionIdentifierPosition = parser.position();
if (parser.testIdentifierAndSkip("="))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier();
parser.seek(position);
return expressions::Unsupported::parse(context);
}
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier();
parser.seek(position);
throw utils::ParserException(parser.coordinate(), "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
};
parser.skipWhiteSpace();
while (parser.currentCharacter() != ')')
{
ExpressionPointer expression;
if ((expression = parseInitialStateElement()))
initialState->m_facts.emplace_back(std::move(expression));
parser.skipWhiteSpace();
}
return initialState;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expressions &InitialState::facts() const
{
return m_facts;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

398
src/plasp/pddl/Problem.cpp Normal file
View File

@@ -0,0 +1,398 @@
#include <plasp/pddl/Problem.h>
#include <algorithm>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/IO.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Problem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Problem::Problem(Context &context, Domain &domain)
: m_context(context),
m_domain(domain),
m_domainPosition{-1},
m_requirementsPosition{-1},
m_objectsPosition{-1},
m_initialStatePosition{-1},
m_goalPosition{-1}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::findSections()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>("define");
parser.expect<std::string>("(");
parser.expect<std::string>("problem");
m_name = parser.parseIdentifier();
parser.expect<std::string>(")");
const auto setSectionPosition =
[&](const std::string &sectionName, auto &sectionPosition, const auto value, bool unique = false)
{
if (unique && sectionPosition != -1)
{
parser.seek(value);
throw utils::ParserException(parser.coordinate(), "only one “:" + sectionName + "” section allowed");
}
sectionPosition = value;
};
parser.skipWhiteSpace();
while (parser.currentCharacter() != ')')
{
const auto position = parser.position();
parser.expect<std::string>("(");
parser.expect<std::string>(":");
const auto sectionIdentifierPosition = parser.position();
// TODO: check order of the sections
if (parser.testIdentifierAndSkip("domain"))
setSectionPosition("domain", m_domainPosition, position, true);
else if (parser.testIdentifierAndSkip("requirements"))
setSectionPosition("requirements", m_requirementsPosition, position, true);
else if (parser.testIdentifierAndSkip("objects"))
setSectionPosition("objects", m_objectsPosition, position, true);
else if (parser.testIdentifierAndSkip("init"))
setSectionPosition("init", m_initialStatePosition, position, true);
else if (parser.testIdentifierAndSkip("goal"))
setSectionPosition("goal", m_goalPosition, position, true);
else if (parser.testIdentifierAndSkip("constraints")
|| parser.testIdentifierAndSkip("metric")
|| parser.testIdentifierAndSkip("length"))
{
parser.seek(sectionIdentifierPosition);
const auto sectionIdentifier = parser.parseIdentifier();
m_context.logger.logWarning(parser.coordinate(), "section type “" + sectionIdentifier + "” currently unsupported");
parser.seek(sectionIdentifierPosition);
}
else
{
const auto sectionIdentifier = parser.parseIdentifier();
parser.seek(position);
throw utils::ParserException(parser.coordinate(), "unknown problem section “" + sectionIdentifier + "");
}
// Skip section for now and parse it later
skipSection(parser);
parser.skipWhiteSpace();
}
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parse()
{
auto &parser = m_context.parser;
if (m_domainPosition == -1)
throw ConsistencyException("problem description does not specify the corresponding domain");
parser.seek(m_domainPosition);
parseDomainSection();
if (m_requirementsPosition != -1)
{
parser.seek(m_requirementsPosition);
parseRequirementSection();
}
if (m_objectsPosition != -1)
{
parser.seek(m_objectsPosition);
parseObjectSection();
}
if (m_initialStatePosition == -1)
throw ConsistencyException("problem description does not specify an initial state");
parser.seek(m_initialStatePosition);
parseInitialStateSection();
if (m_goalPosition == -1)
throw ConsistencyException("problem description does not specify a goal");
parser.seek(m_goalPosition);
parseGoalSection();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Domain &Problem::domain()
{
return m_domain;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Domain &Problem::domain() const
{
return m_domain;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Problem::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Requirements &Problem::requirements() const
{
return m_requirements;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::Constants &Problem::objects()
{
return m_objects;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::Constants &Problem::objects() const
{
return m_objects;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseDomainSection()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("domain");
parser.skipWhiteSpace();
const auto domainName = parser.parseIdentifier();
if (m_domain.name() != domainName)
throw utils::ParserException(parser.coordinate(), "domains do not match (“" + m_domain.name() + "” and “" + domainName + "”)");
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseRequirementSection()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("requirements");
parser.skipWhiteSpace();
while (parser.currentCharacter() != ')')
{
parser.expect<std::string>(":");
m_requirements.emplace_back(Requirement::parse(m_context));
parser.skipWhiteSpace();
}
// TODO: do this check only once the domain is parsed
// If no requirements are specified, assume STRIPS
if (m_requirements.empty())
m_requirements.emplace_back(Requirement::Type::STRIPS);
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Problem::hasRequirement(Requirement::Type requirementType) const
{
const auto match = std::find_if(m_requirements.cbegin(), m_requirements.cend(),
[&](const auto &requirement)
{
return requirement.type() == requirementType;
});
if (match != m_requirements.cend())
return true;
return m_domain.hasRequirement(requirementType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::checkRequirement(Requirement::Type requirementType) const
{
if (hasRequirement(requirementType))
return;
throw ConsistencyException("requirement “" + Requirement(requirementType).toPDDL() + "” used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::computeDerivedRequirements()
{
const auto addRequirementUnique =
[&](const auto requirement)
{
if (hasRequirement(requirement))
return;
m_requirements.push_back(Requirement(requirement));
};
if (hasRequirement(Requirement::Type::ADL))
{
addRequirementUnique(Requirement::Type::STRIPS);
addRequirementUnique(Requirement::Type::Typing);
addRequirementUnique(Requirement::Type::NegativePreconditions);
addRequirementUnique(Requirement::Type::DisjunctivePreconditions);
addRequirementUnique(Requirement::Type::Equality);
addRequirementUnique(Requirement::Type::QuantifiedPreconditions);
addRequirementUnique(Requirement::Type::ConditionalEffects);
}
if (hasRequirement(Requirement::Type::QuantifiedPreconditions))
{
addRequirementUnique(Requirement::Type::ExistentialPreconditions);
addRequirementUnique(Requirement::Type::UniversalPreconditions);
}
if (hasRequirement(Requirement::Type::Fluents))
{
addRequirementUnique(Requirement::Type::NumericFluents);
addRequirementUnique(Requirement::Type::ObjectFluents);
}
if (hasRequirement(Requirement::Type::TimedInitialLiterals))
addRequirementUnique(Requirement::Type::DurativeActions);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseObjectSection()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("objects");
parser.skipWhiteSpace();
// Store constants
expressions::Constant::parseTypedDeclarations(m_context, *this);
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseInitialStateSection()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("init");
// TODO: remove workaround
expressions::Variables noParameters;
ExpressionContext expressionContext(m_domain, this, noParameters);
m_initialState = InitialState::parseDeclaration(m_context, expressionContext);
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseGoalSection()
{
auto &parser = m_context.parser;
parser.expect<std::string>("(");
parser.expect<std::string>(":");
parser.expect<std::string>("goal");
// TODO: remove workaround
expressions::Variables noParameters;
ExpressionContext expressionContext(m_domain, this, noParameters);
m_goal = parsePreconditionExpression(m_context, expressionContext);
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
InitialState &Problem::initialState()
{
BOOST_ASSERT(m_initialState);
return *m_initialState;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const InitialState &Problem::initialState() const
{
BOOST_ASSERT(m_initialState);
return *m_initialState;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression &Problem::goal() const
{
BOOST_ASSERT(m_goal);
return *m_goal;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::checkConsistency()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@@ -0,0 +1,135 @@
#include <plasp/pddl/Requirement.h>
#include <boost/assert.hpp>
#include <boost/assign.hpp>
#include <boost/bimap.hpp>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Requirement
//
////////////////////////////////////////////////////////////////////////////////////////////////////
using RequirementTypeNames = boost::bimap<Requirement::Type, std::string>;
////////////////////////////////////////////////////////////////////////////////////////////////////
const RequirementTypeNames requirementTypesToPDDL = boost::assign::list_of<RequirementTypeNames::relation>
(Requirement::Type::STRIPS, "strips")
(Requirement::Type::Typing, "typing")
(Requirement::Type::NegativePreconditions, "negative-preconditions")
(Requirement::Type::DisjunctivePreconditions, "disjunctive-preconditions")
(Requirement::Type::Equality, "equality")
(Requirement::Type::ExistentialPreconditions, "existential-preconditions")
(Requirement::Type::UniversalPreconditions, "universal-preconditions")
(Requirement::Type::QuantifiedPreconditions, "quantified-preconditions")
(Requirement::Type::ConditionalEffects, "conditional-effects")
(Requirement::Type::Fluents, "fluents")
(Requirement::Type::NumericFluents, "numeric-fluents")
(Requirement::Type::ObjectFluents, "object-fluents")
(Requirement::Type::ADL, "adl")
(Requirement::Type::DurativeActions, "durative-actions")
(Requirement::Type::DurationInequalities, "duration-inequalities")
(Requirement::Type::ContinuousEffects, "continuous-effects")
(Requirement::Type::DerivedPredicates, "derived-predicates")
(Requirement::Type::TimedInitialLiterals, "timed-initial-literals")
(Requirement::Type::Preferences, "preferences")
(Requirement::Type::Constraints, "constraints")
(Requirement::Type::ActionCosts, "action-costs")
(Requirement::Type::GoalUtilities, "goal-utilities");
////////////////////////////////////////////////////////////////////////////////////////////////////
const RequirementTypeNames requirementTypesToASP = boost::assign::list_of<RequirementTypeNames::relation>
(Requirement::Type::STRIPS, "strips")
(Requirement::Type::Typing, "typing")
(Requirement::Type::NegativePreconditions, "negativePreconditions")
(Requirement::Type::DisjunctivePreconditions, "disjunctivePreconditions")
(Requirement::Type::Equality, "equality")
(Requirement::Type::ExistentialPreconditions, "existentialPreconditions")
(Requirement::Type::UniversalPreconditions, "universalPreconditions")
(Requirement::Type::QuantifiedPreconditions, "quantifiedPreconditions")
(Requirement::Type::ConditionalEffects, "conditionalEffects")
(Requirement::Type::Fluents, "fluents")
(Requirement::Type::NumericFluents, "numericFluents")
(Requirement::Type::ObjectFluents, "objectFluents")
(Requirement::Type::ADL, "adl")
(Requirement::Type::DurativeActions, "durativeActions")
(Requirement::Type::DurationInequalities, "durationInequalities")
(Requirement::Type::ContinuousEffects, "continuousEffects")
(Requirement::Type::DerivedPredicates, "derivedPredicates")
(Requirement::Type::TimedInitialLiterals, "timedInitialLiterals")
(Requirement::Type::Preferences, "preferences")
(Requirement::Type::Constraints, "constraints")
(Requirement::Type::ActionCosts, "actionCosts")
(Requirement::Type::GoalUtilities, "goalUtilities");
////////////////////////////////////////////////////////////////////////////////////////////////////
Requirement::Requirement(Requirement::Type type)
: m_type{type}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Requirement Requirement::parse(Context &context)
{
auto &parser = context.parser;
const auto requirementName = parser.parseIdentifier();
const auto match = requirementTypesToPDDL.right.find(requirementName);
if (match == requirementTypesToPDDL.right.end())
throw utils::ParserException(parser.coordinate(), "unknown PDDL requirement “" + requirementName + "");
const auto requirementType = match->second;
if (requirementType == Requirement::Type::GoalUtilities)
context.logger.logWarning(parser.coordinate(), "requirement “goal-utilities” is not part of the PDDL 3.1 specification");
return Requirement(match->second);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Requirement::Type Requirement::type() const
{
return m_type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
std::string Requirement::toPDDL() const
{
const auto match = requirementTypesToPDDL.left.find(m_type);
BOOST_ASSERT(match != requirementTypesToPDDL.left.end());
return match->second;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
std::string Requirement::toASP() const
{
const auto match = requirementTypesToASP.left.find(m_type);
BOOST_ASSERT(match != requirementTypesToASP.left.end());
return match->second;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@@ -0,0 +1,568 @@
#include <plasp/pddl/TranslatorASP.h>
#include <boost/assert.hpp>
#include <plasp/pddl/expressions/And.h>
#include <plasp/pddl/expressions/Not.h>
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/utils/Formatting.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/TranslatorException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// TranslatorASP
//
////////////////////////////////////////////////////////////////////////////////////////////////////
TranslatorASP::TranslatorASP(const Description &description, utils::LogStream &outputStream)
: m_description(description),
m_outputStream(outputStream)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translate() const
{
translateDomain();
if (m_description.containsProblem())
{
m_outputStream << std::endl;
translateProblem();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateDomain() const
{
m_outputStream << utils::Heading1("domain");
const auto &domain = m_description.domain();
// Types
m_outputStream << std::endl;
translateTypes();
// Constants
if (!domain.constants().empty())
{
m_outputStream << std::endl;
translateConstants("constants", domain.constants());
}
// Predicates
if (!domain.predicates().empty())
{
m_outputStream << std::endl;
translatePredicates();
}
// Actions
if (!domain.actions().empty())
{
m_outputStream << std::endl;
translateActions();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateTypes() const
{
m_outputStream << utils::Heading2("types");
m_outputStream << std::endl;
const auto &types = m_description.domain().types();
if (types.empty())
{
m_outputStream
<< utils::Keyword("type") << "("
<< utils::Keyword("type") << "(object))." << std::endl;
return;
}
std::for_each(types.cbegin(), types.cend(),
[&](const auto &type)
{
const auto typeName = utils::escapeASP(type->name());
m_outputStream
<< utils::Keyword("type") << "("
<< utils::Keyword("type") << "("
<< typeName << "))." << std::endl;
const auto &parentTypes = type->parentTypes();
std::for_each(parentTypes.cbegin(), parentTypes.cend(),
[&](const auto &parentType)
{
const auto parentTypeName = utils::escapeASP(parentType->name());
m_outputStream
<< utils::Keyword("inherits") << "(" << utils::Keyword("type")
<< "(" << typeName << "), " << utils::Keyword("type")
<< "(" << parentTypeName << "))." << std::endl
<< utils::Keyword("has") << "(" << utils::Variable("X") << ", "
<< utils::Keyword("type") << "(" << parentTypeName << ")) :- "
<< utils::Keyword("has") << "(" << utils::Variable("X") << ", "
<< utils::Keyword("type") << "(" << typeName << "))." << std::endl;
});
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translatePredicates() const
{
m_outputStream << utils::Heading2("variables");
const auto &predicates = m_description.domain().predicates();
const auto printPredicateName =
[&](const auto &predicate)
{
m_outputStream
<< utils::escapeASP(predicate->name());
this->translateVariablesHead(predicate->arguments());
};
const auto printValueRule =
[&](const auto &predicate, const auto &value)
{
m_outputStream
<< utils::Keyword("contains") << "("
<< utils::Keyword("variable") << "(";
printPredicateName(predicate);
m_outputStream
<< "), " << utils::Keyword("value") << "(";
printPredicateName(predicate);
m_outputStream << ", " << utils::Keyword(value) << "))";
this->translateVariablesBody(predicate->arguments());
m_outputStream << "." << std::endl;
};
std::for_each(predicates.cbegin(), predicates.cend(),
[&](const auto &predicate)
{
m_outputStream
<< std::endl
<< utils::Keyword("variable") << "("
<< utils::Keyword("variable") << "(";
printPredicateName(predicate);
m_outputStream << "))";
this->translateVariablesBody(predicate->arguments());
m_outputStream << "." << std::endl;
printValueRule(predicate, "true");
printValueRule(predicate, "false");
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateActions() const
{
m_outputStream << utils::Heading2("actions");
const auto &actions = m_description.domain().actions();
const auto printActionName =
[&](const auto &action)
{
m_outputStream << utils::Keyword("action") << "(" << utils::escapeASP(action.name());
this->translateVariablesHead(action.parameters());
m_outputStream << ")";
};
std::for_each(actions.cbegin(), actions.cend(),
[&](const auto &action)
{
// TODO: rename
const auto translateLiteral =
[&](const auto &ruleHead, const auto &literal, bool enumerateEffects = false)
{
m_outputStream << std::endl << utils::Keyword(ruleHead) << "(";
printActionName(*action);
// TODO: implement conditional effects
if (enumerateEffects)
m_outputStream << ", " << utils::Keyword("effect") << "(unconditional)";
m_outputStream << ", ";
this->translateLiteral(literal);
m_outputStream << ") :- " << utils::Keyword("action") << "(";
printActionName(*action);
m_outputStream << ").";
};
m_outputStream << std::endl;
// Name
m_outputStream << utils::Keyword("action") << "(";
printActionName(*action);
m_outputStream << ")";
this->translateVariablesBody(action->parameters());
m_outputStream << ".";
// Precondition
if (action->precondition())
{
const auto &precondition = *action->precondition();
if (precondition.expressionType() == Expression::Type::Predicate
|| precondition.expressionType() == Expression::Type::Not)
{
translateLiteral("precondition", precondition);
}
// Assuming a conjunction
else
{
if (precondition.expressionType() != Expression::Type::And)
throw utils::TranslatorException("only “and” expressions and (negated) predicates supported as action preconditions currently");
const auto &andExpression = dynamic_cast<const expressions::And &>(precondition);
std::for_each(andExpression.arguments().cbegin(), andExpression.arguments().cend(),
[&](const auto *argument)
{
translateLiteral("precondition", *argument);
});
}
}
// Effect
if (action->effect())
{
const auto &effect = *action->effect();
if (effect.expressionType() == Expression::Type::Predicate
|| effect.expressionType() == Expression::Type::Not)
{
translateLiteral("postcondition", effect, true);
}
// Assuming a conjunction
else
{
if (effect.expressionType() != Expression::Type::And)
throw utils::TranslatorException("only “and” expressions and (negated) predicates supported as action effects currently");
const auto &andExpression = dynamic_cast<const expressions::And &>(effect);
std::for_each(andExpression.arguments().cbegin(), andExpression.arguments().cend(),
[&](const auto *argument)
{
translateLiteral("postcondition", *argument, true);
});
}
}
m_outputStream << std::endl;
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateConstants(const std::string &heading, const expressions::Constants &constants) const
{
m_outputStream << utils::Heading2(heading);
std::for_each(constants.cbegin(), constants.cend(),
[&](const auto &constant)
{
const auto constantName = utils::escapeASP(constant->name());
m_outputStream << std::endl
<< utils::Keyword("constant") << "("
<< utils::Keyword("constant") << "("
<< constantName
<< "))." << std::endl;
const auto *type = constant->type();
if (type != nullptr)
{
m_outputStream << utils::Keyword("has") << "("
<< utils::Keyword("constant") << "(" << constantName << "), "
<< utils::Keyword("type") << "(" << utils::escapeASP(type->name()) << "))." << std::endl;
}
else
{
m_outputStream << utils::Keyword("has") << "("
<< utils::Keyword("constant") << "(" << constantName << "), "
<< utils::Keyword("type") << "(object))." << std::endl;
}
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateVariablesHead(const expressions::Variables &variables) const
{
if (variables.empty())
return;
m_outputStream << "(";
for (auto i = variables.cbegin(); i != variables.cend(); i++)
{
if (i != variables.cbegin())
m_outputStream << ", ";
const auto &variable = **i;
m_outputStream << utils::Variable(utils::escapeASPVariable(variable.name()));
}
m_outputStream << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateVariablesBody(const expressions::Variables &variables) const
{
if (variables.empty())
return;
m_outputStream << " :- ";
for (auto i = variables.cbegin(); i != variables.cend(); i++)
{
const auto &variable = **i;
if (i != variables.cbegin())
m_outputStream << ", ";
if (variable.type() != nullptr)
{
if (variable.type()->expressionType() != Expression::Type::PrimitiveType)
throw utils::TranslatorException("only primitive types supported currently");
const auto &type = *dynamic_cast<const expressions::PrimitiveType *>(variable.type());
m_outputStream << utils::Keyword("has") << "("
<< utils::Variable(utils::escapeASPVariable(variable.name())) << ", "
<< utils::Keyword("type") << "(" << utils::escapeASP(type.name()) << "))";
}
else
{
m_outputStream << utils::Keyword("has") << "("
<< utils::Variable(utils::escapeASPVariable(variable.name())) << ", "
<< utils::Keyword("type") << "(object))";
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateLiteral(const Expression &literal) const
{
// Translate single predicate
if (literal.expressionType() == Expression::Type::Predicate)
{
const auto &predicate = dynamic_cast<const expressions::Predicate &>(literal);
m_outputStream << utils::Keyword("variable") << "(";
this->translatePredicate(predicate);
m_outputStream << "), " << utils::Keyword("value") << "(";
this->translatePredicate(predicate);
m_outputStream << ", " << utils::Keyword("true") << ")";
}
// Assuming that "not" expression may only contain a predicate
else if (literal.expressionType() == Expression::Type::Not)
{
const auto &notExpression = dynamic_cast<const expressions::Not &>(literal);
const auto &predicate = dynamic_cast<const expressions::Predicate &>(*notExpression.argument());
m_outputStream << utils::Keyword("variable") << "(";
this->translatePredicate(predicate);
m_outputStream << "), " << utils::Keyword("value") << "(";
this->translatePredicate(predicate);
m_outputStream << ", " << utils::Keyword("false") << ")";
}
else
throw utils::TranslatorException("only primitive predicates and their negations supported as literals currently");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translatePredicate(const expressions::Predicate &predicate) const
{
m_outputStream << utils::escapeASP(predicate.name());
const auto &arguments = predicate.arguments();
if (arguments.empty())
{
return;
}
m_outputStream << "(";
for (auto i = arguments.cbegin(); i != arguments.cend(); i++)
{
if (i != arguments.cbegin())
m_outputStream << ", ";
if ((*i)->expressionType() == Expression::Type::Constant)
{
const auto &constant = dynamic_cast<const expressions::Constant &>(**i);
m_outputStream << utils::Keyword("constant") << "(" << utils::escapeASP(constant.name()) << ")";
}
else if ((*i)->expressionType() == Expression::Type::Variable)
{
const auto &variable = dynamic_cast<const expressions::Variable &>(**i);
m_outputStream << utils::Variable(utils::escapeASPVariable(variable.name()));
}
else
throw utils::TranslatorException("only variables and constants supported in predicates currently");
}
m_outputStream << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateProblem() const
{
BOOST_ASSERT(m_description.containsProblem());
m_outputStream << utils::Heading1("problem");
const auto &problem = m_description.problem();
// Objects
if (!problem.objects().empty())
{
m_outputStream << std::endl;
translateConstants("objects", problem.objects());
}
// Initial State
m_outputStream << std::endl;
translateInitialState();
// Goal
m_outputStream << std::endl;
translateGoal();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateInitialState() const
{
BOOST_ASSERT(m_description.containsProblem());
m_outputStream << utils::Heading2("initial state");
const auto &initialStateFacts = m_description.problem().initialState().facts();
std::for_each(initialStateFacts.cbegin(), initialStateFacts.cend(),
[&](const auto &fact)
{
m_outputStream << std::endl << utils::Keyword("initialState") << "(";
// Translate single predicate
if (fact->expressionType() == Expression::Type::Predicate)
{
const auto &predicate = dynamic_cast<const expressions::Predicate &>(*fact);
m_outputStream << utils::Keyword("variable") << "(";
this->translatePredicate(predicate);
m_outputStream << "), " << utils::Keyword("value") << "(";
this->translatePredicate(predicate);
m_outputStream << ", " << utils::Keyword("true") << ")";
}
// Assuming that "not" expression may only contain a predicate
else if (fact->expressionType() == Expression::Type::Not)
{
const auto &notExpression = dynamic_cast<const expressions::Not &>(*fact);
if (notExpression.argument()->expressionType() != Expression::Type::Predicate)
throw utils::TranslatorException("only negations of simple predicates supported in initial state currently");
}
else
throw utils::TranslatorException("only predicates and their negations supported in initial state currently");
m_outputStream << ").";
});
m_outputStream << std::endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateGoal() const
{
BOOST_ASSERT(m_description.containsProblem());
m_outputStream << utils::Heading2("goal");
const auto &goal = m_description.problem().goal();
if (goal.expressionType() == Expression::Type::Predicate
|| goal.expressionType() == Expression::Type::Not)
{
m_outputStream << std::endl << utils::Keyword("goal") << "(";
translateLiteral(goal);
m_outputStream << ").";
}
else if (goal.expressionType() == Expression::Type::And)
{
const auto &andExpression = dynamic_cast<const expressions::And &>(goal);
std::for_each(andExpression.arguments().cbegin(), andExpression.arguments().cend(),
[&](const auto *argument)
{
m_outputStream << std::endl << utils::Keyword("goal") << "(";
this->translateLiteral(*argument);
m_outputStream << ").";
});
}
else
throw utils::TranslatorException("only single predicates, their negations, and conjunctions are currently supported in the goal");
m_outputStream << std::endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@@ -0,0 +1,22 @@
#include <plasp/pddl/expressions/And.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// And
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string And::Identifier = "and";
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,48 @@
#include <plasp/pddl/expressions/At.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// At
//
////////////////////////////////////////////////////////////////////////////////////////////////////
At::At()
: m_argument{nullptr}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void At::setArgument(const Expression *argument)
{
m_argumentStorage = nullptr;
m_argument = argument;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void At::setArgument(ExpressionPointer &&argument)
{
m_argumentStorage = std::move(argument);
m_argument = m_argumentStorage.get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression *At::argument() const
{
return m_argument;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,244 @@
#include <plasp/pddl/expressions/Constant.h>
#include <algorithm>
#include <boost/assert.hpp>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Problem.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constant
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant::Constant()
: m_isDirty{false},
m_type{nullptr}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ConstantPointer Constant::parseDeclaration(Context &context)
{
context.parser.skipWhiteSpace();
auto constant = std::make_unique<Constant>(Constant());
constant->m_name = context.parser.parseIdentifier();
BOOST_ASSERT(constant->m_name != "-");
// Flag constant for potentially upcoming type declaration
constant->setDirty();
return constant;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclaration(Context &context, Domain &domain)
{
parseTypedDeclaration(context, domain, domain.constants());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclaration(Context &context, Problem &problem)
{
parseTypedDeclaration(context, problem.domain(), problem.objects());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclaration(Context &context, Domain &domain, Constants &constants)
{
// Parse and store constant
constants.emplace_back(parseDeclaration(context));
context.parser.skipWhiteSpace();
// Check for typing information
if (!context.parser.testAndSkip<char>('-'))
return;
// If existing, parse and store parent type
auto *type = PrimitiveType::parseAndFind(context, domain);
// Assign parent type to all types that were previously flagged
std::for_each(constants.begin(), constants.end(),
[&](auto &constant)
{
if (!constant->isDirty())
return;
constant->setType(type);
constant->setDirty(false);
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclarations(Context &context, Domain &domain)
{
auto &parser = context.parser;
while (parser.currentCharacter() != ')')
{
parseTypedDeclaration(context, domain);
parser.skipWhiteSpace();
}
if (domain.constants().empty())
return;
// Check correct use of typing requirement
const auto typingUsed = (domain.constants().back()->type() != nullptr);
// If types are given, check that typing is a requirement
if (typingUsed)
domain.checkRequirement(Requirement::Type::Typing);
// If no types are given, check that typing is not a requirement
else if (domain.hasRequirement(Requirement::Type::Typing))
throw utils::ParserException(parser.coordinate(), "constant has undeclared type");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclarations(Context &context, Problem &problem)
{
auto &parser = context.parser;
while (context.parser.currentCharacter() != ')')
{
parseTypedDeclaration(context, problem);
parser.skipWhiteSpace();
}
if (problem.objects().empty())
return;
// Check correct use of typing requirement
const auto typingUsed = (problem.objects().back()->type() != nullptr);
// If types are given, check that typing is a requirement
if (typingUsed)
problem.checkRequirement(Requirement::Type::Typing);
// If no types are given, check that typing is not a requirement
else if (problem.hasRequirement(Requirement::Type::Typing))
throw utils::ParserException(parser.coordinate(), "constant has undeclared type");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant *Constant::parseAndFind(Context &context, const Domain &domain)
{
auto &parser = context.parser;
parser.skipWhiteSpace();
const auto constantName = parser.parseIdentifier();
auto *constant = parseAndFind(constantName, domain.constants());
if (constant != nullptr)
return constant;
throw utils::ParserException(parser.coordinate(), "constant “" + constantName + "” used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant *Constant::parseAndFind(Context &context, const Problem &problem)
{
auto &parser = context.parser;
parser.skipWhiteSpace();
const auto constantName = parser.parseIdentifier();
auto *constant = parseAndFind(constantName, problem.domain().constants());
if (constant)
return constant;
constant = parseAndFind(constantName, problem.objects());
if (constant)
return constant;
throw utils::ParserException(parser.coordinate(), "constant “" + constantName + "” used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant *Constant::parseAndFind(const std::string &constantName, const Constants &constants)
{
const auto match = std::find_if(constants.cbegin(), constants.cend(),
[&](const auto &constant)
{
return constant->name() == constantName;
});
const auto constantExists = (match != constants.cend());
if (!constantExists)
return nullptr;
return match->get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::setDirty(bool isDirty)
{
m_isDirty = isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Constant::isDirty() const
{
return m_isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Constant::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::setType(const PrimitiveType *type)
{
m_type = type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const PrimitiveType *Constant::type() const
{
return m_type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,22 @@
#include <plasp/pddl/expressions/Either.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Either
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string Either::Identifier = "either";
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,23 @@
#include <plasp/pddl/expressions/Imply.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Imply
//
////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: make static character string literal
const std::string Imply::Identifier = "imply";
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,48 @@
#include <plasp/pddl/expressions/Not.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Not
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Not::Not()
: m_argument{nullptr}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Not::setArgument(const Expression *argument)
{
m_argumentStorage = nullptr;
m_argument = argument;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Not::setArgument(ExpressionPointer &&argument)
{
m_argumentStorage = std::move(argument);
m_argument = m_argumentStorage.get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression *Not::argument() const
{
return m_argument;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,22 @@
#include <plasp/pddl/expressions/Or.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Or
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string Or::Identifier = "or";
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,175 @@
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Problem.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/Variable.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Predicate
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Predicate::Predicate()
: m_isDeclared{false}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PredicatePointer Predicate::parse(Context &context, ExpressionContext &expressionContext)
{
auto &parser = context.parser;
const auto position = parser.position();
if (!parser.testAndSkip<std::string>("("))
{
parser.seek(position);
return nullptr;
}
const auto predicateName = parser.parseIdentifier();
const auto &predicates = expressionContext.domain.predicates();
const auto matchingPredicate = std::find_if(predicates.cbegin(), predicates.cend(),
[&](const auto &predicate)
{
return predicate->name() == predicateName;
});
if (matchingPredicate == predicates.cend())
{
parser.seek(position);
return nullptr;
}
auto predicate = std::make_unique<Predicate>(Predicate());
predicate->m_name = predicateName;
context.parser.skipWhiteSpace();
// Parse arguments
while (context.parser.currentCharacter() != ')')
{
// Parse variables
if (context.parser.currentCharacter() == '?')
{
const auto *variable = Variable::parseAndFind(context, expressionContext);
predicate->m_arguments.emplace_back(variable);
}
// Parse constants
else
{
const auto *constant = (expressionContext.problem == nullptr)
? Constant::parseAndFind(context, expressionContext.domain)
: Constant::parseAndFind(context, *expressionContext.problem);
predicate->m_arguments.emplace_back(constant);
}
context.parser.skipWhiteSpace();
}
// TODO: check that signature matches one of the declared ones
parser.expect<std::string>(")");
return predicate;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PredicatePointer Predicate::parse(Context &context, const Problem &problem)
{
auto &parser = context.parser;
const auto position = parser.position();
if (!parser.testAndSkip<std::string>("("))
{
parser.seek(position);
return nullptr;
}
const auto predicateName = parser.parseIdentifier();
const auto &predicates = problem.domain().predicates();
const auto matchingPredicate = std::find_if(predicates.cbegin(), predicates.cend(),
[&](const auto &predicate)
{
return predicate->name() == predicateName;
});
if (matchingPredicate == predicates.cend())
{
parser.seek(position);
return nullptr;
}
auto predicate = std::make_unique<Predicate>(Predicate());
predicate->m_name = predicateName;
parser.skipWhiteSpace();
while (parser.currentCharacter() != ')')
{
if (parser.currentCharacter() == '?')
throw utils::ParserException(parser.coordinate(), "variables not allowed in this context");
// Parse objects and constants
const auto *constant = Constant::parseAndFind(context, problem);
predicate->m_arguments.emplace_back(constant);
}
// TODO: check that signature matches one of the declared ones
parser.expect<std::string>(")");
return predicate;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Predicate::setDeclared()
{
m_isDeclared = true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Predicate::isDeclared() const
{
return m_isDeclared;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Predicate::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::vector<const Expression *> &Predicate::arguments() const
{
return m_arguments;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,84 @@
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/Variable.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PredicateDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
PredicateDeclaration::PredicateDeclaration()
: m_isDeclared{false}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PredicateDeclaration::parse(Context &context, Domain &domain)
{
context.parser.expect<std::string>("(");
auto predicate = std::make_unique<PredicateDeclaration>(PredicateDeclaration());
predicate->m_name = context.parser.parseIdentifier();
// Flag predicate as correctly declared in the types section
predicate->setDeclared();
context.parser.skipWhiteSpace();
ExpressionContext expressionContext(domain, predicate->m_parameters);
// Parse arguments
expressions::Variable::parseTypedDeclarations(context, expressionContext);
context.parser.expect<std::string>(")");
domain.predicates().emplace_back(std::move(predicate));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PredicateDeclaration::setDeclared()
{
m_isDeclared = true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool PredicateDeclaration::isDeclared() const
{
return m_isDeclared;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &PredicateDeclaration::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Variables &PredicateDeclaration::arguments() const
{
return m_parameters;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,174 @@
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <algorithm>
#include <boost/assert.hpp>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PrimitiveType
//
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveType::PrimitiveType()
: m_isDirty{true}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveType::PrimitiveType(std::string name)
: m_isDirty{true},
m_name{name}
{
BOOST_ASSERT(!m_name.empty());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PrimitiveType::parseDeclaration(Context &context, Domain &domain)
{
auto &types = domain.types();
context.parser.skipWhiteSpace();
const auto typeName = context.parser.parseIdentifier();
const auto match = std::find_if(types.cbegin(), types.cend(),
[&](const auto &primitiveType)
{
return primitiveType->name() == typeName;
});
// Return existing primitive type
if (match != types.cend())
{
auto *type = match->get();
type->setDirty();
return;
}
types.emplace_back(std::make_unique<PrimitiveType>(typeName));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PrimitiveType::parseTypedDeclaration(Context &context, Domain &domain)
{
auto &types = domain.types();
// Parse and store type
parseDeclaration(context, domain);
context.parser.skipWhiteSpace();
// Check for type inheritance
if (!context.parser.testAndSkip<char>('-'))
return;
domain.checkRequirement(Requirement::Type::Typing);
// If existing, parse and store parent type
auto *parentType = parseAndFind(context, domain);
parentType->setDirty(false);
// Assign parent type to all types that were previously flagged
std::for_each(types.begin(), types.end(),
[&](auto &childType)
{
if (!childType->isDirty())
return;
childType->m_parentTypes.push_back(parentType);
childType->setDirty(false);
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveType *PrimitiveType::parseAndFind(Context &context, Domain &domain)
{
auto &parser = context.parser;
auto &types = domain.types();
parser.skipWhiteSpace();
const auto typeName = parser.parseIdentifier();
if (typeName.empty())
throw utils::ParserException(parser.coordinate(), "no type supplied");
const auto match = std::find_if(types.cbegin(), types.cend(),
[&](const auto &primitiveType)
{
return primitiveType->name() == typeName;
});
if (match == types.cend())
{
// Only "object" is allowed as an implicit type
if (typeName == "object" || typeName == "objects")
{
context.logger.logWarning(parser.coordinate(), "primitive type “" + typeName + "” should be declared");
types.emplace_back(std::make_unique<expressions::PrimitiveType>(typeName));
}
else
throw utils::ParserException(parser.coordinate(), "type “" + typeName + "” used but never declared");
return types.back().get();
}
auto *type = match->get();
type->setDirty();
return type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PrimitiveType::setDirty(bool isDirty)
{
m_isDirty = isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool PrimitiveType::isDirty() const
{
return m_isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &PrimitiveType::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::vector<const PrimitiveType *> &PrimitiveType::parentTypes() const
{
return m_parentTypes;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,29 @@
#include <plasp/pddl/expressions/Type.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Type
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression *parseExistingPrimitiveType(Context &context, ExpressionContext &expressionContext)
{
return PrimitiveType::parseAndFind(context, expressionContext.domain);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,46 @@
#include <plasp/pddl/expressions/Unsupported.h>
#include <plasp/pddl/IO.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Unsupported
//
////////////////////////////////////////////////////////////////////////////////////////////////////
UnsupportedPointer Unsupported::parse(Context &context)
{
auto &parser = context.parser;
auto expression = std::make_unique<Unsupported>(Unsupported());
parser.expect<std::string>("(");
expression->m_type = parser.parseIdentifier();
context.logger.logWarning(parser.coordinate(), "expression type “" + expression->m_type + "” currently unsupported in this context");
skipSection(parser);
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Unsupported::type() const
{
return m_type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -0,0 +1,204 @@
#include <plasp/pddl/expressions/Variable.h>
#include <algorithm>
#include <boost/assert.hpp>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/expressions/Either.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <plasp/pddl/expressions/Type.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Variable
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Variable::Variable()
: m_isDirty{false},
m_type{nullptr}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::parseDeclaration(Context &context, Variables &parameters)
{
auto &parser = context.parser;
parser.skipWhiteSpace();
parser.expect<std::string>("?");
auto variable = std::make_unique<Variable>(Variable());
variable->m_name = parser.parseIdentifier();
// Check if variable of that name already exists in the current scope
const auto match = std::find_if(parameters.cbegin(), parameters.cend(),
[&](const auto &parameter)
{
return parameter->name() == variable->m_name;
});
if (match != parameters.cend())
throw utils::ParserException(parser.coordinate(), "variable “" + variable->m_name + "” already declared in this scope");
// Flag variable for potentially upcoming type declaration
variable->setDirty();
parameters.emplace_back(std::move(variable));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expressionContext)
{
auto &parser = context.parser;
auto &variables = expressionContext.parameters;
// Parse and store variable itself
parseDeclaration(context, variables);
auto &variable = variables.back();
parser.skipWhiteSpace();
// Check if the variable has a type declaration
if (!parser.testAndSkip<char>('-'))
return;
const auto setType =
[&](const auto *type)
{
// Set the argument type for all previously flagged arguments
std::for_each(variables.begin(), variables.end(),
[&](auto &variable)
{
if (!variable->isDirty())
return;
variable->setType(type);
variable->setDirty(false);
});
};
parser.skipWhiteSpace();
// Parse argument of "either" type (always begins with opening parenthesis)
if ((variable->m_eitherExpression = Either::parse(context, expressionContext, parseExistingPrimitiveType)))
{
setType(variable->m_eitherExpression.get());
return;
}
// Parse primitive type
const auto *type = PrimitiveType::parseAndFind(context, expressionContext.domain);
setType(type);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::parseTypedDeclarations(Context &context, ExpressionContext &expressionContext)
{
auto &parser = context.parser;
while (parser.currentCharacter() != ')')
{
parseTypedDeclaration(context, expressionContext);
parser.skipWhiteSpace();
}
if (expressionContext.parameters.empty())
return;
// Check correct use of typing requirement
const auto typingUsed = (expressionContext.parameters.back()->type() != nullptr);
// If types are given, check that typing is a requirement
if (typingUsed)
expressionContext.checkRequirement(Requirement::Type::Typing);
// If no types are given, check that typing is not a requirement
else if (expressionContext.hasRequirement(Requirement::Type::Typing))
throw utils::ParserException(parser.coordinate(), "variable has undeclared type");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Variable *Variable::parseAndFind(Context &context, const ExpressionContext &expressionContext)
{
auto &parser = context.parser;
parser.skipWhiteSpace();
parser.expect<std::string>("?");
const auto variableName = parser.parseIdentifier();
const auto &variables = expressionContext.parameters;
const auto match = std::find_if(variables.cbegin(), variables.cend(),
[&](const auto &variable)
{
return variable->name() == variableName;
});
if (match == variables.cend())
throw utils::ParserException(parser.coordinate(), "parameter “" + variableName + "” used but never declared");
return match->get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Variable::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression *Variable::type() const
{
return m_type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::setDirty(bool isDirty)
{
m_isDirty = isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Variable::isDirty() const
{
return m_isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::setType(const Expression *type)
{
m_type = type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@@ -4,8 +4,6 @@
#include <boost/assert.hpp>
#include <plasp/utils/Parsing.h>
namespace plasp
{
namespace sas
@@ -33,24 +31,24 @@ AssignedVariable::AssignedVariable(const Variable &variable, const Value &value)
////////////////////////////////////////////////////////////////////////////////////////////////////
AssignedVariable AssignedVariable::fromSAS(std::istream &istream, const Variables &variables)
AssignedVariable AssignedVariable::fromSAS(utils::Parser<> &parser, const Variables &variables)
{
AssignedVariable assignedVariable;
assignedVariable.m_variable = &Variable::referenceFromSAS(istream, variables);
assignedVariable.m_value = &Value::referenceFromSAS(istream, *assignedVariable.m_variable);
assignedVariable.m_variable = &Variable::referenceFromSAS(parser, variables);
assignedVariable.m_value = &Value::referenceFromSAS(parser, *assignedVariable.m_variable);
return assignedVariable;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
AssignedVariable AssignedVariable::fromSAS(std::istream &istream, const Variable &variable)
AssignedVariable AssignedVariable::fromSAS(utils::Parser<> &parser, const Variable &variable)
{
AssignedVariable assignedVariable;
assignedVariable.m_variable = &variable;
assignedVariable.m_value = &Value::referenceFromSAS(istream, *assignedVariable.m_variable);
assignedVariable.m_value = &Value::referenceFromSAS(parser, *assignedVariable.m_variable);
return assignedVariable;
}

View File

@@ -3,7 +3,6 @@
#include <iostream>
#include <plasp/sas/VariableTransition.h>
#include <plasp/utils/Parsing.h>
namespace plasp
{
@@ -24,24 +23,24 @@ AxiomRule::AxiomRule(AxiomRule::Conditions conditions, AxiomRule::Condition post
////////////////////////////////////////////////////////////////////////////////////////////////////
AxiomRule AxiomRule::fromSAS(std::istream &istream, const Variables &variables)
AxiomRule AxiomRule::fromSAS(utils::Parser<> &parser, const Variables &variables)
{
utils::parseExpected<std::string>(istream, "begin_rule");
parser.expect<std::string>("begin_rule");
const auto numberOfConditions = utils::parse<size_t>(istream);
const auto numberOfConditions = parser.parse<size_t>();
Conditions conditions;
conditions.reserve(numberOfConditions);
for (size_t j = 0; j < numberOfConditions; j++)
conditions.emplace_back(Condition::fromSAS(istream, variables));
conditions.emplace_back(Condition::fromSAS(parser, variables));
const auto variableTransition = VariableTransition::fromSAS(istream, variables);
const auto variableTransition = VariableTransition::fromSAS(parser, variables);
if (&variableTransition.valueBefore() != &Value::Any)
conditions.emplace_back(Condition(variableTransition.variable(), variableTransition.valueBefore()));
utils::parseExpected<std::string>(istream, "end_rule");
parser.expect<std::string>("end_rule");
const Condition postcondition(variableTransition.variable(), variableTransition.valueAfter());
const AxiomRule axiomRule(std::move(conditions), std::move(postcondition));

View File

@@ -13,7 +13,7 @@ namespace sas
//
////////////////////////////////////////////////////////////////////////////////////////////////////
std::ostream &operator >>(std::ostream &ostream, const Description &description)
utils::LogStream &operator<<(utils::LogStream &ostream, const Description &description)
{
// Metric section
ostream << "uses action costs: " << (description.usesActionCosts() ? "yes" : "no") << std::endl;

View File

@@ -8,7 +8,6 @@
#include <boost/filesystem.hpp>
#include <plasp/utils/ParserException.h>
#include <plasp/utils/Parsing.h>
#include <plasp/sas/VariableTransition.h>
namespace plasp
@@ -29,22 +28,23 @@ Description::Description()
////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromStream(std::istream &istream)
Description Description::fromParser(utils::Parser<> &&parser)
{
Description description;
description.parseContent(parser);
std::setlocale(LC_NUMERIC, "C");
return description;
}
istream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
////////////////////////////////////////////////////////////////////////////////////////////////////
description.parseVersionSection(istream);
description.parseMetricSection(istream);
description.parseVariablesSection(istream);
description.parseMutexSection(istream);
description.parseInitialStateSection(istream);
description.parseGoalSection(istream);
description.parseOperatorSection(istream);
description.parseAxiomSection(istream);
Description Description::fromStream(std::istream &istream)
{
utils::Parser<> parser;
parser.read("std::cin", istream);
Description description;
description.parseContent(parser);
return description;
}
@@ -54,11 +54,15 @@ Description Description::fromStream(std::istream &istream)
Description Description::fromFile(const boost::filesystem::path &path)
{
if (!boost::filesystem::is_regular_file(path))
throw std::runtime_error("File does not exist: \"" + path.string() + "\"");
throw std::runtime_error("File does not exist: " + path.string() + "");
std::ifstream fileStream(path.string(), std::ios::in);
utils::Parser<> parser;
parser.read(path);
return Description::fromStream(fileStream);
Description description;
description.parseContent(parser);
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -149,85 +153,111 @@ bool Description::usesConditionalEffects() const
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseVersionSection(std::istream &istream) const
bool Description::hasRequirements() const
{
utils::parseExpected<std::string>(istream, "begin_version");
return usesActionCosts() || usesAxiomRules() || usesConditionalEffects();
}
const auto formatVersion = utils::parse<size_t>(istream);
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseContent(utils::Parser<> &parser)
{
parseVersionSection(parser);
parseMetricSection(parser);
parseVariablesSection(parser);
parseMutexSection(parser);
parseInitialStateSection(parser);
parseGoalSection(parser);
parseOperatorSection(parser);
parseAxiomSection(parser);
parser.skipWhiteSpace();
if (!parser.atEnd())
throw utils::ParserException(parser.coordinate(), "expected end of SAS description (perhaps, input contains two SAS descriptions?)");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseVersionSection(utils::Parser<> &parser) const
{
parser.expect<std::string>("begin_version");
const auto formatVersion = parser.parse<size_t>();
if (formatVersion != 3)
throw utils::ParserException("Unsupported SAS format version (" + std::to_string(formatVersion) + ")");
throw utils::ParserException(parser.coordinate(), "unsupported SAS format version (" + std::to_string(formatVersion) + ")");
utils::parseExpected<std::string>(istream, "end_version");
parser.expect<std::string>("end_version");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseMetricSection(std::istream &istream)
void Description::parseMetricSection(utils::Parser<> &parser)
{
utils::parseExpected<std::string>(istream, "begin_metric");
parser.expect<std::string>("begin_metric");
m_usesActionCosts = utils::parse<bool>(istream);
m_usesActionCosts = parser.parse<bool>();
utils::parseExpected<std::string>(istream, "end_metric");
parser.expect<std::string>("end_metric");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseVariablesSection(std::istream &istream)
void Description::parseVariablesSection(utils::Parser<> &parser)
{
const auto numberOfVariables = utils::parse<size_t>(istream);
const auto numberOfVariables = parser.parse<size_t>();
m_variables.reserve(numberOfVariables);
for (size_t i = 0; i < numberOfVariables; i++)
m_variables.emplace_back(Variable::fromSAS(istream));
m_variables.emplace_back(Variable::fromSAS(parser));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseMutexSection(std::istream &istream)
void Description::parseMutexSection(utils::Parser<> &parser)
{
const auto numberOfMutexGroups = utils::parse<size_t>(istream);
const auto numberOfMutexGroups = parser.parse<size_t>();
m_mutexGroups.reserve(numberOfMutexGroups);
for (size_t i = 0; i < numberOfMutexGroups; i++)
m_mutexGroups.emplace_back(MutexGroup::fromSAS(istream, m_variables));
m_mutexGroups.emplace_back(MutexGroup::fromSAS(parser, m_variables));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseInitialStateSection(std::istream &istream)
void Description::parseInitialStateSection(utils::Parser<> &parser)
{
m_initialState = std::make_unique<InitialState>(InitialState::fromSAS(istream, m_variables));
m_initialState = std::make_unique<InitialState>(InitialState::fromSAS(parser, m_variables));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseGoalSection(std::istream &istream)
void Description::parseGoalSection(utils::Parser<> &parser)
{
m_goal = std::make_unique<Goal>(Goal::fromSAS(istream, m_variables));
m_goal = std::make_unique<Goal>(Goal::fromSAS(parser, m_variables));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseOperatorSection(std::istream &istream)
void Description::parseOperatorSection(utils::Parser<> &parser)
{
const auto numberOfOperators = utils::parse<size_t>(istream);
const auto numberOfOperators = parser.parse<size_t>();
m_operators.reserve(numberOfOperators);
for (size_t i = 0; i < numberOfOperators; i++)
m_operators.emplace_back(Operator::fromSAS(istream, m_variables));
m_operators.emplace_back(Operator::fromSAS(parser, m_variables));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseAxiomSection(std::istream &istream)
void Description::parseAxiomSection(utils::Parser<> &parser)
{
const auto numberOfAxiomRules = utils::parse<size_t>(istream);
const auto numberOfAxiomRules = parser.parse<size_t>();
m_axiomRules.reserve(numberOfAxiomRules);
for (size_t i = 0; i < numberOfAxiomRules; i++)
m_axiomRules.emplace_back(AxiomRule::fromSAS(istream, m_variables));
m_axiomRules.emplace_back(AxiomRule::fromSAS(parser, m_variables));
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -3,7 +3,6 @@
#include <iostream>
#include <plasp/sas/VariableTransition.h>
#include <plasp/utils/Parsing.h>
namespace plasp
{
@@ -24,17 +23,17 @@ Effect::Effect(Conditions conditions, Condition postcondition)
////////////////////////////////////////////////////////////////////////////////////////////////////
Effect Effect::fromSAS(std::istream &istream, const Variables &variables, Conditions &preconditions)
Effect Effect::fromSAS(utils::Parser<> &parser, const Variables &variables, Conditions &preconditions)
{
Effect::Conditions conditions;
const auto numberOfEffectConditions = utils::parse<size_t>(istream);
const auto numberOfEffectConditions = parser.parse<size_t>();
conditions.reserve(numberOfEffectConditions);
for (size_t k = 0; k < numberOfEffectConditions; k++)
conditions.emplace_back(Condition::fromSAS(istream, variables));
conditions.emplace_back(Condition::fromSAS(parser, variables));
const auto variableTransition = VariableTransition::fromSAS(istream, variables);
const auto variableTransition = VariableTransition::fromSAS(parser, variables);
if (&variableTransition.valueBefore() != &Value::Any)
preconditions.emplace_back(Condition(variableTransition.variable(), variableTransition.valueBefore()));

View File

@@ -2,8 +2,6 @@
#include <iostream>
#include <plasp/utils/Parsing.h>
namespace plasp
{
namespace sas
@@ -15,19 +13,19 @@ namespace sas
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Goal Goal::fromSAS(std::istream &istream, const Variables &variables)
Goal Goal::fromSAS(utils::Parser<> &parser, const Variables &variables)
{
Goal goal;
utils::parseExpected<std::string>(istream, "begin_goal");
parser.expect<std::string>("begin_goal");
const auto numberOfGoalFacts = utils::parse<size_t>(istream);
const auto numberOfGoalFacts = parser.parse<size_t>();
goal.m_facts.reserve(numberOfGoalFacts);
for (size_t i = 0; i < numberOfGoalFacts; i++)
goal.m_facts.emplace_back(Fact::fromSAS(istream, variables));
goal.m_facts.emplace_back(Fact::fromSAS(parser, variables));
utils::parseExpected<std::string>(istream, "end_goal");
parser.expect<std::string>("end_goal");
return goal;
}

View File

@@ -1,9 +1,5 @@
#include <plasp/sas/InitialState.h>
#include <iostream>
#include <plasp/utils/Parsing.h>
namespace plasp
{
namespace sas
@@ -15,18 +11,18 @@ namespace sas
//
////////////////////////////////////////////////////////////////////////////////////////////////////
InitialState InitialState::fromSAS(std::istream &istream, const Variables &variables)
InitialState InitialState::fromSAS(utils::Parser<> &parser, const Variables &variables)
{
InitialState initialState;
utils::parseExpected<std::string>(istream, "begin_state");
parser.expect<std::string>("begin_state");
initialState.m_facts.reserve(variables.size());
for (size_t i = 0; i < variables.size(); i++)
initialState.m_facts.emplace_back(Fact::fromSAS(istream, variables[i]));
initialState.m_facts.emplace_back(Fact::fromSAS(parser, variables[i]));
utils::parseExpected<std::string>(istream, "end_state");
parser.expect<std::string>("end_state");
return initialState;
}

View File

@@ -2,7 +2,7 @@
#include <iostream>
#include <plasp/utils/Parsing.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
@@ -15,24 +15,24 @@ namespace sas
//
////////////////////////////////////////////////////////////////////////////////////////////////////
MutexGroup MutexGroup::fromSAS(std::istream &istream, const Variables &variables)
MutexGroup MutexGroup::fromSAS(utils::Parser<> &parser, const Variables &variables)
{
MutexGroup mutexGroup;
utils::parseExpected<std::string>(istream, "begin_mutex_group");
parser.expect<std::string>("begin_mutex_group");
const auto numberOfFacts = utils::parse<size_t>(istream);
const auto numberOfFacts = parser.parse<size_t>();
mutexGroup.m_facts.reserve(numberOfFacts);
for (size_t j = 0; j < numberOfFacts; j++)
{
mutexGroup.m_facts.emplace_back(Fact::fromSAS(istream, variables));
mutexGroup.m_facts.emplace_back(Fact::fromSAS(parser, variables));
if (mutexGroup.m_facts[j].value() == Value::None)
throw utils::ParserException("Mutex groups must not contain <none of those> values");
throw utils::ParserException(parser.coordinate(), "mutex groups must not contain <none of those> values");
}
utils::parseExpected<std::string>(istream, "end_mutex_group");
parser.expect<std::string>("end_mutex_group");
return mutexGroup;
}

View File

@@ -4,7 +4,7 @@
#include <limits>
#include <plasp/sas/VariableTransition.h>
#include <plasp/utils/Parsing.h>
#include <plasp/utils/Formatting.h>
namespace plasp
{
@@ -17,40 +17,40 @@ namespace sas
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Operator Operator::fromSAS(std::istream &istream, const Variables &variables)
Operator Operator::fromSAS(utils::Parser<> &parser, const Variables &variables)
{
Operator operator_;
utils::parseExpected<std::string>(istream, "begin_operator");
parser.expect<std::string>("begin_operator");
operator_.m_predicate = Predicate::fromSAS(istream);
operator_.m_predicate = Predicate::fromSAS(parser);
const auto numberOfPrevailConditions = utils::parse<size_t>(istream);
const auto numberOfPrevailConditions = parser.parse<size_t>();
operator_.m_preconditions.reserve(numberOfPrevailConditions);
for (size_t j = 0; j < numberOfPrevailConditions; j++)
operator_.m_preconditions.emplace_back(Condition::fromSAS(istream, variables));
operator_.m_preconditions.emplace_back(Condition::fromSAS(parser, variables));
const auto numberOfEffects = utils::parse<size_t>(istream);
const auto numberOfEffects = parser.parse<size_t>();
operator_.m_effects.reserve(numberOfEffects);
for (size_t j = 0; j < numberOfEffects; j++)
operator_.m_effects.emplace_back(Effect::fromSAS(istream, variables, operator_.m_preconditions));
operator_.m_effects.emplace_back(Effect::fromSAS(parser, variables, operator_.m_preconditions));
operator_.m_costs = utils::parse<size_t>(istream);
operator_.m_costs = parser.parse<size_t>();
utils::parseExpected<std::string>(istream, "end_operator");
parser.expect<std::string>("end_operator");
return operator_;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Operator::printPredicateAsASP(std::ostream &ostream) const
void Operator::printPredicateAsASP(utils::LogStream &outputStream) const
{
ostream << "action(";
m_predicate.printAsASP(ostream);
ostream << ")";
outputStream << utils::Keyword("action") << "(";
m_predicate.printAsASP(outputStream);
outputStream << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////

Some files were not shown because too many files have changed in this diff Show More