2016-08-24 35 views
0

我正在嘗試使用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將導致比上述更好的代碼。它顯示了錯誤信息是如何在元數據中實際存在的,以及如何檢索它 - 這個問題的答案已經在文檔中了!

回答

1

當您在輸入上使用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"