Compare commits
256 Commits
Author | SHA1 | Date | |
---|---|---|---|
9af383d2f6 | |||
d3039d55e5 | |||
6b5c8df03a | |||
8084fe5574 | |||
3d661cd1f4 | |||
853d7471c2 | |||
0a205680fe | |||
52fee6a4c1 | |||
fcdd3bba2b | |||
b491efa9f4 | |||
401cf79cf6 | |||
44a20ca7e3 | |||
5bda1c2245 | |||
eb3d91f085 | |||
aff396d919 | |||
f7cd24b67a | |||
1e21457efb | |||
583ec78eef | |||
9969281b11 | |||
6fec1cc409 | |||
2984da773d | |||
1b83708a6d | |||
0de2489440 | |||
fd5416c94e | |||
48137ec24d | |||
febef4bed4 | |||
b599670572 | |||
57e9de6b05 | |||
9679706a08 | |||
777c9839a1 | |||
a6c9434590 | |||
fd77b65226 | |||
a23063fd4f | |||
a7cf696357 | |||
94d448d438 | |||
c62f3f88f1 | |||
39a32a6e0a | |||
342a346fce | |||
e0dd9833a3 | |||
591d3fcafd | |||
22f294493e | |||
5d3496fa41 | |||
4b500e4bf6 | |||
da85e5dd9b | |||
2b55d156ae | |||
f24491cd5a | |||
268bee3c5f | |||
5c3ea28e48 | |||
fdbcb261df | |||
2c3481d027 | |||
1c2ad0ceec | |||
7899d3e262 | |||
6b88cb7926 | |||
421125fee6 | |||
8563011939 | |||
e07672ffe6 | |||
23f6f9b26b | |||
e9c464b319 | |||
d3dc9101dd | |||
e018cdbc91 | |||
e2b8fd2880 | |||
680206b40b | |||
1c8af793c2 | |||
46351b2fe7 | |||
30cfa1b45e | |||
0756d63769 | |||
87ca54a253 | |||
9c2f49e4a0 | |||
49002ac52d | |||
b70e62ff3b | |||
046f803538 | |||
639b7646c9 | |||
89bb54a3ec | |||
979d9509c1 | |||
e9d48bcb7d | |||
318bd8297c | |||
0513b3aa0c | |||
458dbd723c | |||
8f0f4bfa65 | |||
da71d4947b | |||
6a83147ac0 | |||
f6cfc55e21 | |||
34a413cf05 | |||
854ade5fa9 | |||
be09230410 | |||
20b40d3e1c | |||
9f0e784a4a | |||
168fcc874e | |||
d446c192cf | |||
eb5a120286 | |||
2e1a011dcf | |||
8ef874eb22 | |||
c6dc84f27f | |||
8bb25e9b90 | |||
c6bdfe3f38 | |||
d1063b345d | |||
dea879199a | |||
9a034cb556 | |||
5cd22d284b | |||
f8fc1865a2 | |||
85444f235b | |||
15061f75a9 | |||
d138e869fc | |||
23170e170a | |||
156dfd88c2 | |||
730a9b7e63 | |||
3041b6a278 | |||
2da5be548a | |||
6f1b38cdb7 | |||
a8e4ef7234 | |||
c7405e054f | |||
9506dcb31e | |||
04aac10f1d | |||
bbb6379907 | |||
26d7e216a6 | |||
d629f50661 | |||
2245422d0f | |||
87889f5efe | |||
fb15a131ac | |||
8428c20bd4 | |||
ff7a6b8c8f | |||
d92a3e9239 | |||
d23ec14e9d | |||
ad23c89266 | |||
1c8958ad9d | |||
c99b7018c6 | |||
f2089f48b8 | |||
75e51c856e | |||
e60af33f75 | |||
993d14d409 | |||
bf0e636d57 | |||
374ac3b07f | |||
183b0c954e | |||
42559fd601 | |||
069ad4ca99 | |||
8db4b5a53e | |||
32883910bb | |||
9b3f78559e | |||
7bd2782fc8 | |||
75fbb5fb48 | |||
af2f9290c6 | |||
31fb8ba79b | |||
ee9626e4d2 | |||
9360f4295a | |||
abfa3b3ca1 | |||
a1b93624d6 | |||
69ff84eecc | |||
78889e18c6 | |||
fa178d5ee1 | |||
eea3272c56 | |||
27e76fc035 | |||
188165bc4d | |||
e6ddad5960 | |||
4228ca01dc | |||
64190ba55a | |||
c489c7fd5a | |||
acc063822e | |||
b612122180 | |||
d5fa00a4a4 | |||
e607ca4e8e | |||
d64c68f754 | |||
e5bf7d754f | |||
0e739755b7 | |||
f8eab1cbb6 | |||
0f2c81f894 | |||
e481732fae | |||
ee597c805e | |||
e561c55f73 | |||
2870bc6434 | |||
7e60631840 | |||
f2a1528ea9 | |||
21af7e9983 | |||
4ae37603f4 | |||
30b4a1f614 | |||
2797b58646 | |||
837612bb8d | |||
813fecbf15 | |||
a776fc9e06 | |||
08eb14e400 | |||
60c072a2b3 | |||
feedb95295 | |||
c93661f44e | |||
daa063c338 | |||
5abf1f8a84 | |||
133aa051eb | |||
d334b4150b | |||
36e28994ee | |||
01908c52f8 | |||
f9463d629a | |||
50315f5fae | |||
8817a3f226 | |||
fcde9c9b6b | |||
fb5a5a71a5 | |||
8134c6af80 | |||
7271a5e52b | |||
7baf15d9f0 | |||
d070b5be9e | |||
63d74e3524 | |||
a07019801c | |||
97ab22461c | |||
138db460a9 | |||
a9c0431ded | |||
7e4a05e1db | |||
0a4541a401 | |||
79773ba634 | |||
b249e1cbf8 | |||
25cf7c8ae8 | |||
3c97ced486 | |||
44482ae438 | |||
f597b3ab80 | |||
b8223b42bd | |||
ced1fd0038 | |||
2654a6ff23 | |||
5f763e90fc | |||
cf1c66a085 | |||
1395b62e60 | |||
85da5024ea | |||
a989f5f86e | |||
1c4c035acc | |||
d26ff2df77 | |||
5c37026ec7 | |||
8aa419b5c2 | |||
c191b418f2 | |||
0eb2714c9e | |||
0b33ac0e7d | |||
f55e366b17 | |||
b89b1708c3 | |||
f9c5a830e1 | |||
348bd98de8 | |||
4d984d32c3 | |||
8d879344f2 | |||
40547691a0 | |||
8f705b0737 | |||
67c9e2148d | |||
42fda5925d | |||
2c564f47d3 | |||
b4bc347006 | |||
f81fd1a1b4 | |||
a1b334a302 | |||
ff420fbe57 | |||
07eb23b312 | |||
6017cfe3d5 | |||
8eb0a4847f | |||
47f269782e | |||
d9a40af3f0 | |||
2281967176 | |||
6b38b55c58 | |||
12ffbb4d80 | |||
045239b620 | |||
dda81e9011 | |||
98a15bbf8e | |||
7a8b562173 | |||
0cbb3453bd | |||
062a04233f | |||
75c841e3c5 | |||
441b8b0154 |
5
.gitattributes
vendored
5
.gitattributes
vendored
@@ -1 +1,6 @@
|
||||
.gitignore export-ignore
|
||||
.gitattributes export-ignore
|
||||
.gitmodules export-ignore
|
||||
.travis.yml export-ignore
|
||||
|
||||
tests/data/* linguist-documentation
|
||||
|
10
.travis.yml
10
.travis.yml
@@ -11,11 +11,15 @@ matrix:
|
||||
- boost-latest
|
||||
packages:
|
||||
- g++-5
|
||||
- libboost1.55-all-dev
|
||||
- libgtest-dev
|
||||
- libboost-program-options1.55-dev
|
||||
- libboost-iostreams1.55-dev
|
||||
- libboost-system1.55-dev
|
||||
- libboost-filesystem1.55-dev
|
||||
env: COMPILER=g++-5
|
||||
script:
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake .. -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON -DCMAKE_CXX_COMPILER=$COMPILER
|
||||
- make && make run-tests
|
||||
- make -j3 && make -j3 run-tests
|
||||
|
25
CHANGELOG.md
Normal file
25
CHANGELOG.md
Normal 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
|
@@ -3,11 +3,11 @@ project(plasp CXX)
|
||||
|
||||
find_package(Boost 1.55.0 COMPONENTS program_options iostreams system filesystem REQUIRED)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Wpedantic")
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wpedantic")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g")
|
||||
add_definitions(-std=c++14)
|
||||
|
||||
option(BUILD_TESTS "Build unit tests" OFF)
|
||||
option(BUILD_TESTS "Build unit tests" ON)
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
# The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Patrick Lühne
|
||||
Copyright © 2016 Patrick Lühne
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
68
README.md
68
README.md
@@ -1,39 +1,65 @@
|
||||
# plasp—Translate PDDL to ASP
|
||||
|
||||
[](https://travis-ci.org/potassco/plasp)
|
||||
[](https://github.com/potassco/plasp/releases)
|
||||
[)](https://travis-ci.org/potassco/plasp?branch=master)
|
||||
[)](https://travis-ci.org/potassco/plasp?branch=develop)
|
||||
|
||||
`plasp` 3 is in early development and not intended for productive use yet.
|
||||
|
||||
As of now, `plasp` 3 experimentally supports the full [SAS Format](http://www.fast-downward.org/TranslatorOutputFormat) (as of version 3) used by [Fast Downward](http://www.fast-downward.org/).
|
||||
`plasp` 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.
|
||||
|
||||
## Usage
|
||||
|
||||
To translate an SAS file into ASP facts, call:
|
||||
### Translating PDDL to ASP Facts
|
||||
|
||||
PDDL instances are translated to ASP facts as follows:
|
||||
|
||||
```bash
|
||||
$ plasp file.sas
|
||||
$ plasp domain.pddl problem.pddl
|
||||
```
|
||||
|
||||
For instance, a PDDL instance can be solved as follows.
|
||||
First, use [Fast Downward](http://www.fast-downward.org/) to translate the files from PDDL to SAS:
|
||||
Alternatively, PDDL instances may first be translated to SAS, the output format of [Fast Downward](http://www.fast-downward.org/).
|
||||
|
||||
```bash
|
||||
$ ./fast-downward.py --translate --build=release64 domain.pddl instance.pddl
|
||||
```
|
||||
|
||||
This creates the file `output.sas`.
|
||||
The translated SAS instance can now be solved incrementally with `clingo` and the meta encoding `meta-sequential-incremental.lp`:
|
||||
This creates a file called `output.sas`, which may now be translated by `plasp`.
|
||||
|
||||
```bash
|
||||
$ plasp output.sas > instance.lp
|
||||
$ clingo encodings/meta-sequential-incremental.lp instance.lp
|
||||
$ plasp output.sas
|
||||
```
|
||||
|
||||
### Solving the Translated Instance
|
||||
|
||||
The translated instance can finally be solved incrementally with `clingo` and a meta encoding, for instance, `pddl-meta-sequential-incremental.lp`:
|
||||
|
||||
```bash
|
||||
$ plasp domain.pddl problem.pddl > instance.lp
|
||||
$ clingo encodings/pddl-meta-sequential-incremental.lp instance.lp
|
||||
```
|
||||
|
||||
### Command-Line Interface
|
||||
|
||||
```bash
|
||||
$ plasp [files] [options]
|
||||
```
|
||||
|
||||
`[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
|
||||
|
||||
`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
|
||||
$ 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`.
|
||||
|
||||
### 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
|
||||
|
||||
* [Patrick Lühne](https://www.luehne.de) (`plasp` 3)
|
||||
|
||||
### Earlier Versions
|
||||
|
||||
* René Knaebel (`plasp` 2)
|
||||
* Murat Knecht (`plasp`)
|
||||
* René Knaebel
|
||||
* Murat Knecht
|
||||
|
@@ -1,9 +1,16 @@
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <plasp/LanguageDetection.h>
|
||||
#include <plasp/pddl/Description.h>
|
||||
#include <plasp/pddl/TranslatorASP.h>
|
||||
#include <plasp/sas/Description.h>
|
||||
#include <plasp/sas/TranslatorASP.h>
|
||||
#include <plasp/utils/LogStream.h>
|
||||
#include <plasp/utils/TranslatorException.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
@@ -13,7 +20,10 @@ int main(int argc, char **argv)
|
||||
description.add_options()
|
||||
("help,h", "Display this help message.")
|
||||
("version,v", "Display version information.")
|
||||
("input,i", po::value<std::string>(), "Specify the SAS input file.");
|
||||
("input,i", po::value<std::vector<std::string>>(), "Specify the PDDL or SAS input file.")
|
||||
("language,l", po::value<std::string>(), "Specify the input language (sas or pddl). Omit for automatic detection.")
|
||||
("warning-level", po::value<std::string>()->default_value("normal"), "Specify whether to output warnings normally (normal), to treat them as critical errors (error), or to ignore them (ignore).")
|
||||
("color", po::value<std::string>()->default_value("auto"), "Specify whether to colorize the output (always, never, or auto).");
|
||||
|
||||
po::positional_options_description positionalOptionsDescription;
|
||||
positionalOptionsDescription.add("input", -1);
|
||||
@@ -23,12 +33,14 @@ int main(int argc, char **argv)
|
||||
const auto printHelp =
|
||||
[&]()
|
||||
{
|
||||
std::cout << "Usage: plasp file [options]" << std::endl;
|
||||
std::cout << "Usage: plasp [files] [options]" << std::endl;
|
||||
std::cout << "Translate PDDL instances to ASP facts." << std::endl << std::endl;
|
||||
|
||||
std::cout << description;
|
||||
};
|
||||
|
||||
plasp::utils::Logger logger;
|
||||
|
||||
try
|
||||
{
|
||||
po::store(po::command_line_parser(argc, argv)
|
||||
@@ -40,7 +52,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
catch (const po::error &e)
|
||||
{
|
||||
std::cerr << "Error: " << e.what() << std::endl << std::endl;
|
||||
logger.logError(e.what());
|
||||
std::cout << std::endl;
|
||||
printHelp();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -53,27 +66,110 @@ int main(int argc, char **argv)
|
||||
|
||||
if (variablesMap.count("version"))
|
||||
{
|
||||
std::cout << "plasp version 3.0.0" << std::endl;
|
||||
std::cout << "plasp version 3.0.1" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (!variablesMap.count("input"))
|
||||
const auto warningLevel = variablesMap["warning-level"].as<std::string>();
|
||||
|
||||
if (warningLevel == "error")
|
||||
logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Error);
|
||||
else if (warningLevel == "ignore")
|
||||
logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Ignore);
|
||||
else if (warningLevel == "normal")
|
||||
logger.setWarningLevel(plasp::utils::Logger::WarningLevel::Normal);
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: No input file specified" << std::endl << std::endl;
|
||||
logger.logError("unknown warning level “" + warningLevel + "”");
|
||||
std::cout << std::endl;
|
||||
printHelp();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const auto colorPolicy = variablesMap["color"].as<std::string>();
|
||||
|
||||
if (colorPolicy == "auto")
|
||||
logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Auto);
|
||||
else if (colorPolicy == "never")
|
||||
logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Never);
|
||||
else if (colorPolicy == "always")
|
||||
logger.setColorPolicy(plasp::utils::LogStream::ColorPolicy::Always);
|
||||
else
|
||||
{
|
||||
logger.logError("unknown color policy “" + colorPolicy + "”");
|
||||
std::cout << std::endl;
|
||||
printHelp();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
const auto sasDescription = plasp::sas::Description::fromFile(variablesMap["input"].as<std::string>());
|
||||
const auto sasTranslator = plasp::sas::TranslatorASP(sasDescription);
|
||||
sasTranslator.translate(std::cout);
|
||||
plasp::utils::Parser parser;
|
||||
|
||||
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)
|
||||
{
|
||||
std::cerr << "Error: " << e.what() << std::endl << std::endl;
|
||||
printHelp();
|
||||
logger.logError(e.what());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
31
encodings/pddl-meta-sequential-incremental.lp
Normal file
31
encodings/pddl-meta-sequential-incremental.lp
Normal 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
36
include/plasp/Language.h
Normal 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
|
50
include/plasp/LanguageDetection.h
Normal file
50
include/plasp/LanguageDetection.h
Normal 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
|
48
include/plasp/pddl/Action.h
Normal file
48
include/plasp/pddl/Action.h
Normal 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 ¶meters() 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
|
57
include/plasp/pddl/ConsistencyException.h
Normal file
57
include/plasp/pddl/ConsistencyException.h
Normal 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
|
68
include/plasp/pddl/Context.h
Normal file
68
include/plasp/pddl/Context.h
Normal 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
|
59
include/plasp/pddl/Description.h
Normal file
59
include/plasp/pddl/Description.h
Normal 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
|
92
include/plasp/pddl/Domain.h
Normal file
92
include/plasp/pddl/Domain.h
Normal 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
|
130
include/plasp/pddl/Expression.h
Normal file
130
include/plasp/pddl/Expression.h
Normal 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
|
38
include/plasp/pddl/ExpressionContext.h
Normal file
38
include/plasp/pddl/ExpressionContext.h
Normal 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 ¶meters);
|
||||
ExpressionContext(Domain &domain, Problem *problem, expressions::Variables ¶meters);
|
||||
|
||||
bool hasRequirement(Requirement::Type requirementType) const;
|
||||
void checkRequirement(Requirement::Type requirementType) const;
|
||||
|
||||
Domain &domain;
|
||||
Problem *problem;
|
||||
|
||||
expressions::Variables ¶meters;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
45
include/plasp/pddl/IO.h
Normal file
45
include/plasp/pddl/IO.h
Normal 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
|
32
include/plasp/pddl/Identifier.h
Normal file
32
include/plasp/pddl/Identifier.h
Normal 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
|
35
include/plasp/pddl/InitialState.h
Normal file
35
include/plasp/pddl/InitialState.h
Normal 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
|
84
include/plasp/pddl/Problem.h
Normal file
84
include/plasp/pddl/Problem.h
Normal 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
|
72
include/plasp/pddl/Requirement.h
Normal file
72
include/plasp/pddl/Requirement.h
Normal 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
|
51
include/plasp/pddl/TranslatorASP.h
Normal file
51
include/plasp/pddl/TranslatorASP.h
Normal 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
|
33
include/plasp/pddl/expressions/And.h
Normal file
33
include/plasp/pddl/expressions/And.h
Normal 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
|
106
include/plasp/pddl/expressions/At.h
Normal file
106
include/plasp/pddl/expressions/At.h
Normal 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
|
112
include/plasp/pddl/expressions/Binary.h
Normal file
112
include/plasp/pddl/expressions/Binary.h
Normal 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
|
65
include/plasp/pddl/expressions/Constant.h
Normal file
65
include/plasp/pddl/expressions/Constant.h
Normal 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
|
33
include/plasp/pddl/expressions/Either.h
Normal file
33
include/plasp/pddl/expressions/Either.h
Normal 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
|
33
include/plasp/pddl/expressions/Imply.h
Normal file
33
include/plasp/pddl/expressions/Imply.h
Normal 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
|
118
include/plasp/pddl/expressions/NAry.h
Normal file
118
include/plasp/pddl/expressions/NAry.h
Normal 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
|
78
include/plasp/pddl/expressions/Not.h
Normal file
78
include/plasp/pddl/expressions/Not.h
Normal 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
|
33
include/plasp/pddl/expressions/Or.h
Normal file
33
include/plasp/pddl/expressions/Or.h
Normal 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
|
50
include/plasp/pddl/expressions/Predicate.h
Normal file
50
include/plasp/pddl/expressions/Predicate.h
Normal 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
|
49
include/plasp/pddl/expressions/PredicateDeclaration.h
Normal file
49
include/plasp/pddl/expressions/PredicateDeclaration.h
Normal 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
|
56
include/plasp/pddl/expressions/PrimitiveType.h
Normal file
56
include/plasp/pddl/expressions/PrimitiveType.h
Normal 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
|
28
include/plasp/pddl/expressions/Type.h
Normal file
28
include/plasp/pddl/expressions/Type.h
Normal 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
|
40
include/plasp/pddl/expressions/Unsupported.h
Normal file
40
include/plasp/pddl/expressions/Unsupported.h
Normal 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
|
61
include/plasp/pddl/expressions/Variable.h
Normal file
61
include/plasp/pddl/expressions/Variable.h
Normal 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 ¶meters);
|
||||
|
||||
private:
|
||||
Variable();
|
||||
|
||||
bool m_isDirty;
|
||||
|
||||
std::string m_name;
|
||||
|
||||
const Expression *m_type;
|
||||
|
||||
// Stores "either" expression if necessary
|
||||
ExpressionPointer m_eitherExpression;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <plasp/sas/Value.h>
|
||||
#include <plasp/sas/Variable.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -26,8 +27,8 @@ using AssignedVariables = std::vector<AssignedVariable>;
|
||||
class AssignedVariable
|
||||
{
|
||||
public:
|
||||
static AssignedVariable fromSAS(std::istream &istream, const Variables &variables);
|
||||
static AssignedVariable fromSAS(std::istream &istream, const Variable &variable);
|
||||
static AssignedVariable fromSAS(utils::Parser &parser, const Variables &variables);
|
||||
static AssignedVariable fromSAS(utils::Parser &parser, const Variable &variable);
|
||||
|
||||
public:
|
||||
explicit AssignedVariable(const Variable &variable, const Value &value);
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <plasp/sas/AssignedVariable.h>
|
||||
#include <plasp/sas/Variable.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -28,7 +29,7 @@ class AxiomRule
|
||||
using Condition = AssignedVariable;
|
||||
using Conditions = AssignedVariables;
|
||||
|
||||
static AxiomRule fromSAS(std::istream &istream, const Variables &variables);
|
||||
static AxiomRule fromSAS(utils::Parser &parser, const Variables &variables);
|
||||
|
||||
public:
|
||||
const Conditions &conditions() const;
|
||||
|
@@ -16,7 +16,7 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::ostream &operator >>(std::ostream &ostream, const Description &description);
|
||||
utils::LogStream &operator<<(utils::LogStream &ostream, const Description &description);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include <plasp/sas/MutexGroup.h>
|
||||
#include <plasp/sas/Operator.h>
|
||||
#include <plasp/sas/Variable.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -28,6 +29,7 @@ namespace sas
|
||||
class Description
|
||||
{
|
||||
public:
|
||||
static Description fromParser(utils::Parser &&parser);
|
||||
static Description fromStream(std::istream &istream);
|
||||
static Description fromFile(const boost::filesystem::path &path);
|
||||
|
||||
@@ -46,14 +48,16 @@ class Description
|
||||
private:
|
||||
Description();
|
||||
|
||||
void parseVersionSection(std::istream &istream) const;
|
||||
void parseMetricSection(std::istream &istream);
|
||||
void parseVariablesSection(std::istream &istream);
|
||||
void parseMutexSection(std::istream &istream);
|
||||
void parseInitialStateSection(std::istream &istream);
|
||||
void parseGoalSection(std::istream &istream);
|
||||
void parseOperatorSection(std::istream &istream);
|
||||
void parseAxiomSection(std::istream &istream);
|
||||
void parseContent(utils::Parser &parser);
|
||||
|
||||
void parseVersionSection(utils::Parser &parser) const;
|
||||
void parseMetricSection(utils::Parser &parser);
|
||||
void parseVariablesSection(utils::Parser &parser);
|
||||
void parseMutexSection(utils::Parser &parser);
|
||||
void parseInitialStateSection(utils::Parser &parser);
|
||||
void parseGoalSection(utils::Parser &parser);
|
||||
void parseOperatorSection(utils::Parser &parser);
|
||||
void parseAxiomSection(utils::Parser &parser);
|
||||
|
||||
bool m_usesActionCosts;
|
||||
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <plasp/sas/AssignedVariable.h>
|
||||
#include <plasp/sas/Variable.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -28,7 +29,7 @@ class Effect
|
||||
using Condition = AssignedVariable;
|
||||
using Conditions = AssignedVariables;
|
||||
|
||||
static Effect fromSAS(std::istream &istream, const Variables &variables, Conditions &preconditions);
|
||||
static Effect fromSAS(utils::Parser &parser, const Variables &variables, Conditions &preconditions);
|
||||
|
||||
public:
|
||||
const Conditions &conditions() const;
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#define __PLASP__SAS__GOAL_H
|
||||
|
||||
#include <plasp/sas/AssignedVariable.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -20,7 +21,7 @@ class Goal
|
||||
using Fact = AssignedVariable;
|
||||
using Facts = AssignedVariables;
|
||||
|
||||
static Goal fromSAS(std::istream &istream, const Variables &variables);
|
||||
static Goal fromSAS(utils::Parser &parser, const Variables &variables);
|
||||
|
||||
public:
|
||||
const Facts &facts() const;
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#define __PLASP__SAS__INITIAL_STATE_H
|
||||
|
||||
#include <plasp/sas/AssignedVariable.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -20,7 +21,7 @@ class InitialState
|
||||
using Fact = AssignedVariable;
|
||||
using Facts = AssignedVariables;
|
||||
|
||||
static InitialState fromSAS(std::istream &istream, const Variables &variables);
|
||||
static InitialState fromSAS(utils::Parser &parser, const Variables &variables);
|
||||
|
||||
public:
|
||||
const Facts &facts() const;
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <plasp/sas/AssignedVariable.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -27,7 +28,7 @@ class MutexGroup
|
||||
using Fact = AssignedVariable;
|
||||
using Facts = AssignedVariables;
|
||||
|
||||
static MutexGroup fromSAS(std::istream &istream, const Variables &variables);
|
||||
static MutexGroup fromSAS(utils::Parser &parser, const Variables &variables);
|
||||
|
||||
public:
|
||||
const Facts &facts() const;
|
||||
|
@@ -8,6 +8,8 @@
|
||||
#include <plasp/sas/Effect.h>
|
||||
#include <plasp/sas/Predicate.h>
|
||||
#include <plasp/sas/Variable.h>
|
||||
#include <plasp/utils/LogStream.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -31,10 +33,10 @@ class Operator
|
||||
using Condition = AssignedVariable;
|
||||
using Conditions = AssignedVariables;
|
||||
|
||||
static Operator fromSAS(std::istream &istream, const Variables &variables);
|
||||
static Operator fromSAS(utils::Parser &parser, const Variables &variables);
|
||||
|
||||
public:
|
||||
void printPredicateAsASP(std::ostream &ostream) const;
|
||||
void printPredicateAsASP(utils::LogStream &ostream) const;
|
||||
|
||||
const Predicate &predicate() const;
|
||||
const Conditions &preconditions() const;
|
||||
|
@@ -5,6 +5,9 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <plasp/utils/LogStream.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace sas
|
||||
@@ -19,13 +22,13 @@ namespace sas
|
||||
class Predicate
|
||||
{
|
||||
public:
|
||||
static Predicate fromSAS(std::istream &istream);
|
||||
static Predicate fromSAS(utils::Parser &parser);
|
||||
|
||||
using Arguments = std::vector<std::string>;
|
||||
|
||||
public:
|
||||
void printAsSAS(std::ostream &ostream) const;
|
||||
void printAsASP(std::ostream &ostream) const;
|
||||
void printAsSAS(utils::LogStream &outputStream) const;
|
||||
void printAsASP(utils::LogStream &outputStream) const;
|
||||
|
||||
const std::string &name() const;
|
||||
const Arguments &arguments() const;
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#define __PLASP__SAS__TRANSLATOR_ASP_H
|
||||
|
||||
#include <plasp/sas/Description.h>
|
||||
#include <plasp/utils/LogStream.h>
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
@@ -19,12 +20,21 @@ namespace sas
|
||||
class TranslatorASP
|
||||
{
|
||||
public:
|
||||
explicit TranslatorASP(const Description &description);
|
||||
explicit TranslatorASP(const Description &description, utils::LogStream &outputStream);
|
||||
|
||||
void translate(std::ostream &ostream) const;
|
||||
void translate() const;
|
||||
|
||||
private:
|
||||
void translateRequirements() const;
|
||||
void translateInitialState() const;
|
||||
void translateGoal() const;
|
||||
void translateVariables() const;
|
||||
void translateActions() const;
|
||||
void translateMutexes() const;
|
||||
void translateAxiomRules() const;
|
||||
|
||||
const Description &m_description;
|
||||
utils::LogStream &m_outputStream;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -5,6 +5,9 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <plasp/utils/LogStream.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace sas
|
||||
@@ -36,15 +39,15 @@ struct Value
|
||||
static const Value Any;
|
||||
static const Value None;
|
||||
|
||||
static Value fromSAS(std::istream &istream);
|
||||
static const Value &referenceFromSAS(std::istream &istream, const Variable &variable);
|
||||
static Value fromSAS(utils::Parser &parser);
|
||||
static const Value &referenceFromSAS(utils::Parser &parser, const Variable &variable);
|
||||
|
||||
public:
|
||||
Value negated() const;
|
||||
|
||||
void printAsSAS(std::ostream &ostream) const;
|
||||
void printAsASP(std::ostream &ostream) const;
|
||||
void printAsASPPredicate(std::ostream &ostream) const;
|
||||
void printAsSAS(utils::LogStream &outputStream) const;
|
||||
void printAsASP(utils::LogStream &outputStream) const;
|
||||
void printAsASPPredicate(utils::LogStream &outputStream) const;
|
||||
|
||||
Sign sign() const;
|
||||
const std::string &name() const;
|
||||
|
@@ -6,6 +6,8 @@
|
||||
#include <vector>
|
||||
|
||||
#include <plasp/sas/Value.h>
|
||||
#include <plasp/utils/LogStream.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -26,11 +28,11 @@ using Variables = std::vector<Variable>;
|
||||
class Variable
|
||||
{
|
||||
public:
|
||||
static Variable fromSAS(std::istream &istream);
|
||||
static const Variable &referenceFromSAS(std::istream &istream, const Variables &variables);
|
||||
static Variable fromSAS(utils::Parser &parser);
|
||||
static const Variable &referenceFromSAS(utils::Parser &parser, const Variables &variables);
|
||||
|
||||
public:
|
||||
void printNameAsASPPredicate(std::ostream &ostream) const;
|
||||
void printNameAsASPPredicate(utils::LogStream &outputStream) const;
|
||||
|
||||
const std::string &name() const;
|
||||
int axiomLayer() const;
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <plasp/sas/Value.h>
|
||||
#include <plasp/sas/Variable.h>
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -25,7 +26,7 @@ using VariableTransitions = std::vector<VariableTransition>;
|
||||
class VariableTransition
|
||||
{
|
||||
public:
|
||||
static VariableTransition fromSAS(std::istream &istream, const Variables &variables);
|
||||
static VariableTransition fromSAS(utils::Parser &parser, const Variables &variables);
|
||||
|
||||
public:
|
||||
const Variable &variable() const;
|
||||
|
203
include/plasp/utils/Formatting.h
Normal file
203
include/plasp/utils/Formatting.h
Normal 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
|
@@ -1,17 +1,8 @@
|
||||
#ifndef __PLASP__UTILS__PARSING_H
|
||||
#define __PLASP__UTILS__PARSING_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <iosfwd>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#ifndef __PLASP__UTILS__IO_H
|
||||
#define __PLASP__UTILS__IO_H
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
#include <plasp/utils/ParserException.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace utils
|
||||
@@ -19,46 +10,10 @@ namespace utils
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parsing
|
||||
// IO
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T>
|
||||
T parse(std::istream &istream)
|
||||
{
|
||||
T value;
|
||||
|
||||
try
|
||||
{
|
||||
istream >> value;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
throw ParserException(std::string("Could not parse value of type ") + typeid(T).name() + " (" + e.what() + ")");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T>
|
||||
void parseExpected(std::istream &istream, const T &expectedValue)
|
||||
{
|
||||
const auto value = parse<T>(istream);
|
||||
|
||||
if (value == expectedValue)
|
||||
return;
|
||||
|
||||
std::stringstream errorStream;
|
||||
|
||||
errorStream << "Invalid format, expected " << expectedValue << ", got " + value;
|
||||
|
||||
throw utils::ParserException(errorStream.str());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::string escapeASP(const std::string &string)
|
||||
{
|
||||
auto escaped = string;
|
||||
@@ -85,6 +40,17 @@ inline std::string unescapeASP(const std::string &string)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::string escapeASPVariable(const std::string &string)
|
||||
{
|
||||
auto escaped = escapeASP(string);
|
||||
|
||||
escaped.front() = std::toupper(escaped.front());
|
||||
|
||||
return escaped;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
|
289
include/plasp/utils/LogStream.h
Normal file
289
include/plasp/utils/LogStream.h
Normal 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
|
62
include/plasp/utils/Logger.h
Normal file
62
include/plasp/utils/Logger.h
Normal 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
|
167
include/plasp/utils/Parser.h
Normal file
167
include/plasp/utils/Parser.h
Normal 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
|
@@ -4,6 +4,8 @@
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
#include <plasp/utils/Parser.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace utils
|
||||
@@ -18,17 +20,21 @@ namespace utils
|
||||
class ParserException: public std::exception
|
||||
{
|
||||
public:
|
||||
explicit ParserException()
|
||||
explicit ParserException(const utils::Parser &parser)
|
||||
: ParserException(parser, "unspecified parser error")
|
||||
{
|
||||
}
|
||||
|
||||
explicit ParserException(const char *message)
|
||||
: m_message(message)
|
||||
explicit ParserException(const utils::Parser &parser, const char *message)
|
||||
: ParserException(parser, static_cast<std::string>(message))
|
||||
{
|
||||
}
|
||||
|
||||
explicit ParserException(const std::string &message)
|
||||
: m_message(message)
|
||||
explicit ParserException(const utils::Parser &parser, const std::string &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()
|
||||
{
|
||||
if (m_message.empty())
|
||||
return "Unspecified error while parsing SAS description file";
|
||||
return m_plainMessage.c_str();
|
||||
}
|
||||
|
||||
return m_message.c_str();
|
||||
const Parser::Coordinate &coordinate() const
|
||||
{
|
||||
return m_coordinate;
|
||||
}
|
||||
|
||||
const std::string &message() const
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
private:
|
||||
Parser::Coordinate m_coordinate;
|
||||
std::string m_message;
|
||||
std::string m_plainMessage;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -1,12 +1,12 @@
|
||||
#ifndef __PLASP__SAS__TRANSLATOR_EXCEPTION_H
|
||||
#define __PLASP__SAS__TRANSLATOR_EXCEPTION_H
|
||||
#ifndef __PLASP__UTILS__TRANSLATOR_EXCEPTION_H
|
||||
#define __PLASP__UTILS__TRANSLATOR_EXCEPTION_H
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace sas
|
||||
namespace utils
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -39,7 +39,7 @@ class TranslatorException: public std::exception
|
||||
const char *what() const throw()
|
||||
{
|
||||
if (m_message.empty())
|
||||
return "Unspecified error while translating SAS description";
|
||||
return "Unspecified error while translating description";
|
||||
|
||||
return m_message.c_str();
|
||||
}
|
@@ -3,6 +3,12 @@ set(target plasp)
|
||||
file(GLOB core_sources "plasp/*.cpp")
|
||||
file(GLOB core_headers "../include/plasp/*.h")
|
||||
|
||||
file(GLOB pddl_sources "plasp/pddl/*.cpp")
|
||||
file(GLOB pddl_headers "../include/plasp/pddl/*.h")
|
||||
|
||||
file(GLOB pddl_expressions_sources "plasp/pddl/expressions/*.cpp")
|
||||
file(GLOB pddl_expressions_headers "../include/plasp/pddl/expressions/*.h")
|
||||
|
||||
file(GLOB sas_sources "plasp/sas/*.cpp")
|
||||
file(GLOB sas_headers "../include/plasp/sas/*.h")
|
||||
|
||||
@@ -21,6 +27,12 @@ set(sources
|
||||
${core_sources}
|
||||
${core_headers}
|
||||
|
||||
${pddl_sources}
|
||||
${pddl_headers}
|
||||
|
||||
${pddl_expressions_sources}
|
||||
${pddl_expressions_headers}
|
||||
|
||||
${sas_sources}
|
||||
${sas_headers}
|
||||
|
||||
|
50
src/plasp/Language.cpp
Normal file
50
src/plasp/Language.cpp
Normal 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
92
src/plasp/pddl/Action.cpp
Normal 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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
209
src/plasp/pddl/Description.cpp
Normal file
209
src/plasp/pddl/Description.cpp
Normal 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
419
src/plasp/pddl/Domain.cpp
Normal 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 §ionName, auto §ionPosition, 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
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
253
src/plasp/pddl/Expression.cpp
Normal file
253
src/plasp/pddl/Expression.cpp
Normal 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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
56
src/plasp/pddl/ExpressionContext.cpp
Normal file
56
src/plasp/pddl/ExpressionContext.cpp
Normal 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 ¶meters)
|
||||
: domain(domain),
|
||||
problem(nullptr),
|
||||
parameters(parameters)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionContext::ExpressionContext(Domain &domain, Problem *problem, expressions::Variables ¶meters)
|
||||
: 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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
90
src/plasp/pddl/InitialState.cpp
Normal file
90
src/plasp/pddl/InitialState.cpp
Normal 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
399
src/plasp/pddl/Problem.cpp
Normal 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 §ionName, auto §ionPosition, 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()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
134
src/plasp/pddl/Requirement.cpp
Normal file
134
src/plasp/pddl/Requirement.cpp
Normal 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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
505
src/plasp/pddl/TranslatorASP.cpp
Normal file
505
src/plasp/pddl/TranslatorASP.cpp
Normal 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 ¬Expression = 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 ¬Expression = 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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
22
src/plasp/pddl/expressions/And.cpp
Normal file
22
src/plasp/pddl/expressions/And.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <plasp/pddl/expressions/And.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace pddl
|
||||
{
|
||||
namespace expressions
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// And
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string And::Identifier = "and";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
48
src/plasp/pddl/expressions/At.cpp
Normal file
48
src/plasp/pddl/expressions/At.cpp
Normal 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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
240
src/plasp/pddl/expressions/Constant.cpp
Normal file
240
src/plasp/pddl/expressions/Constant.cpp
Normal 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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
22
src/plasp/pddl/expressions/Either.cpp
Normal file
22
src/plasp/pddl/expressions/Either.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <plasp/pddl/expressions/Either.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace pddl
|
||||
{
|
||||
namespace expressions
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Either
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string Either::Identifier = "either";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
22
src/plasp/pddl/expressions/Imply.cpp
Normal file
22
src/plasp/pddl/expressions/Imply.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <plasp/pddl/expressions/Imply.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace pddl
|
||||
{
|
||||
namespace expressions
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Imply
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string Imply::Identifier = "imply";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
48
src/plasp/pddl/expressions/Not.cpp
Normal file
48
src/plasp/pddl/expressions/Not.cpp
Normal 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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
22
src/plasp/pddl/expressions/Or.cpp
Normal file
22
src/plasp/pddl/expressions/Or.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <plasp/pddl/expressions/Or.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace pddl
|
||||
{
|
||||
namespace expressions
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Or
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string Or::Identifier = "or";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
176
src/plasp/pddl/expressions/Predicate.cpp
Normal file
176
src/plasp/pddl/expressions/Predicate.cpp
Normal 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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
85
src/plasp/pddl/expressions/PredicateDeclaration.cpp
Normal file
85
src/plasp/pddl/expressions/PredicateDeclaration.cpp
Normal 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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
172
src/plasp/pddl/expressions/PrimitiveType.cpp
Normal file
172
src/plasp/pddl/expressions/PrimitiveType.cpp
Normal 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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
29
src/plasp/pddl/expressions/Type.cpp
Normal file
29
src/plasp/pddl/expressions/Type.cpp
Normal 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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
47
src/plasp/pddl/expressions/Unsupported.cpp
Normal file
47
src/plasp/pddl/expressions/Unsupported.cpp
Normal 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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
201
src/plasp/pddl/expressions/Variable.cpp
Normal file
201
src/plasp/pddl/expressions/Variable.cpp
Normal 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 ¶meters)
|
||||
{
|
||||
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 ¶meter)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,8 +4,6 @@
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <plasp/utils/Parsing.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace sas
|
||||
@@ -33,24 +31,24 @@ AssignedVariable::AssignedVariable(const Variable &variable, const Value &value)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AssignedVariable AssignedVariable::fromSAS(std::istream &istream, const Variables &variables)
|
||||
AssignedVariable AssignedVariable::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
{
|
||||
AssignedVariable assignedVariable;
|
||||
|
||||
assignedVariable.m_variable = &Variable::referenceFromSAS(istream, variables);
|
||||
assignedVariable.m_value = &Value::referenceFromSAS(istream, *assignedVariable.m_variable);
|
||||
assignedVariable.m_variable = &Variable::referenceFromSAS(parser, variables);
|
||||
assignedVariable.m_value = &Value::referenceFromSAS(parser, *assignedVariable.m_variable);
|
||||
|
||||
return assignedVariable;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AssignedVariable AssignedVariable::fromSAS(std::istream &istream, const Variable &variable)
|
||||
AssignedVariable AssignedVariable::fromSAS(utils::Parser &parser, const Variable &variable)
|
||||
{
|
||||
AssignedVariable assignedVariable;
|
||||
|
||||
assignedVariable.m_variable = &variable;
|
||||
assignedVariable.m_value = &Value::referenceFromSAS(istream, *assignedVariable.m_variable);
|
||||
assignedVariable.m_value = &Value::referenceFromSAS(parser, *assignedVariable.m_variable);
|
||||
|
||||
return assignedVariable;
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <plasp/sas/VariableTransition.h>
|
||||
#include <plasp/utils/Parsing.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -24,24 +23,24 @@ AxiomRule::AxiomRule(AxiomRule::Conditions conditions, AxiomRule::Condition post
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AxiomRule AxiomRule::fromSAS(std::istream &istream, const Variables &variables)
|
||||
AxiomRule AxiomRule::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
{
|
||||
utils::parseExpected<std::string>(istream, "begin_rule");
|
||||
parser.expect<std::string>("begin_rule");
|
||||
|
||||
const auto numberOfConditions = utils::parse<size_t>(istream);
|
||||
const auto numberOfConditions = parser.parse<size_t>();
|
||||
|
||||
Conditions conditions;
|
||||
conditions.reserve(numberOfConditions);
|
||||
|
||||
for (size_t j = 0; j < numberOfConditions; j++)
|
||||
conditions.emplace_back(Condition::fromSAS(istream, variables));
|
||||
conditions.emplace_back(Condition::fromSAS(parser, variables));
|
||||
|
||||
const auto variableTransition = VariableTransition::fromSAS(istream, variables);
|
||||
const auto variableTransition = VariableTransition::fromSAS(parser, variables);
|
||||
|
||||
if (&variableTransition.valueBefore() != &Value::Any)
|
||||
conditions.emplace_back(Condition(variableTransition.variable(), variableTransition.valueBefore()));
|
||||
|
||||
utils::parseExpected<std::string>(istream, "end_rule");
|
||||
parser.expect<std::string>("end_rule");
|
||||
|
||||
const Condition postcondition(variableTransition.variable(), variableTransition.valueAfter());
|
||||
const AxiomRule axiomRule(std::move(conditions), std::move(postcondition));
|
||||
|
@@ -13,7 +13,7 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::ostream &operator >>(std::ostream &ostream, const Description &description)
|
||||
utils::LogStream &operator<<(utils::LogStream &ostream, const Description &description)
|
||||
{
|
||||
// Metric section
|
||||
ostream << "uses action costs: " << (description.usesActionCosts() ? "yes" : "no") << std::endl;
|
||||
|
@@ -8,7 +8,6 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <plasp/utils/ParserException.h>
|
||||
#include <plasp/utils/Parsing.h>
|
||||
#include <plasp/sas/VariableTransition.h>
|
||||
|
||||
namespace plasp
|
||||
@@ -29,22 +28,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)
|
||||
{
|
||||
utils::Parser parser;
|
||||
parser.readStream("std::cin", istream);
|
||||
|
||||
Description description;
|
||||
|
||||
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);
|
||||
description.parseContent(parser);
|
||||
|
||||
return description;
|
||||
}
|
||||
@@ -54,11 +56,15 @@ Description Description::fromStream(std::istream &istream)
|
||||
Description Description::fromFile(const boost::filesystem::path &path)
|
||||
{
|
||||
if (!boost::filesystem::is_regular_file(path))
|
||||
throw std::runtime_error("File does not exist: \"" + path.string() + "\"");
|
||||
throw std::runtime_error("File does not exist: “" + path.string() + "”");
|
||||
|
||||
std::ifstream fileStream(path.string(), std::ios::in);
|
||||
utils::Parser parser;
|
||||
parser.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)
|
||||
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);
|
||||
|
||||
for (size_t i = 0; i < numberOfVariables; i++)
|
||||
m_variables.emplace_back(Variable::fromSAS(istream));
|
||||
m_variables.emplace_back(Variable::fromSAS(parser));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseMutexSection(std::istream &istream)
|
||||
void Description::parseMutexSection(utils::Parser &parser)
|
||||
{
|
||||
const auto numberOfMutexGroups = utils::parse<size_t>(istream);
|
||||
const auto numberOfMutexGroups = parser.parse<size_t>();
|
||||
m_mutexGroups.reserve(numberOfMutexGroups);
|
||||
|
||||
for (size_t i = 0; i < numberOfMutexGroups; i++)
|
||||
m_mutexGroups.emplace_back(MutexGroup::fromSAS(istream, m_variables));
|
||||
m_mutexGroups.emplace_back(MutexGroup::fromSAS(parser, m_variables));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseInitialStateSection(std::istream &istream)
|
||||
void Description::parseInitialStateSection(utils::Parser &parser)
|
||||
{
|
||||
m_initialState = std::make_unique<InitialState>(InitialState::fromSAS(istream, m_variables));
|
||||
m_initialState = std::make_unique<InitialState>(InitialState::fromSAS(parser, m_variables));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseGoalSection(std::istream &istream)
|
||||
void Description::parseGoalSection(utils::Parser &parser)
|
||||
{
|
||||
m_goal = std::make_unique<Goal>(Goal::fromSAS(istream, m_variables));
|
||||
m_goal = std::make_unique<Goal>(Goal::fromSAS(parser, m_variables));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseOperatorSection(std::istream &istream)
|
||||
void Description::parseOperatorSection(utils::Parser &parser)
|
||||
{
|
||||
const auto numberOfOperators = utils::parse<size_t>(istream);
|
||||
const auto numberOfOperators = parser.parse<size_t>();
|
||||
m_operators.reserve(numberOfOperators);
|
||||
|
||||
for (size_t i = 0; i < numberOfOperators; i++)
|
||||
m_operators.emplace_back(Operator::fromSAS(istream, m_variables));
|
||||
m_operators.emplace_back(Operator::fromSAS(parser, m_variables));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Description::parseAxiomSection(std::istream &istream)
|
||||
void Description::parseAxiomSection(utils::Parser &parser)
|
||||
{
|
||||
const auto numberOfAxiomRules = utils::parse<size_t>(istream);
|
||||
const auto numberOfAxiomRules = parser.parse<size_t>();
|
||||
m_axiomRules.reserve(numberOfAxiomRules);
|
||||
|
||||
for (size_t i = 0; i < numberOfAxiomRules; i++)
|
||||
m_axiomRules.emplace_back(AxiomRule::fromSAS(istream, m_variables));
|
||||
m_axiomRules.emplace_back(AxiomRule::fromSAS(parser, m_variables));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -3,7 +3,6 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <plasp/sas/VariableTransition.h>
|
||||
#include <plasp/utils/Parsing.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -24,17 +23,17 @@ Effect::Effect(Conditions conditions, Condition postcondition)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Effect Effect::fromSAS(std::istream &istream, const Variables &variables, Conditions &preconditions)
|
||||
Effect Effect::fromSAS(utils::Parser &parser, const Variables &variables, Conditions &preconditions)
|
||||
{
|
||||
Effect::Conditions conditions;
|
||||
|
||||
const auto numberOfEffectConditions = utils::parse<size_t>(istream);
|
||||
const auto numberOfEffectConditions = parser.parse<size_t>();
|
||||
conditions.reserve(numberOfEffectConditions);
|
||||
|
||||
for (size_t k = 0; k < numberOfEffectConditions; k++)
|
||||
conditions.emplace_back(Condition::fromSAS(istream, variables));
|
||||
conditions.emplace_back(Condition::fromSAS(parser, variables));
|
||||
|
||||
const auto variableTransition = VariableTransition::fromSAS(istream, variables);
|
||||
const auto variableTransition = VariableTransition::fromSAS(parser, variables);
|
||||
|
||||
if (&variableTransition.valueBefore() != &Value::Any)
|
||||
preconditions.emplace_back(Condition(variableTransition.variable(), variableTransition.valueBefore()));
|
||||
|
@@ -2,8 +2,6 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <plasp/utils/Parsing.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace sas
|
||||
@@ -15,19 +13,19 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Goal Goal::fromSAS(std::istream &istream, const Variables &variables)
|
||||
Goal Goal::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
{
|
||||
Goal goal;
|
||||
|
||||
utils::parseExpected<std::string>(istream, "begin_goal");
|
||||
parser.expect<std::string>("begin_goal");
|
||||
|
||||
const auto numberOfGoalFacts = utils::parse<size_t>(istream);
|
||||
const auto numberOfGoalFacts = parser.parse<size_t>();
|
||||
goal.m_facts.reserve(numberOfGoalFacts);
|
||||
|
||||
for (size_t i = 0; i < numberOfGoalFacts; i++)
|
||||
goal.m_facts.emplace_back(Fact::fromSAS(istream, variables));
|
||||
goal.m_facts.emplace_back(Fact::fromSAS(parser, variables));
|
||||
|
||||
utils::parseExpected<std::string>(istream, "end_goal");
|
||||
parser.expect<std::string>("end_goal");
|
||||
|
||||
return goal;
|
||||
}
|
||||
|
@@ -1,9 +1,5 @@
|
||||
#include <plasp/sas/InitialState.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <plasp/utils/Parsing.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
namespace sas
|
||||
@@ -15,18 +11,18 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
InitialState InitialState::fromSAS(std::istream &istream, const Variables &variables)
|
||||
InitialState InitialState::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
{
|
||||
InitialState initialState;
|
||||
|
||||
utils::parseExpected<std::string>(istream, "begin_state");
|
||||
parser.expect<std::string>("begin_state");
|
||||
|
||||
initialState.m_facts.reserve(variables.size());
|
||||
|
||||
for (size_t i = 0; i < variables.size(); i++)
|
||||
initialState.m_facts.emplace_back(Fact::fromSAS(istream, variables[i]));
|
||||
initialState.m_facts.emplace_back(Fact::fromSAS(parser, variables[i]));
|
||||
|
||||
utils::parseExpected<std::string>(istream, "end_state");
|
||||
parser.expect<std::string>("end_state");
|
||||
|
||||
return initialState;
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <plasp/utils/Parsing.h>
|
||||
#include <plasp/utils/ParserException.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -15,24 +15,24 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MutexGroup MutexGroup::fromSAS(std::istream &istream, const Variables &variables)
|
||||
MutexGroup MutexGroup::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
{
|
||||
MutexGroup mutexGroup;
|
||||
|
||||
utils::parseExpected<std::string>(istream, "begin_mutex_group");
|
||||
parser.expect<std::string>("begin_mutex_group");
|
||||
|
||||
const auto numberOfFacts = utils::parse<size_t>(istream);
|
||||
const auto numberOfFacts = parser.parse<size_t>();
|
||||
mutexGroup.m_facts.reserve(numberOfFacts);
|
||||
|
||||
for (size_t j = 0; j < numberOfFacts; j++)
|
||||
{
|
||||
mutexGroup.m_facts.emplace_back(Fact::fromSAS(istream, variables));
|
||||
mutexGroup.m_facts.emplace_back(Fact::fromSAS(parser, variables));
|
||||
|
||||
if (mutexGroup.m_facts[j].value() == Value::None)
|
||||
throw utils::ParserException("Mutex groups must not contain <none of those> values");
|
||||
throw utils::ParserException(parser, "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;
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
#include <limits>
|
||||
|
||||
#include <plasp/sas/VariableTransition.h>
|
||||
#include <plasp/utils/Parsing.h>
|
||||
#include <plasp/utils/Formatting.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -17,40 +17,40 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Operator Operator::fromSAS(std::istream &istream, const Variables &variables)
|
||||
Operator Operator::fromSAS(utils::Parser &parser, const Variables &variables)
|
||||
{
|
||||
Operator operator_;
|
||||
|
||||
utils::parseExpected<std::string>(istream, "begin_operator");
|
||||
parser.expect<std::string>("begin_operator");
|
||||
|
||||
operator_.m_predicate = Predicate::fromSAS(istream);
|
||||
operator_.m_predicate = Predicate::fromSAS(parser);
|
||||
|
||||
const auto numberOfPrevailConditions = utils::parse<size_t>(istream);
|
||||
const auto numberOfPrevailConditions = parser.parse<size_t>();
|
||||
operator_.m_preconditions.reserve(numberOfPrevailConditions);
|
||||
|
||||
for (size_t j = 0; j < numberOfPrevailConditions; j++)
|
||||
operator_.m_preconditions.emplace_back(Condition::fromSAS(istream, variables));
|
||||
operator_.m_preconditions.emplace_back(Condition::fromSAS(parser, variables));
|
||||
|
||||
const auto numberOfEffects = utils::parse<size_t>(istream);
|
||||
const auto numberOfEffects = parser.parse<size_t>();
|
||||
operator_.m_effects.reserve(numberOfEffects);
|
||||
|
||||
for (size_t j = 0; j < numberOfEffects; j++)
|
||||
operator_.m_effects.emplace_back(Effect::fromSAS(istream, variables, operator_.m_preconditions));
|
||||
operator_.m_effects.emplace_back(Effect::fromSAS(parser, variables, operator_.m_preconditions));
|
||||
|
||||
operator_.m_costs = utils::parse<size_t>(istream);
|
||||
operator_.m_costs = parser.parse<size_t>();
|
||||
|
||||
utils::parseExpected<std::string>(istream, "end_operator");
|
||||
parser.expect<std::string>("end_operator");
|
||||
|
||||
return operator_;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Operator::printPredicateAsASP(std::ostream &ostream) const
|
||||
void Operator::printPredicateAsASP(utils::LogStream &outputStream) const
|
||||
{
|
||||
ostream << "action(";
|
||||
m_predicate.printAsASP(ostream);
|
||||
ostream << ")";
|
||||
outputStream << utils::Keyword("action") << "(";
|
||||
m_predicate.printAsASP(outputStream);
|
||||
outputStream << ")";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -4,7 +4,8 @@
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
#include <plasp/utils/Parsing.h>
|
||||
#include <plasp/utils/IO.h>
|
||||
#include <plasp/utils/ParserException.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -17,31 +18,35 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Predicate Predicate::fromSAS(std::istream &istream)
|
||||
Predicate Predicate::fromSAS(utils::Parser &parser)
|
||||
{
|
||||
Predicate predicate;
|
||||
|
||||
try
|
||||
{
|
||||
istream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
parser.skipLine();
|
||||
|
||||
// TODO: Inefficient, reimplement in one pass
|
||||
std::string line;
|
||||
std::getline(istream, line);
|
||||
predicate.m_name = parser.parse<std::string>();
|
||||
|
||||
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() == ' ')
|
||||
lineStream.ignore(1);
|
||||
|
||||
for (std::string argument; std::getline(lineStream, argument, ' ');)
|
||||
predicate.m_arguments.push_back(std::move(argument));
|
||||
const auto value = parser.parse<std::string>();
|
||||
predicate.m_arguments.emplace_back(std::move(value));
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
throw utils::ParserException("Could not parse operator predicate");
|
||||
throw utils::ParserException(parser, "could not parse operator 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())
|
||||
{
|
||||
ostream << m_name;
|
||||
outputStream << m_name;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_arguments.size(); i++)
|
||||
{
|
||||
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())
|
||||
{
|
||||
ostream << utils::escapeASP(m_name);
|
||||
outputStream << utils::escapeASP(m_name);
|
||||
return;
|
||||
}
|
||||
|
||||
ostream << utils::escapeASP(m_name) << "(";
|
||||
outputStream << utils::escapeASP(m_name) << "(";
|
||||
|
||||
for (size_t i = 0; i < m_arguments.size(); i++)
|
||||
{
|
||||
if (i > 0)
|
||||
ostream << ", ";
|
||||
outputStream << ", ";
|
||||
|
||||
ostream << utils::escapeASP(m_arguments[i]);
|
||||
outputStream << utils::escapeASP(m_arguments[i]);
|
||||
}
|
||||
|
||||
ostream << ")";
|
||||
outputStream << ")";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#include <plasp/sas/TranslatorASP.h>
|
||||
|
||||
#include <plasp/sas/TranslatorException.h>
|
||||
#include <plasp/utils/Parsing.h>
|
||||
#include <plasp/utils/Formatting.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -14,62 +13,90 @@ namespace sas
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TranslatorASP::TranslatorASP(const Description &description)
|
||||
: m_description(description)
|
||||
TranslatorASP::TranslatorASP(const Description &description, utils::LogStream &ostream)
|
||||
: m_description(description),
|
||||
m_outputStream(ostream)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TranslatorASP::translate(std::ostream &ostream) const
|
||||
void TranslatorASP::translate() const
|
||||
{
|
||||
const auto usesActionCosts = m_description.usesActionCosts();
|
||||
const auto usesAxiomRules = m_description.usesAxiomRules();
|
||||
const auto usesConditionalEffects = m_description.usesConditionalEffects();
|
||||
translateRequirements();
|
||||
translateInitialState();
|
||||
translateGoal();
|
||||
translateVariables();
|
||||
translateActions();
|
||||
translateMutexes();
|
||||
translateAxiomRules();
|
||||
}
|
||||
|
||||
ostream << "% feature requirements" << std::endl;
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (usesActionCosts)
|
||||
ostream << "requiresFeature(actionCosts)." << std::endl;
|
||||
void TranslatorASP::translateRequirements() const
|
||||
{
|
||||
m_outputStream << utils::Heading2("feature requirements") << std::endl;
|
||||
|
||||
if (usesAxiomRules)
|
||||
ostream << "requiresFeature(axiomRules)." << std::endl;
|
||||
if (m_description.usesActionCosts())
|
||||
m_outputStream << utils::Keyword("requiresFeature") << "(actionCosts)." << std::endl;
|
||||
|
||||
if (usesConditionalEffects)
|
||||
ostream << "requiresFeature(conditionalEffects)." << std::endl;
|
||||
if (m_description.usesAxiomRules())
|
||||
m_outputStream << utils::Keyword("requiresFeature") << "(axiomRules)." << std::endl;
|
||||
|
||||
ostream << std::endl;
|
||||
ostream << "% initial state" << std::endl;
|
||||
if (m_description.usesConditionalEffects())
|
||||
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();
|
||||
|
||||
std::for_each(initialStateFacts.cbegin(), initialStateFacts.cend(),
|
||||
[&](const auto &fact)
|
||||
{
|
||||
ostream << "initialState(";
|
||||
fact.variable().printNameAsASPPredicate(ostream);
|
||||
ostream << ", ";
|
||||
fact.value().printAsASPPredicate(ostream);
|
||||
ostream << ")." << std::endl;
|
||||
m_outputStream << utils::Keyword("initialState") << "(";
|
||||
fact.variable().printNameAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ", ";
|
||||
fact.value().printAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ")." << std::endl;
|
||||
});
|
||||
|
||||
ostream << std::endl;
|
||||
ostream << "% goal" << std::endl;
|
||||
m_outputStream << std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TranslatorASP::translateGoal() const
|
||||
{
|
||||
m_outputStream << utils::Heading2("goal") << std::endl;
|
||||
|
||||
const auto &goalFacts = m_description.goal().facts();
|
||||
|
||||
std::for_each(goalFacts.cbegin(), goalFacts.cend(),
|
||||
[&](const auto &fact)
|
||||
{
|
||||
ostream << "goal(";
|
||||
fact.variable().printNameAsASPPredicate(ostream);
|
||||
ostream << ", ";
|
||||
fact.value().printAsASPPredicate(ostream);
|
||||
ostream << ")." << std::endl;
|
||||
m_outputStream << utils::Keyword("goal") << "(";
|
||||
fact.variable().printNameAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ", ";
|
||||
fact.value().printAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ")." << std::endl;
|
||||
});
|
||||
|
||||
ostream << std::endl;
|
||||
ostream << "% variables";
|
||||
m_outputStream << std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TranslatorASP::translateVariables() const
|
||||
{
|
||||
m_outputStream << utils::Heading2("variables");
|
||||
|
||||
const auto &variables = m_description.variables();
|
||||
|
||||
@@ -80,45 +107,51 @@ void TranslatorASP::translate(std::ostream &ostream) const
|
||||
|
||||
BOOST_ASSERT(!values.empty());
|
||||
|
||||
ostream << std::endl;
|
||||
variable.printNameAsASPPredicate(ostream);
|
||||
ostream << "." << std::endl;
|
||||
m_outputStream << std::endl;
|
||||
variable.printNameAsASPPredicate(m_outputStream);
|
||||
m_outputStream << "." << std::endl;
|
||||
|
||||
std::for_each(values.cbegin(), values.cend(),
|
||||
[&](const auto &value)
|
||||
{
|
||||
ostream << "contains(";
|
||||
variable.printNameAsASPPredicate(ostream);
|
||||
ostream << ", ";
|
||||
value.printAsASPPredicate(ostream);
|
||||
ostream << ")." << std::endl;
|
||||
m_outputStream << utils::Keyword("contains") << "(";
|
||||
variable.printNameAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ", ";
|
||||
value.printAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ")." << std::endl;
|
||||
});
|
||||
});
|
||||
|
||||
ostream << std::endl;
|
||||
ostream << "% actions";
|
||||
m_outputStream << std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TranslatorASP::translateActions() const
|
||||
{
|
||||
m_outputStream << utils::Heading2("actions");
|
||||
|
||||
const auto &operators = m_description.operators();
|
||||
|
||||
std::for_each(operators.cbegin(), operators.cend(),
|
||||
[&](const auto &operator_)
|
||||
{
|
||||
ostream << std::endl;
|
||||
operator_.printPredicateAsASP(ostream);
|
||||
ostream << "." << std::endl;
|
||||
m_outputStream << std::endl;
|
||||
operator_.printPredicateAsASP(m_outputStream);
|
||||
m_outputStream << "." << std::endl;
|
||||
|
||||
const auto &preconditions = operator_.preconditions();
|
||||
|
||||
std::for_each(preconditions.cbegin(), preconditions.cend(),
|
||||
[&](const auto &precondition)
|
||||
{
|
||||
ostream << "precondition(";
|
||||
operator_.printPredicateAsASP(ostream);
|
||||
ostream << ", ";
|
||||
precondition.variable().printNameAsASPPredicate(ostream);
|
||||
ostream << ", ";
|
||||
precondition.value().printAsASPPredicate(ostream);
|
||||
ostream << ")." << std::endl;
|
||||
m_outputStream << utils::Keyword("precondition") << "(";
|
||||
operator_.printPredicateAsASP(m_outputStream);
|
||||
m_outputStream << ", ";
|
||||
precondition.variable().printNameAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ", ";
|
||||
precondition.value().printAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ")." << std::endl;
|
||||
});
|
||||
|
||||
const auto &effects = operator_.effects();
|
||||
@@ -133,33 +166,39 @@ void TranslatorASP::translate(std::ostream &ostream) const
|
||||
std::for_each(conditions.cbegin(), conditions.cend(),
|
||||
[&](const auto &condition)
|
||||
{
|
||||
ostream << "effectCondition(";
|
||||
operator_.printPredicateAsASP(ostream);
|
||||
ostream << ", effect(" << currentEffectID << "), ";
|
||||
condition.variable().printNameAsASPPredicate(ostream);
|
||||
ostream << ", ";
|
||||
condition.value().printAsASPPredicate(ostream);
|
||||
ostream << ")." << std::endl;
|
||||
m_outputStream << utils::Keyword("effectCondition") << "(";
|
||||
operator_.printPredicateAsASP(m_outputStream);
|
||||
m_outputStream << ", " << utils::Keyword("effect") << "(" << utils::Number(std::to_string(currentEffectID)) << "), ";
|
||||
condition.variable().printNameAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ", ";
|
||||
condition.value().printAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ")." << std::endl;
|
||||
});
|
||||
|
||||
ostream << "postcondition(";
|
||||
operator_.printPredicateAsASP(ostream);
|
||||
ostream << ", effect(" << currentEffectID << "), ";
|
||||
effect.postcondition().variable().printNameAsASPPredicate(ostream);
|
||||
ostream << ", ";
|
||||
effect.postcondition().value().printAsASPPredicate(ostream);
|
||||
ostream << ")." << std::endl;
|
||||
m_outputStream << utils::Keyword("postcondition") << "(";
|
||||
operator_.printPredicateAsASP(m_outputStream);
|
||||
m_outputStream << ", " << utils::Keyword("effect") << "(" << utils::Number(std::to_string(currentEffectID)) << "), ";
|
||||
effect.postcondition().variable().printNameAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ", ";
|
||||
effect.postcondition().value().printAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ")." << std::endl;
|
||||
|
||||
currentEffectID++;
|
||||
});
|
||||
|
||||
ostream << "costs(";
|
||||
operator_.printPredicateAsASP(ostream);
|
||||
ostream << ", " << operator_.costs() << ")." << std::endl;
|
||||
m_outputStream << utils::Keyword("costs") << "(";
|
||||
operator_.printPredicateAsASP(m_outputStream);
|
||||
m_outputStream << ", " << operator_.costs() << ")." << std::endl;
|
||||
});
|
||||
|
||||
ostream << std::endl;
|
||||
ostream << "% mutex groups";
|
||||
m_outputStream << std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TranslatorASP::translateMutexes() const
|
||||
{
|
||||
m_outputStream << utils::Heading2("mutex groups");
|
||||
|
||||
const auto &mutexGroups = m_description.mutexGroups();
|
||||
|
||||
@@ -171,25 +210,31 @@ void TranslatorASP::translate(std::ostream &ostream) const
|
||||
const auto mutexGroupID = std::to_string(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();
|
||||
|
||||
std::for_each(facts.cbegin(), facts.cend(),
|
||||
[&](const auto &fact)
|
||||
{
|
||||
ostream << "contains(mutexGroup(" << mutexGroupID << "), ";
|
||||
fact.variable().printNameAsASPPredicate(ostream);
|
||||
ostream << ", ";
|
||||
fact.value().printAsASPPredicate(ostream);
|
||||
ostream << ")." << std::endl;
|
||||
m_outputStream << utils::Keyword("contains") << "(" << utils::Keyword("mutexGroup") << "(" << utils::Number(mutexGroupID) << "), ";
|
||||
fact.variable().printNameAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ", ";
|
||||
fact.value().printAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ")." << std::endl;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (usesAxiomRules)
|
||||
{
|
||||
ostream << std::endl;
|
||||
ostream << "% axiom rules";
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TranslatorASP::translateAxiomRules() const
|
||||
{
|
||||
if (!m_description.usesActionCosts())
|
||||
return;
|
||||
|
||||
m_outputStream << std::endl;
|
||||
m_outputStream << utils::Heading2("axiom rules");
|
||||
|
||||
const auto &axiomRules = m_description.axiomRules();
|
||||
|
||||
@@ -201,29 +246,28 @@ void TranslatorASP::translate(std::ostream &ostream) const
|
||||
const auto axiomRuleID = std::to_string(currentAxiomRuleID);
|
||||
currentAxiomRuleID++;
|
||||
|
||||
ostream << std::endl << "axiomRule(" << axiomRuleID << ")." << std::endl;
|
||||
m_outputStream << std::endl << utils::Keyword("axiomRule") << "(" << utils::Number(axiomRuleID) << ")." << std::endl;
|
||||
|
||||
const auto &conditions = axiomRule.conditions();
|
||||
|
||||
std::for_each(conditions.cbegin(), conditions.cend(),
|
||||
[&](const auto &condition)
|
||||
{
|
||||
ostream << "condition(axiomRule(" << axiomRuleID << "), ";
|
||||
condition.variable().printNameAsASPPredicate(ostream);
|
||||
ostream << ", ";
|
||||
condition.value().printAsASPPredicate(ostream);
|
||||
ostream << ")." << std::endl;
|
||||
m_outputStream << utils::Keyword("condition") << "(" << utils::Keyword("axiomRule") << "(" << utils::Number(axiomRuleID) << "), ";
|
||||
condition.variable().printNameAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ", ";
|
||||
condition.value().printAsASPPredicate(m_outputStream);
|
||||
m_outputStream << ")." << std::endl;
|
||||
});
|
||||
|
||||
const auto &postcondition = axiomRule.postcondition();
|
||||
|
||||
ostream << "postcondition(axiomRule(axiomRule" << axiomRuleID << "), ";
|
||||
postcondition.variable().printNameAsASPPredicate(ostream);
|
||||
ostream << ", ";
|
||||
postcondition.value().printAsASPPredicate(ostream);
|
||||
ostream << ")." << std::endl;
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -3,7 +3,9 @@
|
||||
#include <iostream>
|
||||
|
||||
#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
|
||||
{
|
||||
@@ -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")
|
||||
{
|
||||
utils::parseExpected<std::string>(istream, "of");
|
||||
utils::parseExpected<std::string>(istream, "those>");
|
||||
parser.expect<std::string>("of");
|
||||
parser.expect<std::string>("those>");
|
||||
|
||||
// TODO: do not return a copy of Value::None
|
||||
return Value::None;
|
||||
@@ -73,12 +75,12 @@ Value Value::fromSAS(std::istream &istream)
|
||||
else if (sasSign == "NegatedAtom")
|
||||
value.m_sign = Value::Sign::Negative;
|
||||
else
|
||||
throw utils::ParserException("Invalid value sign \"" + sasSign + "\"");
|
||||
throw utils::ParserException(parser, "invalid value sign “" + sasSign + "”");
|
||||
|
||||
try
|
||||
{
|
||||
istream.ignore(1);
|
||||
std::getline(istream, value.m_name);
|
||||
parser.skipWhiteSpace();
|
||||
value.m_name = parser.getLine();
|
||||
|
||||
// Remove trailing ()
|
||||
if (value.m_name.find("()") != std::string::npos)
|
||||
@@ -89,7 +91,7 @@ Value Value::fromSAS(std::istream &istream)
|
||||
}
|
||||
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;
|
||||
@@ -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)
|
||||
return Value::Any;
|
||||
|
||||
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];
|
||||
}
|
||||
@@ -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)
|
||||
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
|
||||
if (*this == Value::None)
|
||||
{
|
||||
ostream << "value(none)";
|
||||
outputStream << utils::Keyword("value") << "(" << utils::Keyword("none") << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
ostream << "value(" << utils::escapeASP(m_name) << ", "
|
||||
<< (m_sign == Sign::Positive ? "true" : "false") << ")";
|
||||
outputStream << utils::Keyword("value") << "(" << utils::escapeASP(m_name) << ", "
|
||||
<< (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)
|
||||
ostream << "Atom ";
|
||||
outputStream << "Atom ";
|
||||
else
|
||||
ostream << "NegatedAtom ";
|
||||
outputStream << "NegatedAtom ";
|
||||
|
||||
ostream << m_name;
|
||||
outputStream << m_name;
|
||||
|
||||
if (!m_hasArguments)
|
||||
ostream << "()";
|
||||
outputStream << "()";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -2,7 +2,9 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <plasp/utils/Parsing.h>
|
||||
#include <plasp/utils/Formatting.h>
|
||||
#include <plasp/utils/IO.h>
|
||||
#include <plasp/utils/ParserException.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -22,47 +24,47 @@ Variable::Variable()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Variable Variable::fromSAS(std::istream &istream)
|
||||
Variable Variable::fromSAS(utils::Parser &parser)
|
||||
{
|
||||
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_axiomLayer = utils::parse<int>(istream);
|
||||
variable.m_name = parser.parse<std::string>();
|
||||
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);
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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())
|
||||
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];
|
||||
}
|
||||
|
@@ -4,8 +4,6 @@
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <plasp/utils/Parsing.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
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.m_variable = &Variable::referenceFromSAS(istream, variables);
|
||||
variableTransition.m_valueBefore = &Value::referenceFromSAS(istream, *variableTransition.m_variable);
|
||||
variableTransition.m_valueAfter = &Value::referenceFromSAS(istream, *variableTransition.m_variable);
|
||||
variableTransition.m_variable = &Variable::referenceFromSAS(parser, variables);
|
||||
variableTransition.m_valueBefore = &Value::referenceFromSAS(parser, *variableTransition.m_variable);
|
||||
variableTransition.m_valueAfter = &Value::referenceFromSAS(parser, *variableTransition.m_variable);
|
||||
|
||||
return variableTransition;
|
||||
}
|
||||
|
145
src/plasp/utils/Logger.cpp
Normal file
145
src/plasp/utils/Logger.cpp
Normal 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
621
src/plasp/utils/Parser.cpp
Normal 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");
|
||||
|
||||
// Don’t 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
Reference in New Issue
Block a user