Continued work on cleaning up the parser

This commit is contained in:
Simon Brooke 2023-07-18 22:11:11 +01:00
parent 4de7b0beb4
commit 4b721219bd
5 changed files with 173 additions and 154 deletions

View file

@ -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))

View file

@ -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)))

View file

@ -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`."