lbradstreet / instaparse-cljs

Port of Instaparse to Clojurescript
89 stars 4 forks source link

Parse failures not working properly for later lines #7

Closed aengelberg closed 9 years ago

aengelberg commented 9 years ago

This works properly:

cljs.user=> (def p (insta/parser "S = 'a"))
Error parsing grammar specification:
Parse error at line 1 , column 5 :

S = 'a
    ^
Expected one of:
"!"
"&"
"ε"
"eps"
"EPSILON"
"epsilon"
"Epsilon"
"<"
"("
"{"
"["
#"#\"[^\"\\]*(?:\\.[^\"\\]*)*\""
#"#'[^'\\]*(?:\\.[^'\\]*)*'"
#"\"[^\"\\]*(?:\\.[^\"\\]*)*\""
#"'[^'\\]*(?:\\.[^'\\]*)*'"
"(*"
#"[^, \r\t\n<>(){}\[\]+*?:=|'"#&!;./]+"

     (NO_SOURCE_FILE <eval>:13:0)
     (NO_SOURCE_FILE <eval>:1:0)

This does not:

cljs.user=> (def p (insta/parser "\nS = 'a"))
Error parsing grammar specification:
Parse error at line 2 , column 5 :

    ^
Expected one of:
"!"
"&"
"ε"
"eps"
"EPSILON"
"epsilon"
"Epsilon"
"<"
"("
"{"
"["
#"#\"[^\"\\]*(?:\\.[^\"\\]*)*\""
#"#'[^'\\]*(?:\\.[^'\\]*)*'"
#"\"[^\"\\]*(?:\\.[^\"\\]*)*\""
#"'[^'\\]*(?:\\.[^'\\]*)*'"
"(*"
#"[^, \r\t\n<>(){}\[\]+*?:=|'"#&!;./]+"

     (NO_SOURCE_FILE <eval>:13:0)
     (NO_SOURCE_FILE <eval>:1:0)
aengelberg commented 9 years ago

This may be part of the problem:

cljs.user=> (require '[instaparse.failure :as fail])
nil
cljs.user=> (fail/line-seq "a\nb\nc")
("a" "b" "c")
cljs.user=> (fail/line-seq "a\n\nb")
("a" "b")

line-seq on "a\n\nb" should return a blank line in the middle, but it is skipped over by your partition-by strategy.

aengelberg commented 9 years ago

Perhaps it would be more elegant (and performant) to skip line-seq altogether and write a more straightforward function to get the nth line of the text.

(defn get-line
  [n text]
  (loop [chars (seq (clojure.string/replace text "\r\n" "\n"))
         n n]
    (cond
      (empty? chars) ""
      (= n 1) (apply str (take-while (complement newline-chars?) chars))
      (newline-chars? (first chars)) (recur (next chars) (dec n))
      :else (recur (next chars) n))))
lbradstreet commented 9 years ago

Incorporated your suggested, more elegant, get-line into master. Thanks.