256 Commits

Author SHA1 Message Date
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
143 changed files with 10872 additions and 437 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 tests/data/* linguist-documentation

View File

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

25
CHANGELOG.md Normal file
View File

@@ -0,0 +1,25 @@
# Change Log
## 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) 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") set(CMAKE_CXX_FLAGS_DEBUG "-g")
add_definitions(-std=c++14) 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_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,39 +1,65 @@
# plasp—Translate PDDL to ASP # 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. `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` 3 translates planning problem instances to ASP facts.
`plasp` 3 supports the input languages [PDDL](https://helios.hud.ac.uk/scommv/IPC-14/software.html) (only basic features currently) and the [SAS](http://www.fast-downward.org/TranslatorOutputFormat) (full support of the current version 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. Please get in touch with [Patrick Lühne](https://www.luehne.de) if you have any suggestions.
## Usage ## 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 ```bash
$ plasp file.sas $ plasp domain.pddl problem.pddl
``` ```
For instance, a PDDL instance can be solved as follows. Alternatively, PDDL instances may first be translated to SAS, the output format of [Fast Downward](http://www.fast-downward.org/).
First, use [Fast Downward](http://www.fast-downward.org/) to translate the files from PDDL to SAS:
```bash ```bash
$ ./fast-downward.py --translate --build=release64 domain.pddl instance.pddl $ ./fast-downward.py --translate --build=release64 domain.pddl instance.pddl
``` ```
This creates the file `output.sas`. This creates a file called `output.sas`, which may now be translated by `plasp`.
The translated SAS instance can now be solved incrementally with `clingo` and the meta encoding `meta-sequential-incremental.lp`:
```bash ```bash
$ plasp output.sas > instance.lp $ plasp output.sas
$ clingo encodings/meta-sequential-incremental.lp instance.lp
``` ```
### 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]
```
`[files]` may be omitted, in which case the input is read from `std::cin`.
The `[options]` are listed below:
| **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`). |
## Building ## Building
`plasp` requires a C++14 compiler (preferrably GCC ≥ 6.1), the `boost` libraries (≥ 1.55), and CMake for building. `plasp` requires a C++14 compiler (preferrably GCC ≥ 6.1 or clang ≥ 3.8), the `boost` libraries (≥ 1.55), and CMake for building.
```bash ```bash
$ git clone https://github.com/potassco/plasp.git $ git clone https://github.com/potassco/plasp.git
@@ -46,11 +72,27 @@ $ make
The built `plasp` binary is then located at `plasp/build/release/bin/plasp`. The built `plasp` binary is then located at `plasp/build/release/bin/plasp`.
### 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
```
## Contributors ## Contributors
* [Patrick Lühne](https://www.luehne.de) (`plasp` 3) * [Patrick Lühne](https://www.luehne.de) (`plasp` 3)
### Earlier Versions ### Earlier Versions
* René Knaebel (`plasp` 2) * René Knaebel
* Murat Knecht (`plasp`) * Murat Knecht

View File

@@ -1,9 +1,16 @@
#include <algorithm>
#include <iostream> #include <iostream>
#include <string>
#include <boost/program_options.hpp> #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/Description.h>
#include <plasp/sas/TranslatorASP.h> #include <plasp/sas/TranslatorASP.h>
#include <plasp/utils/LogStream.h>
#include <plasp/utils/TranslatorException.h>
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
@@ -13,7 +20,10 @@ int main(int argc, char **argv)
description.add_options() description.add_options()
("help,h", "Display this help message.") ("help,h", "Display this help message.")
("version,v", "Display version information.") ("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; po::positional_options_description positionalOptionsDescription;
positionalOptionsDescription.add("input", -1); positionalOptionsDescription.add("input", -1);
@@ -23,12 +33,14 @@ int main(int argc, char **argv)
const auto printHelp = 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 << "Translate PDDL instances to ASP facts." << std::endl << std::endl;
std::cout << description; std::cout << description;
}; };
plasp::utils::Logger logger;
try try
{ {
po::store(po::command_line_parser(argc, argv) po::store(po::command_line_parser(argc, argv)
@@ -40,7 +52,8 @@ int main(int argc, char **argv)
} }
catch (const po::error &e) catch (const po::error &e)
{ {
std::cerr << "Error: " << e.what() << std::endl << std::endl; logger.logError(e.what());
std::cout << std::endl;
printHelp(); printHelp();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@@ -53,27 +66,110 @@ int main(int argc, char **argv)
if (variablesMap.count("version")) if (variablesMap.count("version"))
{ {
std::cout << "plasp version 3.0.0" << std::endl; std::cout << "plasp version 3.0.1" << std::endl;
return EXIT_SUCCESS; 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(); printHelp();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
try try
{ {
const auto sasDescription = plasp::sas::Description::fromFile(variablesMap["input"].as<std::string>()); plasp::utils::Parser parser;
const auto sasTranslator = plasp::sas::TranslatorASP(sasDescription);
sasTranslator.translate(std::cout); parser.setCaseSensitive(false);
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.readFile(inputFile);
});
}
else
parser.readStream("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) catch (const std::exception &e)
{ {
std::cerr << "Error: " << e.what() << std::endl << std::endl; logger.logError(e.what());
printHelp();
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View File

@@ -0,0 +1,31 @@
#include <incmode>.
#program base.
% Establish initial state
holds(Predicate, 0) :- initialState(Predicate).
#program step(t).
% Perform actions
1 {occurs(action(Action), t) : action(Action)} 1.
% Check preconditions
:- occurs(Action, t), precondition(Action, Predicate, true), not holds(Predicate, t - 1).
:- occurs(Action, t), precondition(Action, Predicate, false), holds(Predicate, t - 1).
% Apply effects
caused(Predicate, true, t) :- occurs(Action, t), postcondition(Action, Predicate, true).
caused(Predicate, false, t) :- occurs(Action, t), postcondition(Action, Predicate, false).
holds(Predicate, t) :- caused(Predicate, true, t).
holds(Predicate, t) :- holds(Predicate, t - 1), not caused(Predicate, false, t).
#program check(t).
% Verify that goal is met
:- query(t), goal(Predicate, true), not holds(Predicate, t).
:- query(t), goal(Predicate, false), holds(Predicate, 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,50 @@
#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 &parser)
{
parser.setCaseSensitive(false);
parser.skipWhiteSpace();
// SAS begins with "begin_version"
if (parser.probe<std::string>("begin"))
{
parser.seek(std::ios::beg);
return Language::Type::SAS;
}
// Skip potential PDDL comments
while (parser.currentCharacter() == ';')
{
parser.skipLine();
parser.skipWhiteSpace();
}
// PDDL contains sections starting with "(define"
if (parser.probe<std::string>("(") && parser.probe<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,68 @@
#ifndef __PLASP__PDDL__CONTEXT_H
#define __PLASP__PDDL__CONTEXT_H
#include <memory>
#include <unordered_map>
#include <vector>
#include <plasp/utils/Logger.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Context
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Context
{
public:
Context() = default;
explicit Context(utils::Parser &&parser)
: parser{std::move(parser)}
{
}
explicit Context(utils::Logger &&logger)
: logger{std::move(logger)}
{
}
explicit Context(utils::Parser &&parser, utils::Logger &&logger)
: parser{std::move(parser)},
logger{std::move(logger)}
{
}
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;
}
utils::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::Parser::Position m_domainPosition;
std::unique_ptr<Domain> m_domain;
utils::Parser::Position m_problemPosition;
std::unique_ptr<Problem> m_problem;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,92 @@
#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/expressions/Constant.h>
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <plasp/pddl/Requirement.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::Parser::Position m_requirementsPosition;
Requirements m_requirements;
utils::Parser::Position m_typesPosition;
expressions::PrimitiveTypes m_types;
utils::Parser::Position m_constantsPosition;
expressions::Constants m_constants;
utils::Parser::Position m_predicatesPosition;
expressions::PredicateDeclarations m_predicates;
std::vector<utils::Parser::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/utils/Parser.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// IO
//
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void skipSection(utils::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,32 @@
#ifndef __PLASP__PDDL__IDENTIFIER_H
#define __PLASP__PDDL__IDENTIFIER_H
#include <cctype>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Identifier
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const auto isIdentifier =
[](const auto character)
{
return character != '?'
&& character != '('
&& character != ')'
&& character != ';'
&& std::isgraph(character);
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#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,84 @@
#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/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::Parser::Position m_domainPosition;
utils::Parser::Position m_requirementsPosition;
Requirements m_requirements;
utils::Parser::Position m_objectsPosition;
expressions::Constants m_objects;
utils::Parser::Position m_initialStatePosition;
std::unique_ptr<InitialState> m_initialState;
utils::Parser::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,106 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__AT_H
#define __PLASP__PDDL__EXPRESSIONS__AT_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Identifier.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.probe<std::string>("(")
|| !parser.probeIdentifier("at", isIdentifier))
{
parser.seek(position);
return nullptr;
}
size_t timePoint;
const auto timePointPosition = parser.position();
if (parser.probeIdentifier("start", isIdentifier))
timePoint = TimePointStart;
else if (parser.probeIdentifier("end", isIdentifier))
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,112 @@
#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/Identifier.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.probe<std::string>("(")
|| !parser.probeIdentifier(Derived::Identifier, isIdentifier))
{
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,65 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__CONSTANT_H
#define __PLASP__PDDL__EXPRESSIONS__CONSTANT_H
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Identifier.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,118 @@
#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/Identifier.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.probe<std::string>("(")
|| !parser.probeIdentifier(Derived::Identifier, isIdentifier))
{
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(context.parser, "" + 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,78 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__NOT_H
#define __PLASP__PDDL__EXPRESSIONS__NOT_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Identifier.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.probe<std::string>("(")
|| !parser.probeIdentifier("not", isIdentifier))
{
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,56 @@
#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/pddl/Identifier.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/Value.h>
#include <plasp/sas/Variable.h> #include <plasp/sas/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp namespace plasp
{ {
@@ -26,8 +27,8 @@ using AssignedVariables = std::vector<AssignedVariable>;
class AssignedVariable class AssignedVariable
{ {
public: public:
static AssignedVariable fromSAS(std::istream &istream, const Variables &variables); static AssignedVariable fromSAS(utils::Parser &parser, const Variables &variables);
static AssignedVariable fromSAS(std::istream &istream, const Variable &variable); static AssignedVariable fromSAS(utils::Parser &parser, const Variable &variable);
public: public:
explicit AssignedVariable(const Variable &variable, const Value &value); explicit AssignedVariable(const Variable &variable, const Value &value);

View File

@@ -5,6 +5,7 @@
#include <plasp/sas/AssignedVariable.h> #include <plasp/sas/AssignedVariable.h>
#include <plasp/sas/Variable.h> #include <plasp/sas/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp namespace plasp
{ {
@@ -28,7 +29,7 @@ class AxiomRule
using Condition = AssignedVariable; using Condition = AssignedVariable;
using Conditions = AssignedVariables; using Conditions = AssignedVariables;
static AxiomRule fromSAS(std::istream &istream, const Variables &variables); static AxiomRule fromSAS(utils::Parser &parser, const Variables &variables);
public: public:
const Conditions &conditions() const; 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/MutexGroup.h>
#include <plasp/sas/Operator.h> #include <plasp/sas/Operator.h>
#include <plasp/sas/Variable.h> #include <plasp/sas/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp namespace plasp
{ {
@@ -28,6 +29,7 @@ namespace sas
class Description class Description
{ {
public: public:
static Description fromParser(utils::Parser &&parser);
static Description fromStream(std::istream &istream); static Description fromStream(std::istream &istream);
static Description fromFile(const boost::filesystem::path &path); static Description fromFile(const boost::filesystem::path &path);
@@ -46,14 +48,16 @@ class Description
private: private:
Description(); Description();
void parseVersionSection(std::istream &istream) const; void parseContent(utils::Parser &parser);
void parseMetricSection(std::istream &istream);
void parseVariablesSection(std::istream &istream); void parseVersionSection(utils::Parser &parser) const;
void parseMutexSection(std::istream &istream); void parseMetricSection(utils::Parser &parser);
void parseInitialStateSection(std::istream &istream); void parseVariablesSection(utils::Parser &parser);
void parseGoalSection(std::istream &istream); void parseMutexSection(utils::Parser &parser);
void parseOperatorSection(std::istream &istream); void parseInitialStateSection(utils::Parser &parser);
void parseAxiomSection(std::istream &istream); void parseGoalSection(utils::Parser &parser);
void parseOperatorSection(utils::Parser &parser);
void parseAxiomSection(utils::Parser &parser);
bool m_usesActionCosts; bool m_usesActionCosts;

View File

@@ -5,6 +5,7 @@
#include <plasp/sas/AssignedVariable.h> #include <plasp/sas/AssignedVariable.h>
#include <plasp/sas/Variable.h> #include <plasp/sas/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp namespace plasp
{ {
@@ -28,7 +29,7 @@ class Effect
using Condition = AssignedVariable; using Condition = AssignedVariable;
using Conditions = AssignedVariables; 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: public:
const Conditions &conditions() const; const Conditions &conditions() const;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,6 +5,7 @@
#include <plasp/sas/Value.h> #include <plasp/sas/Value.h>
#include <plasp/sas/Variable.h> #include <plasp/sas/Variable.h>
#include <plasp/utils/Parser.h>
namespace plasp namespace plasp
{ {
@@ -25,7 +26,7 @@ using VariableTransitions = std::vector<VariableTransition>;
class VariableTransition class VariableTransition
{ {
public: public:
static VariableTransition fromSAS(std::istream &istream, const Variables &variables); static VariableTransition fromSAS(utils::Parser &parser, const Variables &variables);
public: public:
const Variable &variable() const; 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 #ifndef __PLASP__UTILS__IO_H
#define __PLASP__UTILS__PARSING_H #define __PLASP__UTILS__IO_H
#include <algorithm>
#include <exception>
#include <iosfwd>
#include <sstream>
#include <string>
#include <typeinfo>
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <plasp/utils/ParserException.h>
namespace plasp namespace plasp
{ {
namespace utils 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) inline std::string escapeASP(const std::string &string)
{ {
auto escaped = 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/Parser.h>
#include <plasp/utils/ParserException.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 Parser::Coordinate &coordinate, const std::string &message);
void logWarning(const Parser &parser, const std::string &message);
private:
LogStream m_outputStream;
LogStream m_errorStream;
WarningLevel m_warningLevel;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -0,0 +1,167 @@
#ifndef __PLASP__UTILS__PARSER_H
#define __PLASP__UTILS__PARSER_H
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
#include <boost/filesystem.hpp>
namespace plasp
{
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Parser
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Parser
{
public:
using Position = std::stringstream::pos_type;
struct Coordinate
{
std::string sectionName;
size_t row;
size_t column;
};
struct StreamDelimiter
{
Position position;
std::string sectionName;
};
public:
explicit Parser();
explicit Parser(std::string streamName, std::istream &istream);
// Forbid copy construction/assignment
Parser(const Parser &other) = delete;
Parser &operator=(const Parser &other) = delete;
Parser(Parser &&other);
Parser &operator=(Parser &&other);
void readStream(std::string streamName, std::istream &istream);
void readFile(const boost::filesystem::path &path);
void reset();
void seek(Position position);
Position position() const;
Coordinate coordinate() const;
void setCaseSensitive(bool isCaseInsensitive = true);
char currentCharacter() const;
void advance();
bool atEndOfStream() const;
void removeComments(const std::string &startSequence, const std::string &endSequence, bool removeEnd);
template<typename Type>
Type parse();
template<class CharacterPredicate, class WhiteSpacePredicate>
std::string parseIdentifier(CharacterPredicate characterPredicate, WhiteSpacePredicate whiteSpacePredicate);
template<class CharacterPredicate>
std::string parseIdentifier(CharacterPredicate characterPredicate);
template<typename Type>
bool probe(const Type &expectedValue);
template<class CharacterPredicate>
bool probeIdentifier(const std::string &identifier, CharacterPredicate characterPredicate);
bool probeNumber();
template<typename Type>
void expect(const Type &expectedValue);
template<class WhiteSpacePredicate>
void skipWhiteSpace(WhiteSpacePredicate whiteSpacePredicate);
void skipWhiteSpace();
void skipLine();
std::string getLine();
private:
static const std::istreambuf_iterator<char> EndOfFile;
private:
void checkStream() const;
uint64_t parseIntegerBody();
mutable std::stringstream m_stream;
std::vector<StreamDelimiter> m_streamDelimiters;
bool m_isCaseSensitive;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class CharacterPredicate, class WhiteSpacePredicate>
std::string Parser::parseIdentifier(CharacterPredicate characterPredicate, WhiteSpacePredicate whiteSpacePredicate)
{
skipWhiteSpace(whiteSpacePredicate);
std::string value;
while (true)
{
const auto character = currentCharacter();
if (!characterPredicate(character))
return value;
value.push_back(character);
advance();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class CharacterPredicate>
std::string Parser::parseIdentifier(CharacterPredicate characterPredicate)
{
return parseIdentifier(characterPredicate,
[&](const auto character)
{
return std::isspace(character);
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class CharacterPredicate>
bool Parser::probeIdentifier(const std::string &expectedValue, CharacterPredicate characterPredicate)
{
return probe<std::string>(expectedValue) && !characterPredicate(currentCharacter());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class WhiteSpacePredicate>
void Parser::skipWhiteSpace(WhiteSpacePredicate whiteSpacePredicate)
{
checkStream();
while (!atEndOfStream() && whiteSpacePredicate(currentCharacter()))
advance();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@@ -4,6 +4,8 @@
#include <exception> #include <exception>
#include <string> #include <string>
#include <plasp/utils/Parser.h>
namespace plasp namespace plasp
{ {
namespace utils namespace utils
@@ -18,17 +20,21 @@ namespace utils
class ParserException: public std::exception class ParserException: public std::exception
{ {
public: public:
explicit ParserException() explicit ParserException(const utils::Parser &parser)
: ParserException(parser, "unspecified parser error")
{ {
} }
explicit ParserException(const char *message) explicit ParserException(const utils::Parser &parser, const char *message)
: m_message(message) : ParserException(parser, static_cast<std::string>(message))
{ {
} }
explicit ParserException(const std::string &message) explicit ParserException(const utils::Parser &parser, const std::string &message)
: m_message(message) : m_coordinate{parser.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() const char *what() const throw()
{ {
if (m_message.empty()) return m_plainMessage.c_str();
return "Unspecified error while parsing SAS description file"; }
return m_message.c_str(); const Parser::Coordinate &coordinate() const
{
return m_coordinate;
}
const std::string &message() const
{
return m_message;
} }
private: private:
Parser::Coordinate m_coordinate;
std::string m_message; std::string m_message;
std::string m_plainMessage;
}; };
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

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

View File

@@ -3,6 +3,12 @@ set(target plasp)
file(GLOB core_sources "plasp/*.cpp") file(GLOB core_sources "plasp/*.cpp")
file(GLOB core_headers "../include/plasp/*.h") 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_sources "plasp/sas/*.cpp")
file(GLOB sas_headers "../include/plasp/sas/*.h") file(GLOB sas_headers "../include/plasp/sas/*.h")
@@ -21,6 +27,12 @@ set(sources
${core_sources} ${core_sources}
${core_headers} ${core_headers}
${pddl_sources}
${pddl_headers}
${pddl_expressions_sources}
${pddl_expressions_headers}
${sas_sources} ${sas_sources}
${sas_headers} ${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/Identifier.h>
#include <plasp/pddl/expressions/Type.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Action
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void Action::parseDeclaration(Context &context, Domain &domain)
{
auto action = std::make_unique<Action>(Action());
action->m_name = context.parser.parseIdentifier(isIdentifier);
context.parser.expect<std::string>(":parameters");
context.parser.expect<std::string>("(");
ExpressionContext expressionContext(domain, action->m_parameters);
// Read parameters
expressions::Variable::parseTypedDeclarations(context, expressionContext);
context.parser.expect<std::string>(")");
// Parse preconditions and effects
while (context.parser.currentCharacter() != ')')
{
context.parser.expect<std::string>(":");
if (context.parser.probeIdentifier("precondition", isIdentifier))
action->m_precondition = parsePreconditionExpression(context, expressionContext);
else if (context.parser.probeIdentifier("effect", isIdentifier))
action->m_effect = parseEffectExpression(context, expressionContext);
context.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,209 @@
#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.readStream("std::cin", istream);
description.parse();
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromFile(const std::string &path)
{
Description description;
description.m_context.parser.readFile(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.readFile(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.setCaseSensitive(false);
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.atEndOfStream())
{
const auto position = parser.position();
parser.expect<std::string>("(");
parser.expect<std::string>("define");
parser.expect<std::string>("(");
if (parser.probe<std::string>("domain"))
{
if (m_domainPosition != -1)
throw utils::ParserException(parser, "PDDL description may not contain two domains");
m_domainPosition = position;
parser.seek(position);
m_domain->findSections();
}
else if (m_context.parser.probe<std::string>("problem"))
{
if (m_problemPosition != -1)
throw utils::ParserException(parser, "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, "unknown PDDL section “" + sectionIdentifier + "");
}
m_context.parser.skipWhiteSpace();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::checkConsistency()
{
m_domain->checkConsistency();
m_problem->checkConsistency();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

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

@@ -0,0 +1,419 @@
#include <plasp/pddl/Domain.h>
#include <algorithm>
#include <plasp/pddl/ConsistencyException.h>
#include <plasp/pddl/Identifier.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(isIdentifier);
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, "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.probeIdentifier("requirements", isIdentifier))
setSectionPosition("requirements", m_requirementsPosition, position, true);
else if (parser.probeIdentifier("types", isIdentifier))
setSectionPosition("types", m_typesPosition, position, true);
else if (parser.probeIdentifier("constants", isIdentifier))
setSectionPosition("constants", m_constantsPosition, position, true);
else if (parser.probeIdentifier("predicates", isIdentifier))
setSectionPosition("predicates", m_predicatesPosition, position, true);
else if (parser.probeIdentifier("action", isIdentifier))
{
m_actionPositions.emplace_back(-1);
setSectionPosition("action", m_actionPositions.back(), position);
}
else if (parser.probeIdentifier("functions", isIdentifier)
|| parser.probeIdentifier("constraints", isIdentifier)
|| parser.probeIdentifier("durative-action", isIdentifier)
|| parser.probeIdentifier("derived", isIdentifier))
{
parser.seek(sectionIdentifierPosition);
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
m_context.logger.logWarning(parser, "section type “" + sectionIdentifier + "” currently unsupported");
parser.seek(sectionIdentifierPosition);
}
else
{
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(m_context.parser, "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, "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,253 @@
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Identifier.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.probeIdentifier("forall", isIdentifier)
|| parser.probeIdentifier("preference", isIdentifier))
{
// TODO: refactor
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
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.probeIdentifier("exists", isIdentifier)
|| parser.probeIdentifier("forall", isIdentifier)
|| parser.probeIdentifier("-", isIdentifier)
|| parser.probeIdentifier("=", isIdentifier)
|| parser.probeIdentifier("*", isIdentifier)
|| parser.probeIdentifier("+", isIdentifier)
|| parser.probeIdentifier("-", isIdentifier)
|| parser.probeIdentifier("/", isIdentifier)
|| parser.probeIdentifier(">", isIdentifier)
|| parser.probeIdentifier("<", isIdentifier)
|| parser.probeIdentifier("=", isIdentifier)
|| parser.probeIdentifier(">=", isIdentifier)
|| parser.probeIdentifier("<=", isIdentifier))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
return expressions::Unsupported::parse(context);
}
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(context.parser, "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.probeIdentifier("forall", isIdentifier)
|| parser.probeIdentifier("when", isIdentifier))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
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.probeIdentifier("=", isIdentifier)
|| parser.probeIdentifier("assign", isIdentifier)
|| parser.probeIdentifier("scale-up", isIdentifier)
|| parser.probeIdentifier("scale-down", isIdentifier)
|| parser.probeIdentifier("increase", isIdentifier)
|| parser.probeIdentifier("decrease", isIdentifier))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
return expressions::Unsupported::parse(context);
}
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(context.parser, "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parsePredicate(Context &context, ExpressionContext &expressionContext)
{
ExpressionPointer expression;
if ((expression = expressions::Predicate::parse(context, expressionContext)))
return expression;
throw utils::ParserException(context.parser, "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.probe<std::string>("("))
return nullptr;
const auto expressionIdentifierPosition = parser.position();
if (parser.probeIdentifier("=", isIdentifier))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
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,90 @@
#include <plasp/pddl/InitialState.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Identifier.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.probeIdentifier("=", isIdentifier))
{
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
return expressions::Unsupported::parse(context);
}
parser.seek(expressionIdentifierPosition);
const auto expressionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(parser, "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;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

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

@@ -0,0 +1,399 @@
#include <plasp/pddl/Problem.h>
#include <algorithm>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Identifier.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(isIdentifier);
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, "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.probeIdentifier("domain", isIdentifier))
setSectionPosition("domain", m_domainPosition, position, true);
else if (parser.probeIdentifier("requirements", isIdentifier))
setSectionPosition("requirements", m_requirementsPosition, position, true);
else if (parser.probeIdentifier("objects", isIdentifier))
setSectionPosition("objects", m_objectsPosition, position, true);
else if (parser.probeIdentifier("init", isIdentifier))
setSectionPosition("init", m_initialStatePosition, position, true);
else if (parser.probeIdentifier("goal", isIdentifier))
setSectionPosition("goal", m_goalPosition, position, true);
else if (parser.probeIdentifier("constraints", isIdentifier)
|| parser.probeIdentifier("metric", isIdentifier)
|| parser.probeIdentifier("length", isIdentifier))
{
parser.seek(sectionIdentifierPosition);
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
m_context.logger.logWarning(parser, "section type “" + sectionIdentifier + "” currently unsupported");
parser.seek(sectionIdentifierPosition);
}
else
{
const auto sectionIdentifier = parser.parseIdentifier(isIdentifier);
parser.seek(position);
throw utils::ParserException(m_context.parser, "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(isIdentifier);
if (m_domain.name() != domainName)
throw utils::ParserException(parser, "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,134 @@
#include <plasp/pddl/Requirement.h>
#include <boost/assert.hpp>
#include <boost/assign.hpp>
#include <boost/bimap.hpp>
#include <plasp/pddl/Identifier.h>
#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)
{
const auto requirementName = context.parser.parseIdentifier(isIdentifier);
const auto match = requirementTypesToPDDL.right.find(requirementName);
if (match == requirementTypesToPDDL.right.end())
throw utils::ParserException(context.parser, "unknown PDDL requirement “" + requirementName + "");
const auto requirementType = match->second;
if (requirementType == Requirement::Type::GoalUtilities)
context.logger.logWarning(context.parser, "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,505 @@
#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") << "(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") << "(" << 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("hasType") << "(" << utils::Variable("X") << ", "
<< utils::Keyword("type") << "(" << parentTypeName << ")) :- "
<< utils::Keyword("hasType") << "(" << utils::Variable("X") << ", "
<< utils::Keyword("type") << "(" << typeName << "))." << std::endl;
});
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translatePredicates() const
{
m_outputStream << utils::Heading2("predicates");
const auto &predicates = m_description.domain().predicates();
std::for_each(predicates.cbegin(), predicates.cend(),
[&](const auto &predicate)
{
m_outputStream << std::endl;
m_outputStream << utils::Keyword("predicate") << "(" << utils::escapeASP(predicate->name());
this->translateVariablesHead(predicate->arguments());
m_outputStream << ")";
this->translateVariablesBody(predicate->arguments());
m_outputStream << ".";
});
m_outputStream << std::endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
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)
{
const auto translateLiteral =
[&](const auto &ruleHead, const auto &literal)
{
m_outputStream << std::endl << utils::Keyword(ruleHead) << "(";
printActionName(*action);
m_outputStream << ", ";
this->translateLiteral(literal);
m_outputStream << ") :- ";
printActionName(*action);
m_outputStream << ".";
};
m_outputStream << std::endl;
// Name
printActionName(*action);
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);
}
// 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);
});
}
}
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")
<< "(" << constantName << ")." << std::endl;
const auto *type = constant->type();
if (type != nullptr)
{
m_outputStream << utils::Keyword("hasType") << "("
<< utils::Keyword("constant") << "(" << constantName << "), "
<< utils::Keyword("type") << "(" << utils::escapeASP(type->name()) << "))." << std::endl;
}
else
{
m_outputStream << utils::Keyword("hasType") << "("
<< 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("hasType") << "("
<< utils::Variable(utils::escapeASPVariable(variable.name())) << ", "
<< utils::Keyword("type") << "(" << utils::escapeASP(type.name()) << "))";
}
else
{
m_outputStream << utils::Keyword("hasType") << "("
<< 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)
{
this->translatePredicate(dynamic_cast<const expressions::Predicate &>(literal));
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());
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::Keyword("predicate") << "(" << utils::escapeASP(predicate.name());
const auto &arguments = predicate.arguments();
if (arguments.empty())
{
m_outputStream << ")";
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)
this->translatePredicate(dynamic_cast<const expressions::Predicate &>(*fact));
// 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,240 @@
#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(isIdentifier);
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.probe('-'))
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, "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(context.parser, "constant has undeclared type");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant *Constant::parseAndFind(Context &context, const Domain &domain)
{
context.parser.skipWhiteSpace();
const auto constantName = context.parser.parseIdentifier(isIdentifier);
auto *constant = parseAndFind(constantName, domain.constants());
if (constant != nullptr)
return constant;
throw utils::ParserException(context.parser, "constant “" + constantName + "” used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant *Constant::parseAndFind(Context &context, const Problem &problem)
{
context.parser.skipWhiteSpace();
const auto constantName = context.parser.parseIdentifier(isIdentifier);
auto *constant = parseAndFind(constantName, problem.domain().constants());
if (constant)
return constant;
constant = parseAndFind(constantName, problem.objects());
if (constant)
return constant;
throw utils::ParserException(context.parser, "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,22 @@
#include <plasp/pddl/expressions/Imply.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Imply
//
////////////////////////////////////////////////////////////////////////////////////////////////////
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,176 @@
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Identifier.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.probe<std::string>("("))
{
parser.seek(position);
return nullptr;
}
const auto predicateName = parser.parseIdentifier(isIdentifier);
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.probe<std::string>("("))
{
parser.seek(position);
return nullptr;
}
const auto predicateName = parser.parseIdentifier(isIdentifier);
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;
context.parser.skipWhiteSpace();
while (context.parser.currentCharacter() != ')')
{
if (context.parser.currentCharacter() == '?')
throw utils::ParserException(context.parser, "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,85 @@
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Identifier.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(isIdentifier);
// 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,172 @@
#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(isIdentifier);
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.probe('-'))
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 &types = domain.types();
context.parser.skipWhiteSpace();
const auto typeName = context.parser.parseIdentifier(isIdentifier);
if (typeName.empty())
throw utils::ParserException(context.parser, "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(context.parser, "primitive type “" + typeName + "” should be declared");
types.emplace_back(std::make_unique<expressions::PrimitiveType>(typeName));
}
else
throw utils::ParserException(context.parser, "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,47 @@
#include <plasp/pddl/expressions/Unsupported.h>
#include <plasp/pddl/Identifier.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(isIdentifier);
context.logger.logWarning(context.parser, "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,201 @@
#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/Identifier.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)
{
context.parser.skipWhiteSpace();
context.parser.expect<std::string>("?");
auto variable = std::make_unique<Variable>(Variable());
variable->m_name = context.parser.parseIdentifier(isIdentifier);
// 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(context.parser, "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.probe('-'))
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, "variable has undeclared type");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Variable *Variable::parseAndFind(Context &context, const ExpressionContext &expressionContext)
{
context.parser.skipWhiteSpace();
context.parser.expect<std::string>("?");
const auto variableName = context.parser.parseIdentifier(isIdentifier);
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(context.parser, "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 <boost/assert.hpp>
#include <plasp/utils/Parsing.h>
namespace plasp namespace plasp
{ {
namespace sas 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 assignedVariable;
assignedVariable.m_variable = &Variable::referenceFromSAS(istream, variables); assignedVariable.m_variable = &Variable::referenceFromSAS(parser, variables);
assignedVariable.m_value = &Value::referenceFromSAS(istream, *assignedVariable.m_variable); assignedVariable.m_value = &Value::referenceFromSAS(parser, *assignedVariable.m_variable);
return assignedVariable; return assignedVariable;
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
AssignedVariable AssignedVariable::fromSAS(std::istream &istream, const Variable &variable) AssignedVariable AssignedVariable::fromSAS(utils::Parser &parser, const Variable &variable)
{ {
AssignedVariable assignedVariable; AssignedVariable assignedVariable;
assignedVariable.m_variable = &variable; assignedVariable.m_variable = &variable;
assignedVariable.m_value = &Value::referenceFromSAS(istream, *assignedVariable.m_variable); assignedVariable.m_value = &Value::referenceFromSAS(parser, *assignedVariable.m_variable);
return assignedVariable; return assignedVariable;
} }

View File

@@ -3,7 +3,6 @@
#include <iostream> #include <iostream>
#include <plasp/sas/VariableTransition.h> #include <plasp/sas/VariableTransition.h>
#include <plasp/utils/Parsing.h>
namespace plasp 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 conditions;
conditions.reserve(numberOfConditions); conditions.reserve(numberOfConditions);
for (size_t j = 0; j < numberOfConditions; j++) 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) if (&variableTransition.valueBefore() != &Value::Any)
conditions.emplace_back(Condition(variableTransition.variable(), variableTransition.valueBefore())); 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 Condition postcondition(variableTransition.variable(), variableTransition.valueAfter());
const AxiomRule axiomRule(std::move(conditions), std::move(postcondition)); 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 // Metric section
ostream << "uses action costs: " << (description.usesActionCosts() ? "yes" : "no") << std::endl; ostream << "uses action costs: " << (description.usesActionCosts() ? "yes" : "no") << std::endl;

View File

@@ -8,7 +8,6 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <plasp/utils/ParserException.h> #include <plasp/utils/ParserException.h>
#include <plasp/utils/Parsing.h>
#include <plasp/sas/VariableTransition.h> #include <plasp/sas/VariableTransition.h>
namespace plasp namespace plasp
@@ -29,22 +28,25 @@ Description::Description()
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromParser(utils::Parser &&parser)
{
parser.setCaseSensitive(true);
Description description;
description.parseContent(parser);
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromStream(std::istream &istream) Description Description::fromStream(std::istream &istream)
{ {
utils::Parser parser;
parser.readStream("std::cin", istream);
Description description; Description description;
description.parseContent(parser);
std::setlocale(LC_NUMERIC, "C");
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);
return description; return description;
} }
@@ -54,11 +56,15 @@ Description Description::fromStream(std::istream &istream)
Description Description::fromFile(const boost::filesystem::path &path) Description Description::fromFile(const boost::filesystem::path &path)
{ {
if (!boost::filesystem::is_regular_file(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.readFile(path);
return Description::fromStream(fileStream); Description description;
description.parseContent(parser);
return description;
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -149,85 +155,104 @@ bool Description::usesConditionalEffects() const
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parseVersionSection(std::istream &istream) const void Description::parseContent(utils::Parser &parser)
{ {
utils::parseExpected<std::string>(istream, "begin_version"); parseVersionSection(parser);
parseMetricSection(parser);
parseVariablesSection(parser);
parseMutexSection(parser);
parseInitialStateSection(parser);
parseGoalSection(parser);
parseOperatorSection(parser);
parseAxiomSection(parser);
const auto formatVersion = utils::parse<size_t>(istream); parser.skipWhiteSpace();
if (!parser.atEndOfStream())
throw utils::ParserException(parser, "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) if (formatVersion != 3)
throw utils::ParserException("Unsupported SAS format version (" + std::to_string(formatVersion) + ")"); throw utils::ParserException(parser, "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); m_variables.reserve(numberOfVariables);
for (size_t i = 0; i < numberOfVariables; i++) 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); m_mutexGroups.reserve(numberOfMutexGroups);
for (size_t i = 0; i < numberOfMutexGroups; i++) 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); m_operators.reserve(numberOfOperators);
for (size_t i = 0; i < numberOfOperators; i++) 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); m_axiomRules.reserve(numberOfAxiomRules);
for (size_t i = 0; i < numberOfAxiomRules; i++) 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 <iostream>
#include <plasp/sas/VariableTransition.h> #include <plasp/sas/VariableTransition.h>
#include <plasp/utils/Parsing.h>
namespace plasp 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; Effect::Conditions conditions;
const auto numberOfEffectConditions = utils::parse<size_t>(istream); const auto numberOfEffectConditions = parser.parse<size_t>();
conditions.reserve(numberOfEffectConditions); conditions.reserve(numberOfEffectConditions);
for (size_t k = 0; k < numberOfEffectConditions; k++) 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) if (&variableTransition.valueBefore() != &Value::Any)
preconditions.emplace_back(Condition(variableTransition.variable(), variableTransition.valueBefore())); preconditions.emplace_back(Condition(variableTransition.variable(), variableTransition.valueBefore()));

View File

@@ -2,8 +2,6 @@
#include <iostream> #include <iostream>
#include <plasp/utils/Parsing.h>
namespace plasp namespace plasp
{ {
namespace sas 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; 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); goal.m_facts.reserve(numberOfGoalFacts);
for (size_t i = 0; i < numberOfGoalFacts; i++) 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; return goal;
} }

View File

@@ -1,9 +1,5 @@
#include <plasp/sas/InitialState.h> #include <plasp/sas/InitialState.h>
#include <iostream>
#include <plasp/utils/Parsing.h>
namespace plasp namespace plasp
{ {
namespace sas 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; InitialState initialState;
utils::parseExpected<std::string>(istream, "begin_state"); parser.expect<std::string>("begin_state");
initialState.m_facts.reserve(variables.size()); initialState.m_facts.reserve(variables.size());
for (size_t i = 0; i < variables.size(); i++) 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; return initialState;
} }

View File

@@ -2,7 +2,7 @@
#include <iostream> #include <iostream>
#include <plasp/utils/Parsing.h> #include <plasp/utils/ParserException.h>
namespace plasp 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; 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); mutexGroup.m_facts.reserve(numberOfFacts);
for (size_t j = 0; j < numberOfFacts; j++) 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) if (mutexGroup.m_facts[j].value() == Value::None)
throw utils::ParserException("Mutex groups must not contain <none of those> values"); throw utils::ParserException(parser, "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; return mutexGroup;
} }

View File

@@ -4,7 +4,7 @@
#include <limits> #include <limits>
#include <plasp/sas/VariableTransition.h> #include <plasp/sas/VariableTransition.h>
#include <plasp/utils/Parsing.h> #include <plasp/utils/Formatting.h>
namespace plasp 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_; 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); operator_.m_preconditions.reserve(numberOfPrevailConditions);
for (size_t j = 0; j < numberOfPrevailConditions; j++) 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); operator_.m_effects.reserve(numberOfEffects);
for (size_t j = 0; j < numberOfEffects; j++) 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_; return operator_;
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Operator::printPredicateAsASP(std::ostream &ostream) const void Operator::printPredicateAsASP(utils::LogStream &outputStream) const
{ {
ostream << "action("; outputStream << utils::Keyword("action") << "(";
m_predicate.printAsASP(ostream); m_predicate.printAsASP(outputStream);
ostream << ")"; outputStream << ")";
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -4,7 +4,8 @@
#include <limits> #include <limits>
#include <sstream> #include <sstream>
#include <plasp/utils/Parsing.h> #include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>
namespace plasp namespace plasp
{ {
@@ -17,31 +18,35 @@ namespace sas
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
Predicate Predicate::fromSAS(std::istream &istream) Predicate Predicate::fromSAS(utils::Parser &parser)
{ {
Predicate predicate; Predicate predicate;
try try
{ {
istream.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); parser.skipLine();
// TODO: Inefficient, reimplement in one pass predicate.m_name = parser.parse<std::string>();
std::string line;
std::getline(istream, line);
std::stringstream lineStream(line); while (true)
{
// Parse arguments until reaching newline
parser.skipWhiteSpace(
[&](const auto character)
{
return character != '\n' && std::isspace(character);
});
predicate.m_name = utils::parse<std::string>(lineStream); if (parser.currentCharacter() == '\n')
break;
while (lineStream.peek() == ' ') const auto value = parser.parse<std::string>();
lineStream.ignore(1); predicate.m_arguments.emplace_back(std::move(value));
}
for (std::string argument; std::getline(lineStream, argument, ' ');)
predicate.m_arguments.push_back(std::move(argument));
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
throw utils::ParserException("Could not parse operator predicate"); throw utils::ParserException(parser, "could not parse operator predicate");
} }
return predicate; return predicate;
@@ -63,43 +68,43 @@ const Predicate::Arguments &Predicate::arguments() const
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Predicate::printAsSAS(std::ostream &ostream) const void Predicate::printAsSAS(utils::LogStream &outputStream) const
{ {
if (m_arguments.empty()) if (m_arguments.empty())
{ {
ostream << m_name; outputStream << m_name;
return; return;
} }
for (size_t i = 0; i < m_arguments.size(); i++) for (size_t i = 0; i < m_arguments.size(); i++)
{ {
if (i > 0) if (i > 0)
ostream << " "; outputStream << " ";
ostream << m_arguments[i]; outputStream << m_arguments[i];
} }
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Predicate::printAsASP(std::ostream &ostream) const void Predicate::printAsASP(utils::LogStream &outputStream) const
{ {
if (m_arguments.empty()) if (m_arguments.empty())
{ {
ostream << utils::escapeASP(m_name); outputStream << utils::escapeASP(m_name);
return; return;
} }
ostream << utils::escapeASP(m_name) << "("; outputStream << utils::escapeASP(m_name) << "(";
for (size_t i = 0; i < m_arguments.size(); i++) for (size_t i = 0; i < m_arguments.size(); i++)
{ {
if (i > 0) if (i > 0)
ostream << ", "; outputStream << ", ";
ostream << utils::escapeASP(m_arguments[i]); outputStream << utils::escapeASP(m_arguments[i]);
} }
ostream << ")"; outputStream << ")";
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,7 +1,6 @@
#include <plasp/sas/TranslatorASP.h> #include <plasp/sas/TranslatorASP.h>
#include <plasp/sas/TranslatorException.h> #include <plasp/utils/Formatting.h>
#include <plasp/utils/Parsing.h>
namespace plasp namespace plasp
{ {
@@ -14,62 +13,90 @@ namespace sas
// //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
TranslatorASP::TranslatorASP(const Description &description) TranslatorASP::TranslatorASP(const Description &description, utils::LogStream &ostream)
: m_description(description) : m_description(description),
m_outputStream(ostream)
{ {
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translate(std::ostream &ostream) const void TranslatorASP::translate() const
{ {
const auto usesActionCosts = m_description.usesActionCosts(); translateRequirements();
const auto usesAxiomRules = m_description.usesAxiomRules(); translateInitialState();
const auto usesConditionalEffects = m_description.usesConditionalEffects(); translateGoal();
translateVariables();
translateActions();
translateMutexes();
translateAxiomRules();
}
ostream << "% feature requirements" << std::endl; ////////////////////////////////////////////////////////////////////////////////////////////////////
if (usesActionCosts) void TranslatorASP::translateRequirements() const
ostream << "requiresFeature(actionCosts)." << std::endl; {
m_outputStream << utils::Heading2("feature requirements") << std::endl;
if (usesAxiomRules) if (m_description.usesActionCosts())
ostream << "requiresFeature(axiomRules)." << std::endl; m_outputStream << utils::Keyword("requiresFeature") << "(actionCosts)." << std::endl;
if (usesConditionalEffects) if (m_description.usesAxiomRules())
ostream << "requiresFeature(conditionalEffects)." << std::endl; m_outputStream << utils::Keyword("requiresFeature") << "(axiomRules)." << std::endl;
ostream << std::endl; if (m_description.usesConditionalEffects())
ostream << "% initial state" << std::endl; m_outputStream << utils::Keyword("requiresFeature") << "(conditionalEffects)." << std::endl;
m_outputStream << std::endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateInitialState() const
{
m_outputStream << utils::Heading2("initial state") << std::endl;
const auto &initialStateFacts = m_description.initialState().facts(); const auto &initialStateFacts = m_description.initialState().facts();
std::for_each(initialStateFacts.cbegin(), initialStateFacts.cend(), std::for_each(initialStateFacts.cbegin(), initialStateFacts.cend(),
[&](const auto &fact) [&](const auto &fact)
{ {
ostream << "initialState("; m_outputStream << utils::Keyword("initialState") << "(";
fact.variable().printNameAsASPPredicate(ostream); fact.variable().printNameAsASPPredicate(m_outputStream);
ostream << ", "; m_outputStream << ", ";
fact.value().printAsASPPredicate(ostream); fact.value().printAsASPPredicate(m_outputStream);
ostream << ")." << std::endl; m_outputStream << ")." << std::endl;
}); });
ostream << std::endl; m_outputStream << std::endl;
ostream << "% goal" << std::endl; }
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateGoal() const
{
m_outputStream << utils::Heading2("goal") << std::endl;
const auto &goalFacts = m_description.goal().facts(); const auto &goalFacts = m_description.goal().facts();
std::for_each(goalFacts.cbegin(), goalFacts.cend(), std::for_each(goalFacts.cbegin(), goalFacts.cend(),
[&](const auto &fact) [&](const auto &fact)
{ {
ostream << "goal("; m_outputStream << utils::Keyword("goal") << "(";
fact.variable().printNameAsASPPredicate(ostream); fact.variable().printNameAsASPPredicate(m_outputStream);
ostream << ", "; m_outputStream << ", ";
fact.value().printAsASPPredicate(ostream); fact.value().printAsASPPredicate(m_outputStream);
ostream << ")." << std::endl; m_outputStream << ")." << std::endl;
}); });
ostream << std::endl; m_outputStream << std::endl;
ostream << "% variables"; }
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateVariables() const
{
m_outputStream << utils::Heading2("variables");
const auto &variables = m_description.variables(); const auto &variables = m_description.variables();
@@ -80,45 +107,51 @@ void TranslatorASP::translate(std::ostream &ostream) const
BOOST_ASSERT(!values.empty()); BOOST_ASSERT(!values.empty());
ostream << std::endl; m_outputStream << std::endl;
variable.printNameAsASPPredicate(ostream); variable.printNameAsASPPredicate(m_outputStream);
ostream << "." << std::endl; m_outputStream << "." << std::endl;
std::for_each(values.cbegin(), values.cend(), std::for_each(values.cbegin(), values.cend(),
[&](const auto &value) [&](const auto &value)
{ {
ostream << "contains("; m_outputStream << utils::Keyword("contains") << "(";
variable.printNameAsASPPredicate(ostream); variable.printNameAsASPPredicate(m_outputStream);
ostream << ", "; m_outputStream << ", ";
value.printAsASPPredicate(ostream); value.printAsASPPredicate(m_outputStream);
ostream << ")." << std::endl; m_outputStream << ")." << std::endl;
}); });
}); });
ostream << std::endl; m_outputStream << std::endl;
ostream << "% actions"; }
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateActions() const
{
m_outputStream << utils::Heading2("actions");
const auto &operators = m_description.operators(); const auto &operators = m_description.operators();
std::for_each(operators.cbegin(), operators.cend(), std::for_each(operators.cbegin(), operators.cend(),
[&](const auto &operator_) [&](const auto &operator_)
{ {
ostream << std::endl; m_outputStream << std::endl;
operator_.printPredicateAsASP(ostream); operator_.printPredicateAsASP(m_outputStream);
ostream << "." << std::endl; m_outputStream << "." << std::endl;
const auto &preconditions = operator_.preconditions(); const auto &preconditions = operator_.preconditions();
std::for_each(preconditions.cbegin(), preconditions.cend(), std::for_each(preconditions.cbegin(), preconditions.cend(),
[&](const auto &precondition) [&](const auto &precondition)
{ {
ostream << "precondition("; m_outputStream << utils::Keyword("precondition") << "(";
operator_.printPredicateAsASP(ostream); operator_.printPredicateAsASP(m_outputStream);
ostream << ", "; m_outputStream << ", ";
precondition.variable().printNameAsASPPredicate(ostream); precondition.variable().printNameAsASPPredicate(m_outputStream);
ostream << ", "; m_outputStream << ", ";
precondition.value().printAsASPPredicate(ostream); precondition.value().printAsASPPredicate(m_outputStream);
ostream << ")." << std::endl; m_outputStream << ")." << std::endl;
}); });
const auto &effects = operator_.effects(); const auto &effects = operator_.effects();
@@ -133,33 +166,39 @@ void TranslatorASP::translate(std::ostream &ostream) const
std::for_each(conditions.cbegin(), conditions.cend(), std::for_each(conditions.cbegin(), conditions.cend(),
[&](const auto &condition) [&](const auto &condition)
{ {
ostream << "effectCondition("; m_outputStream << utils::Keyword("effectCondition") << "(";
operator_.printPredicateAsASP(ostream); operator_.printPredicateAsASP(m_outputStream);
ostream << ", effect(" << currentEffectID << "), "; m_outputStream << ", " << utils::Keyword("effect") << "(" << utils::Number(std::to_string(currentEffectID)) << "), ";
condition.variable().printNameAsASPPredicate(ostream); condition.variable().printNameAsASPPredicate(m_outputStream);
ostream << ", "; m_outputStream << ", ";
condition.value().printAsASPPredicate(ostream); condition.value().printAsASPPredicate(m_outputStream);
ostream << ")." << std::endl; m_outputStream << ")." << std::endl;
}); });
ostream << "postcondition("; m_outputStream << utils::Keyword("postcondition") << "(";
operator_.printPredicateAsASP(ostream); operator_.printPredicateAsASP(m_outputStream);
ostream << ", effect(" << currentEffectID << "), "; m_outputStream << ", " << utils::Keyword("effect") << "(" << utils::Number(std::to_string(currentEffectID)) << "), ";
effect.postcondition().variable().printNameAsASPPredicate(ostream); effect.postcondition().variable().printNameAsASPPredicate(m_outputStream);
ostream << ", "; m_outputStream << ", ";
effect.postcondition().value().printAsASPPredicate(ostream); effect.postcondition().value().printAsASPPredicate(m_outputStream);
ostream << ")." << std::endl; m_outputStream << ")." << std::endl;
currentEffectID++; currentEffectID++;
}); });
ostream << "costs("; m_outputStream << utils::Keyword("costs") << "(";
operator_.printPredicateAsASP(ostream); operator_.printPredicateAsASP(m_outputStream);
ostream << ", " << operator_.costs() << ")." << std::endl; m_outputStream << ", " << operator_.costs() << ")." << std::endl;
}); });
ostream << std::endl; m_outputStream << std::endl;
ostream << "% mutex groups"; }
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateMutexes() const
{
m_outputStream << utils::Heading2("mutex groups");
const auto &mutexGroups = m_description.mutexGroups(); const auto &mutexGroups = m_description.mutexGroups();
@@ -171,59 +210,64 @@ void TranslatorASP::translate(std::ostream &ostream) const
const auto mutexGroupID = std::to_string(currentMutexGroupID); const auto mutexGroupID = std::to_string(currentMutexGroupID);
currentMutexGroupID++; currentMutexGroupID++;
ostream << std::endl << "mutexGroup(" << mutexGroupID << ")." << std::endl; m_outputStream << std::endl << utils::Keyword("mutexGroup") << "(" << utils::Number(mutexGroupID) << ")." << std::endl;
const auto &facts = mutexGroup.facts(); const auto &facts = mutexGroup.facts();
std::for_each(facts.cbegin(), facts.cend(), std::for_each(facts.cbegin(), facts.cend(),
[&](const auto &fact) [&](const auto &fact)
{ {
ostream << "contains(mutexGroup(" << mutexGroupID << "), "; m_outputStream << utils::Keyword("contains") << "(" << utils::Keyword("mutexGroup") << "(" << utils::Number(mutexGroupID) << "), ";
fact.variable().printNameAsASPPredicate(ostream); fact.variable().printNameAsASPPredicate(m_outputStream);
ostream << ", "; m_outputStream << ", ";
fact.value().printAsASPPredicate(ostream); fact.value().printAsASPPredicate(m_outputStream);
ostream << ")." << std::endl; m_outputStream << ")." << std::endl;
}); });
}); });
}
if (usesAxiomRules) ////////////////////////////////////////////////////////////////////////////////////////////////////
{
ostream << std::endl;
ostream << "% axiom rules";
const auto &axiomRules = m_description.axiomRules(); void TranslatorASP::translateAxiomRules() const
{
if (!m_description.usesActionCosts())
return;
size_t currentAxiomRuleID = 0; m_outputStream << std::endl;
m_outputStream << utils::Heading2("axiom rules");
std::for_each(axiomRules.cbegin(), axiomRules.cend(), const auto &axiomRules = m_description.axiomRules();
[&](const auto &axiomRule)
{
const auto axiomRuleID = std::to_string(currentAxiomRuleID);
currentAxiomRuleID++;
ostream << std::endl << "axiomRule(" << axiomRuleID << ")." << std::endl; size_t currentAxiomRuleID = 0;
const auto &conditions = axiomRule.conditions(); std::for_each(axiomRules.cbegin(), axiomRules.cend(),
[&](const auto &axiomRule)
{
const auto axiomRuleID = std::to_string(currentAxiomRuleID);
currentAxiomRuleID++;
std::for_each(conditions.cbegin(), conditions.cend(), m_outputStream << std::endl << utils::Keyword("axiomRule") << "(" << utils::Number(axiomRuleID) << ")." << std::endl;
[&](const auto &condition)
{
ostream << "condition(axiomRule(" << axiomRuleID << "), ";
condition.variable().printNameAsASPPredicate(ostream);
ostream << ", ";
condition.value().printAsASPPredicate(ostream);
ostream << ")." << std::endl;
});
const auto &postcondition = axiomRule.postcondition(); const auto &conditions = axiomRule.conditions();
ostream << "postcondition(axiomRule(axiomRule" << axiomRuleID << "), "; std::for_each(conditions.cbegin(), conditions.cend(),
postcondition.variable().printNameAsASPPredicate(ostream); [&](const auto &condition)
ostream << ", "; {
postcondition.value().printAsASPPredicate(ostream); m_outputStream << utils::Keyword("condition") << "(" << utils::Keyword("axiomRule") << "(" << utils::Number(axiomRuleID) << "), ";
ostream << ")." << std::endl; condition.variable().printNameAsASPPredicate(m_outputStream);
}); m_outputStream << ", ";
} condition.value().printAsASPPredicate(m_outputStream);
m_outputStream << ")." << std::endl;
});
const auto &postcondition = axiomRule.postcondition();
m_outputStream << utils::Keyword("postcondition") << "(" << utils::Keyword("axiomRule") << "(" << utils::Number(axiomRuleID) << "), ";
postcondition.variable().printNameAsASPPredicate(m_outputStream);
m_outputStream << ", ";
postcondition.value().printAsASPPredicate(m_outputStream);
m_outputStream << ")." << std::endl;
});
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -3,7 +3,9 @@
#include <iostream> #include <iostream>
#include <plasp/sas/Variable.h> #include <plasp/sas/Variable.h>
#include <plasp/utils/Parsing.h> #include <plasp/utils/Formatting.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>
namespace plasp namespace plasp
{ {
@@ -53,14 +55,14 @@ Value Value::negated() const
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
Value Value::fromSAS(std::istream &istream) Value Value::fromSAS(utils::Parser &parser)
{ {
const auto sasSign = utils::parse<std::string>(istream); const auto sasSign = parser.parse<std::string>();
if (sasSign == "<none") if (sasSign == "<none")
{ {
utils::parseExpected<std::string>(istream, "of"); parser.expect<std::string>("of");
utils::parseExpected<std::string>(istream, "those>"); parser.expect<std::string>("those>");
// TODO: do not return a copy of Value::None // TODO: do not return a copy of Value::None
return Value::None; return Value::None;
@@ -73,12 +75,12 @@ Value Value::fromSAS(std::istream &istream)
else if (sasSign == "NegatedAtom") else if (sasSign == "NegatedAtom")
value.m_sign = Value::Sign::Negative; value.m_sign = Value::Sign::Negative;
else else
throw utils::ParserException("Invalid value sign \"" + sasSign + "\""); throw utils::ParserException(parser, "invalid value sign " + sasSign + "");
try try
{ {
istream.ignore(1); parser.skipWhiteSpace();
std::getline(istream, value.m_name); value.m_name = parser.getLine();
// Remove trailing () // Remove trailing ()
if (value.m_name.find("()") != std::string::npos) if (value.m_name.find("()") != std::string::npos)
@@ -89,7 +91,7 @@ Value Value::fromSAS(std::istream &istream)
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {
throw utils::ParserException(std::string("Could not parse variable value (") + e.what() + ")"); throw utils::ParserException(parser, std::string("could not parse variable value (") + e.what() + ")");
} }
return value; return value;
@@ -97,15 +99,15 @@ Value Value::fromSAS(std::istream &istream)
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
const Value &Value::referenceFromSAS(std::istream &istream, const Variable &variable) const Value &Value::referenceFromSAS(utils::Parser &parser, const Variable &variable)
{ {
const auto valueID = utils::parse<int>(istream); const auto valueID = parser.parse<int>();
if (valueID == -1) if (valueID == -1)
return Value::Any; return Value::Any;
if (valueID < 0 || static_cast<size_t>(valueID) >= variable.values().size()) if (valueID < 0 || static_cast<size_t>(valueID) >= variable.values().size())
throw utils::ParserException("Value index out of range (variable " + variable.name() + ", index " + std::to_string(valueID) + ")"); throw utils::ParserException(parser, "value index out of range (variable " + variable.name() + ", index " + std::to_string(valueID) + ")");
return variable.values()[valueID]; return variable.values()[valueID];
} }
@@ -126,42 +128,42 @@ const std::string &Value::name() const
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Value::printAsASP(std::ostream &ostream) const void Value::printAsASP(utils::LogStream &outputStream) const
{ {
if (m_sign == Value::Sign::Negative) if (m_sign == Value::Sign::Negative)
ostream << "not "; outputStream << utils::Keyword("not") << " ";
ostream << utils::escapeASP(m_name); outputStream << utils::escapeASP(m_name);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Value::printAsASPPredicate(std::ostream &ostream) const void Value::printAsASPPredicate(utils::LogStream &outputStream) const
{ {
// TODO: do not compare by value // TODO: do not compare by value
if (*this == Value::None) if (*this == Value::None)
{ {
ostream << "value(none)"; outputStream << utils::Keyword("value") << "(" << utils::Keyword("none") << ")";
return; return;
} }
ostream << "value(" << utils::escapeASP(m_name) << ", " outputStream << utils::Keyword("value") << "(" << utils::escapeASP(m_name) << ", "
<< (m_sign == Sign::Positive ? "true" : "false") << ")"; << (m_sign == Sign::Positive ? utils::Keyword("true") : utils::Keyword("false")) << ")";
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Value::printAsSAS(std::ostream &ostream) const void Value::printAsSAS(utils::LogStream &outputStream) const
{ {
if (m_sign == Value::Sign::Positive) if (m_sign == Value::Sign::Positive)
ostream << "Atom "; outputStream << "Atom ";
else else
ostream << "NegatedAtom "; outputStream << "NegatedAtom ";
ostream << m_name; outputStream << m_name;
if (!m_hasArguments) if (!m_hasArguments)
ostream << "()"; outputStream << "()";
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -2,7 +2,9 @@
#include <iostream> #include <iostream>
#include <plasp/utils/Parsing.h> #include <plasp/utils/Formatting.h>
#include <plasp/utils/IO.h>
#include <plasp/utils/ParserException.h>
namespace plasp namespace plasp
{ {
@@ -22,47 +24,47 @@ Variable::Variable()
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
Variable Variable::fromSAS(std::istream &istream) Variable Variable::fromSAS(utils::Parser &parser)
{ {
Variable variable; Variable variable;
utils::parseExpected<std::string>(istream, "begin_variable"); parser.expect<std::string>("begin_variable");
variable.m_name = utils::parse<std::string>(istream); variable.m_name = parser.parse<std::string>();
variable.m_axiomLayer = utils::parse<int>(istream); variable.m_axiomLayer = parser.parse<int>();
const auto numberOfValues = utils::parse<size_t>(istream); const auto numberOfValues = parser.parse<size_t>();
variable.m_values.reserve(numberOfValues); variable.m_values.reserve(numberOfValues);
for (size_t j = 0; j < numberOfValues; j++) for (size_t j = 0; j < numberOfValues; j++)
{ {
variable.m_values.emplace_back(Value::fromSAS(istream)); variable.m_values.emplace_back(Value::fromSAS(parser));
// <none of those> values are only allowed at the end // <none of those> values are only allowed at the end
if (j < numberOfValues - 1 && variable.m_values[j] == Value::None) if (j < numberOfValues - 1 && variable.m_values[j] == Value::None)
throw utils::ParserException("<none of those> value must be the last value of a variable"); throw utils::ParserException(parser, "<none of those> value must be the last value of a variable");
} }
utils::parseExpected<std::string>(istream, "end_variable"); parser.expect<std::string>("end_variable");
return variable; return variable;
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::printNameAsASPPredicate(std::ostream &ostream) const void Variable::printNameAsASPPredicate(utils::LogStream &outputStream) const
{ {
ostream << "variable(" << utils::escapeASP(m_name) << ")"; outputStream << utils::Keyword("variable") << "(" << utils::escapeASP(m_name) << ")";
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
const Variable &Variable::referenceFromSAS(std::istream &istream, const Variables &variables) const Variable &Variable::referenceFromSAS(utils::Parser &parser, const Variables &variables)
{ {
const auto variableID = utils::parse<size_t>(istream); const auto variableID = parser.parse<size_t>();
if (variableID >= variables.size()) if (variableID >= variables.size())
throw utils::ParserException("Variable index out of range (index " + std::to_string(variableID) + ")"); throw utils::ParserException(parser, "variable index out of range (index " + std::to_string(variableID) + ")");
return variables[variableID]; return variables[variableID];
} }

View File

@@ -4,8 +4,6 @@
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <plasp/utils/Parsing.h>
namespace plasp namespace plasp
{ {
namespace sas namespace sas
@@ -26,13 +24,13 @@ VariableTransition::VariableTransition()
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
VariableTransition VariableTransition::fromSAS(std::istream &istream, const Variables &variables) VariableTransition VariableTransition::fromSAS(utils::Parser &parser, const Variables &variables)
{ {
VariableTransition variableTransition; VariableTransition variableTransition;
variableTransition.m_variable = &Variable::referenceFromSAS(istream, variables); variableTransition.m_variable = &Variable::referenceFromSAS(parser, variables);
variableTransition.m_valueBefore = &Value::referenceFromSAS(istream, *variableTransition.m_variable); variableTransition.m_valueBefore = &Value::referenceFromSAS(parser, *variableTransition.m_variable);
variableTransition.m_valueAfter = &Value::referenceFromSAS(istream, *variableTransition.m_variable); variableTransition.m_valueAfter = &Value::referenceFromSAS(parser, *variableTransition.m_variable);
return variableTransition; return variableTransition;
} }

145
src/plasp/utils/Logger.cpp Normal file
View File

@@ -0,0 +1,145 @@
#include <plasp/utils/Logger.h>
#include <plasp/utils/Formatting.h>
namespace plasp
{
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Logger
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Logger::Logger()
: m_outputStream(StandardStream::Out),
m_errorStream(StandardStream::Err),
m_warningLevel{Logger::WarningLevel::Normal}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Logger::Logger(const Logger &other)
: m_outputStream{other.m_outputStream},
m_errorStream{other.m_errorStream},
m_warningLevel{other.m_warningLevel}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Logger &Logger::operator=(const Logger &other)
{
m_outputStream = other.m_outputStream;
m_errorStream = other.m_errorStream;
m_warningLevel = other.m_warningLevel;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Logger::Logger(Logger &&other)
: m_outputStream{std::move(other.m_outputStream)},
m_errorStream{std::move(other.m_errorStream)},
m_warningLevel{other.m_warningLevel}
{
other.m_warningLevel = WarningLevel::Normal;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Logger &Logger::operator=(Logger &&other)
{
m_outputStream = std::move(other.m_outputStream);
m_errorStream = std::move(other.m_errorStream);
m_warningLevel = other.m_warningLevel;
other.m_warningLevel = WarningLevel::Normal;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &Logger::outputStream()
{
return m_outputStream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
LogStream &Logger::errorStream()
{
return m_errorStream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Logger::setWarningLevel(WarningLevel warningLevel)
{
m_warningLevel = warningLevel;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Logger::setColorPolicy(LogStream::ColorPolicy colorPolicy)
{
m_outputStream.setColorPolicy(colorPolicy);
m_errorStream.setColorPolicy(colorPolicy);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Logger::logError(const std::string &message)
{
m_errorStream
<< Format(Color::Red, FontWeight::Bold) << "error:"
<< ResetFormat() << " "
<< Format(Color::White, FontWeight::Bold) << message
<< ResetFormat() << std::endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Logger::logError(const Parser::Coordinate &coordinate, const std::string &message)
{
m_errorStream
<< Format(Color::White, FontWeight::Bold) << coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":"
<< ResetFormat() << " "
<< Format(Color::Red, FontWeight::Bold) << "error:"
<< ResetFormat() << " "
<< Format(Color::White, FontWeight::Bold) << message
<< ResetFormat() << std::endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Logger::logWarning(const Parser &parser, const std::string &message)
{
if (m_warningLevel == WarningLevel::Ignore)
return;
if (m_warningLevel == WarningLevel::Error)
throw ParserException(parser, message);
const auto coordinate = parser.coordinate();
m_errorStream
<< Format(Color::White, FontWeight::Bold) << coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":"
<< ResetFormat() << " "
<< Format(Color::Magenta, FontWeight::Bold) << "warning:"
<< ResetFormat() << " "
<< Format(Color::White, FontWeight::Bold) << message
<< ResetFormat() << std::endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

621
src/plasp/utils/Parser.cpp Normal file
View File

@@ -0,0 +1,621 @@
#include <plasp/utils/Parser.h>
#include <algorithm>
#include <fstream>
#include <boost/assert.hpp>
#include <plasp/utils/ParserException.h>
namespace plasp
{
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Parser
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::istreambuf_iterator<char> Parser::EndOfFile = std::istreambuf_iterator<char>();
////////////////////////////////////////////////////////////////////////////////////////////////////
Parser::Parser()
: m_isCaseSensitive{true}
{
std::setlocale(LC_NUMERIC, "C");
// Dont skip whitespace
m_stream.exceptions(std::istream::badbit);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Parser::Parser(std::string streamName, std::istream &istream)
: Parser()
{
readStream(streamName, istream);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Parser::Parser(Parser &&other)
: m_stream{std::move(other.m_stream)},
m_streamDelimiters{std::move(other.m_streamDelimiters)},
m_isCaseSensitive{other.m_isCaseSensitive}
{
other.m_isCaseSensitive = true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Parser &Parser::operator=(Parser &&other)
{
m_stream = std::move(other.m_stream);
m_streamDelimiters = std::move(other.m_streamDelimiters);
m_isCaseSensitive = other.m_isCaseSensitive;
other.m_isCaseSensitive = true;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::readStream(std::string streamName, std::istream &istream)
{
// Store position of new section
const auto position = m_stream.tellp();
m_streamDelimiters.push_back({position, streamName});
m_stream << istream.rdbuf();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::readFile(const boost::filesystem::path &path)
{
if (!boost::filesystem::is_regular_file(path))
throw std::runtime_error("File does not exist: “" + path.string() + "");
std::ifstream fileStream(path.string(), std::ios::in);
readStream(path.string(), fileStream);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::reset()
{
m_stream.clear();
seek(std::ios::beg);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::seek(Position position)
{
m_stream.clear();
m_stream.seekg(position);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Parser::Position Parser::position() const
{
return m_stream.tellg();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Parser::Coordinate Parser::coordinate() const
{
const auto currentPosition = position();
// Find current section
auto currentFile = std::find_if(m_streamDelimiters.crbegin(), m_streamDelimiters.crend(),
[&](const auto &fileDelimiter)
{
return currentPosition >= fileDelimiter.position;
});
// If the parser is at the end of the stream, still count from the beginning of the last section
if (currentFile == m_streamDelimiters.crend())
currentFile = m_streamDelimiters.crbegin();
// Go back to beginning of section
m_stream.clear();
m_stream.seekg(currentFile->position);
size_t row = 1;
size_t column = 1;
// Compute the coordinate character by character
while (true)
{
if (currentPosition == -1 && atEndOfStream())
break;
else if (currentPosition >= 0 && position() >= currentPosition)
break;
const auto character = currentCharacter();
if (character == '\n')
{
row++;
column = 1;
}
else if (std::isblank(character) || std::isprint(character))
column++;
m_stream.ignore(1);
}
return {currentFile->sectionName, row, column};
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::setCaseSensitive(bool isCaseSensitive)
{
m_isCaseSensitive = isCaseSensitive;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
char Parser::currentCharacter() const
{
if (m_isCaseSensitive)
return m_stream.peek();
return std::tolower(m_stream.peek());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Parser::atEndOfStream() const
{
return position() == -1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::checkStream() const
{
if (atEndOfStream())
throw ParserException(*this, "reading past end of file");
if (m_stream.fail())
throw ParserException(*this);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::advance()
{
checkStream();
m_stream.ignore(1);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::skipWhiteSpace()
{
return skipWhiteSpace(
[](const auto character)
{
return std::isspace(character);
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::skipLine()
{
checkStream();
while (currentCharacter() != '\n')
advance();
advance();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
std::string Parser::getLine()
{
checkStream();
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<>
std::string Parser::parse<std::string>()
{
skipWhiteSpace();
std::string value;
while (true)
{
const auto character = currentCharacter();
if (std::isspace(character))
break;
value.push_back(character);
advance();
}
return value;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::probe<std::string>(const std::string &expectedValue)
{
const auto previousPosition = position();
if (!std::iswspace(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;
});
const auto differs = (match != expectedValue.cend());
if (!differs)
return true;
seek(previousPosition);
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<std::string>(const std::string &expectedValue)
{
if (!probe<std::string>(expectedValue))
throw ParserException(*this, "expected “" + expectedValue + "");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
char Parser::parse<char>()
{
const auto value = currentCharacter();
advance();
return value;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::probe<char>(const char &expectedValue)
{
if (currentCharacter() != expectedValue)
return false;
advance();
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<char>(const char &expectedValue)
{
if (!probe<char>(expectedValue))
throw ParserException(*this, std::string("expected “") + expectedValue + "");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
uint64_t Parser::parseIntegerBody()
{
checkStream();
if (!std::isdigit(currentCharacter()))
throw ParserException(*this, "could not parse integer value");
uint64_t value = 0;
while (!atEndOfStream())
{
const auto character = currentCharacter();
if (!std::isdigit(character))
break;
value *= 10;
value += character - '0';
advance();
}
return value;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
int64_t Parser::parse<int64_t>()
{
skipWhiteSpace();
bool positive = probe('+') || !probe('-');
const auto value = parseIntegerBody();
return (positive ? value : -value);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
uint64_t Parser::parse<uint64_t>()
{
skipWhiteSpace();
if (currentCharacter() == '-')
throw ParserException(*this, "expected unsigned integer, got signed one");
return parseIntegerBody();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::probe<int64_t>(const int64_t &expectedValue)
{
const auto previousPosition = position();
const auto value = parse<int64_t>();
if (value == expectedValue)
return true;
seek(previousPosition);
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::probe<uint64_t>(const uint64_t &expectedValue)
{
const auto previousPosition = position();
const auto value = parse<uint64_t>();
if (value == expectedValue)
return true;
seek(previousPosition);
return false;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<int64_t>(const int64_t &expectedValue)
{
if (!probe<int64_t>(expectedValue))
throw ParserException(*this, "expected “" + std::to_string(expectedValue) + "");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<uint64_t>(const uint64_t &expectedValue)
{
if (!probe<uint64_t>(expectedValue))
throw ParserException(*this, "expected “" + std::to_string(expectedValue) + "");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
int32_t Parser::parse<int32_t>()
{
return static_cast<int32_t>(parse<int64_t>());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
uint32_t Parser::parse<uint32_t>()
{
return static_cast<uint32_t>(parse<uint64_t>());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::probe<int32_t>(const int32_t &expectedValue)
{
return probe<int64_t>(static_cast<int64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::probe<uint32_t>(const uint32_t &expectedValue)
{
return probe<uint64_t>(static_cast<uint64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<int32_t>(const int32_t &expectedValue)
{
expect<int64_t>(static_cast<int64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<uint32_t>(const uint32_t &expectedValue)
{
expect<uint64_t>(static_cast<uint64_t>(expectedValue));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
bool Parser::parse<bool>()
{
skipWhiteSpace();
if (probe('0'))
return false;
if (probe('1'))
return true;
throw ParserException(*this, "could not parse Boolean value");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
void Parser::expect<bool>(const bool &expectedValue)
{
const auto value = parse<bool>();
if (value != expectedValue)
throw ParserException(*this, "expected “" + std::to_string(expectedValue) + "");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Parser::probeNumber()
{
const auto previousPosition = position();
skipWhiteSpace();
while (!std::iswspace(currentCharacter()))
if (!std::isdigit(currentCharacter()))
{
seek(previousPosition);
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Parser::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 (atEndOfStream())
return;
m_stream.put(' ');
position += static_cast<std::streamoff>(1);
}
};
while (!atEndOfStream())
{
Position startPosition = m_stream.tellg();
while (!atEndOfStream())
{
startPosition = m_stream.tellg();
if (probe(startSequence))
break;
advance();
}
Position endPosition = m_stream.tellg();
while (!atEndOfStream())
{
endPosition = m_stream.tellg();
if (probe(endSequence))
break;
advance();
}
if (removeEnd)
endPosition = m_stream.tellg();
removeRange(startPosition, endPosition);
}
m_stream.clear();
m_stream.seekg(inPosition);
m_stream.seekp(outPosition);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

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