68 lines
2.9 KiB
Clojure
68 lines
2.9 KiB
Clojure
(ns ^{:doc "A very simple parser which parses flow rules."
|
|
:author "Simon Brooke"}
|
|
mw-parser.flow
|
|
(:require [clojure.string :refer [join]]
|
|
[mw-parser.declarative :refer [build-parser]]
|
|
[mw-parser.simplify :refer [simplify-second-of-two]]))
|
|
|
|
(def flow-grammar
|
|
"Grammar for flow rules.
|
|
|
|
My initial conception of this would be that production rules
|
|
(if-then rules) and flow rules (flow-from-to rules) would be
|
|
entirely separate, presented to the parser as separate text
|
|
files, and parsed and compiled by different chains of functions.
|
|
|
|
This appears not to be necessary. Flow rules are easy to parse
|
|
with the same parser as production rules -- a lot of the grammar
|
|
is intentionally common -- and the rules are easily discriminated
|
|
at the compilation ('generate') stage.
|
|
|
|
The basic rule I want to be able to compile at this stage is the 'mutual
|
|
aid' rule:
|
|
|
|
`flow 1 food from house having food > 1 to house with least food within 2`
|
|
"
|
|
(join "\n" ["FLOW-RULE := FLOW SPACE QUANTITY SPACE PROPERTY SPACE FROM SPACE SOURCE SPACE TO-HOW SPACE DESTINATION;"
|
|
"PERCENTAGE := NUMBER #'%';"
|
|
"QUANTITY := PERCENTAGE | NUMBER | EXPRESSION | SOME;"
|
|
"SOURCE := STATE | STATE SPACE WITH SPACE CONDITIONS;"
|
|
"DESTINATION := STATE | STATE SPACE WITH SPACE FLOW-CONDITIONS | STATE SPACE WITHIN SPACE VALUE SPACE WITH SPACE FLOW-CONDITIONS;"
|
|
"DETERMINER := MOST | LEAST;"
|
|
"DETERMINER-CONDITION := DETERMINER SPACE PROPERTY | DETERMINER SPACE PROPERTY;"
|
|
"FLOW-CONDITIONS := DETERMINER-CONDITION | CONDITIONS"
|
|
"STATE := SYMBOL;"
|
|
"TO-HOW := TO | TO-EACH | TO-FIRST;"
|
|
"TO-EACH := TO SPACE EACH | TO SPACE ALL;"
|
|
"TO-FIRST := TO SPACE FIRST"]))
|
|
|
|
(def parse-flow
|
|
"Parse the argument, assumed to be a string in the correct syntax, and return a parse tree."
|
|
(build-parser flow-grammar))
|
|
|
|
(defn simplify-flow
|
|
[tree]
|
|
(if (coll? tree)
|
|
(case (first tree)
|
|
:CONDITION (simplify-second-of-two tree)
|
|
:CONDITIONS (simplify-second-of-two tree)
|
|
:DETERMINER (simplify-second-of-two tree)
|
|
;; :DETERMINER-CONDITION (simplify-determiner-condition tree)
|
|
:EXPRESSION (simplify-second-of-two tree)
|
|
:FLOW nil
|
|
;; :FLOW-CONDITIONS (simplify-second-of-two tree)
|
|
:PROPERTY (simplify-second-of-two tree)
|
|
:PROPERTY-CONDITION-OR-EXPRESSION (simplify-second-of-two tree)
|
|
:SPACE nil
|
|
:QUANTITY (simplify-second-of-two tree)
|
|
:STATE (list :PROPERTY-CONDITION
|
|
(list :SYMBOL "state")
|
|
'(:QUALIFIER
|
|
(:EQUIVALENCE
|
|
(:IS "is")))
|
|
(list :EXPRESSION
|
|
(list :VALUE (second tree))))
|
|
(remove nil? (map simplify-flow tree)))
|
|
tree))
|
|
|