2016-08-24 6 views
0

Ich versuche, eine Grammatik mit Instaparse aufzubauen. Nicht selten finde ich, dass dieser Code die erste Behauptung fehlschlägt, „Leere Liste“ Emittieren:Instaparse: Es gibt einen Fehler, aber es wird nicht berichtet

(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))) 

ich immer das Problem beheben, aber es geht Versuch und Irrtum. Gibt es eine Möglichkeit, den Fehler zu lokalisieren?

Ein Beispiel für die Behebung des Problems ist das Entfernen nachstehender Leerzeichen aus der Datei, die im obigen Code input wird.

(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])) 

Der obige Code funktioniert den Trick:

bearbeiten

Basierend auf Stefan Antwort habe ich den Code geändert immer eine zielgenaue Antwort. Für mich ist es nicht so offensichtlich, dass nach insta/parses eine leere Liste zurückgibt, muss insta/parse aufgerufen werden, um die Fehlerinformationen zu erhalten. Die Verwendung der Analysefehler documentation führt zu besserem Code als oben. Es zeigt, wie die Fehlerinformationen tatsächlich in den Metadaten vorhanden sind und wie sie abgerufen werden können - die Antwort auf diese Frage befindet sich bereits in der Dokumentation!

Antwort

1

Wenn Sie parser selbst am Eingang verwenden, anstatt insta/parses zu durchlaufen, wird eine ziemlich genaue Meldung des Fehlers an der REPL ausgegeben.

Ein Beispiel:

(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" 
Verwandte Themen