Documentation.

This commit is contained in:
Simon Brooke 2014-07-06 14:31:10 +01:00
parent 51388b5be4
commit 723a23e3dc
2 changed files with 122 additions and 8 deletions

110
README.md
View file

@ -4,7 +4,115 @@ A rule parser for MicroWorld
## 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

View file

@ -7,13 +7,14 @@
;; * "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 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:
;; * "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 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
@ -79,9 +80,8 @@
"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."
[[OR token & tokens] expect-int]
(println OR)
(cond (member? OR '("or" "in"))
(let [[others remainder] (parse-disjunct-value2 tokens expect-int)]
(let [[others remainder] (parse-disjunct-value tokens expect-int)]
[(cons
(cond
expect-int (first (parse-simple-value (list token) true))
@ -171,9 +171,15 @@
(let [[value & remainder] rest]
(gen-neighbours-condition '= quantity :state value remainder))
(= have-or-are "have")
(let [[property EQUAL TO value & remainder] rest]
(cond (and (= EQUAL "equal") (= TO "to"))
(gen-neighbours-condition '= quantity property value remainder)))))))
(let [[property comp1 comp2 value & remainder] rest]
(cond (and (= comp1 "equal") (= comp2 "to"))
(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
"Parse conditions referring to neighbours"