Continued work on cleaning up the parser
This commit is contained in:
parent
4de7b0beb4
commit
4b721219bd
5 changed files with 173 additions and 154 deletions
|
|
@ -1,10 +1,9 @@
|
|||
(ns ^{:doc "parse multiple rules from a stream, possibly a file."
|
||||
:author "Simon Brooke"}
|
||||
mw-parser.bulk
|
||||
(:require [clojure.string :refer [split trim]]
|
||||
[mw-engine.utils :refer [member?]]
|
||||
[mw-parser.declarative :refer [compile-rule]])
|
||||
(:import (java.io BufferedReader StringReader)))
|
||||
(:require [clojure.string :refer [split]]
|
||||
[mw-parser.declarative :refer [compile]]
|
||||
[mw-parser.utils :refer [comment?]]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;
|
||||
|
|
@ -29,16 +28,12 @@
|
|||
;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn comment?
|
||||
"Is this `line` a comment?"
|
||||
[line]
|
||||
(or (empty? (trim line)) (member? (first line) '(nil \# \;))))
|
||||
|
||||
(defn parse-string
|
||||
"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]
|
||||
(map compile-rule
|
||||
(map compile
|
||||
(remove comment? (split string #"\n"))))
|
||||
|
||||
(defn parse-file
|
||||
|
|
@ -47,14 +42,8 @@
|
|||
[filename]
|
||||
(parse-string (slurp filename)))
|
||||
|
||||
(defn compile-string
|
||||
"Compile each non-comment line of this `string` into an executable anonymous
|
||||
function, and return the sequence of such functions."
|
||||
[string]
|
||||
(map #(compile-rule % true) (remove comment? (split string #"\n"))))
|
||||
|
||||
(defn compile-file
|
||||
"Compile each non-comment line of the file indicated by this `filename` into
|
||||
an executable anonymous function, and return the sequence of such functions."
|
||||
[filename]
|
||||
(compile-string (slurp filename)))
|
||||
(compile (slurp filename) true))
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
(ns ^{:doc "A very simple parser which parses production rules."
|
||||
:author "Simon Brooke"}
|
||||
mw-parser.declarative
|
||||
(:require [clojure.string :refer [join split trim]]
|
||||
(:require [clojure.string :refer [join split split-lines trim]]
|
||||
[instaparse.core :refer [parser]]
|
||||
[mw-parser.errors :refer [throw-parse-exception]]
|
||||
[mw-parser.flow :refer [flow-grammar]]
|
||||
[mw-parser.generate :refer [generate]]
|
||||
[mw-parser.simplify :refer [simplify]]
|
||||
[mw-parser.utils :refer [rule?]]
|
||||
[mw-parser.utils :refer [comment?]]
|
||||
[trptr.java-wrapper.locale :refer [get-default]])
|
||||
(:import [java.util Locale]))
|
||||
|
||||
|
|
@ -148,7 +147,7 @@
|
|||
";;" nil
|
||||
(throw (ex-info "Rule text was not recognised" {:text text}))))))
|
||||
|
||||
(defn compile-rule
|
||||
(defn compile
|
||||
"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
|
||||
|
|
@ -158,20 +157,23 @@
|
|||
|
||||
Throws an exception if parsing fails."
|
||||
([rule-text return-tuple?]
|
||||
(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)))
|
||||
(let [lines (remove comment? (split-lines rule-text))]
|
||||
(if (> (count lines) 1)
|
||||
(map #(compile % return-tuple?) lines)
|
||||
(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?
|
||||
(vary-meta (list afn src fn') merge (meta afn))
|
||||
afn)))))
|
||||
([rule-text]
|
||||
(compile-rule rule-text false)))
|
||||
(compile rule-text false)))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
(ns ^{:doc "Utilities used in more than one namespace within the parser."
|
||||
:author "Simon Brooke"}
|
||||
mw-parser.utils)
|
||||
mw-parser.utils
|
||||
(:require [clojure.string :refer [trim]]
|
||||
[mw-engine.utils :refer [member?]]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;
|
||||
|
|
@ -25,6 +27,10 @@
|
|||
;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn comment?
|
||||
"Is this `line` a comment?"
|
||||
[line]
|
||||
(or (empty? (trim line)) (member? (first line) '(nil \# \;))))
|
||||
|
||||
(defn suitable-fragment?
|
||||
"Return `true` if `tree-fragment` appears to be a tree fragment of the expected `type`."
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue