Instaparse:出现错误,但未报告

Instaparse:出现错误,但未报告

问题描述:

我正在尝试使用Instaparse构建语法。很多时候,我觉得这代码失败的第一个断言,发出“空单”:Instaparse:出现错误,但未报告

(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的文件中删除尾随空格。

编辑

基于斯特凡的答案,我已经改变了代码:

(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返回一个空列表后不是很明显,需要调用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"