2016-08-24 7 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

parserinsta/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" 
関連する問題