Fixed seqability of cons cell, added quote read macro
This commit is contained in:
parent
6853c6c29c
commit
b4091f28dc
|
@ -3,22 +3,35 @@
|
|||
|
||||
(def NIL (symbol "NIL"))
|
||||
|
||||
(def NIL (symbol "NIL"))
|
||||
|
||||
(deftype ConsCell [CAR CDR]
|
||||
clojure.lang.ISeq
|
||||
(cons [this x] (ConsCell. x this))
|
||||
(count [this] (if
|
||||
(= (.CDR this) NIL)
|
||||
0
|
||||
(inc (count (.CDR this)))))
|
||||
(first [this] (.CAR this))
|
||||
;; next and more must return ISeq:
|
||||
;; https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ISeq.java
|
||||
(more [this] (if
|
||||
(= (.CDR this) NIL)
|
||||
clojure.lang.PersistentList/EMPTY
|
||||
(.CDR this)))
|
||||
(next [this] (.CDR this))
|
||||
(seq [this] this) ;; doesn't work - `Method beowulf/cons_cell/ConsCell.seq()Lclojure/lang/ISeq; is abstract`
|
||||
(next [this] (if
|
||||
(= (.CDR this) NIL)
|
||||
nil ;; next returns nil when empty
|
||||
(.CDR this)))
|
||||
|
||||
clojure.lang.Seqable
|
||||
(seq [this] this)
|
||||
|
||||
;; for some reason this marker protocol is needed otherwise compiler complains
|
||||
;; that `nth not supported on ConsCell`
|
||||
clojure.lang.Sequential
|
||||
|
||||
clojure.lang.IPersistentCollection
|
||||
(count [this] (if
|
||||
(= (.CDR this) NIL)
|
||||
0
|
||||
(inc (count (.CDR this)))))
|
||||
(empty [this] false)
|
||||
(equiv [this other] false))
|
||||
|
||||
|
|
|
@ -4,12 +4,19 @@
|
|||
;; (:import [beowulf.cons-cell ConsCell])
|
||||
)
|
||||
|
||||
(declare generate)
|
||||
|
||||
(def parse
|
||||
"Parse a string presented as argument into a parse tree which can then
|
||||
be operated upon further."
|
||||
(i/parser
|
||||
"expr := mexpr | sexpr;
|
||||
mexpr := fncall | defn | cond;
|
||||
(str
|
||||
;; top level: we accept mexprs as well as sexprs.
|
||||
"expr := mexpr | sexpr;"
|
||||
|
||||
;; mexprs. I'm pretty clear that Lisp 1.5 could never read these,
|
||||
;; but it's a convenience.
|
||||
"mexpr := fncall | defn | cond;
|
||||
fncall := fn-name lsqb args rsqb;
|
||||
lsqb := '[';
|
||||
rsqb := ']';
|
||||
|
@ -20,20 +27,24 @@
|
|||
args := (arg semi-colon opt-space)* arg;
|
||||
arg := mexpr | sexpr;
|
||||
fn-name := #'[a-z]*';
|
||||
semi-colon := ';';
|
||||
semi-colon := ';';"
|
||||
|
||||
list := lpar sexpr rpar | lpar (sexpr sep)* rpar | lpar (sexpr sep)* dot-terminal;
|
||||
;; sexprs. Note it's not clear to me whether Lisp 1.5 had the quote macro,
|
||||
;; but I've included it on the basis that it can do little harm.
|
||||
"list := lpar sexpr rpar | lpar (sexpr sep)* rpar | lpar (sexpr sep)* dot-terminal;
|
||||
dotted-pair := lpar dot-terminal ;
|
||||
dot := '.';
|
||||
lpar := '(';
|
||||
rpar := ')';
|
||||
sexpr := atom | number | dotted-pair | list;
|
||||
sexpr := atom | number | dotted-pair | list | quoted-expr;
|
||||
quoted-expr := quote sexpr;
|
||||
quote := '\\'';
|
||||
dot-terminal := sexpr space dot space sexpr rpar;
|
||||
space := #'\\p{javaWhitespace}+';
|
||||
opt-space := #'\\p{javaWhitespace}*';
|
||||
sep := ',' | opt-space;
|
||||
atom := #'[A-Z][A-Z0-9]*';
|
||||
number := #'-?[0-9][0-9.]*';"))
|
||||
number := #'-?[0-9][0-9.]*';")))
|
||||
|
||||
(defn simplify
|
||||
"Simplify this parse tree `p`."
|
||||
|
@ -45,9 +56,11 @@
|
|||
(remove
|
||||
#(if (coll? %) (empty? %))
|
||||
(case (first p)
|
||||
(:arrow :dot :lpar :lsqb :opt-space :rpar :rsqb :semi-colon :sep :space) nil
|
||||
(:arrow :dot :lpar :lsqb :opt-space :quote :rpar :rsqb :semi-colon :sep :space) nil
|
||||
(:arg :expr :mexpr :sexpr) (simplify (second p))
|
||||
(:args :cond :cond-clause :dot-terminal :dotted-pair :fncall :list) (map simplify p)
|
||||
;; the quote read macro (which probably didn't exist in Lisp 1.5, but...)
|
||||
:quoted-expr [:fncall [:fn-name "quote"] [:args (simplify (nth p 2))]]
|
||||
;;default
|
||||
p)))
|
||||
p))
|
||||
|
|
Loading…
Reference in a new issue