Instaparse:有错误但未报告
Instaparse: there's an error but it is not reported
我正在尝试使用 Instaparse 构建语法。我经常发现这段代码在第一个断言中失败,发出 "Empty list":
(defn parse-it []
(let [parser (insta/parser ebnf)
res (insta/parses parser input)
_ (assert (seq res) (str "Empty list"))
choices (count res)
_ (assert (= choices 1))]
(first res)))
我总是能解决问题,但它涉及反复试验。有什么方法可以查明错误?
解决该问题的一个示例是从上述代码中变为 input
的文件中删除尾随空格。
编辑
根据 Stefan 的回答,我更改了代码:
(defn parse-it []
(let [my-parser (insta/parser ebnf)
xs (insta/parses my-parser input)
num-choices (count xs)
msg (cond
(zero? num-choices) "insta/parses might be able to be corrected"
(> num-choices 1) (str "insta/parses shows more than one way to parse: " num-choices)
(= 1 num-choices) "insta/parses shows one choice, so all good")
res (cond
;; Just fix there being more than one rather than show them all
;(> num-choices 1) xs
(= num-choices 1) (first xs)
(zero? num-choices) (insta/parse my-parser input))
_ (assert res (str "No result. Num of choices is: " num-choices))]
[msg res]))
上面的代码起到了作用:总能得到一个精确的答案。对我来说,在 insta/parses
returns 一个空列表之后,需要调用 insta/parse
来获取错误信息并不是那么明显。使用解析错误 documentation 会产生比上面更好的代码。它显示了错误信息实际上是如何存在于元数据中的,以及如何检索它 - 这个问题的答案已经在文档中了!
当您在输入中使用 parser
本身而不是通过 insta/parses
时,它会在 REPL 中打印一条非常准确的错误消息。
一个例子:
(def ebnf
"expr = A DOT
A = 'A'
DOT = '.'")
user> ((insta/parser ebnf) "A.")
[:expr [:A "A"] [:DOT "."]]
user> ((insta/parser ebnf) "B.")
Parse error at line 1, column 1:
B.
^
Expected:
"A"
我正在尝试使用 Instaparse 构建语法。我经常发现这段代码在第一个断言中失败,发出 "Empty list":
(defn parse-it []
(let [parser (insta/parser ebnf)
res (insta/parses parser input)
_ (assert (seq res) (str "Empty list"))
choices (count res)
_ (assert (= choices 1))]
(first res)))
我总是能解决问题,但它涉及反复试验。有什么方法可以查明错误?
解决该问题的一个示例是从上述代码中变为 input
的文件中删除尾随空格。
编辑
根据 Stefan 的回答,我更改了代码:
(defn parse-it []
(let [my-parser (insta/parser ebnf)
xs (insta/parses my-parser input)
num-choices (count xs)
msg (cond
(zero? num-choices) "insta/parses might be able to be corrected"
(> num-choices 1) (str "insta/parses shows more than one way to parse: " num-choices)
(= 1 num-choices) "insta/parses shows one choice, so all good")
res (cond
;; Just fix there being more than one rather than show them all
;(> num-choices 1) xs
(= num-choices 1) (first xs)
(zero? num-choices) (insta/parse my-parser input))
_ (assert res (str "No result. Num of choices is: " num-choices))]
[msg res]))
上面的代码起到了作用:总能得到一个精确的答案。对我来说,在 insta/parses
returns 一个空列表之后,需要调用 insta/parse
来获取错误信息并不是那么明显。使用解析错误 documentation 会产生比上面更好的代码。它显示了错误信息实际上是如何存在于元数据中的,以及如何检索它 - 这个问题的答案已经在文档中了!
当您在输入中使用 parser
本身而不是通过 insta/parses
时,它会在 REPL 中打印一条非常准确的错误消息。
一个例子:
(def ebnf
"expr = A DOT
A = 'A'
DOT = '.'")
user> ((insta/parser ebnf) "A.")
[:expr [:A "A"] [:DOT "."]]
user> ((insta/parser ebnf) "B.")
Parse error at line 1, column 1:
B.
^
Expected:
"A"