Documentation.
This commit is contained in:
parent
51388b5be4
commit
723a23e3dc
110
README.md
110
README.md
|
@ -4,7 +4,115 @@ A rule parser for MicroWorld
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
FIXME
|
Main entry point is (parse-rule <string>), where string takes a form detailed
|
||||||
|
in **grammar**, below. If the rule is interpretted correctly the result will
|
||||||
|
be a Clojure anonymous function; if the rule is not interpretted, currently nil
|
||||||
|
is returned and there's no helpful error message.
|
||||||
|
|
||||||
|
### Generated function and evaluation environment
|
||||||
|
|
||||||
|
The generated function is a function of two arguments
|
||||||
|
|
||||||
|
* **cell** a cell in a world as defined in mw-engine.world, q.v.;
|
||||||
|
* **world** the world of which that cell forms part.
|
||||||
|
|
||||||
|
It returns a new cell, based on the cell passed.
|
||||||
|
|
||||||
|
Actions of the rule will (can only) modify properties of the cell; there are two
|
||||||
|
properties which are special and SHOULD NOT be modified, namely the properties
|
||||||
|
**x** and **y**. Currently there is no policing that these properties are not
|
||||||
|
modified.
|
||||||
|
|
||||||
|
### Grammar
|
||||||
|
|
||||||
|
A rule comprises:
|
||||||
|
|
||||||
|
* if *conditions* then *actions*
|
||||||
|
|
||||||
|
#### Conditions
|
||||||
|
|
||||||
|
where *conditions* is:
|
||||||
|
|
||||||
|
* *condition*
|
||||||
|
|
||||||
|
or
|
||||||
|
* *condition* and *conditions*
|
||||||
|
|
||||||
|
A *condition* is one of:
|
||||||
|
|
||||||
|
* *property* is *value*
|
||||||
|
* *property* is not *value*
|
||||||
|
* *property* is in *values*
|
||||||
|
* *property* is not in *values*
|
||||||
|
* *property* is more than *numeric-value*
|
||||||
|
* *property* is less than *numeric-value*
|
||||||
|
* *number* neighbours have *property* equal to *value*
|
||||||
|
* more than *number* neighbours have *property* equal to *value*
|
||||||
|
* fewer than *number* neighbours have *property* equal to *value*
|
||||||
|
|
||||||
|
#### Actions
|
||||||
|
|
||||||
|
Where *actions* is:
|
||||||
|
|
||||||
|
* *action*
|
||||||
|
|
||||||
|
or
|
||||||
|
* *action* and *actions*
|
||||||
|
|
||||||
|
and *action* is:
|
||||||
|
|
||||||
|
* *property* should be *value*
|
||||||
|
|
||||||
|
#### Properties
|
||||||
|
|
||||||
|
In the above, *property* is the name of any property of a cell. Any alpha-numeric
|
||||||
|
string of characters can form the name of a property. Actions should NOT refer
|
||||||
|
to the reserved properties **x** and **y**.
|
||||||
|
|
||||||
|
#### Values in Conditions
|
||||||
|
|
||||||
|
Values in conditions and actions are considered slightly differently. In a
|
||||||
|
condition, a value is one of
|
||||||
|
|
||||||
|
* *symbolic-value*
|
||||||
|
* *numeric-value*
|
||||||
|
|
||||||
|
The '...more than...' and '...less than...' conditions imply a *numeric-value*.
|
||||||
|
Thus "if altitude is more than fertility..." is interpreted as meaning "if the value
|
||||||
|
of the property of the current cell called 'altitude' is greater than the value
|
||||||
|
of the property of the current cell called 'fertility'", whereas the apparently
|
||||||
|
similar condition 'if altitude is fertility...' is interpreted as meaning
|
||||||
|
"if the value of the property of the current cell called 'altitude' is the symbol
|
||||||
|
'fertility'".
|
||||||
|
|
||||||
|
Thus *symbolic-value* is any sequence of alphanumeric characters, whereas
|
||||||
|
*numeric-value* is one of:
|
||||||
|
|
||||||
|
* *number*
|
||||||
|
* *property*
|
||||||
|
|
||||||
|
and *number* is any sequence of the decimal digits 0...9, the minus character
|
||||||
|
'-' and the period character '.', provided that the minus character can only be
|
||||||
|
in the first position, and the period character can only appear once.
|
||||||
|
|
||||||
|
#### Values in Actions
|
||||||
|
|
||||||
|
A *value* in an action is one of
|
||||||
|
|
||||||
|
* *symbolic-value*
|
||||||
|
* *arithmetic-value*
|
||||||
|
* *number*
|
||||||
|
|
||||||
|
where *arithmetic-value* is:
|
||||||
|
|
||||||
|
* *property* *operator* *numeric-value*
|
||||||
|
|
||||||
|
and *operator* is one of the simple arithmetic operators '+', '-', '*' and '/'.
|
||||||
|
|
||||||
|
### Shorthand
|
||||||
|
|
||||||
|
Note that '...members are...' is equivalent to '...members have state equal to...',
|
||||||
|
and 'some neighbours...' is equivalent to 'more than 0 neighbours...'
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,14 @@
|
||||||
;; * "if deer is more than 1 and wolves is more than 1 then deer should be deer - wolves"
|
;; * "if deer is more than 1 and wolves is more than 1 then deer should be deer - wolves"
|
||||||
;; * "if state is grassland and 4 neighbours have state equal to water then state should be village"
|
;; * "if state is grassland and 4 neighbours have state equal to water then state should be village"
|
||||||
;; * "if state is forest and fertility is between 55 and 75 then state should be climax"
|
;; * "if state is forest and fertility is between 55 and 75 then state should be climax"
|
||||||
;; * "if 6 neighbours have state equal to water then state should be fishery"
|
;; * "if 6 neighbours have state equal to water then state should be village"
|
||||||
|
;; * "if state is in grassland or pasture or heath and 4 neighbours are water then state should be village"
|
||||||
;;
|
;;
|
||||||
;; It should also but does not yet parse rules of the form:
|
;; It should also but does not yet parse rules of the form:
|
||||||
|
|
||||||
;; * "if state is forest or state is climax and some neighbours have state is fire then 3 in 5 chance that state should be fire"
|
;; * "if state is forest or state is climax and some neighbours have state is fire then 3 in 5 chance that state should be fire"
|
||||||
;; * "if state is pasture and more than 3 neighbours have state equal to scrub then state should be scrub"
|
;; * "if state is pasture and more than 3 neighbours have state equal to scrub then state should be scrub"
|
||||||
;; * "if state is in grassland or pasture or heath and 4 neighbours are water then state should be village"
|
;; *
|
||||||
;;
|
;;
|
||||||
;; it generates rules in the form expected by mw-engine.core
|
;; it generates rules in the form expected by mw-engine.core
|
||||||
|
|
||||||
|
@ -79,9 +80,8 @@
|
||||||
"Parse a list of values from among these `tokens`. If `expect-int` is true, return
|
"Parse a list of values from among these `tokens`. If `expect-int` is true, return
|
||||||
an integer or something which will evaluate to an integer."
|
an integer or something which will evaluate to an integer."
|
||||||
[[OR token & tokens] expect-int]
|
[[OR token & tokens] expect-int]
|
||||||
(println OR)
|
|
||||||
(cond (member? OR '("or" "in"))
|
(cond (member? OR '("or" "in"))
|
||||||
(let [[others remainder] (parse-disjunct-value2 tokens expect-int)]
|
(let [[others remainder] (parse-disjunct-value tokens expect-int)]
|
||||||
[(cons
|
[(cons
|
||||||
(cond
|
(cond
|
||||||
expect-int (first (parse-simple-value (list token) true))
|
expect-int (first (parse-simple-value (list token) true))
|
||||||
|
@ -171,9 +171,15 @@
|
||||||
(let [[value & remainder] rest]
|
(let [[value & remainder] rest]
|
||||||
(gen-neighbours-condition '= quantity :state value remainder))
|
(gen-neighbours-condition '= quantity :state value remainder))
|
||||||
(= have-or-are "have")
|
(= have-or-are "have")
|
||||||
(let [[property EQUAL TO value & remainder] rest]
|
(let [[property comp1 comp2 value & remainder] rest]
|
||||||
(cond (and (= EQUAL "equal") (= TO "to"))
|
(cond (and (= comp1 "equal") (= comp2 "to"))
|
||||||
(gen-neighbours-condition '= quantity property value remainder)))))))
|
(gen-neighbours-condition '= quantity property value remainder)
|
||||||
|
;; (and (= comp1 "more") (= comp2 "than"))
|
||||||
|
;; (gen-neighbours-condition '> quantity property value remainder)
|
||||||
|
;; (and (= comp1 "less") (= comp2 "than"))
|
||||||
|
;; (gen-neighbours-condition '< quantity property value remainder)
|
||||||
|
)
|
||||||
|
)))))
|
||||||
|
|
||||||
(defn parse-neighbours-condition
|
(defn parse-neighbours-condition
|
||||||
"Parse conditions referring to neighbours"
|
"Parse conditions referring to neighbours"
|
||||||
|
|
Loading…
Reference in a new issue