This page purpose is to help HATP developers : it describes how HATP works under the hood.
Contents |
Where to start
Architecture
Core files
Parsing
1. Antlr 2
The parser is based on Antlr2.7.7 which is no longer maintained.
The reference manual can be found here: http://www.antlr2.org/doc/index.html
And a good getting started can be found here: http://supportweb.cs.bham.ac.uk/docs/tutorials/docsystem/build/tutorials/antlr/antlr.html
If the link is dead you can download the PDF copy here
The example uses Java output, but it is still relevant and relatively easy.
2. Preconditions
2.1. Grammar
The parsing of the preconditions are based on the following formal grammar:
term := e | (e, a) | size(e, a) | f(x1, ..., xn) | const literal := term = term | term ≠ term | term > term | term ≥ term | term < term | term ≤ term | term ∈ (e, a) | term ∉ (e, a) precond := precond ⋁ precond | ∀(e' ∈ t), precond → precond | ∃(e' ∈ t), precond → precond | literal | precond
In the file HATP.g for the antlr parser, the name are respectively singleTerm, precondTerm and preconds (there is a precondsPrivate just due to implementation issue but it is a subpart of preconds)
When the parser identifies a literal, it turns it into a C++ lambda expression, for instance:
Entity.attribute == "some_text";
becomes
[&]()(->bool{return(Entity->get<string>("attribute")=="some_text");}()
Using the same principle the other constructs -FORALL, EXIST and OR- are turned into lambda expression to ease any further development.
2.2. Reports
HATP relies on "reports" to understand what happened in an action or the dependencies of another (the variables read in the preconditions).
Each task will generate reports:
- In its preconditions to tell which variables it depends on and what is the value needed.
- In its effect to tell what it produce/changes.
By comparing the preconditions reports of some action with the effects reports of some other, HATP builds a set of causal links. In order to generate those report there exists a variant of the lambda expression depicted above to integrate the report:
[&]()->bool{bool ret=true; if(!(Entity->get<string>("attribute")=="some_text")){report.clearTests(); ret=false;} report.addAtomTestEqual(Entity->getName(), "attribute", "some_text"); return ret;}()
Note that this form is quite similar to the one above there is just the report management added, this was the kind of reason behind the use of lambda expressions: we can have the same definition whatever the actual behaviour.