This is very close to right, but it isn't working yet.
This commit is contained in:
parent
93a0f3ea1d
commit
4de7b0beb4
|
@ -1,10 +1,9 @@
|
|||
(ns ^{:doc "parse multiple rules from a stream, possibly a file."
|
||||
:author "Simon Brooke"}
|
||||
mw-parser.bulk
|
||||
(:use mw-parser.core
|
||||
mw-engine.utils
|
||||
clojure.java.io
|
||||
[clojure.string :only [split trim]])
|
||||
(:require [clojure.string :refer [split trim]]
|
||||
[mw-engine.utils :refer [member?]]
|
||||
[mw-parser.declarative :refer [compile-rule]])
|
||||
(:import (java.io BufferedReader StringReader)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -30,7 +29,6 @@
|
|||
;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
(defn comment?
|
||||
"Is this `line` a comment?"
|
||||
[line]
|
||||
|
@ -40,8 +38,8 @@
|
|||
"Parse rules from successive lines in this `string`, assumed to have multiple
|
||||
lines delimited by the new-line character. Return a list of S-expressions."
|
||||
[string]
|
||||
;; TODO: tried to do this using with-open, but couldn't make it work.
|
||||
(map #(parse-rule (trim %)) (remove comment? (split string #"\n"))))
|
||||
(map compile-rule
|
||||
(remove comment? (split string #"\n"))))
|
||||
|
||||
(defn parse-file
|
||||
"Parse rules from successive lines in the file loaded from this `filename`.
|
||||
|
|
|
@ -150,24 +150,28 @@
|
|||
|
||||
(defn compile-rule
|
||||
"Parse this `rule-text`, a string conforming to the grammar of MicroWorld rules,
|
||||
into Clojure source, and then compile it into an anonymous
|
||||
function object, getting round the problem of binding mw-engine.utils in
|
||||
the compiling environment. If `return-tuple?` is present and true, return
|
||||
a list comprising the anonymous function compiled, and the function from
|
||||
which it was compiled.
|
||||
into Clojure source, and then compile it into an anonymous
|
||||
function object, getting round the problem of binding mw-engine.utils in
|
||||
the compiling environment. If `return-tuple?` is present and true, return
|
||||
a list comprising the anonymous function compiled, and the function from
|
||||
which it was compiled.
|
||||
|
||||
Throws an exception if parsing fails."
|
||||
Throws an exception if parsing fails."
|
||||
([rule-text return-tuple?]
|
||||
(assert (string? rule-text))
|
||||
(let [rule (trim rule-text)
|
||||
tree (simplify (parse-rule rule))
|
||||
afn (if (rule? tree) (eval (generate tree))
|
||||
;; else
|
||||
(throw-parse-exception tree))]
|
||||
(if return-tuple?
|
||||
(list afn rule)
|
||||
;; else
|
||||
(let [src (trim rule-text)
|
||||
parse-tree (simplify (parse src))
|
||||
fn' (generate parse-tree)
|
||||
afn (try
|
||||
(if (= 'fn (first fn'))
|
||||
(vary-meta (eval fn') merge (meta fn'))
|
||||
(throw (Exception. (format "Parse of `%s` did not return a functionn" src))))
|
||||
(catch Exception any (throw (ex-info (.getMessage any)
|
||||
{:src src
|
||||
:parse parse-tree
|
||||
:fn fn'}))))]
|
||||
(if
|
||||
return-tuple?
|
||||
(list afn (trim rule-text))
|
||||
afn)))
|
||||
([rule-text]
|
||||
(compile-rule rule-text false)))
|
||||
|
||||
|
|
|
@ -32,13 +32,11 @@
|
|||
;; (3) the reason for the error
|
||||
(def bad-parse-error "I did not understand:\n '%s'\n %s\n %s")
|
||||
|
||||
|
||||
(defn- explain-parse-error-reason
|
||||
"Attempt to explain the reason for the parse error."
|
||||
[reason]
|
||||
(str "Expecting one of (" (apply str (map #(str (:expecting %) " ") reason)) ")"))
|
||||
|
||||
|
||||
(defn- parser-error-to-map
|
||||
[parser-error]
|
||||
(let [m (reduce (fn [map item](merge map {(first item)(second item)})) {} parser-error)
|
||||
|
@ -47,7 +45,6 @@
|
|||
(:reason m))]
|
||||
(merge m {:reason reason})))
|
||||
|
||||
|
||||
(defn throw-parse-exception
|
||||
"Construct a helpful error message from this `parser-error`, and throw an exception with that message."
|
||||
[parser-error]
|
||||
|
|
|
@ -289,7 +289,7 @@
|
|||
[source property quantity-frag destinations]
|
||||
(vary-meta
|
||||
(list 'fn ['cell 'world]
|
||||
(list 'when (list 'and source (list 'pos? 'cell property))
|
||||
(list 'when (list 'and source (list 'pos? (list 'cell property)))
|
||||
(list 'map
|
||||
(list 'fn ['d]
|
||||
{:source (list 'select-keys 'cell [:x :y])
|
||||
|
@ -310,6 +310,12 @@
|
|||
:NUMBER (generate q-clause)
|
||||
:PERCENTAGE (let [multiplier (/ (generate (second q-clause)) 100)]
|
||||
(list '* multiplier (list property 'cell)))
|
||||
:SIMPLE-EXPRESSION (if (= (count q-clause) 2)
|
||||
(generate-quantity-accessor (second q-clause) property)
|
||||
(throw (ex-info
|
||||
(format "Cannot yet handle q-clause of form: `%s`" q-clause)
|
||||
{:clause q-clause
|
||||
:property property})))
|
||||
:SOME (list 'rand (list property 'cell))
|
||||
(throw (ex-info
|
||||
(format "Unexpected QUANTITY type: `%s`" (first q-clause))
|
||||
|
@ -343,30 +349,6 @@
|
|||
:LEAST (list 'mw-engine.utils/get-least-cell 'candidates prop)
|
||||
:MOST (list 'mw-engine.utils/get-most-cell 'candidates prop))))
|
||||
'candidates))))
|
||||
;; (fn
|
||||
;; [cell world]
|
||||
;; (when
|
||||
;; (and (= (:state cell) (or (:house cell) :house)) (pos? cell :food))
|
||||
;; (map
|
||||
;; (fn
|
||||
;; [d]
|
||||
;; (assoc
|
||||
;; {}
|
||||
;; :source
|
||||
;; (select-keys cell [:x :y])
|
||||
;; :destination
|
||||
;; (select-keys d [:x :y])
|
||||
;; :property
|
||||
;; :food
|
||||
;; :quantity
|
||||
;; (* 1/10 (:food cell)))
|
||||
;; {})
|
||||
;; (let
|
||||
;; [candidates
|
||||
;; (filter
|
||||
;; (fn [cell] (= (:state cell) (or (:house cell) :house)))
|
||||
;; (mw-engine.utils/get-neighbours world cell 2))]
|
||||
;; (list (mw-engine.utils/get-least-cell candidates :food))))))
|
||||
|
||||
(defn generate-flow
|
||||
[tree]
|
||||
|
|
Loading…
Reference in a new issue