Clojure Spec解析问题

时间:2017-12-15 19:06:06

标签: clojure clojure.spec

我正在进行一些编程语言练习,并且我尝试使用Spec来定义语言语法并对其进行解析。代码很简单,如下所示。但我对如何正确解析子表达式有疑问。

(:require [clojure.spec.alpha :as s]
        [clojure.edn :as e])

(s/def ::const-exp integer?)
(s/def ::var-exp symbol?)

;; -(1,2)
(s/def ::diff-exp (s/cat :minus #{'-} :exps (s/coll-of ::expr :count 2)))

;; zero? 2
(s/def ::zero?-exp (s/cat :zero? #{'zero?} :exp1 ::expr))

;; if x then y else c
(s/def ::if-exp (s/cat :if #{'if} :exp1 ::expr :then #{'then} :exp2 ::expr :else #{'else} :exp3 ::expr))

;; let x = y in c
(s/def ::let-exp (s/cat :let #{'let} :id ::var-exp :eq #{'=} :exp1 ::expr :in #{'in} :body ::expr))

(s/def ::expr
  (s/or
   :const-exp ::const-exp
   :diff-exp ::diff-exp
   :var-exp ::var-exp
   :zero?-exp ::zero?-exp
   :if-exp ::if-exp
   :let-exp ::let-exp))

(defn pgm [x] (e/read-string (format "[%s]" x)))

到目前为止,它可以很好地解析基本表达式。 比如(s/conform ::expr (pgm "let x = 7 in x"))

但是对于let表达式的示例,如果我将最后一个x更改为某个复杂表达式(s/conform ::expr (pgm "let x = 7 in let y = 8 in y")),则解析将失败并显示以下内容:

In: [6] val: (y = 8 in y) fails spec: :eopl.let-spec/let-exp at: [:let-exp] predicate: (cat :let #{(quote let)} :id :eopl.let-spec/var-exp :eq #{(quote =)} :exp1 :eopl.let-spec/expr :in #{(quote in)} :body :eopl.let-spec/expr), Extra input

它似乎无法前瞻或正确地进行递归整合?或者我在这里定义错误的语法?

如何解决这个问题,让它与Spec正确解析?

提前致谢。

0 个答案:

没有答案