diff --git a/.gitignore b/.gitignore
index 1e9a86e..328b5b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
+/.idea
target
codox
+.DS_Store
*.jar
*.class
.lein*
@@ -7,3 +9,6 @@ codox
\#*
.project
.classpath
+
+/resources
+/out
\ No newline at end of file
diff --git a/project.clj b/project.clj
index 4c8a69e..abe8a2a 100644
--- a/project.clj
+++ b/project.clj
@@ -3,11 +3,23 @@
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:url "https://github.com/blancas/kern"
- :dependencies [[org.clojure/clojure "1.8.0"]]
+ :dependencies [[org.clojure/clojure "1.8.0"]
+ [org.clojure/clojurescript "1.9.854"]]
:source-paths ["src/main/clojure"]
:test-paths ["src/test/clojure"]
:jvm-opts ["-Dfile.encoding=UTF-8"]
:deploy-repositories [["releases" :clojars]]
+ :cljsbuild {:builds {:dev {:source-paths ["src/main/clojure" "src/test/clojure"]
+ :compiler {:main blancas.kern.core
+ :optimizations :none
+ :asset-path "js/out"
+ :output-to "resources/public/js/dev.js"
+ :output-dir "resources/public/js/out"}
+ :figwheel true}
+ :test {:source-paths ["src/main/clojure" "src/test/clojure"]
+ :compiler {:output-to "out/testable.js"
+ :main blancas.kern.runnner
+ :optimizations :none}}}}
:profiles
{:1.3 {:dependencies [[org.clojure/clojure "1.3.0"]]}
:1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]}
@@ -20,8 +32,14 @@
[org.clojure/tools.macro "0.1.2"]
[org.clojure/tools.trace "0.7.9"]
[org.clojure/tools.nrepl "0.2.11"]
- [midje "1.8.3" :exclusions [org.clojure/clojure]]
+ [bultitude "0.2.6"] [org.clojure/core.match "0.3.0-alpha5"]
[criterium "0.4.4"]
- [jline "1.0"]]
- :plugins [[codox "0.9.4"][lein-midje "3.2"]]
- :codox {:source-paths ["src/main/clojure"] :output-path "codox"}}})
+ [jline "1.0"]
+ [doo "0.1.7"]]
+ :plugins [[codox "0.9.4"]
+ [lein-doo "0.1.7"]
+ [lein-figwheel "0.5.12"]]
+ :codox {:source-paths ["src/main/clojure"] :output-path "codox"}
+ :doo {:build "test"
+ :alias {:browsers [:chrome :firefox]
+ :all [:browsers :headless]}}}})
diff --git a/src/main/clojure/blancas/kern/char.clj b/src/main/clojure/blancas/kern/char.clj
new file mode 100644
index 0000000..659acfb
--- /dev/null
+++ b/src/main/clojure/blancas/kern/char.clj
@@ -0,0 +1,38 @@
+(ns blancas.kern.char)
+
+(defn is-letter [^Character c]
+ (Character/isLetter c))
+
+
+(defn is-lower-case [^Character c]
+ (Character/isLowerCase c))
+
+
+(defn is-upper-case [^Character c]
+ (Character/isUpperCase c))
+
+
+(defn is-white-space [^Character c]
+ (Character/isWhitespace c))
+
+
+(defn is-space [^Character c]
+ (.equals c \space))
+
+
+(defn is-space [^Character c]
+ (.equals c \space))
+
+
+(defn is-tab [^Character c]
+ (.equals c \tab))
+
+
+(defn is-digit [^Character c]
+ (Character/isDigit c))
+
+(defn is-letter-or-digit [^Character c]
+ (Character/isLetterOrDigit c))
+
+(defn upper-case [^Character c]
+ (Character/toUpperCase c))
\ No newline at end of file
diff --git a/src/main/clojure/blancas/kern/char.cljs b/src/main/clojure/blancas/kern/char.cljs
new file mode 100644
index 0000000..7a33077
--- /dev/null
+++ b/src/main/clojure/blancas/kern/char.cljs
@@ -0,0 +1,35 @@
+(ns blancas.kern.char
+ (:require [clojure.string :as str]))
+
+(defn is-letter [c]
+ (re-find #"^[a-zA-Z]$" c))
+
+
+(defn is-lower-case [c]
+ (re-find #"^[a-z]$" c))
+
+
+(defn is-upper-case [c]
+ (re-find #"^[A-Z]$" c))
+
+
+(defn is-white-space [c]
+ (re-find #"^\s$" c))
+
+
+(defn is-space [c]
+ (= c \space))
+
+
+(defn is-tab [c]
+ (= c \tab))
+
+
+(defn is-digit [c]
+ (re-find #"^[0-9]$" c))
+
+
+(defn is-letter-or-digit [c]
+ (re-find #"^[a-zA-Z0-9]$" c))
+
+(defn upper-case [c] (str/upper-case c))
\ No newline at end of file
diff --git a/src/main/clojure/blancas/kern/core.clj b/src/main/clojure/blancas/kern/core.cljc
similarity index 74%
rename from src/main/clojure/blancas/kern/core.clj
rename to src/main/clojure/blancas/kern/core.cljc
index 72f2991..11164d4 100644
--- a/src/main/clojure/blancas/kern/core.clj
+++ b/src/main/clojure/blancas/kern/core.cljc
@@ -6,7 +6,8 @@
;; the terms of this license.
;; You must not remove this notice, or any other, from this software.
-(ns ^{:doc "The core Kern library.
+(ns
+ ^{:doc "The core Kern library.
Kern is a library of parser combinators for Clojure. It is useful for
implementing recursive-descent parsers based on predictive LL(1) grammars
@@ -28,49 +29,46 @@ http://eprints.nottingham.ac.uk/237/1/monparsing.pdf
William H. Burge
Recursive Programming Techniques
Addison-Wesley, 1975"
- :author "Armando Blancas"}
+ :author "Armando Blancas"}
blancas.kern.core
(:refer-clojure :exclude [cat])
- (:require [blancas.kern.i18n :refer :all]
- [clojure.string :refer [join]]
- [clojure.java.io :refer [reader]]
+ (:require [blancas.kern.i18n :refer [fmt i18n di18n]]
+ [blancas.kern.char :as char]
+ [clojure.string :refer [join] :as str]
[clojure.pprint :refer [pprint]]))
-(defmacro def-
- "Same as def, yielding a private def."
- [name & more]
- (list* `def (with-meta name (assoc (meta name) :private true)) more))
-
-
(defmacro defn*
"Same as def, yielding a dynamic def."
[name & more]
(list* `defn (with-meta name (assoc (meta name) :dynamic true)) more))
-(defmacro fwd
- "Delays the evaluation of a parser that was forward (declare)d and
- it has not been defined yet. For use in (def)s of no-arg parsers,
- since the parser expression evaluates immediately."
- [p]
- (let [x (gensym)]
- `(fn [~x] (~p ~x))))
+#?(:clj
+ (defmacro fwd
+ "Delays the evaluation of a parser that was forward (declare)d and
+it has not been defined yet. For use in (def)s of no-arg parsers,
+since the parser expression evaluates immediately."
+ [p]
+ (let [x (gensym)]
+ `(fn [~x] (~p ~x)))))
-(defn char-seq
- "Returns characters from rdr as a lazy sequence.
- rdr must implement java.io.Reader"
- [^java.io.Reader rdr]
- (let [c (.read rdr)]
- (when-not (neg? c)
- (cons (char c) (lazy-seq (char-seq rdr))))))
+#?(:clj
+ (defn char-seq
+ "Returns characters from rdr as a lazy sequence.
+ rdr must implement java.io.Reader"
+ [^java.io.Reader rdr]
+ (let [c (.read rdr)]
+ (when-not (neg? c)
+ (cons (char c) (lazy-seq (char-seq rdr)))))))
-(defn f->s
- "Gets a character sequence from a file-like object."
- ([f] (slurp f))
- ([f e] (slurp f :encoding e)))
+#?(:clj
+ (defn f->s
+ "Gets a character sequence from a file-like object."
+ ([f] (slurp f))
+ ([f e] (slurp f :encoding e))))
(defn member?
@@ -95,22 +93,22 @@ Addison-Wesley, 1975"
;; Error types.
-(def- err-system 0) ;; Used in satisfy for specific unexpected input.
-(def- err-unexpect 1) ;; Used on any unexpected input to show a message.
-(def- err-expect 2) ;; Used to show a message of what's expected.
-(def- err-message 3) ;; Used for any kind of message from client code.
+(def err-system 0) ;; Used in satisfy for specific unexpected input.
+(def err-unexpect 1) ;; Used on any unexpected input to show a message.
+(def err-expect 2) ;; Used to show a message of what's expected.
+(def err-message 3) ;; Used for any kind of message from client code.
;; Keeps the position of the input:
;; src - a string that identifies the source of input
;; line - the line into the input stream.
;; col - the column into the line.
(defrecord PPosition [src line col]
- Comparable
- (compareTo [this other]
- (let [result (compare line (:line other))]
- (if (zero? result)
- (compare col (:col other))
- result))))
+ #?(:clj Comparable :cljs IComparable)
+ (#?(:clj compareTo :cljs -compare) [this other]
+ (let [result (compare line (:line other))]
+ (if (zero? result)
+ (compare col (:col other))
+ result))))
;; A PMessage consists of:
;; type - One of the error types listed above.
@@ -133,67 +131,67 @@ Addison-Wesley, 1975"
(defrecord PState [input pos value ok empty user error])
-(defn- make-pos
+(defn make-pos
"Makes a position record."
([src] (make-pos src 1 1))
([src ln col] (->PPosition (or src "") ln col)))
-(defn- ^:dynamic char-pos
+(defn ^:dynamic char-pos
"Computes the new position of the character c."
[pos c]
(cond (= c \newline) (assoc pos :col 1 :line (inc (:line pos)))
- (= c \tab) (assoc pos :col (+ (:col pos) *tab-width*))
- :else (assoc pos :col (inc (:col pos)))))
+ (= c \tab) (assoc pos :col (+ (:col pos) *tab-width*))
+ :else (assoc pos :col (inc (:col pos)))))
-(defn- ^:dynamic str-pos
+(defn ^:dynamic str-pos
"Computes the stream position after the character sequence cs."
[pos cs] (if (empty? cs) pos (recur (char-pos pos (first cs)) (rest cs))))
-(defn- make-err-system
+(defn make-err-system
"Makes a message of type err-system."
[pos text] (->PError pos (list (->PMessage err-system text))))
-(defn- make-err-unexpect
+(defn make-err-unexpect
"Makes a message of type err-unexpect."
[pos text] (->PError pos (list (->PMessage err-unexpect text))))
-(defn- make-err-expect
+(defn make-err-expect
"Makes a message of type err-expect."
[pos text] (->PError pos (list (->PMessage err-expect text))))
-(defn- make-err-message
+(defn make-err-message
"Makes a message of type err-message."
[pos text] (->PError pos (list (->PMessage err-message text))))
-(defn- get-msg
+(defn get-msg
"Get the text from message types system, unexpect, and message."
[pmsg]
(let [type (:type pmsg)
- text (-> pmsg :text force)]
- (cond (= type err-system) (fmt :unexpected text)
- (= type err-unexpect) (fmt :unexpected text)
- (= type err-message) text)))
+ text (-> pmsg :text force)]
+ (cond (= type err-system) (fmt :unexpected text)
+ (= type err-unexpect) (fmt :unexpected text)
+ (= type err-message) text)))
-(defn- get-msg-expect
+(defn get-msg-expect
"Get the text from a list of messages of type expect."
[lst]
(let [show (fn [xs]
- (let [comma-sep (join (i18n :comma) (butlast xs))
- or-last (fmt :or (last xs))]
- (str comma-sep or-last)))
- opts (map (comp force :text) lst)
- cnt (count opts)]
+ (let [comma-sep (join (i18n :comma) (butlast xs))
+ or-last (fmt :or (last xs))]
+ (str comma-sep or-last)))
+ opts (map (comp force :text) lst)
+ cnt (count opts)]
(fmt :expecting (if (= cnt 1) (first opts) (show opts)))))
-
+
(defn- get-msg-list
"Gets the text of error messages as a list."
[{msgs :msgs}]
@@ -209,10 +207,10 @@ Addison-Wesley, 1975"
(reduce #(conj %1 (get-msg %2)) [] lst)))))
-(defn- get-msg-str
+(defn get-msg-str
"Gets the text of error messages separated by \\n."
[err]
- (let [eol (System/getProperty "line.separator")]
+ (let [eol #?(:clj (System/getProperty "line.separator") :cljs "\n")]
(join eol (get-msg-list err))))
@@ -220,12 +218,13 @@ Addison-Wesley, 1975"
"Merges errors from two state records."
[{e1 :error} {e2 :error}]
(cond (and (nil? e1) (nil? e2)) nil
- (nil? e1) e2
- (nil? e2) e1
- :else (let [r (compare (:pos e1) (:pos e2))]
- (cond (zero? r) (update-in e1 [:msgs] concat (:msgs e2))
- (pos? r) e1
- :else e2))))
+ (nil? e1) e2
+ (nil? e2) e1
+ :else (let [pos1 (:pos e1) pos2 (:pos e2)
+ r (compare [(:line pos1) (:col pos1)] [(:line pos2) (:col pos2)])]
+ (cond (zero? r) (update-in e1 [:msgs] concat (:msgs e2))
+ (pos? r) e1
+ :else e2))))
(defn- cat
@@ -241,12 +240,12 @@ Addison-Wesley, 1975"
"Replace expect errors with expecting msg."
[msg s]
(letfn [(not-ex [{type :type}]
- (not (= type err-expect)))
- (update [lst err]
- (cons err (filter not-ex lst)))]
+ (not (= type err-expect)))
+ (update [lst err]
+ (cons err (filter not-ex lst)))]
(let [m (->PMessage err-expect msg)]
(update-in s [:error :msgs] update m))))
-
+
;; +-------------------------------------------------------------+
;; | Public supporting functions. |
@@ -318,10 +317,10 @@ Addison-Wesley, 1975"
(let [stm (:input s)]
(if (empty? stm)
(unexpected (i18n :eof) s)
- (let [c (first stm)]
- (if (pred c)
- (->PState (rest stm) (char-pos (:pos s) c) c true false (:user s) nil)
- (unexpected-input (with-out-str (pr c)) s)))))))
+ (let [c (first stm)]
+ (if (pred c)
+ (->PState (rest stm) (char-pos (:pos s) c) c true false (:user s) nil)
+ (unexpected-input (with-out-str (pr c)) s)))))))
;; +-------------------------------------------------------------+
@@ -359,9 +358,9 @@ Addison-Wesley, 1975"
(let [s2 (p s)]
(if (failed-empty? s2)
(let [s3 (q s)]
- (if (:ok s3)
- s3
- (assoc s3 :error (merge-err s2 s3))))
+ (if (:ok s3)
+ s3
+ (assoc s3 :error (merge-err s2 s3))))
s2))))
([p q & more]
(reduce <|> (list* p q more))))
@@ -376,16 +375,16 @@ Addison-Wesley, 1975"
(fn [s]
(let [s1 (p s)]
(if (:ok s1)
- (let [s2 ((f (:value s1)) s1)
- s3 (assoc s2 :empty (and (:empty s1) (:empty s2)))]
- (if (:ok s3)
- s3
- (assoc s3 :error (merge-err s1 s3))))
- s1))))
-
+ (let [s2 ((f (:value s1)) s1)
+ s3 (assoc s2 :empty (and (:empty s1) (:empty s2)))]
+ (if (:ok s3)
+ s3
+ (assoc s3 :error (merge-err s1 s3))))
+ s1))))
-(defmacro bind
- "Expands into nested >>= forms and a function body. The pattern:
+#?(:clj
+ (defmacro bind
+ "Expands into nested >>= forms and a function body. The pattern:
(>>= p1 (fn [v1]
(>>= p2 (fn [v2]
@@ -395,11 +394,11 @@ Addison-Wesley, 1975"
can be more conveniently be written as:
(bind [v1 p1 v2 p2 ...] (return (f v1 v2 ...)))"
- [[& bindings] & body]
- (let [[sym p] (take 2 bindings)]
- (if (= 2 (count bindings))
- `(>>= ~p (fn [~sym] ~@body))
- `(>>= ~p (fn [~sym] (bind ~(drop 2 bindings) ~@body))))))
+ [[& bindings] & body]
+ (let [[sym p] (take 2 bindings)]
+ (if (= 2 (count bindings))
+ `(>>= ~p (fn [~sym] ~@body))
+ `(>>= ~p (fn [~sym] (bind ~(drop 2 bindings) ~@body)))))))
(defn >>
@@ -486,8 +485,8 @@ Addison-Wesley, 1975"
(fn [s]
(let [st (p s)]
(if (failed-empty? st)
- (reply x s)
- st))))
+ (reply x s)
+ st))))
(defn skip
@@ -536,7 +535,7 @@ Addison-Wesley, 1975"
of sep; returns the results of p in a vector."
[sep p] (many (<< p sep)))
-
+
(defn end-by1
"Parses p one or more times, separated and ended by applications
of sep; returns the results of p in a vector."
@@ -549,7 +548,7 @@ Addison-Wesley, 1975"
"Parses p one or more times separated, and optionally ended by sep;
collects the results in a vector."
[sep p]
- (>>= p (fn [x]
+ (>>= p (fn [x]
(<|> (>>= (>> sep (sep-end-by sep p)) (fn [y] (return (reduce conj [x] y))))
(return [x])))))
@@ -573,14 +572,14 @@ Addison-Wesley, 1975"
(apply <*> (repeat n p))
(return [])))
-
+
(defn look-ahead
"Applies p and returns the result; it consumes no input."
[p]
(fn [s]
(let [st (p s)]
(assoc s :value (:value st)))))
-
+
(defn predict
"Applies p; if it succeeds it consumes no input."
@@ -604,7 +603,7 @@ Addison-Wesley, 1975"
Returns the results in a vector."
[p end]
(letfn [(scan [] (<|> (>> end (return []))
- (>>= p (fn [x] (>>= (scan) (fn [y] (return (reduce conj [x] y))))))))]
+ (>>= p (fn [x] (>>= (scan) (fn [y] (return (reduce conj [x] y))))))))]
(scan)))
@@ -638,80 +637,92 @@ Addison-Wesley, 1975"
(def letter
"Parses a letter."
- (> (satisfy (fn [^Character c] (Character/isLetter c)))
+ (> (satisfy char/is-letter)
(di18n :letter)))
(def lower
"Parses a lower-case letter."
- (> (satisfy (fn [^Character c] (Character/isLowerCase c)))
+ (> (satisfy char/is-lower-case)
(di18n :lower)))
(def upper
"Parses an upper-case letter."
- (> (satisfy (fn [^Character c] (Character/isUpperCase c)))
+ (> (satisfy char/is-upper-case)
(di18n :upper)))
(def white-space
"Parses a whitespace character."
- (> (satisfy (fn [^Character c] (Character/isWhitespace c)))
+ (> (satisfy char/is-white-space)
(di18n :whitespace)))
(def space
"Parses the space character."
- (> (satisfy (fn [^Character c] (.equals c \space)))
+ (> (satisfy char/is-space)
(di18n :space)))
(def tab
"Parses the tab character."
- (> (satisfy (fn [^Character c] (.equals c \tab)))
+ (> (satisfy char/is-tab)
(di18n :tab)))
(def digit
"Parses a digit."
- (> (satisfy (fn [^Character c] (Character/isDigit c)))
+ (> (satisfy char/is-digit)
(di18n :digit)))
(def hex-digit
"Parses a hexadecimal digit."
(let [hex (set "0123456789abcdefABCDEF")]
- (> (satisfy (fn [^Character c] (hex c)))
- (di18n :hex-digit))))
+ (> (satisfy (fn [c] (hex c)))
+ (di18n :hex-digit))))
(def oct-digit
"Parses an octal digit."
(let [oct (set "01234567")]
- (> (satisfy (fn [^Character c] (oct c)))
- (di18n :oct-digit))))
+ (> (satisfy (fn [c] (oct c)))
+ (di18n :oct-digit))))
(def alpha-num
"Parses a letter or digit."
- (> (satisfy (fn [^Character c] (Character/isLetterOrDigit c)))
+ (> (satisfy char/is-letter-or-digit)
(di18n :alpha-num)))
-(defn sym*
- "Parses a single symbol x (a character)."
- [^Character x]
- (> (satisfy (fn [^Character c] (.equals c x)))
- (with-out-str (pr x))))
-
+#?(:clj (defn sym*
+ "Parses a single symbol x (a character)."
+ [^Character x]
+ (> (satisfy (fn [^Character c] (.equals c x)))
+ (with-out-str (pr x))))
+ :cljs (defn sym*
+ "Parses a single symbol x (a character)."
+ [x]
+ (> (satisfy (fn [c] (= c x)))
+ (with-out-str (pr x)))))
+
+#?(:clj (defn sym-
+ "Parses a single symbol x (a character); not case-sensitive."
+ [^Character x]
+ (> (>> (satisfy (fn [^Character c]
+ (= (Character/toLowerCase x) (Character/toLowerCase c))))
+ (return x))
+ (with-out-str (pr x))))
+ :cljs (defn sym-
+ "Parses a single symbol x (a character); not case-sensitive."
+ [x]
+ (> (>> (satisfy (fn [c]
+ (= (str/lower-case x) (str/lower-case c))))
+ (return x))
+ (with-out-str (pr x)))))
-(defn sym-
- "Parses a single symbol x (a character); not case-sensitive."
- [^Character x]
- (> (>> (satisfy (fn [^Character c]
- (= (Character/toLowerCase x) (Character/toLowerCase c))))
- (return x))
- (with-out-str (pr x))))
(defn token*
@@ -723,12 +734,12 @@ Addison-Wesley, 1975"
(if (:ok st)
(assoc st :value xs)
(let [in (:input s)]
- (if (seq in)
+ (if (seq in)
(unexpected (join (take (count xs) in)) s)
- (assoc s :value nil :ok false :empty true :error (:error st)))))))
+ (assoc s :value nil :ok false :empty true :error (:error st)))))))
(str xs)))
- ([xs & more]
- (apply <|> (map token* (cons xs more)))))
+ ([xs & more]
+ (apply <|> (map token* (cons xs more)))))
(defn token-
@@ -741,9 +752,9 @@ Addison-Wesley, 1975"
(if (:ok st)
(assoc st :value xs)
(let [in (:input s)]
- (if (seq in)
+ (if (seq in)
(unexpected (join (take (count xs) in)) s)
- (assoc s :value nil :ok false :empty true :error (:error st)))))))
+ (assoc s :value nil :ok false :empty true :error (:error st)))))))
(str xs)))
([xs & more]
(apply <|> (map token- (cons xs more)))))
@@ -769,14 +780,14 @@ Addison-Wesley, 1975"
(apply <|> (map #(word- letter %) (cons cs more)))))
+
(defn one-of*
"Succeeds if the next character is in the supplied string."
- [^String cs] (satisfy #(>= (.indexOf cs (int %)) 0)))
-
+ [cs] (satisfy #(str/index-of cs %)))
(defn none-of*
"Succeeds if the next character is not in the supplied string."
- [^String cs] (satisfy #(neg? (.indexOf cs (int %)))))
+ [cs] (satisfy #(nil? (str/index-of cs %))))
(def new-line*
@@ -834,7 +845,8 @@ Addison-Wesley, 1975"
"Parses a decimal integer delimited by any character that
is not a decimal digit."
(> (>>= (<+> (many1 digit))
- (fn [x] (return (read-string (rmvz x)))))
+ (fn [x] (return #?(:clj (read-string (rmvz x))
+ :cljs (js/eval (rmvz x))))))
(di18n :dec-lit)))
@@ -842,7 +854,8 @@ Addison-Wesley, 1975"
"Parses an octal integer delimited by any character that
is not an octal digit."
(> (>>= (<+> (many1 oct-digit))
- (fn [x] (return (read-string (str "0" x)))))
+ (fn [x] (return #?(:clj (read-string (str "0" x))
+ :cljs (js/eval (str "0" x))))))
(di18n :oct-lit)))
@@ -850,7 +863,8 @@ Addison-Wesley, 1975"
"Parses a hex integer delimited by any character that
is not a hex digit."
(> (>>= (<+> (many1 hex-digit))
- (fn [x] (return (read-string (str "0x" x)))))
+ (fn [x] (return #?(:clj (read-string (str "0x" x))
+ :cljs (js/eval (str "0x" x))))))
(di18n :hex-lit)))
@@ -860,8 +874,9 @@ Addison-Wesley, 1975"
digit. It cannot start with a period; the first period
found must be followed by at least one digit."
(> (>>= (<+> (many1 digit)
- (option ".0" (<*> (sym* \.) (many1 digit))))
- (fn [x] (return (read-string x))))
+ (option ".0" (<*> (sym* \.) (many1 digit))))
+ (fn [x] (return #?(:clj (read-string x)
+ :cljs (js/eval x)))))
(di18n :float-lit)))
@@ -939,10 +954,10 @@ Addison-Wesley, 1975"
[s]
(let [err (:error s)
pos (:pos err)
- src (let [l (:src pos)] (if (empty? l) "" (str l " ")))
- ln (:line pos)
- col (:col pos)]
- (printf (i18n :err-pos) src ln col)
+ src (let [l (:src pos)] (if (empty? l) "" (str l " ")))
+ ln (:line pos)
+ col (:col pos)]
+ (print (fmt :err-pos src ln col))
(println (get-msg-str err))))
@@ -953,12 +968,12 @@ Addison-Wesley, 1975"
([p cs] (run p cs nil nil))
([p cs src] (run p cs src nil))
([p cs src us]
- (let [s (parse p cs src us)]
- (if (:ok s)
- (pprint (:value s))
- (print-error s))
- (if-let [us (:user s)]
- (pprint us)))))
+ (let [s (parse p cs src us)]
+ (if (:ok s)
+ (pprint (:value s))
+ (print-error s))
+ (if-let [us (:user s)]
+ (pprint us)))))
(defn run*
@@ -969,28 +984,28 @@ Addison-Wesley, 1975"
([p cs src us] (pprint (parse p cs src us))))
-(defn parse-file
- "Parses a file; takes an optional encoding and user state,
- which default to utf-8 and nil. Returns a PState record."
- ([p f] (parse-file p f "UTF-8" nil))
- ([p f en] (parse-file p f en nil))
- ([p f en us] (parse p (slurp f :encoding en) f us)))
+#?(:clj (defn parse-file
+ "Parses a file; takes an optional encoding and user state,
+ which default to utf-8 and nil. Returns a PState record."
+ ([p f] (parse-file p f "UTF-8" nil))
+ ([p f en] (parse-file p f en nil))
+ ([p f en us] (parse p (slurp f :encoding en) f us))))
-(defn runf
- "For testing, e.g. at the REPL, with input from files.
- Prints the results."
- ([p f] (runf p f "UTF-8" nil))
- ([p f en] (runf p f en nil))
- ([p f en us] (run p (slurp f :encoding en) f us)))
+#?(:clj (defn runf
+ "For testing, e.g. at the REPL, with input from files.
+ Prints the results."
+ ([p f] (runf p f "UTF-8" nil))
+ ([p f en] (runf p f en nil))
+ ([p f en us] (run p (slurp f :encoding en) f us))))
-(defn runf*
- "For testing, e.g. at the REPL, with input from files.
- Pretty-prints the results."
- ([p f] (runf* p f "UTF-8" nil))
- ([p f en] (runf* p f en nil))
- ([p f en us] (pprint (parse-file p f en us))))
+#?(:clj (defn runf*
+ "For testing, e.g. at the REPL, with input from files.
+ Pretty-prints the results."
+ ([p f] (runf* p f "UTF-8" nil))
+ ([p f en] (runf* p f en nil))
+ ([p f en us] (pprint (parse-file p f en us)))))
;; +-------------------------------------------------------------+
@@ -1000,10 +1015,10 @@ Addison-Wesley, 1975"
;; +-------------------------------------------------------------+
-(defn- char-pos-x [x _] x)
-(defn- str-pos-x [x _] x)
+(defn- char-pos-x [x _] x)
+(defn- str-pos-x [x _] x)
(defn- merge-err-x [_ _] nil)
-(defn- set-ex-x [_ x] x)
+(defn- set-ex-x [_ x] x)
(defn parse-data
@@ -1013,22 +1028,23 @@ Addison-Wesley, 1975"
([p cs] (parse-data p cs nil nil))
([p cs src] (parse-data p cs src nil))
([p cs src us]
- (binding [char-pos char-pos-x
- str-pos str-pos-x
- merge-err merge-err-x
- set-ex set-ex-x]
- (parse p cs src us))))
-
-
-(defn parse-data-file
- "Works like (parse-file) but with error diagnostics disabled for
- better performance. It's intended for data files that can be
- assumed to be correct or its diagnosis postponed."
- ([p f] (parse-data-file p f "UTF-8" nil))
- ([p f en] (parse-data-file p f en nil))
- ([p f en us]
- (binding [char-pos char-pos-x
- str-pos str-pos-x
- merge-err merge-err-x
- set-ex set-ex-x]
- (parse-file p f en us))))
+ (binding [char-pos char-pos-x
+ str-pos str-pos-x
+ merge-err merge-err-x
+ set-ex set-ex-x]
+ (parse p cs src us))))
+
+
+#?(:clj
+ (defn parse-data-file
+ "Works like (parse-file) but with error diagnostics disabled for
+ better performance. It's intended for data files that can be
+ assumed to be correct or its diagnosis postponed."
+ ([p f] (parse-data-file p f "UTF-8" nil))
+ ([p f en] (parse-data-file p f en nil))
+ ([p f en us]
+ (binding [char-pos char-pos-x
+ str-pos str-pos-x
+ merge-err merge-err-x
+ set-ex set-ex-x]
+ (parse-file p f en us)))))
diff --git a/src/main/clojure/blancas/kern/expr.clj b/src/main/clojure/blancas/kern/expr.cljc
similarity index 81%
rename from src/main/clojure/blancas/kern/expr.clj
rename to src/main/clojure/blancas/kern/expr.cljc
index 960eced..09e5961 100644
--- a/src/main/clojure/blancas/kern/expr.clj
+++ b/src/main/clojure/blancas/kern/expr.cljc
@@ -9,8 +9,10 @@
(ns ^{:doc "Support for the evaluation of expressions."
:author "Armando Blancas"}
blancas.kern.expr
- (:use [blancas.kern core i18n]
- [blancas.kern.lexer.c-style]))
+ (:require [blancas.kern.core :as k :refer [<|> return >>]]
+ [blancas.kern.i18n :as i18n]
+ [blancas.kern.lexer.c-style :as c-style])
+ #?(:cljs (:require-macros [blancas.kern.core :as k])))
;; +-------------------------------------------------------------+
@@ -23,9 +25,9 @@
another instance of p, then applies the operator on both values.
The operator associates to the left."
[p op]
- (letfn [(rest [a] (<|> (bind [f op b p] (rest (f a b)))
+ (letfn [(rest [a] (<|> (k/bind [f op b p] (rest (f a b)))
(return a)))]
- (bind [a p] (rest a))))
+ (k/bind [a p] (rest a))))
(defn chainl
@@ -39,8 +41,8 @@
calls itself to compute the rest of the expression, then it applies
the operator on both values. The operator associates to the right."
[p op]
- (bind [a p]
- (<|> (bind [f op b (chainr1 p op)] (return (f a b)))
+ (k/bind [a p]
+ (<|> (k/bind [f op b (chainr1 p op)] (return (f a b)))
(return a))))
@@ -55,10 +57,10 @@
another p, then makes an AST node with the operator on both values.
The operator associates to the left."
[tok p op]
- (letfn [(rest [a] (<|> (bind [f op b p]
+ (letfn [(rest [a] (<|> (k/bind [f op b p]
(rest {:token tok :op f :left a :right b}))
(return a)))]
- (bind [a p] (rest a))))
+ (k/bind [a p] (rest a))))
(defn chainl*
@@ -74,8 +76,8 @@
an AST node with the operator on both values. The operator associates
to the right."
[tok p op]
- (bind [a p]
- (<|> (bind [f op b (chainr1* tok p op)]
+ (k/bind [a p]
+ (<|> (k/bind [f op b (chainr1* tok p op)]
(return {:token tok :op f :left a :right b}))
(return a))))
@@ -91,8 +93,8 @@
"Parses zero or more operators op before an operand p. It applies
the parsed functions to the operand in reverse order of parsing."
[p op]
- (<|> (bind [f op a (prefix1 p op)] (return (f a)))
- (bind [a p] (return a))))
+ (<|> (k/bind [f op a (prefix1 p op)] (return (f a)))
+ (k/bind [a p] (return a))))
(defn prefix
@@ -106,8 +108,8 @@
AST node for each parsed function, where the operand is a node
for a value or a further application of a prefix operator."
[tok p op]
- (<|> (bind [f op a (prefix1* tok p op)] (return {:token tok :op f :right a}))
- (bind [a p] (return a))))
+ (<|> (k/bind [f op a (prefix1* tok p op)] (return {:token tok :op f :right a}))
+ (k/bind [a p] (return a))))
(defn prefix*
@@ -120,9 +122,9 @@
"Parses an operand p followed by zero or more operators. It applies the
parsed functions to the operand or the result of a previous application."
[p op]
- (letfn [(rest [a] (<|> (bind [f op] (rest (f a)))
+ (letfn [(rest [a] (<|> (k/bind [f op] (rest (f a)))
(return a)))]
- (bind [a p] (rest a))))
+ (k/bind [a p] (rest a))))
(defn postfix
@@ -136,9 +138,9 @@
an AST node for each parsed function, where the operand is a node
for a value or a previous application of a postfix operator."
[tok p op]
- (letfn [(rest [a] (<|> (bind [f op] (rest {:token tok :op f :left a}))
+ (letfn [(rest [a] (<|> (k/bind [f op] (rest {:token tok :op f :left a}))
(return a)))]
- (bind [a p] (rest a))))
+ (k/bind [a p] (rest a))))
(defn postfix*
@@ -154,38 +156,38 @@
(def pow-op
"Parses the POW operator."
- (>> (sym \^) (return #(Math/pow %1 %2))))
+ (>> (c-style/sym \^) (return #(Math/pow %1 %2))))
(def uni-op
"Unary prefix operator: logical not or numeric minus."
- (bind [op (one-of "!-")]
+ (k/bind [op (c-style/one-of "!-")]
(return ({\! not \- -} op))))
(def mul-op
"Multiplicative operator: multiplication, division, or modulo."
- (bind [op (one-of "*/%")]
+ (k/bind [op (c-style/one-of "*/%")]
(return ({\* * \/ quot \% mod} op))))
(def add-op
"Additive operator: addition or subtraction."
- (bind [op (one-of "+-")]
+ (k/bind [op (c-style/one-of "+-")]
(return ({\+ + \- -} op))))
(def rel-op
"Parses one of the relational operators."
- (bind [op (token "==" "!=" ">=" "<=" ">" "<")]
+ (k/bind [op (c-style/token "==" "!=" ">=" "<=" ">" "<")]
(return ({"==" = "!=" not= ">=" >= "<=" <= ">" > "<" <} op))))
(def and-op
"Parses the logical AND operator."
- (>> (token "&&") (return #(and %1 %2))))
+ (>> (c-style/token "&&") (return #(and %1 %2))))
(def or-op
"Parses the logical OR operator."
- (>> (token "||") (return #(or %1 %2))))
+ (>> (c-style/token "||") (return #(or %1 %2))))
diff --git a/src/main/clojure/blancas/kern/i18n.clj b/src/main/clojure/blancas/kern/i18n.clj
deleted file mode 100644
index d256b23..0000000
--- a/src/main/clojure/blancas/kern/i18n.clj
+++ /dev/null
@@ -1,80 +0,0 @@
-;; Copyright (c) 2013 Armando Blancas. All rights reserved.
-;; The use and distribution terms for this software are covered by the
-;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-;; which can be found in the file epl-v10.html at the root of this distribution.
-;; By using this software in any fashion, you are agreeing to be bound by
-;; the terms of this license.
-;; You must not remove this notice, or any other, from this software.
-
-(ns ^{:doc "Support for a simple i18n scheme."
- :author "Armando Blancas"}
- blancas.kern.i18n)
-
-
-(def ^:private default
- { :unexpected "unexpected %s"
- :expecting "expecting %s"
- :comma ", "
- :or " or %s"
- :err-pos "%sline %d column %d\n"
- :eof "end of input"
- :letter "letter"
- :lower "lowercase letter"
- :upper "uppercase letter"
- :whitespace "whitespace"
- :space "space"
- :new-line "new line"
- :tab "tab"
- :digit "digit"
- :hex-digit "hexadecimal digit"
- :oct-digit "octal digit"
- :alpha-num "letter or digit"
- :end-comment "end of comment"
- :char-lit "character literal"
- :end-char "end of character literal"
- :esc-code-b "escaped code: b, t, n, f, r, ', \\"
- :esc-code-c "escaped code: b, t, n, f, r, ', \\, ?, a, v, 0, ooo, uhhhh, xhh"
- :esc-code-j "escaped code: b, t, n, f, r, ', \\, ooo, hhhh"
- :esc-code-h "escaped code: b, t, n, f, r, ', \\, ?, a, v, 0, nnn, onnn, xnnnn"
- :string-lit "string literal"
- :end-string "end of string literal"
- :end-of "end of "
- :dec-lit "decimal literal"
- :oct-lit "octal literal"
- :hex-lit "hex literal"
- :float-lit "floating-point literal"
- :reserved "%s is a reserved name"
- })
-
-
-(def ^:private text (atom default))
-
-
-(defn i18n-merge
- "Merges m into the text map for customization."
- [m] (swap! text merge m))
-
-
-(defn i18n
- "Gets or sets the value for the supplied key."
- ([k] (k (deref text)))
- ([k v] (swap! text assoc k v)))
-
-
-(defn fmt
- "Formats a string with a key and more arguments."
- [k & more]
- (apply format (i18n k) more))
-
-
-(defn di18n
- "Returns a Delay instance with the value for the supplied key.
- Useful in (def)'ed expressions that evaluate too soon."
- [k] (delay (k (deref text))))
-
-
-(defn dfmt
- "Returns a Delay instance with a string formatted with a key and more
- arguments. Useful in (def)'ed expressions that evaluate too soon."
- [k & more]
- (delay (apply format (i18n k) more)))
diff --git a/src/main/clojure/blancas/kern/i18n.cljc b/src/main/clojure/blancas/kern/i18n.cljc
new file mode 100644
index 0000000..054fd1b
--- /dev/null
+++ b/src/main/clojure/blancas/kern/i18n.cljc
@@ -0,0 +1,83 @@
+;; Copyright (c) 2013 Armando Blancas. All rights reserved.
+;; The use and distribution terms for this software are covered by the
+;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this distribution.
+;; By using this software in any fashion, you are agreeing to be bound by
+;; the terms of this license.
+;; You must not remove this notice, or any other, from this software.
+
+(ns ^{:doc "Support for a simple i18n scheme."
+ :author "Armando Blancas"}
+ blancas.kern.i18n
+ #?(:cljs (:require
+ [goog.string :refer [format]]
+ [goog.string.format])))
+
+
+(def ^:private default
+ { :unexpected "unexpected %s"
+ :expecting "expecting %s"
+ :comma ", "
+ :or " or %s"
+ :err-pos "%sline %d column %d\n"
+ :eof "end of input"
+ :letter "letter"
+ :lower "lowercase letter"
+ :upper "uppercase letter"
+ :whitespace "whitespace"
+ :space "space"
+ :new-line "new line"
+ :tab "tab"
+ :digit "digit"
+ :hex-digit "hexadecimal digit"
+ :oct-digit "octal digit"
+ :alpha-num "letter or digit"
+ :end-comment "end of comment"
+ :char-lit "character literal"
+ :end-char "end of character literal"
+ :esc-code-b "escaped code: b, t, n, f, r, ', \\"
+ :esc-code-c "escaped code: b, t, n, f, r, ', \\, ?, a, v, 0, ooo, uhhhh, xhh"
+ :esc-code-j "escaped code: b, t, n, f, r, ', \\, ooo, hhhh"
+ :esc-code-h "escaped code: b, t, n, f, r, ', \\, ?, a, v, 0, nnn, onnn, xnnnn"
+ :string-lit "string literal"
+ :end-string "end of string literal"
+ :end-of "end of "
+ :dec-lit "decimal literal"
+ :oct-lit "octal literal"
+ :hex-lit "hex literal"
+ :float-lit "floating-point literal"
+ :reserved "%s is a reserved name"
+ })
+
+
+(def ^:private text (atom default))
+
+
+(defn i18n-merge
+ "Merges m into the text map for customization."
+ [m] (swap! text merge m))
+
+
+(defn i18n
+ "Gets or sets the value for the supplied key."
+ ([k] (k (deref text)))
+ ([k v] (swap! text assoc k v)))
+
+
+(defn fmt
+ "Formats a string with a key and more arguments."
+ [k & more]
+ (apply format (i18n k) more))
+
+
+(defn di18n
+ "Returns a Delay instance with the value for the supplied key.
+ Useful in (def)'ed expressions that evaluate too soon."
+ [k] (delay (k (deref text))))
+
+
+(defn dfmt
+ "Returns a Delay instance with a string formatted with a key and more
+ arguments. Useful in (def)'ed expressions that evaluate too soon."
+ [k & more]
+ (delay (apply format (i18n k) more)))
diff --git a/src/main/clojure/blancas/kern/lexer.clj b/src/main/clojure/blancas/kern/lexer.clj
deleted file mode 100644
index 8292259..0000000
--- a/src/main/clojure/blancas/kern/lexer.clj
+++ /dev/null
@@ -1,734 +0,0 @@
-;; Copyright (c) 2013 Armando Blancas. All rights reserved.
-;; The use and distribution terms for this software are covered by the
-;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-;; which can be found in the file epl-v10.html at the root of this distribution.
-;; By using this software in any fashion, you are agreeing to be bound by
-;; the terms of this license.
-;; You must not remove this notice, or any other, from this software.
-
-(ns ^{:doc "The Kern Lexer library."
- :author "Armando Blancas"}
- blancas.kern.lexer
- (:use [blancas.kern core i18n]
- [clojure.string :only (lower-case)]))
-
-
-;; +-------------------------------------------------------------+
-;; | Language definitions. |
-;; +-------------------------------------------------------------+
-
-
-;; A language def record customizes the parsers returned by make-parsers.
-(defrecord LanguageDef
- [type ;; Identifies the type of settings.
- comment-start ;; A string that marks the start of a block comment.
- comment-end ;; A string that marks the end of a block comment.
- comment-line ;; A string that marks the start of a line comment.
- nested-comments ;; Whether the lexer accepts nested comments; a boolean.
- identifier-start ;; A parser for the start of an identifier.
- identifier-letter ;; A parser for the subsequent characters of an identifier.
- reserved-names ;; A list of names that cannot be identifiers.
- case-sensitive ;; Whether tokens are case-sensitive; a boolean.
- line-continuation ;; A parser for the token that precedes the new line.
- trim-newline ;; Treats newline character(s) as whitespace.
- leading-sign]) ;; Whether numbers accept an optional leading sign.
-
-
-(def basic-def
- "The most basic record; for use to build new styles."
- (map->LanguageDef
- {:type :basic
- :comment-start ""
- :comment-end ""
- :comment-line ""
- :nested-comments false
- :identifier-start (<|> letter (sym* \_))
- :identifier-letter (<|> alpha-num (sym* \_))
- :reserved-names []
- :case-sensitive true
- :line-continuation (sym* \\)
- :trim-newline true
- :leading-sign true}))
-
-
-(def haskell-style
- "Lexical settings for Haskell-style languages."
- (assoc basic-def
- :type :Haskell
- :comment-start "{-"
- :comment-end "-}"
- :comment-line "--"
- :nested-comments true))
-
-
-(def java-style
- "Lexical settings for Java-style languages."
- (assoc basic-def
- :type :Java
- :comment-start "/*"
- :comment-end "*/"
- :comment-line "//"))
-
-
-(def c-style
- "Lexical settings for C-style languages."
- (assoc java-style
- :type :C))
-
-
-(def shell-style
- "Lexical settings for shell-style languages."
- (assoc basic-def
- :type :Shell
- :comment-line "#"
- :identifier-letter (<|> alpha-num (one-of* "_-."))
- :trim-newline false))
-
-
-;; +-------------------------------------------------------------+
-;; | Parser definitions. |
-;; +-------------------------------------------------------------+
-
-
-(defrecord TokenParsers
- [trim
- lexeme
- sym
- new-line
- one-of
- none-of
- token
- word
- identifier
- field
- char-lit
- string-lit
- dec-lit
- oct-lit
- hex-lit
- float-lit
- bool-lit
- nil-lit
- parens
- braces
- angles
- brackets
- semi
- comma
- colon
- dot
- semi-sep
- semi-sep1
- comma-sep
- comma-sep1])
-
-
-(defn* trim
- "Skips over any whitespace, including comments (if defined), at
- the start of the input. Whether newline characters are removed
- as whitespace is configured by :trim-newline. When that setting
- is true, the setting :line-continuation is activated."
- [] nil)
-
-(defn* lexeme
- "Applies parser p, then calls (trim)."
- [p] nil)
-
-(defn* sym
- "Parses a single character c. Compares according to
- :case-sensitive. Calls (trim) afterwards."
- [c] nil)
-
-(defn* new-line
- "Parses a new line, UNIX or Windows style; then calls (trim)."
- [] nil)
-
-(defn* one-of
- "Succeeds if the next character is in the supplied string.
- Calls (trim) afterwards."
- [cs] nil)
-
-(defn* none-of
- "Succeeds if the next character is not in the supplied string.
- Calls (trim) afterwards."
- [] nil)
-
-(defn* token
- "Parses a specific string, not necessarily delimited. If more
- than one are given it will try each choice in turn. Compares
- according to :case-sensitive. Calls (trim) afterwards."
- ([cs] nil)
- ([cs & more] nil))
-
-(defn* word
- "Parses a specific string; must be delimited by any character not
- parsed by :identifier-letter. If more than one are given it will
- try each choice in turn. Compares according to :case-sensitive.
- Calls (trim) afterwards."
- ([cs] nil)
- ([cs & more] nil))
-
-(defn* identifier
- "Parses an unquoted string suitable for an identifier or a name.
- The start of the input is defined by :identifier-start, and
- subsequent symbols by :identtifier-letter. It will check that
- the parsed value not be in the list of :reserved-names, if any,
- comparing according to :case-sensitive. Calls (trim) afterwards."
- [] nil)
-
-(defn* field
- "Parses an unquoted text field terminated by any character
- in cs. Calls (trim) afterwards."
- [cs] nil)
-
-(defn* char-lit
- "Parses a character literal according to the :type setting. The
- common syntax is a symbol in single quotes with the usual
- escape codes. Calls (trim) afterwards.
-
- The following styles add escaped characters:
-
- :basic \\b \\t \\n \\f \\r \\' \\\" \\/
- :C :basic + \\0ooo \\0xnn \\unnnnnnnn
- :Haskell :basic + \\nnnn \\onnnn \\xnnnn
- :Java :basic + \\0ooo \\unnnn
- :Shell :basic + \\0ooo \\0xnn \\unnnnnnnn"
- [] nil)
-
-(defn* string-lit
- "Parses a string literal according to the :type setting. The
- common syntax is any number of symbols in double quotes
- with the usual escape codes. Calls (trim) afterward.
-
- The following styles add escaped characters:
-
- :basic \\b \\t \\n \\f \\r \\' \\\" \\/
- :C :basic + \\0ooo \\0xnn \\unnnnnnnn
- :Haskell :basic + \\nnnn \\onnnn \\xnnnn
- :Java :basic + \\0ooo \\unnnn
- :Shell :basic + \\0ooo \\0xnn \\unnnnnnnn"
- [] nil)
-
-(defn* dec-lit
- "Parses a decimal number as Long or BigInt depending on the
- magnitude or if it ends with N. Calls (trim) afterward."
- [] nil)
-
-(defn* oct-lit
- "Parses an octal number as Long or BigInt depending on the
- magnitude or if it ends with N. Calls (trim) afterward."
- [] nil)
-
-(defn* hex-lit
- "Parses a hexadecimal number as Long or BigInt depending on the
- magnitude or if it ends with N. Calls (trim) afterward."
- [] nil)
-
-(defn* float-lit
- "Parses a floating-point number as Double or BigDecimal depending
- on the magnitude or if it ends with M. It cannot start with a
- period. The first period found must be followed by at least one
- digit. Calls (trim) afterward."
- [] nil)
-
-(defn* bool-lit
- "Parses a boolean value, true or false, comparing according to
- :case-sensitive. Calls (trim) afterward."
- [] nil)
-
-(defn* nil-lit
- "Parses a null value, nil or null, comparing according to
- :case-sensitive. Calls (trim) afterward."
- [] nil)
-
-(defn* parens
- "Applies parser p skiping over surrounding parenthesis.
- Calls (trim) after the opening paren, after p, and after
- the closing paren."
- [p] nil)
-
-(defn* braces
- "Applies parser p skiping over surrounding braces.
- Calls (trim) after the opening brace, after p, and after
- the closing brace."
- [p] nil)
-
-(defn* angles
- "Applies parser p skiping over surrounding angle brackets.
- Calls (trim) after the opening bracket, after p, and after
- the closing bracket."
- [p] nil)
-
-(defn* brackets
- "Applies parser p skiping over surrounding brackets.
- Calls (trim) after the opening bracket, after p, and after
- the closing bracket."
- [p] nil)
-
-(defn* semi
- "Parses a single semicolon; then calls (trim)."
- [] nil)
-
-(defn* comma
- "Parses a single comma; then calls (trim)."
- [] nil)
-
-(defn* colon
- "Parses a single colon; then calls (trim)."
- [] nil)
-
-(defn* dot
- "Parses a single dot; then calls (trim)."
- [] nil)
-
-(defn* semi-sep
- "Applies parser p zero or more times, skiping over separating
- semicolons. Calls (trim) after each p and semicolon."
- [] nil)
-
-(defn* semi-sep1
- "Applies parser p one or more times, skiping over separating
- semicolons. Calls (trim) after each p and semicolon."
- [] nil)
-
-(defn* comma-sep
- "Applies parser p zero or more times, skiping over separating
- commas. Calls (trim) after each p and comma."
- [] nil)
-
-(defn* comma-sep1
- "Applies parser p one or more times, skiping over separating
- commas. Calls (trim) after each p and comma."
- [] nil)
-
-
-(defmacro with-parsers
- "Binds the parser vars in the kern.lexer namespace to the values in rec."
- [rec & body]
- (list 'binding
- ['blancas.kern.lexer/trim (list :trim rec)
- 'blancas.kern.lexer/lexeme (list :lexeme rec)
- 'blancas.kern.lexer/sym (list :sym rec)
- 'blancas.kern.lexer/new-line (list :new-line rec)
- 'blancas.kern.lexer/one-of (list :one-of rec)
- 'blancas.kern.lexer/none-of (list :none-of rec)
- 'blancas.kern.lexer/token (list :token rec)
- 'blancas.kern.lexer/word (list :word rec)
- 'blancas.kern.lexer/identifier (list :identifier rec)
- 'blancas.kern.lexer/field (list :field rec)
- 'blancas.kern.lexer/char-lit (list :char-lit rec)
- 'blancas.kern.lexer/string-lit (list :string-lit rec)
- 'blancas.kern.lexer/dec-lit (list :dec-lit rec)
- 'blancas.kern.lexer/oct-lit (list :oct-lit rec)
- 'blancas.kern.lexer/hex-lit (list :hex-lit rec)
- 'blancas.kern.lexer/float-lit (list :float-lit rec)
- 'blancas.kern.lexer/bool-lit (list :bool-lit rec)
- 'blancas.kern.lexer/nil-lit (list :nil-lit rec)
- 'blancas.kern.lexer/parens (list :parens rec)
- 'blancas.kern.lexer/braces (list :braces rec)
- 'blancas.kern.lexer/angles (list :angles rec)
- 'blancas.kern.lexer/brackets (list :brackets rec)
- 'blancas.kern.lexer/semi (list :semi rec)
- 'blancas.kern.lexer/comma (list :comma rec)
- 'blancas.kern.lexer/colon (list :colon rec)
- 'blancas.kern.lexer/dot (list :dot rec)
- 'blancas.kern.lexer/semi-sep (list :semi-sep rec)
- 'blancas.kern.lexer/semi-sep1 (list :semi-sep1 rec)
- 'blancas.kern.lexer/comma-sep (list :comma-sep rec)
- 'blancas.kern.lexer/comma-sep1 (list :comma-sep1 rec)]
- (cons 'do body)))
-
-
-;; +-------------------------------------------------------------+
-;; | Private functions for whitespace. |
-;; +-------------------------------------------------------------+
-
-
-(defn- line-comment
- "Parses a line comment."
- [rec]
- (let [start (:comment-line rec)]
- (>>= (token* start)
- (fn [_] (>>= (many-till any-char (<|> new-line* eof))
- (fn [_] (return nil)))))))
-
-
-(defn- block-nested
- "Parses the contents and end of a nested block comment."
- [rec]
- (let [start (:comment-start rec)
- end (:comment-end rec)]
- (expect (many-till (<|> (>>= (<:> (token* start)) (fn [_] (block-nested rec)))
- any-char)
- (token* end))
- (i18n :end-comment))))
-
-
-(defn- block-rest
- "Parses the contents and end of a block comment."
- [rec]
- (let [end (:comment-end rec)]
- (expect (many-till any-char (token* end)) (i18n :end-comment))))
-
-
-(defn- block-comment
- "Parses a block comment."
- [rec]
- (let [start (:comment-start rec)
- nest? (:nested-comments rec)]
- (skip (<:> (token* start))
- (if nest? (block-nested rec) (block-rest rec)))))
-
-
-;; +-------------------------------------------------------------+
-;; | Private functions for character and string literals. |
-;; +-------------------------------------------------------------+
-
-
-(def space-ascii 32)
-
-
-(def- esc-char
- "Parses an escape code for a basic char."
- (let [codes (zipmap "btnfr'\"\\/" "\b\t\n\f\r'\"\\/")]
- (>>= (> (one-of* "btnfr'\"\\/") (i18n :esc-code))
- (fn [x] (return (get codes x))))))
-
-
-(defn- basic-char
- "Parses an unquoted character literal. Character c must be escaped."
- [c]
- (> (<|> (satisfy #(and (not= % c) (not= % \\) (>= (int %) space-ascii)))
- (>> (sym* \\) esc-char))
- (i18n :char-lit)))
-
-
-(def- esc-oct
- "Parses an octal escape code; the result is the encoded char."
- (>>= (<+> (many1 oct-digit))
- (fn [x]
- (let [n (Integer/parseInt x 8)]
- (if (<= n 0377)
- (return (char n))
- (fail (i18n :bad-octal)))))))
-
-
-(def- esc-uni
- "Parses a unicode escape code; the result is the encoded char."
- (>>= (<+> (>> (sym* \u) (times 4 hex-digit)))
- (fn [x] (return (aget (Character/toChars (Integer/parseInt x 16)) 0)))))
-
-
-(defn- java-char
- "Parses an unquoted Java character literal. Character c must be escaped."
- [c]
- (> (<|> (satisfy #(and (not= % c) (not= % \\) (>= (int %) space-ascii)))
- (>> (sym* \\)
- (> (<|> esc-char esc-oct esc-uni)
- (i18n :esc-code-j))))
- (i18n :char-lit)))
-
-
-(def- c-esc-char
- "Parses an escape code for a C char."
- (let [codes (assoc (zipmap "btnfr'\"\\?/" "\b\t\n\f\r'\"\\?/")
- \a (char 7) \v (char 11) \0 (char 0))]
- (>>= (one-of* "btnfr'\"\\?/av0") (fn [x] (return (get codes x))))))
-
-
-(def- c-esc-uni
- "Parses a long unicode escape code; the result is the encoded char."
- (>>= (<+> (>> (sym* \U) (times 8 hex-digit)))
- (fn [x] (return (aget (Character/toChars (Integer/parseInt x 16)) 0)))))
-
-
-(def- c-esc-hex
- "Parses a hex escape code; the result is the encoded char."
- (>>= (<+> (>> (sym- \x) (times 2 hex-digit)))
- (fn [x] (return (aget (Character/toChars (Integer/parseInt x 16)) 0)))))
-
-
-(defn- c-char
- "Parses an unquoted C character literal. Character c must be escaped."
- [c]
- (> (<|> (satisfy #(and (not= % c) (not= % \\) (>= (int %) space-ascii)))
- (>> (sym* \\)
- (> (<|> c-esc-hex c-esc-char esc-oct esc-uni c-esc-uni)
- (i18n :esc-code-c))))
- (i18n :char-lit)))
-
-
-(def- h-esc-oct
- "Parses a Haskell octal escape code; the result is the encoded char."
- (>>= (<+> (>> (sym* \o) (many1 oct-digit)))
- (fn [x]
- (let [n (Integer/parseInt x 8)]
- (if (<= n 04177777)
- (return (char n))
- (fail (i18n :bad-oct-h)))))))
-
-
-(def- h-esc-dec
- "Parses a Haskell decimal escape code; the result is the encoded char."
- (>>= (<+> (many1 digit))
- (fn [x]
- (let [n (Integer/parseInt x)]
- (if (<= n 1114111)
- (return (char n))
- (fail (i18n :bad-dec-h)))))))
-
-
-(def- h-esc-hex
- "Parses a Haskell hex escape code; the result is the encoded char."
- (>>= (<+> (>> (sym* \x) (many1 hex-digit)))
- (fn [x]
- (let [n (Integer/parseInt x 16)]
- (if (<= n 0x10ffff)
- (return (char n))
- (fail (i18n :bad-hex-h)))))))
-
-
-(defn- haskell-char
- "Parses Haskell character literals."
- [c]
- (> (<|> (satisfy #(and (not= % c) (not= % \\) (>= (int %) space-ascii)))
- (>> (sym* \\)
- (> (<|> h-esc-hex h-esc-oct c-esc-char h-esc-dec)
- (i18n :esc-code-h))))
- (i18n :char-lit)))
-
-
-(defn- char-parser
- "Parses character literals delimited by single quotes."
- [lex f]
- (> (lex (between (sym* \') (> (sym* \') (i18n :end-char)) (f \')))
- (i18n :char-lit)))
-
-
-(defn- str-parser
- "Parses string literals delimited by double quotes."
- [lex f]
- (> (lex (between (sym* \")
- (> (sym* \") (i18n :end-string))
- (<+> (many (f \")))))
- (i18n :string-lit)))
-
-
-;; +-------------------------------------------------------------+
-;; | Private functions for numeric literals. |
-;; +-------------------------------------------------------------+
-
-
-(def- sign (optional (one-of* "+-")))
-
-(def- int-suffix (<|> (<< (sym* \N) (not-followed-by letter))
- (not-followed-by (<|> letter (sym* \.)))))
-
-(def- float-suffix (<< (optional (sym* \M)) (not-followed-by letter)))
-
-
-;; +-------------------------------------------------------------+
-;; | Parser generator. |
-;; +-------------------------------------------------------------+
-
-
-(defn make-parsers
- "Returns a function map that corresponds to the customization
- values of the input record, whose fields are as follows:
-
- :type Identifies the type of settings.
- :comment-start A string that marks the start of a block comment.
- :comment-end A string that marks the end of a block comment.
- :comment-line A string that marks the start of a line comment.
- :nested-comments Whether the lexer accepts nested comments; a boolean.
- :identifier-start A parser for the start of an identifier.
- :identifier-letter A parser for the subsequent characters of an identifier.
- :reserved-names A list of names that cannot be identifiers.
- :case-sensitive Whether tokens are case-sensitive; a boolean.
- :line-continuation A parser for the token that precedes the new line.
- :trim-newline Treats newline character(s) as whitespace.
- :leading-sign Whether numbers accept an optional leading sign."
- [rec]
- (let [trim
- (let [line? (seq (:comment-line rec))
- multi? (seq (:comment-start rec))
- both? (and line? multi?)
- ws (if (:trim-newline rec)
- white-space
- (<|> (one-of* "\t\f\r ")
- (skip (:line-continuation rec) new-line*)))
- many-ws (skip-many1 ws)]
- (cond both? (skip-many (<|> many-ws (line-comment rec) (block-comment rec)))
- line? (skip-many (<|> many-ws (line-comment rec)))
- multi? (skip-many (<|> many-ws (block-comment rec)))
- :else (skip-many ws)))
-
- lexeme
- (fn [p] (<< p trim))
-
- sym
- (if (:case-sensitive rec)
- (fn [x] (lexeme (sym* x)))
- (fn [x] (lexeme (sym- x))))
-
- new-line
- (lexeme new-line*)
-
- one-of
- (fn [cs] (lexeme (one-of* cs)))
-
- none-of
- (fn [cs] (lexeme (none-of* cs)))
-
- token
- (if (:case-sensitive rec)
- (fn ([cs] (lexeme (token* cs)))
- ([cs & more] (lexeme (apply token* cs more))))
- (fn ([cs] (lexeme (token- cs)))
- ([cs & more] (lexeme (apply token- cs more)))))
-
- word
- (let [il (:identifier-letter rec)]
- (if (:case-sensitive rec)
- (fn ([cs] (lexeme (word* il cs)))
- ([cs & more] (lexeme (apply word* il cs more))))
- (fn ([cs] (lexeme (word- il cs)))
- ([cs & more] (lexeme (apply word- il cs more))))))
-
- identifier
- (let [start (:identifier-start rec)
- other (:identifier-letter rec)
- names (:reserved-names rec)
- elem? (fn [s coll] (member? (lower-case s) (map #(lower-case %) coll)))
- is-in (if (:case-sensitive rec) member? elem?)
- check (fn [p] (>>= p (fn [s] (if (is-in s names)
- (fail (fmt :reserved s))
- (return s)))))
- t (:type rec)]
- (cond (= t :basic) (<:> (check (lexeme (<+> start (many0 other)))))
- (= t :C) (<:> (check (lexeme (<+> start (many0 other)))))
- (= t :Haskell) (<:> (check (lexeme (<+> start (many0 other)))))
- (= t :Java) (<:> (check (lexeme (<+> start (many0 other)))))
- (= t :Shell) (<:> (check (lexeme (<+> start (many0 other)))))))
-
- field
- (fn [cs] (lexeme (field* cs)))
-
- char-lit
- (let [t (:type rec)]
- (cond (= t :basic) (char-parser lexeme basic-char)
- (= t :C) (char-parser lexeme c-char)
- (= t :Haskell) (char-parser lexeme haskell-char)
- (= t :Java) (char-parser lexeme java-char)
- (= t :Shell) (char-parser lexeme c-char)))
-
- string-lit
- (let [t (:type rec)]
- (cond (= t :basic) (str-parser lexeme basic-char)
- (= t :C) (<+> (many1 (str-parser lexeme c-char)))
- (= t :Haskell) (str-parser lexeme haskell-char)
- (= t :Java) (str-parser lexeme java-char)
- (= t :Shell) (<+> (many1 (str-parser lexeme c-char)))))
-
- dec-lit
- (let [lead (if (:leading-sign rec) sign (return nil))]
- (> (>>= (<:> (lexeme (<+> lead (many1 digit) int-suffix)))
- (fn [x] (return (read-string x))))
- (i18n :dec-lit)))
-
- oct-lit
- (let [lead (if (:leading-sign rec) sign (return nil))]
- (> (>>= (<:> (lexeme (<+> lead (sym* \0) (many oct-digit) int-suffix)))
- (fn [x] (return (read-string x))))
- (i18n :oct-lit)))
-
- hex-lit
- (let [lead (if (:leading-sign rec) sign (return nil))]
- (> (>>= (<:> (lexeme (<+> lead (token- "0x") (many1 hex-digit) int-suffix)))
- (fn [x] (return (read-string x))))
- (i18n :hex-lit)))
-
- float-lit
- (let [lead (if (:leading-sign rec) sign (return nil))]
- (> (>>= (<:> (lexeme
- (<+> lead (many1 digit)
- (option ".0" (<*> (sym* \.) (many1 digit)))
- (optional (<*> (one-of* "eE") sign (many1 digit)))
- float-suffix)))
- (fn [x] (>> (return (read-string x)) clear-empty)))
- (i18n :float-lit)))
-
- bool-lit
- (<|> (>> (word "true") (return true))
- (>> (word "false") (return false)))
-
- nil-lit
- (>> (word "nil" "null") (return nil))
-
- parens
- (fn [p] (between (sym \() (sym \)) (lexeme p)))
-
- braces
- (fn [p] (between (sym \{) (sym \}) (lexeme p)))
-
- angles
- (fn [p] (between (sym \<) (sym \>) (lexeme p)))
-
- brackets
- (fn [p] (between (sym \[) (sym \]) (lexeme p)))
-
- semi
- (sym \;)
-
- comma
- (sym \,)
-
- colon
- (sym \:)
-
- dot
- (sym \.)
-
- semi-sep
- (fn [p] (sep-by semi (lexeme p)))
-
- semi-sep1
- (fn [p] (sep-by1 semi (lexeme p)))
-
- comma-sep
- (fn [p] (sep-by comma (lexeme p)))
-
- comma-sep1
- (fn [p] (sep-by1 comma (lexeme p)))]
-
- (map->TokenParsers
- {:trim trim
- :lexeme lexeme
- :sym sym
- :new-line new-line
- :one-of one-of
- :none-of none-of
- :token token
- :word word
- :identifier identifier
- :field field
- :char-lit char-lit
- :string-lit string-lit
- :dec-lit dec-lit
- :oct-lit oct-lit
- :hex-lit hex-lit
- :float-lit float-lit
- :bool-lit bool-lit
- :nil-lit nil-lit
- :parens parens
- :braces braces
- :angles angles
- :brackets brackets
- :semi semi
- :comma comma
- :colon colon
- :dot dot
- :semi-sep semi-sep
- :semi-sep1 semi-sep1
- :comma-sep comma-sep
- :comma-sep1 comma-sep1})))
diff --git a/src/main/clojure/blancas/kern/lexer.cljc b/src/main/clojure/blancas/kern/lexer.cljc
new file mode 100644
index 0000000..8433060
--- /dev/null
+++ b/src/main/clojure/blancas/kern/lexer.cljc
@@ -0,0 +1,747 @@
+;; Copyright (c) 2013 Armando Blancas. All rights reserved.
+;; The use and distribution terms for this software are covered by the
+;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this distribution.
+;; By using this software in any fashion, you are agreeing to be bound by
+;; the terms of this license.
+;; You must not remove this notice, or any other, from this software.
+
+(ns ^{:doc "The Kern Lexer library."
+ :author "Armando Blancas"}
+blancas.kern.lexer
+ (:require [blancas.kern.core :refer [<|> > >> >>= <:> <+> << <*>] :as k]
+ [blancas.kern.i18n :refer [i18n fmt]]
+ [clojure.string :refer [lower-case]])
+ #?(:cljs (:require-macros [blancas.kern.core :as k])))
+
+
+;; +-------------------------------------------------------------+
+;; | Language definitions. |
+;; +-------------------------------------------------------------+
+
+
+;; A language def record customizes the parsers returned by make-parsers.
+(defrecord LanguageDef
+ [type ;; Identifies the type of settings.
+ comment-start ;; A string that marks the start of a block comment.
+ comment-end ;; A string that marks the end of a block comment.
+ comment-line ;; A string that marks the start of a line comment.
+ nested-comments ;; Whether the lexer accepts nested comments; a boolean.
+ identifier-start ;; A parser for the start of an identifier.
+ identifier-letter ;; A parser for the subsequent characters of an identifier.
+ reserved-names ;; A list of names that cannot be identifiers.
+ case-sensitive ;; Whether tokens are case-sensitive; a boolean.
+ line-continuation ;; A parser for the token that precedes the new line.
+ trim-newline ;; Treats newline character(s) as whitespace.
+ leading-sign]) ;; Whether numbers accept an optional leading sign.
+
+
+(def basic-def
+ "The most basic record; for use to build new styles."
+ (map->LanguageDef
+ {:type :basic
+ :comment-start ""
+ :comment-end ""
+ :comment-line ""
+ :nested-comments false
+ :identifier-start (<|> k/letter (k/sym* \_))
+ :identifier-letter (<|> k/alpha-num (k/sym* \_))
+ :reserved-names []
+ :case-sensitive true
+ :line-continuation (k/sym* \\)
+ :trim-newline true
+ :leading-sign true}))
+
+
+(def haskell-style-def
+ "Lexical settings for Haskell-style languages."
+ (assoc basic-def
+ :type :Haskell
+ :comment-start "{-"
+ :comment-end "-}"
+ :comment-line "--"
+ :nested-comments true))
+
+
+(def java-style-def
+ "Lexical settings for Java-style languages."
+ (assoc basic-def
+ :type :Java
+ :comment-start "/*"
+ :comment-end "*/"
+ :comment-line "//"))
+
+
+(def c-style-def
+ "Lexical settings for C-style languages."
+ (assoc java-style-def
+ :type :C))
+
+
+(def shell-style-def
+ "Lexical settings for shell-style languages."
+ (assoc basic-def
+ :type :Shell
+ :comment-line "#"
+ :identifier-letter (<|> k/alpha-num (k/one-of* "_-."))
+ :trim-newline false))
+
+
+;; +-------------------------------------------------------------+
+;; | Parser definitions. |
+;; +-------------------------------------------------------------+
+
+
+(defrecord TokenParsers
+ [trim
+ lexeme
+ sym
+ new-line
+ one-of
+ none-of
+ token
+ word
+ identifier
+ field
+ char-lit
+ string-lit
+ dec-lit
+ oct-lit
+ hex-lit
+ float-lit
+ bool-lit
+ nil-lit
+ parens
+ braces
+ angles
+ brackets
+ semi
+ comma
+ colon
+ dot
+ semi-sep
+ semi-sep1
+ comma-sep
+ comma-sep1])
+
+
+(k/defn* trim
+ "Skips over any whitespace, including comments (if defined), at
+ the start of the input. Whether newline characters are removed
+ as whitespace is configured by :trim-newline. When that setting
+ is true, the setting :line-continuation is activated."
+ [] nil)
+
+(k/defn* lexeme
+ "Applies parser p, then calls (trim)."
+ [p] nil)
+
+(k/defn* sym
+ "Parses a single character c. Compares according to
+ :case-sensitive. Calls (trim) afterwards."
+ [c] nil)
+
+(k/defn* new-line
+ "Parses a new line, UNIX or Windows style; then calls (trim)."
+ [] nil)
+
+(k/defn* one-of
+ "Succeeds if the next character is in the supplied string.
+ Calls (trim) afterwards."
+ [cs] nil)
+
+(k/defn* none-of
+ "Succeeds if the next character is not in the supplied string.
+ Calls (trim) afterwards."
+ [] nil)
+
+(k/defn* token
+ "Parses a specific string, not necessarily delimited. If more
+ than one are given it will try each choice in turn. Compares
+ according to :case-sensitive. Calls (trim) afterwards."
+ ([cs] nil)
+ ([cs & more] nil))
+
+(k/defn* word
+ "Parses a specific string; must be delimited by any character not
+ parsed by :identifier-letter. If more than one are given it will
+ try each choice in turn. Compares according to :case-sensitive.
+ Calls (trim) afterwards."
+ ([cs] nil)
+ ([cs & more] nil))
+
+(k/defn* identifier
+ "Parses an unquoted string suitable for an identifier or a name.
+ The start of the input is defined by :identifier-start, and
+ subsequent symbols by :identtifier-letter. It will check that
+ the parsed value not be in the list of :reserved-names, if any,
+ comparing according to :case-sensitive. Calls (trim) afterwards."
+ [] nil)
+
+(k/defn* field
+ "Parses an unquoted text field terminated by any character
+ in cs. Calls (trim) afterwards."
+ [cs] nil)
+
+(k/defn* char-lit
+ "Parses a character literal according to the :type setting. The
+ common syntax is a symbol in single quotes with the usual
+ escape codes. Calls (trim) afterwards.
+
+ The following styles add escaped characters:
+
+ :basic \\b \\t \\n \\f \\r \\' \\\" \\/
+ :C :basic + \\0ooo \\0xnn \\unnnnnnnn
+ :Haskell :basic + \\nnnn \\onnnn \\xnnnn
+ :Java :basic + \\0ooo \\unnnn
+ :Shell :basic + \\0ooo \\0xnn \\unnnnnnnn"
+ [] nil)
+
+(k/defn* string-lit
+ "Parses a string literal according to the :type setting. The
+ common syntax is any number of symbols in double quotes
+ with the usual escape codes. Calls (trim) afterward.
+
+ The following styles add escaped characters:
+
+ :basic \\b \\t \\n \\f \\r \\' \\\" \\/
+ :C :basic + \\0ooo \\0xnn \\unnnnnnnn
+ :Haskell :basic + \\nnnn \\onnnn \\xnnnn
+ :Java :basic + \\0ooo \\unnnn
+ :Shell :basic + \\0ooo \\0xnn \\unnnnnnnn"
+ [] nil)
+
+(k/defn* dec-lit
+ "Parses a decimal number as Long or BigInt depending on the
+ magnitude or if it ends with N. Calls (trim) afterward."
+ [] nil)
+
+(k/defn* oct-lit
+ "Parses an octal number as Long or BigInt depending on the
+ magnitude or if it ends with N. Calls (trim) afterward."
+ [] nil)
+
+(k/defn* hex-lit
+ "Parses a hexadecimal number as Long or BigInt depending on the
+ magnitude or if it ends with N. Calls (trim) afterward."
+ [] nil)
+
+(k/defn* float-lit
+ "Parses a floating-point number as Double or BigDecimal depending
+ on the magnitude or if it ends with M. It cannot start with a
+ period. The first period found must be followed by at least one
+ digit. Calls (trim) afterward."
+ [] nil)
+
+(k/defn* bool-lit
+ "Parses a boolean value, true or false, comparing according to
+ :case-sensitive. Calls (trim) afterward."
+ [] nil)
+
+(k/defn* nil-lit
+ "Parses a null value, nil or null, comparing according to
+ :case-sensitive. Calls (trim) afterward."
+ [] nil)
+
+(k/defn* parens
+ "Applies parser p skiping over surrounding parenthesis.
+ Calls (trim) after the opening paren, after p, and after
+ the closing paren."
+ [p] nil)
+
+(k/defn* braces
+ "Applies parser p skiping over surrounding braces.
+ Calls (trim) after the opening brace, after p, and after
+ the closing brace."
+ [p] nil)
+
+(k/defn* angles
+ "Applies parser p skiping over surrounding angle brackets.
+ Calls (trim) after the opening bracket, after p, and after
+ the closing bracket."
+ [p] nil)
+
+(k/defn* brackets
+ "Applies parser p skiping over surrounding brackets.
+ Calls (trim) after the opening bracket, after p, and after
+ the closing bracket."
+ [p] nil)
+
+(k/defn* semi
+ "Parses a single semicolon; then calls (trim)."
+ [] nil)
+
+(k/defn* comma
+ "Parses a single comma; then calls (trim)."
+ [] nil)
+
+(k/defn* colon
+ "Parses a single colon; then calls (trim)."
+ [] nil)
+
+(k/defn* dot
+ "Parses a single dot; then calls (trim)."
+ [] nil)
+
+(k/defn* semi-sep
+ "Applies parser p zero or more times, skiping over separating
+ semicolons. Calls (trim) after each p and semicolon."
+ [] nil)
+
+(k/defn* semi-sep1
+ "Applies parser p one or more times, skiping over separating
+ semicolons. Calls (trim) after each p and semicolon."
+ [] nil)
+
+(k/defn* comma-sep
+ "Applies parser p zero or more times, skiping over separating
+ commas. Calls (trim) after each p and comma."
+ [] nil)
+
+(k/defn* comma-sep1
+ "Applies parser p one or more times, skiping over separating
+ commas. Calls (trim) after each p and comma."
+ [] nil)
+
+
+#?(:clj
+ (defmacro with-parsers
+ "Binds the parser vars in the kern.lexer namespace to the values in rec."
+ [rec & body]
+ (list 'binding
+ ['blancas.kern.lexer/trim (list :trim rec)
+ 'blancas.kern.lexer/lexeme (list :lexeme rec)
+ 'blancas.kern.lexer/sym (list :sym rec)
+ 'blancas.kern.lexer/new-line (list :new-line rec)
+ 'blancas.kern.lexer/one-of (list :one-of rec)
+ 'blancas.kern.lexer/none-of (list :none-of rec)
+ 'blancas.kern.lexer/token (list :token rec)
+ 'blancas.kern.lexer/word (list :word rec)
+ 'blancas.kern.lexer/identifier (list :identifier rec)
+ 'blancas.kern.lexer/field (list :field rec)
+ 'blancas.kern.lexer/char-lit (list :char-lit rec)
+ 'blancas.kern.lexer/string-lit (list :string-lit rec)
+ 'blancas.kern.lexer/dec-lit (list :dec-lit rec)
+ 'blancas.kern.lexer/oct-lit (list :oct-lit rec)
+ 'blancas.kern.lexer/hex-lit (list :hex-lit rec)
+ 'blancas.kern.lexer/float-lit (list :float-lit rec)
+ 'blancas.kern.lexer/bool-lit (list :bool-lit rec)
+ 'blancas.kern.lexer/nil-lit (list :nil-lit rec)
+ 'blancas.kern.lexer/parens (list :parens rec)
+ 'blancas.kern.lexer/braces (list :braces rec)
+ 'blancas.kern.lexer/angles (list :angles rec)
+ 'blancas.kern.lexer/brackets (list :brackets rec)
+ 'blancas.kern.lexer/semi (list :semi rec)
+ 'blancas.kern.lexer/comma (list :comma rec)
+ 'blancas.kern.lexer/colon (list :colon rec)
+ 'blancas.kern.lexer/dot (list :dot rec)
+ 'blancas.kern.lexer/semi-sep (list :semi-sep rec)
+ 'blancas.kern.lexer/semi-sep1 (list :semi-sep1 rec)
+ 'blancas.kern.lexer/comma-sep (list :comma-sep rec)
+ 'blancas.kern.lexer/comma-sep1 (list :comma-sep1 rec)]
+ (cons 'do body))))
+
+
+;; +-------------------------------------------------------------+
+;; | Private functions for whitespace. |
+;; +-------------------------------------------------------------+
+
+
+(defn line-comment
+ "Parses a line comment."
+ [rec]
+ (let [start (:comment-line rec)]
+ (>>= (k/token* start)
+ (fn [_] (>>= (k/many-till k/any-char (<|> k/new-line* k/eof))
+ (fn [_] (k/return nil)))))))
+
+
+(defn block-nested
+ "Parses the contents and end of a nested block comment."
+ [rec]
+ (let [start (:comment-start rec)
+ end (:comment-end rec)]
+ (k/expect (k/many-till (<|> (>>= (<:> (k/token* start)) (fn [_] (block-nested rec)))
+ k/any-char)
+ (k/token* end))
+ (i18n :end-comment))))
+
+
+(defn block-rest
+ "Parses the contents and end of a block comment."
+ [rec]
+ (let [end (:comment-end rec)]
+ (k/expect (k/many-till k/any-char (k/token* end)) (i18n :end-comment))))
+
+
+(defn block-comment
+ "Parses a block comment."
+ [rec]
+ (let [start (:comment-start rec)
+ nest? (:nested-comments rec)]
+ (k/skip (<:> (k/token* start))
+ (if nest? (block-nested rec) (block-rest rec)))))
+
+
+;; +-------------------------------------------------------------+
+;; | Private functions for character and string literals. |
+;; +-------------------------------------------------------------+
+
+
+(def space-ascii 32)
+
+
+(def esc-char
+ "Parses an escape code for a basic char."
+ (let [codes (zipmap "btnfr'\"\\/" "\b\t\n\f\r'\"\\/")]
+ (>>= (> (k/one-of* "btnfr'\"\\/") (i18n :esc-code))
+ (fn [x] (k/return (get codes x))))))
+
+(defn char-code [c]
+ #?(:clj (int c)
+ :cljs (.charCodeAt c 0)))
+
+
+(defn basic-char
+ "Parses an unquoted character literal. Character c must be escaped."
+ [c]
+ (> (<|> (k/satisfy #(and (not= % c) (not= % \\) (>= (char-code %) space-ascii)))
+ (>> (k/sym* \\) esc-char))
+ (i18n :char-lit)))
+
+
+(def esc-oct
+ "Parses an octal escape code; the result is the encoded char."
+ (>>= (<+> (k/many1 k/oct-digit))
+ (fn [x]
+ (let [n #?(:clj (Integer/parseInt x 8) :cljs (js/parseInt x 8))]
+ (if (<= n 0377)
+ (k/return (char n))
+ (k/fail (i18n :bad-octal)))))))
+
+
+(def esc-uni
+ "Parses a unicode escape code; the result is the encoded char."
+ (>>= (<+> (>> (k/sym* \u) (k/times 4 k/hex-digit)))
+ (fn [x] (k/return (aget #?(:clj (Character/toChars (Integer/parseInt x 16))
+ :cljs (.fromCodePoint js/String (js/parseInt x 16))) 0)))))
+
+
+(defn java-char
+ "Parses an unquoted Java character literal. Character c must be escaped."
+ [c]
+ (> (<|> (k/satisfy #(and (not= % c) (not= % \\) (>= (char-code %) space-ascii)))
+ (>> (k/sym* \\)
+ (> (<|> esc-char esc-oct esc-uni)
+ (i18n :esc-code-j))))
+ (i18n :char-lit)))
+
+
+(def c-esc-char
+ "Parses an escape code for a C char."
+ (let [codes (assoc (zipmap "btnfr'\"\\?/" "\b\t\n\f\r'\"\\?/")
+ \a (char 7) \v (char 11) \0 (char 0))]
+ (>>= (k/one-of* "btnfr'\"\\?/av0") (fn [x] (k/return (get codes x))))))
+
+
+(def c-esc-uni
+ "Parses a long unicode escape code; the result is the encoded char."
+ (>>= (<+> (>> (k/sym* \U) (k/times 8 k/hex-digit)))
+ (fn [x] (k/return (aget #?(:clj (Character/toChars (Integer/parseInt x 16))
+ :cljs (.fromCodePoint js/String (js/parseInt x 16))) 0)))))
+
+
+(def c-esc-hex
+ "Parses a hex escape code; the result is the encoded char."
+ (>>= (<+> (>> (k/sym- \x) (k/times 2 k/hex-digit)))
+ (fn [x] (k/return (aget #?(:clj (Character/toChars (Integer/parseInt x 16))
+ :cljs (.fromCodePoint js/String (js/parseInt x 16))) 0)))))
+
+
+(defn c-char
+ "Parses an unquoted C character literal. Character c must be escaped."
+ [c]
+ (> (<|> (k/satisfy #(and (not= % c) (not= % \\) (>= (char-code %) space-ascii)))
+ (>> (k/sym* \\)
+ (> (<|> c-esc-hex c-esc-char esc-oct esc-uni c-esc-uni)
+ (i18n :esc-code-c))))
+ (i18n :char-lit)))
+
+
+(def h-esc-oct
+ "Parses a Haskell octal escape code; the result is the encoded char."
+ (>>= (<+> (>> (k/sym* \o) (k/many1 k/oct-digit)))
+ (fn [x]
+ (let [n #?(:clj (Integer/parseInt x 8) :cljs (js/parseInt x 8))]
+ (if (<= n 04177777)
+ (k/return (char n))
+ (k/fail (i18n :bad-oct-h)))))))
+
+
+(def h-esc-dec
+ "Parses a Haskell decimal escape code; the result is the encoded char."
+ (>>= (<+> (k/many1 k/digit))
+ (fn [x]
+ (let [n #?(:clj (Integer/parseInt x) :cljs (js/parseInt x))]
+ (if (<= n 1114111)
+ (k/return (char n))
+ (k/fail (i18n :bad-dec-h)))))))
+
+
+(def h-esc-hex
+ "Parses a Haskell hex escape code; the result is the encoded char."
+ (>>= (<+> (>> (k/sym* \x) (k/many1 k/hex-digit)))
+ (fn [x]
+ (let [n #?(:clj (Integer/parseInt x 16) :cljs (js/parseInt x 16))]
+ (if (<= n 0x10ffff)
+ (k/return (char n))
+ (k/fail (i18n :bad-hex-h)))))))
+
+
+(defn haskell-char
+ "Parses Haskell character literals."
+ [c]
+ (> (<|> (k/satisfy #(and (not= % c) (not= % \\) (>= (char-code %) space-ascii)))
+ (>> (k/sym* \\)
+ (> (<|> h-esc-hex h-esc-oct c-esc-char h-esc-dec)
+ (i18n :esc-code-h))))
+ (i18n :char-lit)))
+
+
+(defn char-parser
+ "Parses character literals delimited by single quotes."
+ [lex f]
+ (> (lex (k/between (k/sym* \') (> (k/sym* \') (i18n :end-char)) (f \')))
+ (i18n :char-lit)))
+
+
+(defn str-parser
+ "Parses string literals delimited by double quotes."
+ [lex f]
+ (> (lex (k/between (k/sym* \")
+ (> (k/sym* \") (i18n :end-string))
+ (<+> (k/many (f \")))))
+ (i18n :string-lit)))
+
+
+;; +-------------------------------------------------------------+
+;; | Private functions for numeric literals. |
+;; +-------------------------------------------------------------+
+
+
+(def sign (k/optional (k/one-of* "+-")))
+
+(def int-suffix (<|> (<< #?(:clj (k/sym* \N) :cljs (k/skip (k/sym* \N))) (k/not-followed-by k/letter))
+ (k/not-followed-by (<|> k/letter (k/sym* \.)))))
+
+(def float-suffix (<< (k/optional #?(:clj (k/sym* \M) :cljs (k/skip (k/sym* \M)))) (k/not-followed-by k/letter)))
+
+
+;; +-------------------------------------------------------------+
+;; | Parser generator. |
+;; +-------------------------------------------------------------+
+
+(defn read-num-lit [x]
+ #?(:clj (read-string x)
+ :cljs (js/eval x)))
+
+(defn make-parsers
+ "Returns a function map that corresponds to the customization
+ values of the input record, whose fields are as follows:
+
+ :type Identifies the type of settings.
+ :comment-start A string that marks the start of a block comment.
+ :comment-end A string that marks the end of a block comment.
+ :comment-line A string that marks the start of a line comment.
+ :nested-comments Whether the lexer accepts nested comments; a boolean.
+ :identifier-start A parser for the start of an identifier.
+ :identifier-letter A parser for the subsequent characters of an identifier.
+ :reserved-names A list of names that cannot be identifiers.
+ :case-sensitive Whether tokens are case-sensitive; a boolean.
+ :line-continuation A parser for the token that precedes the new line.
+ :trim-newline Treats newline character(s) as whitespace.
+ :leading-sign Whether numbers accept an optional leading sign."
+ [rec]
+ (let [trim
+ (let [line? (seq (:comment-line rec))
+ multi? (seq (:comment-start rec))
+ both? (and line? multi?)
+ ws (if (:trim-newline rec)
+ k/white-space
+ (<|> (k/one-of* "\t\f\r ")
+ (k/skip (:line-continuation rec) k/new-line*)))
+ many-ws (k/skip-many1 ws)]
+ (cond both? (k/skip-many (<|> many-ws (line-comment rec) (block-comment rec)))
+ line? (k/skip-many (<|> many-ws (line-comment rec)))
+ multi? (k/skip-many (<|> many-ws (block-comment rec)))
+ :else (k/skip-many ws)))
+
+ lexeme
+ (fn [p] (<< p trim))
+
+ sym
+ (if (:case-sensitive rec)
+ (fn [x] (lexeme (k/sym* x)))
+ (fn [x] (lexeme (k/sym- x))))
+
+ new-line
+ (lexeme k/new-line*)
+
+ one-of
+ (fn [cs] (lexeme (k/one-of* cs)))
+
+ none-of
+ (fn [cs] (lexeme (k/none-of* cs)))
+
+ token
+ (if (:case-sensitive rec)
+ (fn ([cs] (lexeme (k/token* cs)))
+ ([cs & more] (lexeme (apply k/token* cs more))))
+ (fn ([cs] (lexeme (k/token- cs)))
+ ([cs & more] (lexeme (apply k/token- cs more)))))
+
+ word
+ (let [il (:identifier-letter rec)]
+ (if (:case-sensitive rec)
+ (fn ([cs] (lexeme (k/word* il cs)))
+ ([cs & more] (lexeme (apply k/word* il cs more))))
+ (fn ([cs] (lexeme (k/word- il cs)))
+ ([cs & more] (lexeme (apply k/word- il cs more))))))
+
+ identifier
+ (let [start (:identifier-start rec)
+ other (:identifier-letter rec)
+ names (:reserved-names rec)
+ elem? (fn [s coll] (k/member? (lower-case s) (map #(lower-case %) coll)))
+ is-in (if (:case-sensitive rec) k/member? elem?)
+ check (fn [p] (>>= p (fn [s] (if (is-in s names)
+ (k/fail (fmt :reserved s))
+ (k/return s)))))
+ t (:type rec)]
+ (cond (= t :basic) (<:> (check (lexeme (<+> start (k/many0 other)))))
+ (= t :C) (<:> (check (lexeme (<+> start (k/many0 other)))))
+ (= t :Haskell) (<:> (check (lexeme (<+> start (k/many0 other)))))
+ (= t :Java) (<:> (check (lexeme (<+> start (k/many0 other)))))
+ (= t :Shell) (<:> (check (lexeme (<+> start (k/many0 other)))))))
+
+ field
+ (fn [cs] (lexeme (k/field* cs)))
+
+ char-lit
+ (let [t (:type rec)]
+ (cond (= t :basic) (char-parser lexeme basic-char)
+ (= t :C) (char-parser lexeme c-char)
+ (= t :Haskell) (char-parser lexeme haskell-char)
+ (= t :Java) (char-parser lexeme java-char)
+ (= t :Shell) (char-parser lexeme c-char)))
+
+ string-lit
+ (let [t (:type rec)]
+ (cond (= t :basic) (str-parser lexeme basic-char)
+ (= t :C) (<+> (k/many1 (str-parser lexeme c-char)))
+ (= t :Haskell) (str-parser lexeme haskell-char)
+ (= t :Java) (str-parser lexeme java-char)
+ (= t :Shell) (<+> (k/many1 (str-parser lexeme c-char)))))
+
+ dec-lit
+ (let [lead (if (:leading-sign rec) sign (k/return nil))]
+ (> (>>= (<:> (lexeme (<+> lead (k/many1 k/digit) int-suffix)))
+ (fn [x] (k/return (read-num-lit x))))
+ (i18n :dec-lit)))
+
+ oct-lit
+ (let [lead (if (:leading-sign rec) sign (k/return nil))]
+ (> (>>= (<:> (lexeme (<+> lead (k/sym* \0) (k/many k/oct-digit) int-suffix)))
+ (fn [x] (k/return (read-num-lit x))))
+ (i18n :oct-lit)))
+
+ hex-lit
+ (let [lead (if (:leading-sign rec) sign (k/return nil))]
+ (> (>>= (<:> (lexeme (<+> lead (k/token- "0x") (k/many1 k/hex-digit) int-suffix)))
+ (fn [x] (k/return (read-num-lit x))))
+ (i18n :hex-lit)))
+
+ float-lit
+ (let [lead (if (:leading-sign rec) sign (k/return nil))]
+ (> (>>= (<:> (lexeme
+ (<+> lead (k/many1 k/digit)
+ (k/option ".0" (<*> (k/sym* \.) (k/many1 k/digit)))
+ (k/optional (<*> (k/one-of* "eE") sign (k/many1 k/digit)))
+ float-suffix)))
+ (fn [x] (>> (k/return (read-num-lit x)) k/clear-empty)))
+ (i18n :float-lit)))
+
+ bool-lit
+ (<|> (>> (word "true") (k/return true))
+ (>> (word "false") (k/return false)))
+
+ nil-lit
+ (>> (word "nil" "null") (k/return nil))
+
+ parens
+ (fn [p] (k/between (sym \() (sym \)) (lexeme p)))
+
+ braces
+ (fn [p] (k/between (sym \{) (sym \}) (lexeme p)))
+
+ angles
+ (fn [p] (k/between (sym \<) (sym \>) (lexeme p)))
+
+ brackets
+ (fn [p] (k/between (sym \[) (sym \]) (lexeme p)))
+
+ semi
+ (sym \;)
+
+ comma
+ (sym \,)
+
+ colon
+ (sym \:)
+
+ dot
+ (sym \.)
+
+ semi-sep
+ (fn [p] (k/sep-by semi (lexeme p)))
+
+ semi-sep1
+ (fn [p] (k/sep-by1 semi (lexeme p)))
+
+ comma-sep
+ (fn [p] (k/sep-by comma (lexeme p)))
+
+ comma-sep1
+ (fn [p] (k/sep-by1 comma (lexeme p)))]
+
+ (map->TokenParsers
+ {:trim trim
+ :lexeme lexeme
+ :sym sym
+ :new-line new-line
+ :one-of one-of
+ :none-of none-of
+ :token token
+ :word word
+ :identifier identifier
+ :field field
+ :char-lit char-lit
+ :string-lit string-lit
+ :dec-lit dec-lit
+ :oct-lit oct-lit
+ :hex-lit hex-lit
+ :float-lit float-lit
+ :bool-lit bool-lit
+ :nil-lit nil-lit
+ :parens parens
+ :braces braces
+ :angles angles
+ :brackets brackets
+ :semi semi
+ :comma comma
+ :colon colon
+ :dot dot
+ :semi-sep semi-sep
+ :semi-sep1 semi-sep1
+ :comma-sep comma-sep
+ :comma-sep1 comma-sep1})))
diff --git a/src/main/clojure/blancas/kern/lexer/basic.clj b/src/main/clojure/blancas/kern/lexer/basic.cljc
similarity index 94%
rename from src/main/clojure/blancas/kern/lexer/basic.clj
rename to src/main/clojure/blancas/kern/lexer/basic.cljc
index 8a07229..144fee1 100644
--- a/src/main/clojure/blancas/kern/lexer/basic.clj
+++ b/src/main/clojure/blancas/kern/lexer/basic.cljc
@@ -22,10 +22,10 @@ line-continuation Backslash
trim-newline Yes"
:author "Armando Blancas"}
blancas.kern.lexer.basic
- (:use [blancas.kern.core])
- (:require [blancas.kern.lexer :as lex]))
+ (:require [blancas.kern.core :as k]
+ [blancas.kern.lexer :as lex]))
-(def- rec (lex/make-parsers lex/basic-def))
+(def rec (lex/make-parsers lex/basic-def))
(def trim (:trim rec))
(def lexeme (:lexeme rec))
diff --git a/src/main/clojure/blancas/kern/lexer/c_style.clj b/src/main/clojure/blancas/kern/lexer/c_style.cljc
similarity index 94%
rename from src/main/clojure/blancas/kern/lexer/c_style.clj
rename to src/main/clojure/blancas/kern/lexer/c_style.cljc
index 064cb95..0efb23f 100644
--- a/src/main/clojure/blancas/kern/lexer/c_style.clj
+++ b/src/main/clojure/blancas/kern/lexer/c_style.cljc
@@ -24,10 +24,10 @@ trim-newline Yes
Literal values follow the rules of the C programming language."
:author "Armando Blancas"}
blancas.kern.lexer.c-style
- (:use [blancas.kern.core])
- (:require [blancas.kern.lexer :as lex]))
+ (:require [blancas.kern.core :as k]
+ [blancas.kern.lexer :as lex]))
-(def- rec (lex/make-parsers lex/c-style))
+(def rec (lex/make-parsers lex/c-style-def))
(def trim (:trim rec))
(def lexeme (:lexeme rec))
diff --git a/src/main/clojure/blancas/kern/lexer/haskell_style.clj b/src/main/clojure/blancas/kern/lexer/haskell_style.cljc
similarity index 93%
rename from src/main/clojure/blancas/kern/lexer/haskell_style.clj
rename to src/main/clojure/blancas/kern/lexer/haskell_style.cljc
index ed3d3f4..f4e6626 100644
--- a/src/main/clojure/blancas/kern/lexer/haskell_style.clj
+++ b/src/main/clojure/blancas/kern/lexer/haskell_style.cljc
@@ -24,10 +24,10 @@ trim-newline Yes
Literal values follow the rules of the Haskell programming language."
:author "Armando Blancas"}
blancas.kern.lexer.haskell-style
- (:use [blancas.kern.core])
- (:require [blancas.kern.lexer :as lex]))
+ (:require [blancas.kern.core :as k]
+ [blancas.kern.lexer :as lex]))
-(def- rec (lex/make-parsers lex/haskell-style))
+(def rec (lex/make-parsers lex/haskell-style-def))
(def trim (:trim rec))
(def lexeme (:lexeme rec))
diff --git a/src/main/clojure/blancas/kern/lexer/java_style.clj b/src/main/clojure/blancas/kern/lexer/java_style.cljc
similarity index 94%
rename from src/main/clojure/blancas/kern/lexer/java_style.clj
rename to src/main/clojure/blancas/kern/lexer/java_style.cljc
index 9c0abb1..2f48e76 100644
--- a/src/main/clojure/blancas/kern/lexer/java_style.clj
+++ b/src/main/clojure/blancas/kern/lexer/java_style.cljc
@@ -24,10 +24,10 @@ trim-newline Yes
Literal values follow the rules of the Java programming language."
:author "Armando Blancas"}
blancas.kern.lexer.java-style
- (:use [blancas.kern.core])
- (:require [blancas.kern.lexer :as lex]))
+ (:require [blancas.kern.core :as k]
+ [blancas.kern.lexer :as lex]))
-(def- rec (lex/make-parsers lex/java-style))
+(def rec (lex/make-parsers lex/java-style-def))
(def trim (:trim rec))
(def lexeme (:lexeme rec))
diff --git a/src/main/clojure/blancas/kern/lexer/shell_style.clj b/src/main/clojure/blancas/kern/lexer/shell_style.cljc
similarity index 93%
rename from src/main/clojure/blancas/kern/lexer/shell_style.clj
rename to src/main/clojure/blancas/kern/lexer/shell_style.cljc
index 60dbea1..0f78fa8 100644
--- a/src/main/clojure/blancas/kern/lexer/shell_style.clj
+++ b/src/main/clojure/blancas/kern/lexer/shell_style.cljc
@@ -22,10 +22,10 @@ line-continuation Backslash
trim-newline No"
:author "Armando Blancas"}
blancas.kern.lexer.shell-style
- (:use [blancas.kern.core])
- (:require [blancas.kern.lexer :as lex]))
+ (:require [blancas.kern.core :as k]
+ [blancas.kern.lexer :as lex]))
-(def- rec (lex/make-parsers lex/shell-style))
+(def rec (lex/make-parsers lex/shell-style-def))
(def trim (:trim rec))
(def lexeme (:lexeme rec))
diff --git a/src/main/resources/custom_lexer.clj b/src/main/resources/custom_lexer.clj
index 3ba9802..4f15987 100644
--- a/src/main/resources/custom_lexer.clj
+++ b/src/main/resources/custom_lexer.clj
@@ -15,7 +15,7 @@
:trim-newline false))
;; Then make the customized parsers.
-(def- rec (lex/make-parsers hoc-style))
+(def rec (lex/make-parsers hoc-style))
;; For easy access, store the parsers in vars.
(def trim (:trim rec))
diff --git a/src/main/resources/customhoc.clj b/src/main/resources/customhoc.clj
index 7f53a66..4fe536b 100644
--- a/src/main/resources/customhoc.clj
+++ b/src/main/resources/customhoc.clj
@@ -27,7 +27,7 @@
:trim-newline false))
;; Then make the customized parsers.
-(def- rec (lex/make-parsers hoc-style))
+(def rec (lex/make-parsers hoc-style))
;; For easy access, store the parsers in vars.
(def trim (:trim rec))
diff --git a/src/main/resources/public/index.html b/src/main/resources/public/index.html
new file mode 100644
index 0000000..fd2ddfa
--- /dev/null
+++ b/src/main/resources/public/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/clojure/blancas/kern/runnner.cljs b/src/test/clojure/blancas/kern/runnner.cljs
new file mode 100644
index 0000000..5262944
--- /dev/null
+++ b/src/test/clojure/blancas/kern/runnner.cljs
@@ -0,0 +1,18 @@
+(ns blancas.kern.runnner
+ (:require [cljs.test :as test]
+ [doo.runner :refer-macros [doo-all-tests doo-tests]]
+ [blancas.kern.test-core]
+ [blancas.kern.test-lexer]
+ [blancas.kern.test-lexer-c]
+ [blancas.kern.test-lexer-haskell]
+ [blancas.kern.test-lexer-java]
+ [blancas.kern.test-lexer-shell]))
+
+(enable-console-print!)
+
+(doo-tests 'blancas.kern.test-core
+ 'blancas.kern.test-lexer
+ 'blancas.kern.test-lexer-c
+ 'blancas.kern.test-lexer-haskell
+ 'blancas.kern.test-lexer-java
+ 'blancas.kern.test-lexer-shell)
diff --git a/src/test/clojure/blancas/kern/test_core.clj b/src/test/clojure/blancas/kern/test_core.clj
deleted file mode 100644
index 32314cf..0000000
--- a/src/test/clojure/blancas/kern/test_core.clj
+++ /dev/null
@@ -1,3441 +0,0 @@
-;; Copyright (c) 2013 Armando Blancas. All rights reserved.
-;; The use and distribution terms for this software are covered by the
-;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-;; which can be found in the file epl-v10.html at the root of this distribution.
-;; By using this software in any fashion, you are agreeing to be bound by
-;; the terms of this license.
-;; You must not remove this notice, or any other, from this software.
-
-(ns blancas.kern.test-core
- (:use [blancas.kern.core]
- [clojure.test]
- [midje.sweet :exclude (expect one-of)]))
-
-;; Private functions from kern.core
-
-(def make-err-message (ns-resolve 'blancas.kern.core 'make-err-message))
-(def make-err-unexpect (ns-resolve 'blancas.kern.core 'make-err-unexpect))
-(def make-err-system (ns-resolve 'blancas.kern.core 'make-err-system))
-(def get-msg-str (ns-resolve 'blancas.kern.core 'get-msg-str))
-(def make-pos (ns-resolve 'blancas.kern.core 'make-pos))
-
-
-;; +-------------------------------------------------------------+
-;; | Basic parsers. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-0000
- (let [s1 (parse letter "xyz")
- s2 ((return 0) s1)]
- (fact "return"
- (:value s2) => 0
- (:ok s2) => true
- (:error s2) => nil
- (:input s2) => (:input s1)
- (:empty s2) => (:empty s1)
- (:pos s2) => (:pos s1)
- (:user s2) => (:user s1))))
-
-
-(deftest test-0005
- (let [em "the buck stops here"
- s1 (parse letter "xyz")
- s2 ((fail em) s1)]
- (fact "fail"
- (:value s2) => nil
- (:ok s2) => false
- (:empty s2) => true
- (:error s2) => (make-err-message (:pos s1) em)
- (:input s2) => (:input s1)
- (:pos s2) => (:pos s1)
- (:user s2) => (:user s1))))
-
-
-(deftest test-0010
- (let [s1 (parse letter "xyz")
- s2 ((satisfy #(Character/isLetter %)) s1)]
- (fact "satisfy - advances one char"
- (:input s2) => [\z]
- (:value s2) => \y
- (:ok s2) => true
- (:empty s2) => false
- (:user s2) => (:user s1)
- (:error s2) => nil
- (:pos s2) => (contains {:line 1 :col 3}))))
-
-
-(deftest test-0015
- (let [s1 (parse letter "u2")
- s2 ((satisfy #(Character/isDigit %)) s1)]
- (fact "satisfy - reaches the end of input"
- (:input s2) => empty?
- (:value s2) => \2
- (:ok s2) => true
- (:empty s2) => false
- (:user s2) => (:user s1)
- (:error s2) => nil
- (:pos s2) => (contains {:line 1 :col 3}))))
-
-
-(deftest test-0020
- (let [s1 (parse letter "u\t")
- s2 ((satisfy #(= \tab %)) s1)]
- (fact "satisfy - advnaces one tab; default 4 positions"
- (:value s2) => \tab
- (:ok s2) => true
- (:empty s2) => false
- (:user s2) => (:user s1)
- (:error s2) => nil
- (:pos s2) => (contains {:line 1 :col 6}))))
-
-
-(deftest test-0025
- (binding [*tab-width* 8]
- (let [s1 (parse letter "u\t")
- s2 ((satisfy #(= \tab %)) s1)]
- (fact "satisfy - advances one tab of 8 positions"
- (:value s2) => \tab
- (:ok s2) => true
- (:empty s2) => false
- (:user s2) => (:user s1)
- (:error s2) => nil
- (:pos s2) => (contains {:line 1 :col 10})))))
-
-
-(deftest test-0030
- (let [s1 (parse letter "u\n")
- s2 ((satisfy #(= \newline %)) s1)]
- (fact "satisfy - advances to the next line, first column"
- (:value s2) => \newline
- (:ok s2) => true
- (:empty s2) => false
- (:user s2) => (:user s1)
- (:error s2) => nil
- (:pos s2) => (contains {:line 2 :col 1}))))
-
-
-(deftest test-0035
- (let [em "end of input"
- s1 (parse (many letter) "xyz")
- s2 ((satisfy (fn [_] true)) s1)]
- (fact "satisfy - attempts to read past the end of input"
- (:input s2) => empty?
- (:value s2) => nil
- (:ok s2) => false
- (:empty s2) => true
- (:user s2) => (:user s1)
- (:error s2) => (make-err-unexpect (:pos s1) em)
- (:pos s2) => (:pos s1))))
-
-
-(deftest test-0040
- (let [em "\\2"
- s1 (parse letter "u2")
- s2 ((satisfy #(Character/isLetter %)) s1)]
- (fact "satisfy - the predicate fails"
- (:input s2) => [\2]
- (:value s2) => nil
- (:ok s2) => false
- (:empty s2) => true
- (:user s2) => (:user s1)
- (:error s2) => (make-err-system (:pos s1) em)
- (:pos s2) => (:pos s1))))
-
-
-;; +-------------------------------------------------------------+
-;; | Primitive parsers. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-0045
- (let [in "#(f %)"
- s1 (parse any-char in)]
- (fact "any-char"
- (:input s1) => (rest in)
- (:value s1) => \#
- (:ok s1) => true
- (:empty s1) => false
- (:user s1) => (:user s1)
- (:error s1) => nil
- (:pos s1) => (contains {:line 1 :col 2}))))
-
-
-(deftest test-0050
- (let [in "xyz"
- s1 (parse (>>= any-char
- (fn [a]
- (>>= any-char
- (fn [b]
- (>>= any-char
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "any-char - three in a row"
- (:value s1) => (seq in))))
-
-
-(deftest test-0055
- (let [em "end of input"
- s1 (parse any-char "")]
- (fact "any-char - fails on end of input"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- (:user s1) => (:user s1)
- (:error s1) => (make-err-unexpect (:pos s1) em)
- (:pos s1) => (contains {:line 1 :col 1}))))
-
-
-(deftest test-0060
- (let [in "abc"
- s1 (parse letter in)]
- (fact "letter - parses a single letter"
- (:input s1) => (rest in)
- (:value s1) => \a
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0065
- (let [in "xyz"
- s1 (parse (>>= letter
- (fn [a]
- (>>= letter
- (fn [b]
- (>>= letter
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "letter - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0070
- (let [in "123"
- s1 (parse letter in)]
- (fact "letter - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0075
- (let [in "abc"
- s1 (parse lower in)]
- (fact "lower - parses a single lower-case letter"
- (:input s1) => (rest in)
- (:value s1) => \a
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0080
- (let [in "xyz"
- s1 (parse (>>= lower
- (fn [a]
- (>>= lower
- (fn [b]
- (>>= lower
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "lower - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0085
- (let [in "XYZ"
- s1 (parse lower in)]
- (fact "lower - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0090
- (let [in "ABC"
- s1 (parse upper in)]
- (fact "upper - parses a single upper-case letter"
- (:input s1) => (rest in)
- (:value s1) => \A
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0095
- (let [in "XYZ"
- s1 (parse (>>= upper
- (fn [a]
- (>>= upper
- (fn [b]
- (>>= upper
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "upper - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0100
- (let [in "123"
- s1 (parse upper in)]
- (fact "upper - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0105
- (let [in " \t\t"
- s1 (parse white-space in)]
- (fact "white-space - parses a single whitespace character"
- (:input s1) => (rest in)
- (:value s1) => \space
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0110
- (let [in " \t "
- s1 (parse (>>= white-space
- (fn [a]
- (>>= white-space
- (fn [b]
- (>>= white-space
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "white-space - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0115
- (let [in "***"
- s1 (parse white-space in)]
- (fact "white-space - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0120
- (let [in " "
- s1 (parse space in)]
- (fact "space - parses a single space character"
- (:input s1) => (rest in)
- (:value s1) => \space
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0125
- (let [in " "
- s1 (parse (>>= space
- (fn [a]
- (>>= space
- (fn [b]
- (>>= space
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "space - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0130
- (let [in "***"
- s1 (parse space in)]
- (fact "space - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0135
- (let [in "\n\t."
- s1 (parse new-line* in)]
- (fact "new-line - parses a single newline character"
- (:input s1) => (rest in)
- (:value s1) => \newline
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0140
- (let [in "\n\n\n"
- s1 (parse (>>= new-line*
- (fn [a]
- (>>= new-line*
- (fn [b]
- (>>= new-line*
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "new-line* - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0145
- (let [in "***"
- s1 (parse new-line* in)]
- (fact "new-line* - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0150
- (let [in "\t|\t|"
- s1 (parse tab in)]
- (fact "tab - parses a single tab character"
- (:input s1) => (rest in)
- (:value s1) => \tab
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0155
- (let [in "\t\t\t"
- s1 (parse (>>= tab
- (fn [a]
- (>>= tab
- (fn [b]
- (>>= tab
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "tab - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0160
- (let [in "***"
- s1 (parse tab in)]
- (fact "tab - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0165
- (let [in "12345"
- s1 (parse digit in)]
- (fact "digit - parses a single digit"
- (:input s1) => (rest in)
- (:value s1) => \1
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0170
- (let [in "012"
- s1 (parse (>>= digit
- (fn [a]
- (>>= digit
- (fn [b]
- (>>= digit
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "digit - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0175
- (let [in "***"
- s1 (parse digit in)]
- (fact "digit - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0180
- (let [in "ABCDEF"
- s1 (parse hex-digit in)]
- (fact "hex-digit - parses a single hex digit"
- (:input s1) => (rest in)
- (:value s1) => \A
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0185
- (let [in "CAB"
- s1 (parse (>>= hex-digit
- (fn [a]
- (>>= hex-digit
- (fn [b]
- (>>= hex-digit
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "hex-digit - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0190
- (let [in "***"
- s1 (parse digit in)]
- (fact "hex-digit - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0195
- (let [in "12345"
- s1 (parse oct-digit in)]
- (fact "oct-digit - parses a single octal digit"
- (:input s1) => (rest in)
- (:value s1) => \1
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0200
- (let [in "567"
- s1 (parse (>>= oct-digit
- (fn [a]
- (>>= oct-digit
- (fn [b]
- (>>= oct-digit
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "oct-digit - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0205
- (let [in "***"
- s1 (parse digit in)]
- (fact "oct-digit - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0210
- (let [in "a0b1"
- s1 (parse alpha-num in)]
- (fact "alpha-num - parses a single alpha-numeric character"
- (:input s1) => (rest in)
- (:value s1) => \a
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0215
- (let [in "a1b"
- s1 (parse (>>= alpha-num
- (fn [a]
- (>>= alpha-num
- (fn [b]
- (>>= alpha-num
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "alpha-num - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0220
- (let [in "+*&"
- s1 (parse alpha-num in)]
- (fact "alpha-num - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0225
- (let [in "X()"
- s1 (parse (sym* \X) in)]
- (fact "sym* - parses a single X"
- (:input s1) => (rest in)
- (:value s1) => \X
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0230
- (let [in "p\t;"
- s1 (parse (>>= (sym* \p)
- (fn [a]
- (>>= (sym* \tab)
- (fn [b]
- (>>= (sym* \;)
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "sym* - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0235
- (let [in "***"
- s1 (parse (sym* \X) in)]
- (fact "sym* - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0235-05
- (let [in "x()"
- s1 (parse (sym- \X) in)]
- (fact "sym- - parses a single x"
- (:input s1) => (rest in)
- (:value s1) => \X
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0235-10
- (let [in "X()"
- s1 (parse (sym- \X) in)]
- (fact "sym- - parses a single X"
- (:input s1) => (rest in)
- (:value s1) => \X
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0235-15
- (let [in "A()"
- s1 (parse (sym- \X) in)
- em (get-msg-str (:error s1))]
- (fact "sym- - parses a single X"
- (:input s1) => [\A \( \)]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\A\nexpecting \\X")))
-
-
-(deftest test-0240
- (let [in "program foo()"
- s1 (parse (token* "program") in)]
- (fact "token* - parses a specific word"
- (:input s1) => (drop (count "program") in)
- (:value s1) => "program"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0245
- (let [in "foo(bar)baz"
- s1 (parse (>>= (token* "foo")
- (fn [a]
- (>>= (token* "(bar)")
- (fn [b]
- (>>= (token* "baz")
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "token* - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => ["foo" "(bar)" "baz"])))
-
-
-(deftest test-0250
- (let [in "goat"
- s1 (parse (token* "goal") in)
- em (get-msg-str (:error s1))]
- (fact "token* - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected goat\nexpecting goal")))
-
-
-(deftest test-0250-05
- (let [in "function foo()"
- s1 (parse (token* "function" "procedure") in)]
- (fact "token* - parses one of multiple word choices"
- (:input s1) => (drop (count "function") in)
- (:value s1) => "function"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-10
- (let [in "procedure foo()"
- s1 (parse (token* "function" "procedure") in)]
- (fact "token* - parses one of multiple word choices"
- (:input s1) => (drop (count "procedure") in)
- (:value s1) => "procedure"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-15
- (let [in "program foo()"
- s1 (parse (token- "PROGRAM") in)]
- (fact "token- - parses a specific word; non case-sensetive"
- (:input s1) => (drop (count "program") in)
- (:value s1) => "PROGRAM"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-20
- (let [in "Program foo()"
- s1 (parse (token- "PROGRAM") in)]
- (fact "token- - parses a specific word; non case-sensetive"
- (:input s1) => (drop (count "program") in)
- (:value s1) => "PROGRAM"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-25
- (let [in "PROGRAM foo()"
- s1 (parse (token- "PROGRAM") in)]
- (fact "token- - parses a specific word; non case-sensetive"
- (:input s1) => (drop (count "program") in)
- (:value s1) => "PROGRAM"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-30
- (let [in "goat"
- s1 (parse (token- "goal") in)
- em (get-msg-str (:error s1))]
- (fact "token- - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected goat\nexpecting goal")))
-
-
-(deftest test-0250-35
- (let [in "FUNction foo()"
- s1 (parse (token- "function" "procedure") in)]
- (fact "token- - parses one of multiple word choices"
- (:input s1) => (drop (count "function") in)
- (:value s1) => "function"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-40
- (let [in "PROCedure foo()"
- s1 (parse (token- "function" "procedure") in)]
- (fact "token- - parses one of multiple word choices"
- (:input s1) => (drop (count "procedure") in)
- (:value s1) => "procedure"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-45
- (let [in "program foo()"
- s1 (parse (word* letter "program") in)]
- (fact "word* - parses a specific, delimited word"
- (:input s1) => (drop (count "program") in)
- (:value s1) => "program"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-50
- (let [in "else{}"
- s1 (parse (word* letter "else") in)]
- (fact "word* - parses a specific, delimited word"
- (:input s1) => [\{ \}]
- (:value s1) => "else"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-55
- (let [in "procedure"
- s1 (parse (word* letter "proc") in)
- em (get-msg-str (:error s1))]
- (fact "word* - fails because is not delimited"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected e\nexpecting end of proc")))
-
-
-(deftest test-0250-60
- (let [in "otherwise{}"
- s1 (parse (word* letter "else" "otherwise") in)]
- (fact "word* - parses a specific, delimited word"
- (:input s1) => [\{ \}]
- (:value s1) => "otherwise"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-65
- (let [in "subroutine"
- s1 (parse (word* letter "proc" "func" "method") in)
- em (get-msg-str (:error s1))]
- (fact "word* - fails with incorrect input"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected subr\nunexpected subrou\nexpecting proc, func or method")))
-
-
-(deftest test-0250-70
- (let [in "PROGRAM foo()"
- s1 (parse (word- letter "program") in)]
- (fact "word- - parses a specific, delimited word; not case-senstive"
- (:input s1) => (drop (count "program") in)
- (:value s1) => "program"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-75
- (let [in "Else{}"
- s1 (parse (word- letter "else") in)]
- (fact "word- - parses a specific, delimited word; not case-senstive"
- (:input s1) => [\{ \}]
- (:value s1) => "else"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-80
- (let [in "ProcEdure"
- s1 (parse (word- letter "proc") in)
- em (get-msg-str (:error s1))]
- (fact "word- - fails because is not delimited"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected E\nexpecting end of proc")))
-
-
-(deftest test-0250-85
- (let [in "OtherWise{}"
- s1 (parse (word- letter "else" "otherwise") in)]
- (fact "word- - parses a specific, delimited word; not case-senstive"
- (:input s1) => [\{ \}]
- (:value s1) => "otherwise"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0250-90
- (let [in "SUBroutine"
- s1 (parse (word- letter "proc" "func" "method") in)
- em (get-msg-str (:error s1))]
- (fact "word- - fails with incorrect input"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected SUBr\nunexpected SUBrou\nexpecting proc, func or method")))
-
-
-(deftest test-0255
- (let [in "* 2"
- s1 (parse (one-of* "+-*/^") in)]
- (fact "one-of* - parses one of the supplied characters"
- (:input s1) => (rest in)
- (:value s1) => \*
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0260
- (let [in "*-+"
- op "+-*/"
- s1 (parse (>>= (one-of* op)
- (fn [a]
- (>>= (one-of* op)
- (fn [b]
- (>>= (one-of* op)
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "one-of* - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0265
- (let [in "abc"
- s1 (parse (one-of* "+-*/") in)]
- (fact "one-of* - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0270
- (let [in ": 2"
- s1 (parse (none-of* "+-*/^") in)]
- (fact "none-of* - parses a character not supplied"
- (:input s1) => (rest in)
- (:value s1) => \:
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0275
- (let [in "^&%"
- op "+-*/"
- s1 (parse (>>= (none-of* op)
- (fn [a]
- (>>= (none-of* op)
- (fn [b]
- (>>= (none-of* op)
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "none-of* - three in a row until end of input"
- (:input s1) => empty?
- (:value s1) => (seq in))))
-
-
-(deftest test-0280
- (let [in "$foo"
- s1 (parse (none-of* "!@#$%^*()") in)]
- (fact "none-of* - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0280-05
- (let [in ""
- s1 (parse eof in)]
- (fact "eof - parses an empty string"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => true)))
-
-
-(deftest test-0280-10
- (let [in "END."
- s1 (parse (>> (token* "END.") eof) in)]
- (fact "eof - verifies that input ends"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0280-15
- (let [in "END.// the end"
- s1 (parse (>> (token* "END.") eof) in)
- em (get-msg-str (:error s1))]
- (fact "eof - verifies that input ends"
- (:input s1) => (seq "// the end")
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected /\nexpecting end of input")))
-
-
-(deftest test-0280-20
- (let [in "12\n"
- s1 (parse (<*> digit digit new-line*) in)]
- (fact "new-line* - a new line after two digits"
- (:input s1) => empty?
- (:value s1) => [\1 \2 \newline]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0280-25
- (let [in "AB\r\nCD\r\n"
- s1 (parse (many1 (<< (many1 upper) new-line*)) in)]
- (fact "new-line* - pairs of letters separated by a new line"
- (:input s1) => empty?
- (:value s1) => [[\A \B] [\C \D]]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0280-30
- (let [in "12345 "
- s1 (parse (<< (many1 digit) new-line*) in)
- em (get-msg-str (:error s1))]
- (fact "new-line* - the line doesn't end with a new line"
- (:input s1) => [\space]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\space\nexpecting new line")))
-
-
-(deftest test-0280-35
- (let [in " \t \t \n \t *"
- s1 (parse (skip-ws (sym* \*)) in)]
- (fact "skip-ws - skips whitespaces before parsing a star"
- (:input s1) => empty?
- (:value s1) => \*
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0280-40
- (let [in "*"
- s1 (parse (skip-ws (sym* \*)) in)]
- (fact "skip-ws - nothing to skip before parsing a star"
- (:input s1) => empty?
- (:value s1) => \*
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0280-45
- (let [in "Now is the time... right... now."
- s1 (parse (field* "!") in)]
- (fact "field* - reads the whole string"
- (:input s1) => empty?
- (:value s1) => in
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0280-50
- (let [in "Now is the time; right... now."
- s1 (parse (field* ";") in)]
- (fact "field* - reads the field delimited by a semicolon"
- (:input s1) => (seq "; right... now.")
- (:value s1) => "Now is the time"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0280-55
- (let [in "Now-is-the-time"
- s1 (parse (split-on "-") in)]
- (fact "field - breaks the string into the words"
- (:value s1) => ["Now" "is" "the" "time"]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
- (deftest test-0280-60
- (let [in "Software,Tooling,495.95,0.00,,15,,xyz"
- s1 (parse (split-on ",") in)]
- (fact "field - breaks the string into fields; some are empty"
- (:value s1) => ["Software" "Tooling" "495.95" "0.00" "15" "xyz"]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0280-65
- (let [in "Now is the time. Or, is it? Yes! yes! that's it."
- s1 (parse (split-on " ,?!.") in)]
- (fact "field - collects all words; skips the given punctuation"
- (:value s1) => ["Now" "is" "the" "time" "Or" "is" "it" "Yes" "yes" "that's" "it"]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0280-70
- (fact "mark parses a punctuation mark."
- (value mark "!") => \!
- (value mark "@") => \@
- (value mark "*") => \*
- (value mark ":") => \:
- (value mark "/") => \/
- (value mark ".") => \.))
-
-
-;; +-------------------------------------------------------------+
-;; | Parser combinators. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-0285
- (let [s1 (parse letter "1")
- em (-> s1 :error :msgs first :text force)]
- (fact "first message in the msgs list"
- em => "letter")))
-
-
-(deftest test-0290
- (let [s1 (parse letter "1")
- em (get-msg-str (:error s1))]
- (fact "verify error messages"
- em => "unexpected \\1\nexpecting letter")))
-
-
-(deftest test-0295
- (let [s1 (parse (> (<*> digit letter) "digit,letter") "01")
- em (-> s1 :error :msgs first :text force)]
- (fact "> - does not add message when input is consumed"
- em =not=> "digit,letter")))
-
-
-(deftest test-0300
- (let [s1 (parse (> (<*> digit letter) "digit,letter") "01")
- em (get-msg-str (:error s1))]
- (fact "> - verifies error messages in <*>"
- em => "unexpected \\1\nexpecting letter")))
-
-
-(deftest test-0305
- (let [s1 (parse (> (<*> digit letter) "digit,letter") "0")
- em (get-msg-str (:error s1))]
- (fact "> - verifies error messages in <*>"
- em => "unexpected end of input\nexpecting letter")))
-
-
-(deftest test-0310
- (let [s1 (parse (<|> digit letter) "*")
- em (get-msg-str (:error s1))]
- (fact "<|> - verifies error messages"
- em => "unexpected \\*\nexpecting digit or letter")))
-
-
-(deftest test-0315
- (let [s1 (parse (<|> (sym* \x) (<|> letter digit)) "*")
- em (get-msg-str (:error s1))]
- (fact "<|> - verifies error messages with 3 choices"
- em => "unexpected \\*\nexpecting \\x, letter or digit")))
-
-
-(deftest test-0320
- (let [s1 (parse (<|> (<|> white-space (sym* \x)) (<|> letter digit)) "*")
- em (get-msg-str (:error s1))]
- (fact "<|> - verifies error messages with 4 choices"
- em => "unexpected \\*\nexpecting whitespace, \\x, letter or digit")))
-
-
-(deftest test-0320-05
- (let [s1 (parse (expect (<+> letter digit) "number two") "U2")]
- (fact "expect - parser succeeds"
- (:value s1) => "U2"
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0320-10
- (let [s1 (parse (expect (<+> letter digit) "number two") "UX")
- em (get-msg-str (:error s1))]
- (fact "expect - parser fails consuming input"
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\X\nexpecting number two")))
-
-
-(deftest test-0320-15
- (let [s1 (parse (expect (<+> letter digit) "number two") "007")
- em (get-msg-str (:error s1))]
- (fact "expect - parser fails without consuming any input"
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- (:input s1) => [\0 \0 \7]
- em => "unexpected \\0\nexpecting number two")))
-
-
-(deftest test-0325
- (let [s1 (parse (<|> letter digit) "U2")]
- (fact "<|> - the first parser succeeds"
- (:value s1) => \U
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\2]
- (:empty s1) => false)))
-
-
-(deftest test-0330
- (let [s1 (parse (<|> digit letter) "XYZ")]
- (fact "<|> - the second parser succeeds"
- (:value s1) => \X
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\Y \Z]
- (:empty s1) => false)))
-
-
-(deftest test-0335
- (let [s1 (parse (<|> (>> letter digit) letter) "XYZ")
- em (get-msg-str (:error s1))]
- (fact "<|> - the first parse fails consuming input"
- (:value s1) => nil
- (:ok s1) => false
- (:input s1) => [\Y \Z]
- (:empty s1) => false
- em => "unexpected \\Y\nexpecting digit")))
-
-
-(deftest test-0340
- (let [s1 (parse (<|> white-space letter digit) "*")
- em (get-msg-str (:error s1))]
- (fact "<|> - verifies error messages with 3 choices"
- em => "unexpected \\*\nexpecting whitespace, letter or digit")))
-
-
-(deftest test-0345
- (let [s1 (parse (<|> white-space (sym* \x) letter digit) "*")
- em (get-msg-str (:error s1))]
- (fact "<|> - verifies error messages with 4 choices"
- em => "unexpected \\*\nexpecting whitespace, \\x, letter or digit")))
-
-
-(deftest test-0350
- (let [s1 (parse (<|> white-space (sym* \x) letter digit) "\t")]
- (fact "<|> - the first of 4 parser succeeds"
- (:value s1) => \tab
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0355
- (let [s1 (parse (<|> white-space (sym* \x) letter digit) "x")]
- (fact "<|> - the second of 4 parser succeeds"
- (:value s1) => \x
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0360
- (let [s1 (parse (<|> white-space (sym* \x) letter digit) "z")]
- (fact "<|> - the third of 4 parser succeeds"
- (:value s1) => \z
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0365
- (let [s1 (parse (<|> white-space (sym* \x) letter digit) "0")]
- (fact "<|> - the fourth parser succeeds"
- (:value s1) => \0
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0370
- (let [p1 (>>= letter (fn [x] (return (Character/toUpperCase x))))
- s1 (parse p1 "xyz")]
- (fact ">>= - advances one char"
- (:input s1) => [\y \z]
- (:value s1) => \X
- (:ok s1) => true
- (:empty s1) => false
- (:user s1) => nil
- (:error s1) => nil
- (:pos s1) => (contains {:line 1 :col 2}))))
-
-
-(deftest test-0375
- (let [p1 (>>= digit
- (fn [x] (>>= digit
- (fn [y] (return (Integer/parseInt (str x y)))))))
- s1 (parse p1 "50113")]
- (fact ">>= - advances two chars"
- (:input s1) => [\1 \1 \3]
- (:value s1) => 50
- (:ok s1) => true
- (:empty s1) => false
- (:user s1) => nil
- (:error s1) => nil
- (:pos s1) => (contains {:line 1 :col 3}))))
-
-
-(deftest test-0380
- (let [in "012345"
- p1 (>>= letter (fn [x] (return (int x))))
- s1 (parse p1 in)
- em (get-msg-str (:error s1))]
- (fact ">>= - the first parser fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- (:user s1) => nil
- (:pos s1) => (contains {:line 1 :col 1})
- em => "unexpected \\0\nexpecting letter")))
-
-
-(deftest test-0385
- (let [p1 (>>= letter (fn [_] digit))
- s1 (parse p1 "xyz")
- em (get-msg-str (:error s1))]
- (fact ">>= - the second parser fails"
- (:input s1) => [\y \z]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- (:user s1) => nil
- (:pos s1) => (contains {:line 1 :col 2})
- em => "unexpected \\y\nexpecting digit")))
-
-
-(deftest test-0385-05
- (let [p1 (bind [x letter] (return (Character/toUpperCase x)))
- s1 (parse p1 "xyz")]
- (fact "bind - advances one char"
- (:input s1) => [\y \z]
- (:value s1) => \X
- (:ok s1) => true
- (:empty s1) => false
- (:user s1) => nil
- (:error s1) => nil
- (:pos s1) => (contains {:line 1 :col 2}))))
-
-
-(deftest test-0385-10
- (let [p1 (bind [x digit y digit]
- (return (Integer/parseInt (str x y))))
- s1 (parse p1 "50113")]
- (fact "bind - advances two chars"
- (:input s1) => [\1 \1 \3]
- (:value s1) => 50
- (:ok s1) => true
- (:empty s1) => false
- (:user s1) => nil
- (:error s1) => nil
- (:pos s1) => (contains {:line 1 :col 3}))))
-
-
-(deftest test-0385-15
- (let [p1 (bind [_ (sym* \()
- s (<+> (many1 digit))
- _ (sym* \))]
- (return (* (Integer/parseInt s) -1)))
- s1 (parse p1 "(50113)")]
- (fact "bind - reads a negative number in parens, as in accounting"
- (:input s1) => empty?
- (:value s1) => -50113
- (:ok s1) => true
- (:empty s1) => false
- (:user s1) => nil
- (:error s1) => nil)))
-
-
-(deftest test-0385-20
- (let [p1 (bind [x letter]
- (if (= x \x)
- (bind [y (sym* \Y)
- z (sym* \Z)] (return "first"))
- (bind [n (many1 digit)] (return 5005))))
- s1 (parse p1 "xYZ")]
- (fact "bind - uses nested bind inside the first function body"
- (:input s1) => empty?
- (:value s1) => "first"
- (:ok s1) => true
- (:empty s1) => false
- (:user s1) => nil
- (:error s1) => nil)))
-
-
-(deftest test-0385-25
- (let [p1 (bind [x letter]
- (if (= x \x)
- (bind [y (sym* \Y)
- z (sym* \Z)] (return "first"))
- (bind [n (many1 digit)] (return 666))))
- s1 (parse p1 "A10002450")]
- (fact "bind - uses nested bind inside the first function body"
- (:input s1) => empty?
- (:value s1) => 666
- (:ok s1) => true
- (:empty s1) => false
- (:user s1) => nil
- (:error s1) => nil)))
-
-
-(deftest test-0385-30
- (let [p1 (<|> (bind [x (many1 digit)] (return true))
- (bind [x (many1 letter)] (return false)))
- s1 (parse p1 "FALSE")]
- (fact "bind - the first bind fails, the second succeeds"
- (:input s1) => empty?
- (:value s1) => false
- (:ok s1) => true
- (:empty s1) => false
- (:user s1) => nil
- (:error s1) => nil)))
-
-
-(deftest test-0390
- (let [p1 (>> (sym* \+) digit)
- s1 (parse p1 "+1")]
- (fact ">> - consumes two chars, keeps the second"
- (:input s1) => empty?
- (:value s1) => \1
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0395
- (let [p1 (>> (sym* \+) digit)
- s1 (parse p1 "01")]
- (fact ">> - the first parser fails"
- (:input s1) => [\0 \1]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0400
- (let [p1 (>> (sym* \+) digit)
- s1 (parse p1 "+A")]
- (fact ">> - the second parser fails"
- (:input s1) => [\A]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false)))
-
-
-(deftest test-0405
- (let [p1 (>> digit digit letter)
- s1 (parse p1 "01A")]
- (fact ">> - consumes three chars, keeps the last"
- (:input s1) => empty?
- (:value s1) => \A
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0410
- (let [p1 (>> digit digit digit letter)
- s1 (parse p1 "012A")]
- (fact ">> - consumes four chars, keeps the last"
- (:input s1) => empty?
- (:value s1) => \A
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0415
- (let [p1 (>> digit digit digit letter)
- s1 (parse p1 "A")]
- (fact ">> - the first fails"
- (:input s1) => [\A]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0420
- (let [p1 (>> digit digit digit letter)
- s1 (parse p1 "01A")]
- (fact ">> - the third fails"
- (:input s1) => [\A]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false)))
-
-
-(deftest test-0425
- (let [p1 (<< letter (sym* \;))
- s1 (parse p1 "a;")]
- (fact "<< - consumes two chars, keeps the first"
- (:input s1) => empty?
- (:value s1) => \a
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0430
- (let [p1 (<< letter (sym* \;))
- s1 (parse p1 "0;")]
- (fact "<< - the first parser fails"
- (:input s1) => [\0 \;]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0435
- (let [p1 (<< letter (sym* \;))
- s1 (parse p1 "A*")]
- (fact "<< - the second parser fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false)))
-
-
-(deftest test-0440
- (let [p1 (<< any-char digit digit)
- s1 (parse p1 "+01")]
- (fact "<< - consumes three chars, keeps the first"
- (:input s1) => empty?
- (:value s1) => \+
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0445
- (let [p1 (<< any-char digit digit digit digit)
- s1 (parse p1 "+0123")]
- (fact "<< - consumes five chars, keeps the first"
- (:input s1) => empty?
- (:value s1) => \+
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0450
- (let [p1 (<< any-char digit digit digit digit)
- s1 (parse p1 "+01*")]
- (fact "<< - the fourth parser fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false)))
-
-
-(deftest test-0455
- (let [s1 (parse (<$> count (many any-char)) "abcdef+01234*")]
- (fact "<$> - counts the length of the input"
- (:input s1) => empty?
- (:value s1) => 13
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0460
- (let [s1 (parse (<$> #(- (int %) (int \0)) digit) "9")]
- (fact "<$> - converts a char digit into an int"
- (:input s1) => empty?
- (:value s1) => 9
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0465
- (let [s1 (parse (<$> #(- (int %) (int \0)) digit) "A")]
- (fact "<$> - fails and the function is not applied"
- (:input s1) => [\A]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0469-a
- (let [s1 (parse (<*> digit) "9")]
- (fact "<*> - collects from one parser"
- (:input s1) => empty?
- (:value s1) => [\9]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0469-b
- (let [s1 (parse (<*> letter) "U2")]
- (fact "<*> - collects from one parser"
- (:input s1) => [\2]
- (:value s1) => [\U]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0470
- (let [s1 (parse (<*> (sym* \-) digit) "-1")]
- (fact "<*> - collects from two parsers"
- (:input s1) => empty?
- (:value s1) => [\- \1]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0475
- (let [s1 (parse (<*> (sym* \-) digit (sym* \;)) "-1;")]
- (fact "<*> - collects from three parsers"
- (:input s1) => empty?
- (:value s1) => [\- \1 \;]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0480
- (let [p1 (<*> letter (>> (sym* \|) letter) (>> (sym* \|) digit))
- s1 (parse p1 "X|Y|9")]
- (fact "<*> - collects from filtering parsers"
- (:input s1) => empty?
- (:value s1) => [\X \Y \9]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0485
- (let [in "ABC012"
- p1 (<*> (<*> letter letter letter) (<*> digit digit digit))
- s1 (parse p1 in)]
- (fact "<*> - collects from compound parsers"
- (:input s1) => empty?
- (:value s1) => '((\A \B \C) (\0 \1 \2))
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0485-05
- (let [s1 (parse (<*> letter digit) "u2")]
- (fact "<*> - collects results in a vector"
- (:input s1) => empty?
- (:value s1) => vector?
- (:value s1) => [\u \2]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0490
- (let [s1 (parse (<*> letter digit) "*")]
- (fact "<*> - the first parser fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0495
- (let [s1 (parse (<*> letter digit) "A*")]
- (fact "<*> - the second parser fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false)))
-
-
-(deftest test-0500
- (let [s1 (parse (<*> letter tab digit) "A\t*")]
- (fact "<*> - the third parser fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false)))
-
-
-(deftest test-0505
- (let [p1 (<*> letter tab tab tab tab tab (sym* \x))
- s1 (parse p1 "A\t\t\t\t\t*")]
- (fact "<*> - the seventh parser fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false)))
-
-
-(deftest test-0510
- (let [s1 (parse (<:> lower) "a")]
- (fact "<:> - parses an item; consumes all input"
- (:input s1) => empty?
- (:value s1) => \a
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0515
- (let [s1 (parse (<:> (<$> (partial apply str) (<*> (token* "end") space))) "end ")]
- (fact "<:> - parses nested items; consumes all input"
- (:input s1) => empty?
- (:value s1) => "end "
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0520
- (let [in "a1b3c4d5e7f8"
- p1 (<*> letter digit)
- s1 (parse (<:> (many p1)) in)]
- (fact "<:> - parses six pairs; consumes all input"
- (:input s1) => empty?
- (:value s1) => '((\a \1) (\b \3) (\c \4) (\d \5) (\e \7) (\f \8))
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0525
- (let [s1 (parse (<:> lower) "*&!")]
- (fact "<:> - fails with parsers consuming no input; consumes no input"
- (:input s1) => [\* \& \!]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-0530
- (let [s1 (parse (<:> (<*> upper lower upper)) "Mi*")
- em (get-msg-str (:error s1))]
- (fact "<:> - fails with parsers consuming input; consumes no input"
- (:input s1) => [\M \i \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\*\nexpecting uppercase letter")))
-
-
-(deftest test-0535
- (let [s1 (parse (<|> (<:> (>> digit letter)) digit) "1*")
- em (get-msg-str (:error s1))]
- (fact "<:> - verifies that it allows <|> to test the next choice"
- (:input s1) => [\*]
- (:value s1) => \1
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0540
- (let [s1 (parse (<|> (<:> letter) digit) "***")
- em (get-msg-str (:error s1))]
- (fact "<:> - verifies that it carries over the error msg"
- (:input s1) => [\* \* \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\*\nexpecting letter or digit")))
-
-
-(deftest test-0545
- (let [s1 (parse (many lower) "*")]
- (fact "many - parses zero items"
- (:input s1) => [\*]
- (:value s1) => empty?
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-0550
- (let [s1 (parse (many lower) "a*")]
- (fact "many - parses one item"
- (:input s1) => [\*]
- (:value s1) => [\a]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0555
- (let [s1 (parse (many (optional letter)) "ABCDEGFHIJK*")]
- (fact "many - skips optional items; consumes input though value is empty"
- (:input s1) => [\*]
- (:value s1) => (seq "ABCDEGFHIJK")
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0560
- (let [in "a1b3c4d5e7f8"
- p1 (<*> letter digit)
- s1 (parse (many p1) in)]
- (fact "many - parses six compound items"
- (:input s1) => empty?
- (:value s1) => '((\a \1) (\b \3) (\c \4) (\d \5) (\e \7) (\f \8))
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0560-05
- (let [s1 (parse (many lower) "*")]
- (fact "many - collects the result in a vector; parses zero items"
- (:input s1) => [\*]
- (:value s1) => empty?
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-0560-10
- (let [s1 (parse (many lower) "a*")]
- (fact "many - collects the result in a vector; parses one item"
- (:input s1) => [\*]
- (:value s1) => [\a]
-
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0565
- (let [s1 (parse (<|> (many lower) (sym* \*)) "*")]
- (fact "many - consumes no input and succeeds; <|> returns its value"
- (:input s1) => [\*]
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-0570
- (let [in "a1b3c4d5ee"
- p1 (<*> letter digit)
- s1 (parse (many p1) in)
- em (get-msg-str (:error s1))]
- (fact "many - parses four compound items, then fails in the next compound item"
- (:input s1) => [\e]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\e\nexpecting digit")))
-
-
-(deftest test-0575
- (let [s1 (parse (many1 lower) "*")
- em (get-msg-str (:error s1))]
- (fact "many1 - fails with zero items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\*\nexpecting lowercase letter")))
-
-
-(deftest test-0580
- (let [s1 (parse (many1 lower) "a*")]
- (fact "many1 - parses one item"
- (:input s1) => [\*]
- (:value s1) => [\a]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0580-05
- (let [s1 (parse (many1 lower) "a*")]
- (fact "many1 - collects the result in a vector; parses one item"
- (:input s1) => [\*]
- (:value s1) => [\a]
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0585
- (let [in "a1b3c4d5e7f8"
- p1 (<*> letter digit)
- s1 (parse (many1 p1) in)]
- (fact "many1 - parses six compound items"
- (:input s1) => empty?
- (:value s1) => '((\a \1) (\b \3) (\c \4) (\d \5) (\e \7) (\f \8))
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0590
- (let [s1 (parse (<|> (many1 lower) (sym* \*)) "w*")]
- (fact "many1 - consumes input; <|> returns its value"
- (:input s1) => [\*]
- (:value s1) => [\w]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0595
- (let [s1 (parse (<|> (many1 digit) upper) "*")
- em (get-msg-str (:error s1))]
- (fact "many1 - fails; passes on empty, errors to <|>"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\*\nexpecting digit or uppercase letter")))
-
-
-(deftest test-0600
- (let [s1 (parse (<|> (many1 digit) upper) "A")]
- (fact "many1 - fails; passes on empty, are cleared in <|>"
- (:input s1) => empty?
- (:value s1) => \A
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0605
- (let [in "a1b3c4d5ee"
- p1 (<*> letter digit)
- s1 (parse (many1 p1) in)
- em (get-msg-str (:error s1))]
- (fact "many1 - parses four compound items, then fails in the next compound item"
- (:input s1) => [\e]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\e\nexpecting digit")))
-
-
-(deftest test-0610
- (let [s1 (parse (optional (<*> upper digit)) "U2*")]
- (fact "optional - parses an optional item"
- (:input s1) => [\*]
- (:value s1) => [\U \2]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0615
- (let [s1 (parse (optional (<*> upper digit)) "u2*")]
- (fact "optional - fails consuming no input"
- (:input s1) => [\u \2 \*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-0620
- (let [s1 (parse (optional (<*> upper digit)) "UP*")
- em (get-msg-str (:error s1))]
- (fact "optional - fails consuming input"
- (:input s1) => [\P \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\P\nexpecting digit")))
-
-
-(deftest test-0625
- (let [p1 (<$> (partial apply str) (<*> (optional upper) (sym* \*)))
- s1 (parse p1 "U*")]
- (fact "optional - skips the optional char"
- (:input s1) => empty?
- (:value s1) => "U*"
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0630
- (let [s1 (parse (option "XY" (<*> upper digit)) "U2*")]
- (fact "option - parses an item"
- (:input s1) => [\*]
- (:value s1) => [\U \2]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0635
- (let [s1 (parse (option "XY" (<*> upper digit)) "u2*")]
- (fact "option - fails without consuming input; produces optional value"
- (:input s1) => [\u \2 \*]
- (:value s1) => "XY"
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-0640
- (let [s1 (parse (option "XY" (<*> upper digit)) "UP*")
- em (get-msg-str (:error s1))]
- (fact "option - fails consuming input"
- (:input s1) => [\P \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\P\nexpecting digit")))
-
-
-(deftest test-0640-05
- (let [s1 (parse (skip (sym* \*)) "*")]
- (fact "skip - skips a star"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0640-10
- (let [s1 (parse (skip letter digit) "U2")]
- (fact "skip - skips a letter and a digit"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0640-15
- (let [s1 (parse (skip (sym* \*) letter digit (sym* \*)) "*U2*")]
- (fact "skip - skips a star, a letter, a digit, and a star"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0645
- (let [s1 (parse (skip-many letter) "*")]
- (fact "skip-many - skips zero letters"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-0650
- (let [s1 (parse (skip-many (<*> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "skip-many - skips zero compound items; <*> fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0655
- (let [s1 (parse (skip-many (<*> digit lower)) "0x*")]
- (fact "skip-many - skips one compound item"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0660
- (let [s1 (parse (skip-many letter) "abcdefghijk*")]
- (fact "skip-many - skips letters"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0665
- (let [s1 (parse (skip-many (<*> digit lower)) "0x1y2z*")]
- (fact "skip-many - skips three compound items; consumes no more input"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0670
- (let [s1 (parse (>> (skip-many (optional digit)) (sym* \*)) "0123456789*")]
- (fact "skip-many - skips optional items; then consumes more input"
- (:input s1) => empty?
- (:value s1) => \*
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0675
- (let [s1 (parse (skip-many1 letter) "*")
- em (get-msg-str (:error s1))]
- (fact "skip-many1 - fails with zero letters"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\*\nexpecting letter")))
-
-
-(deftest test-0680
- (let [s1 (parse (skip-many1 (<*> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "skip-many1 - skips zero compound items; <*> fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0685
- (let [s1 (parse (skip-many1 (<*> digit lower)) "0x*")]
- (fact "skip-many1 - skips one compound item"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0690
- (let [s1 (parse (skip-many1 letter) "abcdefghijk*")]
- (fact "skip-many1 - skips letters"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0695
- (let [s1 (parse (skip-many1 (<*> digit lower)) "0x1y2z*")]
- (fact "skip-many1 - skips three compound items; consumes no more input"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0700
- (let [s1 (parse (>> (skip-many1 (optional digit)) (sym* \*)) "0123456789*")]
- (fact "skip-many1 - skips optional items; then consumes more input"
- (:input s1) => empty?
- (:value s1) => \*
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0705
- (let [s1 (parse (sep-by (sym* \,) digit) "*")]
- (fact "sep-by - there are no separated items"
- (:input s1) => [\*]
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-0710
- (let [s1 (parse (sep-by (sym* \,) (>> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "sep-by - there are no separated compound items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0715
- (let [s1 (parse (sep-by (sym* \,) digit) "0*")]
- (fact "sep-by - one item, no separator"
- (:input s1) => [\*]
- (:value s1) => [\0]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0720
- (let [s1 (parse (sep-by (sym* \,) (<*> upper digit)) "U2*")]
- (fact "sep-by - one compound item, no separator"
- (:input s1) => [\*]
- (:value s1) => [[\U \2]]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0725
- (let [s1 (parse (sep-by (sym* \,) (>> letter digit)) "U2,*")
- em (get-msg-str (:error s1))]
- (fact "sep-by - there is only one item and the separator"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting letter")))
-
-
-(deftest test-0730
- (let [s1 (parse (sep-by (sym* \,) digit) "0,1*")]
- (fact "sep-by - two simple items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0730-05
- (let [s1 (parse (sep-by (sym* \,) digit) "0,1*")]
- (fact "sep-by - collects the result in a vector; two simple items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0735
- (let [s1 (parse (sep-by (sym* \,) (>> (sym* \+) digit)) "+0,+1*")]
- (fact "sep-by - two compound items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0740
- (let [p1 (sep-by (many white-space) (many letter))
- s1 (parse p1 "one two \t\t three")]
- (fact "sep-by - three compound items"
- (:input s1) => empty?
- (:value s1) => (list (seq "one") (seq "two") (seq "three"))
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0745
- (let [s1 (parse (sep-by1 (sym* \,) digit) "*")
- em (get-msg-str (:error s1))]
- (fact "sep-by1 - there are no separated items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0750
- (let [s1 (parse (sep-by1 (sym* \,) (>> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "sep-by1 - there are no separated compound items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0755
- (let [s1 (parse (sep-by1 (sym* \,) digit) "0*")]
- (fact "sep-by1 - one item, no separator"
- (:input s1) => [\*]
- (:value s1) => [\0]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0760
- (let [s1 (parse (sep-by1 (sym* \,) (<*> upper digit)) "U2*")]
- (fact "sep-by1 - one compound item, no separator"
- (:input s1) => [\*]
- (:value s1) => [[\U \2]]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0765
- (let [s1 (parse (sep-by1 (sym* \,) (>> letter digit)) "U2,*")
- em (get-msg-str (:error s1))]
- (fact "sep-by1 - there is only one item and the separator"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting letter")))
-
-
-(deftest test-0770
- (let [s1 (parse (sep-by1 (sym* \,) digit) "0,1*")]
- (fact "sep-by1 - two simple items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0770-05
- (let [s1 (parse (sep-by1 (sym* \,) digit) "0,1*")]
- (fact "sep-by1 - collects the result in a vector; two simple items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0775
- (let [s1 (parse (sep-by1 (sym* \,) (>> (sym* \+) digit)) "+0,+1*")]
- (fact "sep-by1 - two compound items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0780
- (let [p1 (sep-by1 (many white-space) (many letter))
- s1 (parse p1 "one two \t\t three")]
- (fact "sep-by1 - three compound items"
- (:input s1) => empty?
- (:value s1) => (list (seq "one") (seq "two") (seq "three"))
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0785
- (let [s1 (parse (sep-by1 (sym* \|) (>> upper digit)) "A1|B2|C3|DD,*")
- em (get-msg-str (:error s1))]
- (fact "sep-by1 - compound item fails after reading several items"
- (:input s1) => [\D \, \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\D\nexpecting digit")))
-
-
-(deftest test-0790
- (let [s1 (parse (end-by (sym* \,) digit) "*")]
- (fact "end-by - there are no separated items"
- (:input s1) => [\*]
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-0800
- (let [s1 (parse (end-by (sym* \,) (>> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "end-by - there are no separated compound items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0805
- (let [s1 (parse (end-by (sym* \,) digit) "0*")
- em (get-msg-str (:error s1))]
- (fact "end-by - one item; with no separator it fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting \\,")))
-
-
-(deftest test-0810
- (let [s1 (parse (end-by (sym* \,) (<*> upper digit)) "U2*")
- em (get-msg-str (:error s1))]
- (fact "end-by - one compound item, no separator"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting \\,")))
-
-
-(deftest test-0815
- (let [s1 (parse (end-by (sym* \,) (>> letter digit)) "U2,*")]
- (fact "end-by - there is one item that ends with a separator"
- (:input s1) => [\*]
- (:value s1) => [\2]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0820
- (let [s1 (parse (end-by (sym* \,) digit) "0,1,*")]
- (fact "end-by - two simple items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0820-05
- (let [s1 (parse (end-by (sym* \,) digit) "0,1,*")]
- (fact "end-by - collects the result in a vector; two simple items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0825
- (let [s1 (parse (end-by (sym* \,) (>> (sym* \+) digit)) "+0,+1,*")]
- (fact "end-by - two compound items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0830
- (let [p1 (end-by (many white-space) (many letter))
- s1 (parse p1 "one two \t\t three\n")]
- (fact "end-by - three compound items"
- (:input s1) => empty?
- (:value s1) => (list (seq "one") (seq "two") (seq "three"))
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0835
- (let [s1 (parse (end-by1 (sym* \,) digit) "*")
- em (get-msg-str (:error s1))]
- (fact "end-by1 - there are no separated items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0840
- (let [s1 (parse (end-by1 (sym* \,) (>> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "end-by1 - there are no separated compound items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0845
- (let [s1 (parse (end-by1 (sym* \,) digit) "0*")
- em (get-msg-str (:error s1))]
- (fact "end-by1 - one item; with no separator it fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting \\,")))
-
-
-(deftest test-0850
- (let [s1 (parse (end-by1 (sym* \,) (<*> upper digit)) "U2*")
- em (get-msg-str (:error s1))]
- (fact "end-by1 - one compound item, no separator"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting \\,")))
-
-
-(deftest test-0855
- (let [s1 (parse (end-by1 (sym* \,) (>> letter digit)) "U2,*")]
- (fact "end-by1 - there is one item and the separator"
- (:input s1) => [\*]
- (:value s1) => [\2]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0860
- (let [s1 (parse (end-by1 (sym* \,) digit) "0,1,*")]
- (fact "end-by1 - two simple items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0860-05
- (let [s1 (parse (end-by1 (sym* \,) digit) "0,1,*")]
- (fact "end-by1 - collects the result in a vector; two simple items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0865
- (let [s1 (parse (end-by1 (sym* \,) (>> (sym* \+) digit)) "+0,+1,*")]
- (fact "end-by1 - two compound items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0870
- (let [p1 (end-by1 (many white-space) (many letter))
- s1 (parse p1 "one two \t\t three\n")]
- (fact "end-by1 - three compound items"
- (:input s1) => empty?
- (:value s1) => (list (seq "one") (seq "two") (seq "three"))
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0880
- (let [s1 (parse (end-by1 (sym* \|) (>> upper digit)) "A1|B2|C3|DD,*")
- em (get-msg-str (:error s1))]
- (fact "end-by1 - compound item fails after reading several items"
- (:input s1) => [\D \, \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\D\nexpecting digit")))
-
-
-(deftest test-0885
- (let [s1 (parse (sep-end-by (sym* \,) digit) "*")]
- (fact "sep-end-by - there are no separated items"
- (:input s1) => [\*]
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-0890
- (let [s1 (parse (sep-end-by (sym* \,) (>> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "sep-end-by - there are no separated compound items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0895
- (let [s1 (parse (sep-end-by (sym* \,) digit) "0*")]
- (fact "sep-end-by - one item, no separator"
- (:input s1) => [\*]
- (:value s1) => [\0]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0900
- (let [s1 (parse (sep-by (sym* \,) (<*> upper digit)) "U2*")]
- (fact "sep-by - one compound item, no separator"
- (:input s1) => [\*]
- (:value s1) => [[\U \2]]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0905
- (let [s1 (parse (sep-end-by (sym* \,) (>> letter digit)) "U2,*")]
- (fact "sep-end-by - one item ended by the separator"
- (:input s1) => [\*]
- (:value s1) => [\2]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0910
- (let [s1 (parse (sep-end-by (sym* \,) digit) "0,1*")]
- (fact "sep-end-by - two simple items separated by ,"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0910-05
- (let [s1 (parse (sep-end-by (sym* \,) digit) "0,1*")]
- (fact "sep-end-by - collects the result in a vector; two simple items separated by ,"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-(deftest test-0915
- (let [s1 (parse (sep-end-by (sym* \,) (>> (sym* \+) digit)) "+0,+1,*")]
- (fact "sep-end-by - two compound items separated and ended by ,"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0920
- (let [p1 (sep-end-by (many1 white-space) (<*> letter letter letter))
- s1 (parse p1 "one two\t \tsix\n")]
- (fact "sep-end-by - three compound items; using many1 to avoid an SO"
- (:input s1) => empty?
- (:value s1) => (list (seq "one") (seq "two") (seq "six"))
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0925
- (let [s1 (parse (sep-end-by1 (sym* \,) digit) "*")
- em (get-msg-str (:error s1))]
- (fact "sep-end-by1 - there are no separated items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0930
- (let [s1 (parse (sep-end-by1 (sym* \,) (>> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "sep-end-by1 - there are no separated compound items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0935
- (let [s1 (parse (sep-end-by1 (sym* \,) digit) "0*")]
- (fact "sep-end-by1 - one item, no separator"
- (:input s1) => [\*]
- (:value s1) => [\0]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0940
- (let [s1 (parse (sep-end-by1 (sym* \,) (<*> upper digit)) "U2*")]
- (fact "sep-end-by1 - one compound item, no separator"
- (:input s1) => [\*]
- (:value s1) => [[\U \2]]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0950
- (let [s1 (parse (sep-end-by1 (sym* \,) (>> letter digit)) "U2,*")]
- (fact "sep-end-by1 - one compound item ended by the separator"
- (:input s1) => [\*]
- (:value s1) => [\2]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0960
- (let [s1 (parse (sep-end-by1 (sym* \,) digit) "0,1*")]
- (fact "sep-end-by1 - two simple items"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0965
- (let [s1 (parse (sep-end-by1 (sym* \,) (>> (sym* \+) digit)) "+0,+1,*")]
- (fact "sep-end-by1 - two compound items ended by the separator"
- (:input s1) => [\*]
- (:value s1) => [\0 \1]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0970
- (let [p1 (sep-end-by1 white-space (<*> letter letter letter))
- s1 (parse p1 "one two\tsix\n")]
- (fact "sep-end-by1 - three compound items"
- (:input s1) => empty?
- (:value s1) => (list (seq "one") (seq "two") (seq "six"))
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0970-05
- (let [p1 (sep-end-by1 white-space (<*> letter letter letter))
- s1 (parse p1 "one two\tsix\n")]
- (fact "sep-end-by1 - collects the result in a vector; three compound items"
- (:input s1) => empty?
- (:value s1) => (list (seq "one") (seq "two") (seq "six"))
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0970-10
- (let [p1 (sep-end-by1 white-space (many1 letter))
- s1 (parse p1 "one")]
- (fact "sep-end-by1 - collects the result in a vector; one compound item"
- (:input s1) => empty?
- (:value s1) => [(seq "one")]
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0975
- (let [s1 (parse (sep-end-by1 (sym* \|) (>> upper digit)) "A1|B2|C3|DD,*")
- em (get-msg-str (:error s1))]
- (fact "sep-end-by1 - compound item fails after reading several items"
- (:input s1) => [\D \, \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\D\nexpecting digit")))
-
-
-(deftest test-0980
- (let [s1 (parse (between (sym* \{) (sym* \}) digit) "{0}*")]
- (fact "between - one item"
- (:input s1) => [\*]
- (:value s1) => \0
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0980-05
- (let [s1 (parse (between (sym* \:) digit) ":0:*")]
- (fact "between - with same delimiter - one item"
- (:input s1) => [\*]
- (:value s1) => \0
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0980-10
- (let [s1 (parse (between (sym* \|) (many digit)) "|5005|*")]
- (fact "between - with same delimiter - multiple items"
- (:input s1) => [\*]
- (:value s1) => [\5 \0 \0 \5]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0985
- (let [p1 (>>= letter
- (fn [x] (>>= (many alpha-num)
- (fn [y] (return (cons x y))))))
- s1 (parse (between (sym* \{) (sym* \}) p1) "{abc101z}*")]
- (fact "between - one compound item"
- (:input s1) => [\*]
- (:value s1) => (seq "abc101z")
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0990
- (let [s1 (parse (between (sym* \{) (sym* \}) digit) "(0}*")
- em (get-msg-str (:error s1))]
- (fact "between - the open parser fails"
- (:input s1) => [\( \0 \} \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\(\nexpecting \\{")))
-
-
-(deftest test-0995
- (let [s1 (parse (between (sym* \{) (sym* \}) digit) "{0)*")
- em (get-msg-str (:error s1))]
- (fact "between - the close parser fails"
- (:input s1) => [\) \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\)\nexpecting \\}")))
-
-
-(deftest test-1000
- (let [s1 (parse (times 0 digit) "0*")]
- (fact "times - zero items"
- (:input s1) => [\0 \*]
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-1001
- (let [s1 (parse (times 1 letter) "x")]
- (fact "times - one item"
- (:input s1) => []
- (:value s1) => [\x]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-1005
- (let [s1 (parse (times 3 (>> any-char letter)) "*a@b$c")]
- (fact "times - three items"
- (:input s1) => empty?
- (:value s1) => [\a \b \c]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-1005-05
- (let [s1 (parse (times 3 (>> any-char letter)) "*a@b$c")]
- (fact "times - collects the result in a vector; three items"
- (:input s1) => empty?
- (:value s1) => [\a \b \c]
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-1010
- (let [s1 (parse (times 3 (>> any-char letter)) "*a@b$$")
- em (get-msg-str (:error s1))]
- (fact "times - two items, then fails"
- (:input s1) => [\$]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\$\nexpecting letter")))
-
-
-(deftest test-1015
- (let [s1 (parse (<$> count (look-ahead (many digit))) "12345678")]
- (fact "look-ahead - succeeds consuming input"
- (:input s1) => (seq "12345678")
- (:value s1) => 8
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-1020
- (let [s1 (parse (look-ahead (many digit)) "YYZ")]
- (fact "look-ahead - succeeds consuming no input"
- (:input s1) => [\Y \Y \Z]
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-1025
- (let [s1 (parse (look-ahead digit) "*")]
- (fact "look-ahead - fails consuming no input"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-1030
- (let [s1 (parse (look-ahead (>> letter digit)) "A*")]
- (fact "look-ahead - fails consuming no input"
- (:input s1) => [\A \*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-1030-05
- (let [s1 (parse (predict (sym* \=)) "=10")]
- (fact "predict - if p succeeds it consumes no input"
- (:input s1) => [\= \1 \0]
- (:value s1) => \=
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-1030-10
- (let [s1 (parse (predict (sym* \=)) "<10")]
- (fact "predict - if p succeeds it consumes no input"
- (:input s1) => [\< \1 \0]
- (:value s1) => nil?
- (:ok s1) => false?
- (:empty s1) => true?)))
-
-
-(deftest test-1035
- (let [s1 (parse (not-followed-by digit) "**")]
- (fact "not-followed-by - succeeds as digit fails"
- (:input s1) => [\* \*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-1040
- (let [s1 (parse (not-followed-by (>> letter letter digit)) "xy**")]
- (fact "not-followed-by - succeeds as compound item fails"
- (:input s1) => [\x \y \* \*]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-1045
- (let [s1 (parse (not-followed-by (<*> upper digit)) "U2*")
- em (get-msg-str (:error s1))]
- (fact "not-followed-by - fails as the parse succeeds"
- (:input s1) => [\U \2 \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected [\\U \\2]")))
-
-
-(deftest test-1050
- (let [s1 (parse (>> upper upper upper eof) "YYZ")]
- (fact "eof - there's nothing left"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-1055
- (let [s1 (parse eof "")]
- (fact "eof - there's nothing to begin with"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-1060
- (let [s1 (parse (<*> upper digit eof) "U2*")
- em (get-msg-str (:error s1))]
- (fact "eof - fails because the input isn't empty"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected *\nexpecting end of input")))
-
-
-(deftest test-1065
- (let [s1 (parse (many-till digit letter) "123456A")]
- (fact "many-till - parses several numbers, then a letter"
- (:input s1) => empty?
- (:value s1) => (seq "123456")
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-1065-05
- (let [s1 (parse (many-till digit letter) "123456A")]
- (fact "many-till - collects the result in a vector; several numbers and a letter"
- (:input s1) => empty?
- (:value s1) => (seq "123456")
- (:value s1) => vector?
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-1070
- (let [s1 (parse (many-till digit letter) "A*")]
- (fact "many-till - just the end parser"
- (:input s1) => [\*]
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-1075
- (let [p1 (>> (token* ""))))
- s1 (parse p1 "")]
- (fact "many-till - reads a space between xml comments"
- (:input s1) => empty?
- (:value s1) => [\space]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-1080
- (let [p1 (>> (token* ""))))
- s1 (parse p1 "")]
- (fact "many-till - reads a word between xml comments"
- (:input s1) => empty?
- (:value s1) => (seq "foobar")
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-1085
- (let [s1 (parse (many-till digit letter) "*A")
- em (get-msg-str (:error s1))]
- (fact "many-till - fails parsing the prefix"
- (:input s1) => [\* \A]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\*\nexpecting letter or digit")))
-
-
-(deftest test-1090
- (let [s1 (parse (many-till digit letter) "12345*A")
- em (get-msg-str (:error s1))]
- (fact "many-till - parses several prefixes and then fails"
- (:input s1) => [\* \A]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting letter or digit")))
-
-
-(deftest test-1095
- (let [s1 (parse (many-till digit (>> upper (sym* \X))) "12345A*")
- em (get-msg-str (:error s1))]
- (fact "many-till - parses the prefix, then fails reading the end parser"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting \\X")))
-
-
-(deftest test-1113
- (let [s1 (parse (<+> letter) "a")]
- (fact "<+> - cats from one parser"
- (:input s1) => empty?
- (:value s1) => "a"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1114
- (let [s1 (parse (<+> (times 3 (sym* \S))) "SSS")]
- (fact "<+> - cats from one parser"
- (:input s1) => empty?
- (:value s1) => "SSS"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1115
- (let [s1 (parse (<+> (sym* \-) digit) "-1")]
- (fact "<+> - cats from two parsers"
- (:input s1) => empty?
- (:value s1) => "-1"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1120
- (let [s1 (parse (<+> (sym* \-) digit (sym* \;)) "-1;")]
- (fact "<+> - cats from three parsers"
- (:input s1) => empty?
- (:value s1) => "-1;"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1125
- (let [p1 (<+> letter (>> (sym* \|) letter) (>> (sym* \|) digit))
- s1 (parse p1 "X|Y|9")]
- (fact "<+> - cats from filtering parsers"
- (:input s1) => empty?
- (:value s1) => "XY9"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1130
- (let [in "ABC012"
- p1 (<+> (<*> letter letter letter) (<*> digit digit digit))
- s1 (parse p1 in)]
- (fact "<+> - cats from compound parsers"
- (:input s1) => empty?
- (:value s1) => "ABC012"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1135
- (let [s1 (parse (<+> letter digit) "*")]
- (fact "<+> - the first parser fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true)))
-
-
-(deftest test-1140
- (let [s1 (parse (<+> letter digit) "A*")]
- (fact "<+> - the second parser fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false)))
-
-
-(deftest test-1145
- (let [s1 (parse (<+> letter tab digit) "A\t*")]
- (fact "<+> - the third parser fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false)))
-
-
-(deftest test-1150
- (let [p1 (<+> letter tab tab tab tab tab (sym* \x))
- s1 (parse p1 "A\t\t\t\t\t*")]
- (fact "<+> - the seventh parser fails"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false)))
-
-
-(deftest test-1150-05
- (let [s1 (parse (search dec-num) "Now I have 20 dollars")]
- (fact "search - a simple number"
- (:input s1) => (seq " dollars")
- (:value s1) => 20
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1150-10
- (let [s1 (parse (many (search dec-num)) "Now I have 20 dollars, or 2 tens")]
- (fact "search - multiple numbers"
- (:input s1) => empty?
- (:value s1) => [20 2]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1150-15
- (let [s1 (parse (many (search (<|> dec-num (token* "dollars")))) "Now I have 20 dollars")]
- (fact "search - multiple choices, multiple times"
- (:input s1) => empty?
- (:value s1) => [20 "dollars"]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-;; +-------------------------------------------------------------+
-;; | Parser state. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-1155
- (let [p1 (>> (put-state 0)
- (skip-many
- (bind [x any-char]
- (if (= x \newline) (modify-state inc) (return nil)))))
- s1 (parse p1 "aaa\nbbb\nccc\nddd\nfff\nggg\nhhh\n\niii\njjj\n\nkkk")]
- (fact "put-state, modify-state"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => true
- (:user s1) => 11
- (:empty s1) => false)))
-
-
-(deftest test-1160
- (let [p1 (>> (skip (put-state 0)
- (skip-many
- (bind [x any-char]
- (if (= x \newline) (modify-state inc) (return nil)))))
- get-state)
- s1 (parse p1 "aaa\nbbb\nccc\nddd\nfff\nggg\nhhh\n\niii\njjj\n\nkkk")]
- (fact "put-state, get-state; get user state as the parser's value"
- (:input s1) => empty?
- (:value s1) => 11
- (:ok s1) => true
- (:user s1) => 11
- (:empty s1) => false)))
-
-
-(deftest test-1165
- (let [in "ABC"
- p1 (<+> letter letter letter)
- p2 (>> (set-input "XYZ") p1)
- s1 (parse (<*> p1 p2) in)]
- (fact "set-input"
- (:input s1) => empty?
- (:value s1) => ["ABC" "XYZ"]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1170
- (let [in "ABC"
- p1 (<+> letter letter letter)
- p2 (>> (skip (set-input "XY0")
- (set-position (make-pos "include"))) p1)
- s1 (parse (<*> p1 p2) in)
- em (get-msg-str (:error s1))
- ip (:pos s1)]
- (fact "set-input, set-position"
- (:input s1) => [\0]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- (:src ip) => "include"
- (:line ip) => 1
- (:col ip) => 3
- em => "unexpected \\0\nexpecting letter")))
-
-
-(deftest test-1175
- (let [in "ABC"
- p1 (<+> letter letter letter)
- p2 (>> (skip (set-input "WXYZ")
- (set-position (make-pos "include"))) get-position)
- s1 (parse (>> p1 p2) in)
- v1 (:value s1)]
- (fact "set-input, set-position, get-position"
- (:input s1) => (seq "WXYZ")
- (:src v1) => "include"
- (:line v1) => 1
- (:col v1) => 1
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1180
- (let [in "ABC"
- p1 (<+> letter letter letter)
- p2 (>> (set-input "XYZ") get-input)
- s1 (parse (>> p1 p2) in)]
- (fact "set-input, get-input"
- (:input s1) => [\X \Y \Z]
- (:value s1) => [\X \Y \Z]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-;; +-------------------------------------------------------------+
-;; | Numeric parsers. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-1185
- (let [s1 (parse dec-num "747")]
- (fact "dec-num - reads a simple integer"
- (:input s1) => empty?
- (:value s1) => 747
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1190
- (let [s1 (parse dec-num "747-600")]
- (fact "dec-num - reads a simple integer, delimited"
- (:input s1) => [\- \6 \0 \0]
- (:value s1) => 747
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1195
- (let [s1 (parse (>> upper dec-num) "A380aircraft")]
- (fact "dec-num - reads an integer, delimited"
- (:input s1) => (seq "aircraft")
- (:value s1) => 380
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1200
- (let [s1 (parse dec-num "987654321987654321000|")]
- (fact "dec-num - reads an integer, delimited"
- (:input s1) => [\|]
- (:value s1) => 987654321987654321000N
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1205
- (let [s1 (parse oct-num "0747")]
- (fact "oct-num - reads a simple octal number"
- (:input s1) => empty?
- (:value s1) => 0747
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1210
- (let [s1 (parse oct-num "0747-600")]
- (fact "oct-num - reads a simple octal number, delimited"
- (:input s1) => [\- \6 \0 \0]
- (:value s1) => 0747
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1215
- (let [s1 (parse (>> upper oct-num) "B767aircraft")]
- (fact "oct-num - reads an octal number, delimited"
- (:input s1) => (seq "aircraft")
- (:value s1) => 0767
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1220
- (let [s1 (parse oct-num "76543217654321000000|")]
- (fact "oct-num - reads an octal number, delimited"
- (:input s1) => [\|]
- (:value s1) => 076543217654321000000N
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1225
- (let [s1 (parse hex-num "747")]
- (fact "hex-num - reads a simple hex number"
- (:input s1) => empty?
- (:value s1) => 0x747
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1230
- (let [s1 (parse hex-num "747-600")]
- (fact "hex-num - reads a simple hex number, delimited"
- (:input s1) => [\- \6 \0 \0]
- (:value s1) => 0x747
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1235
- (let [s1 (parse (>> upper hex-num) "A380plane")]
- (fact "hex-num - reads a hex number, delimited"
- (:input s1) => (seq "plane")
- (:value s1) => 0x380
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1240
- (let [s1 (parse hex-num "ABCDEF987654321987654321000|")]
- (fact "hex-num - reads a hex number, delimited"
- (:input s1) => [\|]
- (:value s1) => 0xABCDEF987654321987654321000N
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1245
- (let [s1 (parse float-num "100")]
- (fact "float-num - reads a simple floating-point number"
- (:input s1) => empty?
- (:value s1) => 100.0
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1250
- (let [s1 (parse float-num "3.1415927")]
- (fact "float-num - reads a simple floating-point number"
- (:input s1) => empty?
- (:value s1) => 3.1415927
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1255
- (let [s1 (parse float-num "9.8m/s")]
- (fact "float-num - reads a simple floating-point number, delimited"
- (:input s1) => [\m \/ \s]
- (:value s1) => 9.8
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1260
- (let [s1 (parse float-num "0.00343ms")]
- (fact "float-num - reads a floating-point number, delimited"
- (:input s1) => [\m \s]
- (:value s1) => 0.00343
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-1265
- (let [s1 (parse float-num "98765432.19876543555666|")]
- (fact "float-num - reads a floating-point number, delimited"
- (:input s1) => [\|]
- (:value s1) => 9.876543219876544E7
- (:ok s1) => true
- (:empty s1) => false)))
diff --git a/src/test/clojure/blancas/kern/test_core.cljc b/src/test/clojure/blancas/kern/test_core.cljc
new file mode 100644
index 0000000..5e1f13a
--- /dev/null
+++ b/src/test/clojure/blancas/kern/test_core.cljc
@@ -0,0 +1,3548 @@
+;; Copyright (c) 2013 Armando Blancas. All rights reserved.
+;; The use and distribution terms for this software are covered by the
+;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this distribution.
+;; By using this software in any fashion, you are agreeing to be bound by
+;; the terms of this license.
+;; You must not remove this notice, or any other, from this software.
+
+(ns blancas.kern.test-core
+ (:require [blancas.kern.core :as k :refer [parse value return fail
+ >>= >> <*> > <|> <+> << <:> <$>
+ letter digit satisfy many space new-line* tab
+ sym* token* token- word* one-of* none-of* eof
+ many1 optional option skip skip-many skip-many1 sep-by sep-by1 end-by end-by1
+ sep-end-by sep-end-by1 between alpha-num times dec-num]]
+ [blancas.kern.char :as char]
+ [clojure.test :refer [deftest is testing]]
+ [blancas.kern.char :as char])
+ #?(:clj (:require [blancas.kern.core :refer [bind]])
+ :cljs (:require-macros [blancas.kern.core :refer [bind]])))
+
+(defn check-pos [line col pos]
+ (is (= line (:line pos)))
+ (is (= col (:col pos))))
+
+;; +-------------------------------------------------------------+
+;; | Basic parsers. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-0000
+ (let [s1 (parse letter "xyz")
+ s2 ((return 0) s1)]
+ (testing "return"
+ (is (= 0 (:value s2)))
+ (is (:ok s2))
+ (is (nil? (:error s2)))
+ (is (= (:input s1) (:input s2)))
+ (is (= (:empty s1) (:empty s2)))
+ (is (= (:pos s1) (:pos s2)))
+ (is (= (:user s1)))) (:user s2)))
+
+
+(deftest test-0005
+ (let [em "the buck stops here"
+ s1 (parse letter "xyz")
+ s2 ((fail em) s1)]
+ (testing "fail"
+ (is (nil? (:value s2)))
+ (is (false? (:ok s2)))
+ (is (:empty s2))
+ (is (= (k/make-err-message (:pos s1) em) (:error s2)))
+ (is (= (:input s1) (:input s2)))
+ (is (= (:pos s1) (:pos s2)))
+ (is (= (:user s1)))) (:user s2)))
+
+
+(deftest test-0010
+ (let [s1 (parse letter "xyz")
+ s2 ((satisfy char/is-letter) s1)]
+ (testing "satisfy - advances one char"
+ (is (= [\z] (:input s2)))
+ (is (= \y (:value s2)))
+ (is (:ok s2))
+ (is (false? (:empty s2)))
+ (is (= (:user s1) (:user s2)))
+ (is (nil? (:error s2)))
+ (check-pos 1 3 (:pos s2)))))
+
+
+(deftest test-0015
+ (let [s1 (parse letter "u2")
+ s2 ((satisfy char/is-digit) s1)]
+ (testing "satisfy - reaches the end of input"
+ (is (empty? (:input s2)))
+ (is (= \2 (:value s2)))
+ (is (:ok s2))
+ (is (false? (:empty s2)))
+ (is (= (:user s1) (:user s2)))
+ (is (nil? (:error s2)))
+ (check-pos 1 3 (:pos s2)))))
+
+
+(deftest test-0020
+ (let [s1 (parse letter "u\t")
+ s2 ((satisfy #(= \tab %)) s1)]
+ (testing "satisfy - advnaces one tab; default 4 positions"
+ (is (= \tab (:value s2)))
+ (is (:ok s2))
+ (is (false? (:empty s2)))
+ (is (= (:user s1) (:user s2)))
+ (is (nil? (:error s2)))
+ (check-pos 1 6 (:pos s2)))))
+
+
+(deftest test-0025
+ (binding [k/*tab-width* 8]
+ (let [s1 (parse letter "u\t")
+ s2 ((satisfy #(= \tab %)) s1)]
+ (testing "satisfy - advances one tab of 8 positions"
+ (is (= \tab (:value s2)))
+ (is (:ok s2))
+ (is (false? (:empty s2)))
+ (is (= (:user s1) (:user s2)))
+ (is (nil? (:error s2)))
+ (check-pos 1 10 (:pos s2))))))
+
+
+(deftest test-0030
+ (let [s1 (parse letter "u\n")
+ s2 ((satisfy #(= \newline %)) s1)]
+ (testing "satisfy - advances to the next line, first column"
+ (is (= \newline (:value s2)))
+ (is (:ok s2))
+ (is (false? (:empty s2)))
+ (is (= (:user s1) (:user s2)))
+ (is (nil? (:error s2)))
+ (check-pos 2 1 (:pos s2)))))
+
+
+(deftest test-0035
+ (let [em "end of input"
+ s1 (parse (many letter) "xyz")
+ s2 ((satisfy (fn [_] true)) s1)]
+ (testing "satisfy - attempts to read past the end of input"
+ (is (empty? (:input s2)))
+ (is (nil? (:value s2)))
+ (is (false? (:ok s2)))
+ (is (:empty s2))
+ (is (= (:user s1) (:user s2)))
+ (is (= (k/make-err-unexpect (:pos s1) em) (:error s2)))
+ (is (= (:pos s1)))) (:pos s2)))
+
+
+(deftest test-0040
+ (let [em #?(:clj "\\2" :cljs "\"2\"")
+ s1 (parse letter "u2")
+ s2 ((satisfy char/is-letter) s1)]
+ (testing "satisfy - the predicate fails"
+ (is (= [\2] (:input s2)))
+ (is (nil? (:value s2)))
+ (is (false? (:ok s2)))
+ (is (:empty s2))
+ (is (= (:user s1) (:user s2)))
+ (is (= (k/make-err-system (:pos s1) em) (:error s2)))
+ (is (= (:pos s1)))) (:pos s2)))
+
+
+;; +-------------------------------------------------------------+
+;; | Primitive parsers. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-0045
+ (let [in "#(f %)"
+ s1 (parse k/any-char in)]
+ (testing "any-char"
+ (is (= (rest in) (:input s1)))
+ (is (= \# (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (= (:user s1) (:user s1)))
+ (is (nil? (:error s1)))
+ (check-pos 1 2 (:pos s1)))))
+
+
+(deftest test-0050
+ (let [in "xyz"
+ s1 (parse (>>= k/any-char
+ (fn [a]
+ (>>= k/any-char
+ (fn [b]
+ (>>= k/any-char
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "any-char - three in a row"
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0055
+ (let [em "end of input"
+ s1 (parse k/any-char "")]
+ (testing "any-char - fails on end of input"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= (:user s1) (:user s1)))
+ (is (= (k/make-err-unexpect (:pos s1) em) (:error s1)))
+ (check-pos 1 1 (:pos s1)))))
+
+
+(deftest test-0060
+ (let [in "abc"
+ s1 (parse letter in)]
+ (testing "letter - parses a single letter"
+ (is (= (rest in) (:input s1)))
+ (is (= \a (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0065
+ (let [in "xyz"
+ s1 (parse (>>= letter
+ (fn [a]
+ (>>= letter
+ (fn [b]
+ (>>= letter
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "letter - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0070
+ (let [in "123"
+ s1 (parse letter in)]
+ (testing "letter - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0075
+ (let [in "abc"
+ s1 (parse k/lower in)]
+ (testing "k/lower - parses a single k/lower-case letter"
+ (is (= (rest in) (:input s1)))
+ (is (= \a (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0080
+ (let [in "xyz"
+ s1 (parse (>>= k/lower
+ (fn [a]
+ (>>= k/lower
+ (fn [b]
+ (>>= k/lower
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "k/lower - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0085
+ (let [in "XYZ"
+ s1 (parse k/lower in)]
+ (testing "k/lower - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0090
+ (let [in "ABC"
+ s1 (parse k/upper in)]
+ (testing "k/upper - parses a single k/upper-case letter"
+ (is (= (rest in) (:input s1)))
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0095
+ (let [in "XYZ"
+ s1 (parse (>>= k/upper
+ (fn [a]
+ (>>= k/upper
+ (fn [b]
+ (>>= k/upper
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "k/upper - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0100
+ (let [in "123"
+ s1 (parse k/upper in)]
+ (testing "k/upper - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0105
+ (let [in " \t\t"
+ s1 (parse k/white-space in)]
+ (testing "k/white-space - parses a single whitespace character"
+ (is (= (rest in) (:input s1)))
+ (is (= \space (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0110
+ (let [in " \t "
+ s1 (parse (>>= k/white-space
+ (fn [a]
+ (>>= k/white-space
+ (fn [b]
+ (>>= k/white-space
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "k/white-space - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0115
+ (let [in "***"
+ s1 (parse k/white-space in)]
+ (testing "k/white-space - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0120
+ (let [in " "
+ s1 (parse space in)]
+ (testing "space - parses a single space character"
+ (is (= (rest in) (:input s1)))
+ (is (= \space (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0125
+ (let [in " "
+ s1 (parse (>>= space
+ (fn [a]
+ (>>= space
+ (fn [b]
+ (>>= space
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "space - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0130
+ (let [in "***"
+ s1 (parse space in)]
+ (testing "space - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0135
+ (let [in "\n\t."
+ s1 (parse new-line* in)]
+ (testing "new-line - parses a single newline character"
+ (is (= (rest in) (:input s1)))
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0140
+ (let [in "\n\n\n"
+ s1 (parse (>>= new-line*
+ (fn [a]
+ (>>= new-line*
+ (fn [b]
+ (>>= new-line*
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "new-line* - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0145
+ (let [in "***"
+ s1 (parse new-line* in)]
+ (testing "new-line* - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0150
+ (let [in "\t|\t|"
+ s1 (parse tab in)]
+ (testing "tab - parses a single tab character"
+ (is (= (rest in) (:input s1)))
+ (is (= \tab (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0155
+ (let [in "\t\t\t"
+ s1 (parse (>>= tab
+ (fn [a]
+ (>>= tab
+ (fn [b]
+ (>>= tab
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "tab - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0160
+ (let [in "***"
+ s1 (parse tab in)]
+ (testing "tab - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0165
+ (let [in "12345"
+ s1 (parse digit in)]
+ (testing "digit - parses a single digit"
+ (is (= (rest in) (:input s1)))
+ (is (= \1 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0170
+ (let [in "012"
+ s1 (parse (>>= digit
+ (fn [a]
+ (>>= digit
+ (fn [b]
+ (>>= digit
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "digit - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0175
+ (let [in "***"
+ s1 (parse digit in)]
+ (testing "digit - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0180
+ (let [in "ABCDEF"
+ s1 (parse k/hex-digit in)]
+ (testing "hex-digit - parses a single hex digit"
+ (is (= (rest in) (:input s1)))
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0185
+ (let [in "CAB"
+ s1 (parse (>>= k/hex-digit
+ (fn [a]
+ (>>= k/hex-digit
+ (fn [b]
+ (>>= k/hex-digit
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "hex-digit - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0190
+ (let [in "***"
+ s1 (parse digit in)]
+ (testing "hex-digit - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0195
+ (let [in "12345"
+ s1 (parse k/oct-digit in)]
+ (testing "oct-digit - parses a single octal digit"
+ (is (= (rest in) (:input s1)))
+ (is (= \1 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0200
+ (let [in "567"
+ s1 (parse (>>= k/oct-digit
+ (fn [a]
+ (>>= k/oct-digit
+ (fn [b]
+ (>>= k/oct-digit
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "oct-digit - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0205
+ (let [in "***"
+ s1 (parse digit in)]
+ (testing "oct-digit - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0210
+ (let [in "a0b1"
+ s1 (parse k/alpha-num in)]
+ (testing "alpha-num - parses a single alpha-numeric character"
+ (is (= (rest in) (:input s1)))
+ (is (= \a (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0215
+ (let [in "a1b"
+ s1 (parse (>>= k/alpha-num
+ (fn [a]
+ (>>= k/alpha-num
+ (fn [b]
+ (>>= k/alpha-num
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "alpha-num - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0220
+ (let [in "+*&"
+ s1 (parse k/alpha-num in)]
+ (testing "alpha-num - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0225
+ (let [in "X()"
+ s1 (parse (sym* \X) in)]
+ (testing "sym* - parses a single X"
+ (is (= (rest in) (:input s1)))
+ (is (= \X (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0230
+ (let [in "p\t;"
+ s1 (parse (>>= (sym* \p)
+ (fn [a]
+ (>>= (sym* \tab)
+ (fn [b]
+ (>>= (sym* \;)
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "sym* - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0235
+ (let [in "***"
+ s1 (parse (sym* \X) in)]
+ (testing "sym* - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0235-05
+ (let [in "x()"
+ s1 (parse (k/sym- \X) in)]
+ (testing "sym- - parses a single x"
+ (is (= (rest in) (:input s1)))
+ (is (= \X (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0235-10
+ (let [in "X()"
+ s1 (parse (k/sym- \X) in)]
+ (testing "sym- - parses a single X"
+ (is (= (rest in) (:input s1)))
+ (is (= \X (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0235-15
+ (let [in "A()"
+ s1 (parse (k/sym- \X) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "sym- - parses a single X"
+ (is (= [\A \( \)] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= em #?(:clj "unexpected \\A\nexpecting \\X"
+ :cljs "unexpected \"A\"\nexpecting \"X\""))))))
+
+
+(deftest test-0240
+ (let [in "program foo()"
+ s1 (parse (token* "program") in)]
+ (testing "token* - parses a specific word"
+ (is (= (drop (count "program") in) (:input s1)))
+ (is (= "program" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0245
+ (let [in "foo(bar)baz"
+ s1 (parse (>>= (token* "foo")
+ (fn [a]
+ (>>= (token* "(bar)")
+ (fn [b]
+ (>>= (token* "baz")
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "token* - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= ["foo" "(bar)" "baz"]))) (:value s1)))
+
+
+(deftest test-0250
+ (let [in "goat"
+ s1 (parse (token* "goal") in)
+ em (k/get-msg-str (:error s1))]
+ (testing "token* - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= em "unexpected goat\nexpecting goal")))))
+
+
+(deftest test-0250-05
+ (let [in "function foo()"
+ s1 (parse (token* "function" "procedure") in)]
+ (testing "token* - parses one of multiple word choices"
+ (is (= (drop (count "function") in) (:input s1)))
+ (is (= "function" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-10
+ (let [in "procedure foo()"
+ s1 (parse (token* "function" "procedure") in)]
+ (testing "token* - parses one of multiple word choices"
+ (is (= (drop (count "procedure") in) (:input s1)))
+ (is (= "procedure" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-15
+ (let [in "program foo()"
+ s1 (parse (token- "PROGRAM") in)]
+ (testing "token- - parses a specific word; non case-sensetive"
+ (is (= (drop (count "program") in) (:input s1)))
+ (is (= "PROGRAM" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-20
+ (let [in "Program foo()"
+ s1 (parse (token- "PROGRAM") in)]
+ (testing "token- - parses a specific word; non case-sensetive"
+ (is (= (drop (count "program") in) (:input s1)))
+ (is (= "PROGRAM" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-25
+ (let [in "PROGRAM foo()"
+ s1 (parse (token- "PROGRAM") in)]
+ (testing "token- - parses a specific word; non case-sensetive"
+ (is (= (drop (count "program") in) (:input s1)))
+ (is (= "PROGRAM" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-30
+ (let [in "goat"
+ s1 (parse (token- "goal") in)
+ em (k/get-msg-str (:error s1))]
+ (testing "token- - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (= em "unexpected goat\nexpecting goal"))))
+
+
+(deftest test-0250-35
+ (let [in "FUNction foo()"
+ s1 (parse (token- "function" "procedure") in)]
+ (testing "token- - parses one of multiple word choices"
+ (is (= (drop (count "function") in) (:input s1)))
+ (is (= "function" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-40
+ (let [in "PROCedure foo()"
+ s1 (parse (token- "function" "procedure") in)]
+ (testing "token- - parses one of multiple word choices"
+ (is (= (drop (count "procedure") in) (:input s1)))
+ (is (= "procedure" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-45
+ (let [in "program foo()"
+ s1 (parse (word* letter "program") in)]
+ (testing "word* - parses a specific, delimited word"
+ (is (= (drop (count "program") in) (:input s1)))
+ (is (= "program" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-50
+ (let [in "else{}"
+ s1 (parse (word* letter "else") in)]
+ (testing "word* - parses a specific, delimited word"
+ (is (= [\{ \}] (:input s1)))
+ (is (= "else" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-55
+ (let [in "procedure"
+ s1 (parse (word* letter "proc") in)
+ em (k/get-msg-str (:error s1))]
+ (testing "word* - fails because is not delimited"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= em "unexpected e\nexpecting end of proc")))))
+
+
+(deftest test-0250-60
+ (let [in "otherwise{}"
+ s1 (parse (word* letter "else" "otherwise") in)]
+ (testing "word* - parses a specific, delimited word"
+ (is (= [\{ \}] (:input s1)))
+ (is (= "otherwise" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-65
+ (let [in "subroutine"
+ s1 (parse (word* letter "proc" "func" "method") in)
+ em (k/get-msg-str (:error s1))]
+ (testing "word* - fails with incorrect input"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= em "unexpected subr\nunexpected subrou\nexpecting proc, func or method")))))
+
+
+(deftest test-0250-70
+ (let [in "PROGRAM foo()"
+ s1 (parse (k/word- letter "program") in)]
+ (testing "word- - parses a specific, delimited word; not case-senstive"
+ (is (= (drop (count "program") in) (:input s1)))
+ (is (= "program" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-75
+ (let [in "Else{}"
+ s1 (parse (k/word- letter "else") in)]
+ (testing "word- - parses a specific, delimited word; not case-senstive"
+ (is (= [\{ \}] (:input s1)))
+ (is (= "else" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-80
+ (let [in "ProcEdure"
+ s1 (parse (k/word- letter "proc") in)
+ em (k/get-msg-str (:error s1))]
+ (testing "word- - fails because is not delimited"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected E\nexpecting end of proc" em)))))
+
+
+(deftest test-0250-85
+ (let [in "OtherWise{}"
+ s1 (parse (k/word- letter "else" "otherwise") in)]
+ (testing "word- - parses a specific, delimited word; not case-senstive"
+ (is (= [\{ \}] (:input s1)))
+ (is (= "otherwise" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0250-90
+ (let [in "SUBroutine"
+ s1 (parse (k/word- letter "proc" "func" "method") in)
+ em (k/get-msg-str (:error s1))]
+ (testing "word- - fails with incorrect input"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected SUBr\nunexpected SUBrou\nexpecting proc, func or method" em)))))
+
+
+(deftest test-0255
+ (let [in "* 2"
+ s1 (parse (one-of* "+-*/^") in)]
+ (testing "one-of* - parses one of the supplied characters"
+ (is (= (rest in) (:input s1)))
+ (is (= \* (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0260
+ (let [in "*-+"
+ op "+-*/"
+ s1 (parse (>>= (one-of* op)
+ (fn [a]
+ (>>= (one-of* op)
+ (fn [b]
+ (>>= (one-of* op)
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "one-of* - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0265
+ (let [in "abc"
+ s1 (parse (one-of* "+-*/") in)]
+ (testing "one-of* - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0270
+ (let [in ": 2"
+ s1 (parse (none-of* "+-*/^") in)]
+ (testing "none-of* - parses a character not supplied"
+ (is (= (rest in) (:input s1)))
+ (is (= \: (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0275
+ (let [in "^&%"
+ op "+-*/"
+ s1 (parse (>>= (none-of* op)
+ (fn [a]
+ (>>= (none-of* op)
+ (fn [b]
+ (>>= (none-of* op)
+ (fn [c]
+ (return [a b c])))))))
+ in)]
+ (testing "none-of* - three in a row until end of input"
+ (is (empty? (:input s1)))
+ (is (= (seq in)))) (:value s1)))
+
+
+(deftest test-0280
+ (let [in "$foo"
+ s1 (parse (none-of* "!@#$%^*()") in)]
+ (testing "none-of* - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0280-05
+ (let [in ""
+ s1 (parse eof in)]
+ (testing "eof - parses an empty string"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1)))))
+
+
+(deftest test-0280-10
+ (let [in "END."
+ s1 (parse (>> (token* "END.") eof) in)]
+ (testing "eof - verifies that input ends"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0280-15
+ (let [in "END.// the end"
+ s1 (parse (>> (token* "END.") eof) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "eof - verifies that input ends"
+ (is (= (seq "// the end") (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= "unexpected /\nexpecting end of input" em)))))
+
+
+(deftest test-0280-20
+ (let [in "12\n"
+ s1 (parse (<*> digit digit new-line*) in)]
+ (testing "new-line* - a new line after two digits"
+ (is (empty? (:input s1)))
+ (is (= [\1 \2 \newline] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0280-25
+ (let [in "AB\r\nCD\r\n"
+ s1 (parse (many1 (<< (many1 k/upper) new-line*)) in)]
+ (testing "new-line* - pairs of letters separated by a new line"
+ (is (empty? (:input s1)))
+ (is (= [[\A \B] [\C \D]] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0280-30
+ (let [in "12345 "
+ s1 (parse (<< (many1 digit) new-line*) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "new-line* - the line doesn't end with a new line"
+ (is (= [\space] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\space\nexpecting new line"
+ :cljs "unexpected \" \"\nexpecting new line")
+ em)))))
+
+
+(deftest test-0280-35
+ (let [in " \t \t \n \t *"
+ s1 (parse (k/skip-ws (sym* \*)) in)]
+ (testing "skip-ws - skips whitespaces before parsing a star"
+ (is (empty? (:input s1)))
+ (is (= \* (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0280-40
+ (let [in "*"
+ s1 (parse (k/skip-ws (sym* \*)) in)]
+ (testing "skip-ws - nothing to skip before parsing a star"
+ (is (empty? (:input s1)))
+ (is (= \* (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0280-45
+ (let [in "Now is the time... right... now."
+ s1 (parse (k/field* "!") in)]
+ (testing "field* - reads the whole string"
+ (is (empty? (:input s1)))
+ (is (= in (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0280-50
+ (let [in "Now is the time; right... now."
+ s1 (parse (k/field* ";") in)]
+ (testing "field* - reads the field delimited by a semicolon"
+ (is (= (seq "; right... now.") (:input s1)))
+ (is (= "Now is the time" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0280-55
+ (let [in "Now-is-the-time"
+ s1 (parse (k/split-on "-") in)]
+ (testing "field - breaks the string into the words"
+ (is (= ["Now" "is" "the" "time"] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0280-60
+ (let [in "Software,Tooling,495.95,0.00,,15,,xyz"
+ s1 (parse (k/split-on ",") in)]
+ (testing "field - breaks the string into fields; some are empty"
+ (is (= ["Software" "Tooling" "495.95" "0.00" "15" "xyz"] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0280-65
+ (let [in "Now is the time. Or, is it? Yes! yes! that's it."
+ s1 (parse (k/split-on " ,?!.") in)]
+ (testing "field - collects all words; skips the given punctuation"
+ (is (= ["Now" "is" "the" "time" "Or" "is" "it" "Yes" "yes" "that's" "it"] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0280-70
+ (testing "mark parses a punctuation mark."
+ (is (= \! (value k/mark "!")))
+ (is (= \@ (value k/mark "@")))
+ (is (= \* (value k/mark "*")))
+ (is (= \: (value k/mark ":")))
+ (is (= \/ (value k/mark "/")))
+ (is (= \. (value k/mark ".")))))
+
+
+;; +-------------------------------------------------------------+
+;; | Parser combinators. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-0285
+ (let [s1 (parse letter "1")
+ em (-> s1 :error :msgs first :text force)]
+ (testing "first message in the msgs list"
+ (is (= "letter" em)))))
+
+
+(deftest test-0290
+ (let [s1 (parse letter "1")
+ em (k/get-msg-str (:error s1))]
+ (testing "verify error messages"
+ (is (= #?(:clj "unexpected \\1\nexpecting letter"
+ :cljs "unexpected \"1\"\nexpecting letter")
+ em)))))
+
+
+(deftest test-0295
+ (let [s1 (parse (> (<*> digit letter) "digit,letter") "01")
+ em (-> s1 :error :msgs first :text force)]
+ (testing "> - does not add message when input is consumed"
+ (is (not= "digit,letter" em)))))
+
+
+(deftest test-0300
+ (let [s1 (parse (> (<*> digit letter) "digit,letter") "01")
+ em (k/get-msg-str (:error s1))]
+ (testing "> - verifies error messages in <*>"
+ (is (= #?(:clj "unexpected \\1\nexpecting letter"
+ :cljs "unexpected \"1\"\nexpecting letter")
+ em)))))
+
+
+(deftest test-0305
+ (let [s1 (parse (> (<*> digit letter) "digit,letter") "0")
+ em (k/get-msg-str (:error s1))]
+ (testing "> - verifies error messages in <*>"
+ (is (= "unexpected end of input\nexpecting letter" em)))))
+
+
+(deftest test-0310
+ (let [s1 (parse (<|> digit letter) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "<|> - verifies error messages"
+ (is (= #?(:clj "unexpected \\*\nexpecting digit or letter"
+ :cljs "unexpected \"*\"\nexpecting digit or letter")
+ em)))))
+
+
+(deftest test-0315
+ (let [s1 (parse (<|> (sym* \x) (<|> letter digit)) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "<|> - verifies error messages with 3 choices"
+ (is (= #?(:clj "unexpected \\*\nexpecting \\x, letter or digit"
+ :cljs "unexpected \"*\"\nexpecting \"x\", letter or digit")
+ em)))))
+
+
+(deftest test-0320
+ (let [s1 (parse (<|> (<|> k/white-space (sym* \x)) (<|> letter digit)) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "<|> - verifies error messages with 4 choices"
+ (is (= #?(:clj "unexpected \\*\nexpecting whitespace, \\x, letter or digit"
+ :cljs "unexpected \"*\"\nexpecting whitespace, \"x\", letter or digit")
+ em)))))
+
+
+(deftest test-0320-05
+ (let [s1 (parse (k/expect (<+> letter digit) "number two") "U2")]
+ (testing "expect - parser succeeds"
+ (is (= "U2" (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0320-10
+ (let [s1 (parse (k/expect (<+> letter digit) "number two") "UX")
+ em (k/get-msg-str (:error s1))]
+ (testing "expect - parser fails consuming input"
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\X\nexpecting number two"
+ :cljs "unexpected \"X\"\nexpecting number two")
+ em)))))
+
+
+(deftest test-0320-15
+ (let [s1 (parse (k/expect (<+> letter digit) "number two") "007")
+ em (k/get-msg-str (:error s1))]
+ (testing "expect - parser fails without consuming any input"
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= [\0 \0 \7] (:input s1)))
+ (is (= #?(:clj "unexpected \\0\nexpecting number two"
+ :cljs "unexpected \"0\"\nexpecting number two")
+ em)))))
+
+
+(deftest test-0325
+ (let [s1 (parse (<|> letter digit) "U2")]
+ (testing "<|> - the first parser succeeds"
+ (is (= \U (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\2] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0330
+ (let [s1 (parse (<|> digit letter) "XYZ")]
+ (testing "<|> - the second parser succeeds"
+ (is (= \X (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\Y \Z] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0335
+ (let [s1 (parse (<|> (>> letter digit) letter) "XYZ")
+ em (k/get-msg-str (:error s1))]
+ (testing "<|> - the first parse fails consuming input"
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (= [\Y \Z] (:input s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\Y\nexpecting digit"
+ :cljs "unexpected \"Y\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0340
+ (let [s1 (parse (<|> k/white-space letter digit) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "<|> - verifies error messages with 3 choices"
+ (is (= #?(:clj "unexpected \\*\nexpecting whitespace, letter or digit"
+ :cljs "unexpected \"*\"\nexpecting whitespace, letter or digit")
+ em)))))
+
+
+(deftest test-0345
+ (let [s1 (parse (<|> k/white-space (sym* \x) letter digit) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "<|> - verifies error messages with 4 choices"
+ (is (= #?(:clj "unexpected \\*\nexpecting whitespace, \\x, letter or digit"
+ :cljs "unexpected \"*\"\nexpecting whitespace, \"x\", letter or digit")
+ em)))))
+
+
+(deftest test-0350
+ (let [s1 (parse (<|> k/white-space (sym* \x) letter digit) "\t")]
+ (testing "<|> - the first of 4 parser succeeds"
+ (is (= \tab (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0355
+ (let [s1 (parse (<|> k/white-space (sym* \x) letter digit) "x")]
+ (testing "<|> - the second of 4 parser succeeds"
+ (is (= \x (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0360
+ (let [s1 (parse (<|> k/white-space (sym* \x) letter digit) "z")]
+ (testing "<|> - the third of 4 parser succeeds"
+ (is (= \z (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0365
+ (let [s1 (parse (<|> k/white-space (sym* \x) letter digit) "0")]
+ (testing "<|> - the fourth parser succeeds"
+ (is (= \0 (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0370
+ (let [p1 (>>= letter (fn [x] (return (char/upper-case x))))
+ s1 (parse p1 "xyz")]
+ (testing ">>= - advances one char"
+ (is (= [\y \z] (:input s1)))
+ (is (= \X (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:user s1)))
+ (is (nil? (:error s1)))
+ (check-pos 1 2 (:pos s1)))))
+
+
+(deftest test-0375
+ (let [p1 (>>= digit
+ (fn [x] (>>= digit
+ (fn [y] (return #?(:clj (Integer/parseInt (str x y))
+ :cljs (js/parseInt (str x y))))))))
+ s1 (parse p1 "50113")]
+ (testing ">>= - advances two chars"
+ (is (= [\1 \1 \3] (:input s1)))
+ (is (= 50 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:user s1)))
+ (is (nil? (:error s1)))
+ (check-pos 1 3 (:pos s1)))))
+
+
+(deftest test-0380
+ (let [in "012345"
+ p1 (>>= letter (fn [x] (return (int x))))
+ s1 (parse p1 in)
+ em (k/get-msg-str (:error s1))]
+ (testing ">>= - the first parser fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (nil? (:user s1)))
+ (check-pos 1 1 (:pos s1))
+ (is (= #?(:clj "unexpected \\0\nexpecting letter"
+ :cljs "unexpected \"0\"\nexpecting letter")
+ em)))))
+
+
+(deftest test-0385
+ (let [p1 (>>= letter (fn [_] digit))
+ s1 (parse p1 "xyz")
+ em (k/get-msg-str (:error s1))]
+ (testing ">>= - the second parser fails"
+ (is (= [\y \z] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (nil? (:user s1)))
+ (check-pos 1 2 (:pos s1))
+ (is (= #?(:clj "unexpected \\y\nexpecting digit"
+ :cljs "unexpected \"y\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0385-05
+ (let [p1 (bind [x letter] (return (char/upper-case x)))
+ s1 (parse p1 "xyz")]
+
+ (testing "bind - advances one char"
+ (is (= [\y \z] (:input s1)))
+ (is (= \X (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:user s1)))
+ (is (nil? (:error s1)))
+ (check-pos 1 2 (:pos s1)))))
+
+
+(deftest test-0385-10
+ (let [p1 (bind [x digit y digit]
+ (return #?(:clj (Integer/parseInt (str x y))
+ :cljs (js/parseInt (str x y)))))
+ s1 (parse p1 "50113")]
+ (testing "bind - advances two chars"
+ (is (= [\1 \1 \3] (:input s1)))
+ (is (= 50 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:user s1)))
+ (is (nil? (:error s1)))
+ (check-pos 1 3 (:pos s1)))))
+
+
+(deftest test-0385-15
+ (let [p1 (bind [_ (sym* \()
+ s (<+> (many1 digit))
+ _ (sym* \))]
+ (return (* #?(:clj (Integer/parseInt s) :cljs (js/parseInt s))
+ -1)))
+ s1 (parse p1 "(50113)")]
+ (testing "bind - reads a negative number in parens, as in accounting"
+ (is (empty? (:input s1)))
+ (is (= -50113 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:user s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0385-20
+ (let [p1 (bind [x letter]
+ (if (= x \x)
+ (bind [y (sym* \Y)
+ z (sym* \Z)] (return "first"))
+ (bind [n (many1 digit)] (return 5005))))
+ s1 (parse p1 "xYZ")]
+ (testing "bind - uses nested bind inside the first function body"
+ (is (empty? (:input s1)))
+ (is (= "first" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:user s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0385-25
+ (let [p1 (bind [x letter]
+ (if (= x \x)
+ (bind [y (sym* \Y)
+ z (sym* \Z)] (return "first"))
+ (bind [n (many1 digit)] (return 666))))
+ s1 (parse p1 "A10002450")]
+ (testing "bind - uses nested bind inside the first function body"
+ (is (empty? (:input s1)))
+ (is (= 666 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:user s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0385-30
+ (let [p1 (<|> (bind [x (many1 digit)] (return true))
+ (bind [x (many1 letter)] (return false)))
+ s1 (parse p1 "FALSE")]
+ (testing "bind - the first bind fails, the second succeeds"
+ (is (empty? (:input s1)))
+ (is (false? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:user s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0390
+ (let [p1 (>> (sym* \+) digit)
+ s1 (parse p1 "+1")]
+ (testing ">> - consumes two chars, keeps the second"
+ (is (empty? (:input s1)))
+ (is (= \1 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0395
+ (let [p1 (>> (sym* \+) digit)
+ s1 (parse p1 "01")]
+ (testing ">> - the first parser fails"
+ (is (= [\0 \1] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0400
+ (let [p1 (>> (sym* \+) digit)
+ s1 (parse p1 "+A")]
+ (testing ">> - the second parser fails"
+ (is (= [\A] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0405
+ (let [p1 (>> digit digit letter)
+ s1 (parse p1 "01A")]
+ (testing ">> - consumes three chars, keeps the last"
+ (is (empty? (:input s1)))
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0410
+ (let [p1 (>> digit digit digit letter)
+ s1 (parse p1 "012A")]
+ (testing ">> - consumes four chars, keeps the last"
+ (is (empty? (:input s1)))
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0415
+ (let [p1 (>> digit digit digit letter)
+ s1 (parse p1 "A")]
+ (testing ">> - the first fails"
+ (is (= [\A] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0420
+ (let [p1 (>> digit digit digit letter)
+ s1 (parse p1 "01A")]
+ (testing ">> - the third fails"
+ (is (= [\A] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0425
+ (let [p1 (<< letter (sym* \;))
+ s1 (parse p1 "a;")]
+ (testing "<< - consumes two chars, keeps the first"
+ (is (empty? (:input s1)))
+ (is (= \a (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0430
+ (let [p1 (<< letter (sym* \;))
+ s1 (parse p1 "0;")]
+ (testing "<< - the first parser fails"
+ (is (= [\0 \;] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0435
+ (let [p1 (<< letter (sym* \;))
+ s1 (parse p1 "A*")]
+ (testing "<< - the second parser fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0440
+ (let [p1 (<< k/any-char digit digit)
+ s1 (parse p1 "+01")]
+ (testing "<< - consumes three chars, keeps the first"
+ (is (empty? (:input s1)))
+ (is (= \+ (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0445
+ (let [p1 (<< k/any-char digit digit digit digit)
+ s1 (parse p1 "+0123")]
+ (testing "<< - consumes five chars, keeps the first"
+ (is (empty? (:input s1)))
+ (is (= \+ (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0450
+ (let [p1 (<< k/any-char digit digit digit digit)
+ s1 (parse p1 "+01*")]
+ (testing "<< - the fourth parser fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0455
+ (let [s1 (parse (<$> count (many k/any-char)) "abcdef+01234*")]
+ (testing "<$> - counts the length of the input"
+ (is (empty? (:input s1)))
+ (is (= 13 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0460
+ (let [s1 (parse (<$> #(- (int %) (int \0)) digit) "9")]
+ (testing "<$> - converts a char digit into an int"
+ (is (empty? (:input s1)))
+ (is (= 9 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0465
+ (let [s1 (parse (<$> #(- (int %) (int \0)) digit) "A")]
+ (testing "<$> - fails and the function is not applied"
+ (is (= [\A] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0469-a
+ (let [s1 (parse (<*> digit) "9")]
+ (testing "<*> - collects from one parser"
+ (is (empty? (:input s1)))
+ (is (= [\9] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0469-b
+ (let [s1 (parse (<*> letter) "U2")]
+ (testing "<*> - collects from one parser"
+ (is (= [\2] (:input s1)))
+ (is (= [\U] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0470
+ (let [s1 (parse (<*> (sym* \-) digit) "-1")]
+ (testing "<*> - collects from two parsers"
+ (is (empty? (:input s1)))
+ (is (= [\- \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0475
+ (let [s1 (parse (<*> (sym* \-) digit (sym* \;)) "-1;")]
+ (testing "<*> - collects from three parsers"
+ (is (empty? (:input s1)))
+ (is (= [\- \1 \;] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0480
+ (let [p1 (<*> letter (>> (sym* \|) letter) (>> (sym* \|) digit))
+ s1 (parse p1 "X|Y|9")]
+ (testing "<*> - collects from filtering parsers"
+ (is (empty? (:input s1)))
+ (is (= [\X \Y \9] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0485
+ (let [in "ABC012"
+ p1 (<*> (<*> letter letter letter) (<*> digit digit digit))
+ s1 (parse p1 in)]
+ (testing "<*> - collects from compound parsers"
+ (is (empty? (:input s1)))
+ (is (= '((\A \B \C) (\0 \1 \2)) (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0485-05
+ (let [s1 (parse (<*> letter digit) "u2")]
+ (testing "<*> - collects results in a vector"
+ (is (empty? (:input s1)))
+ (is (vector? (:value s1)))
+ (is (= [\u \2] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0490
+ (let [s1 (parse (<*> letter digit) "*")]
+ (testing "<*> - the first parser fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0495
+ (let [s1 (parse (<*> letter digit) "A*")]
+ (testing "<*> - the second parser fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0500
+ (let [s1 (parse (<*> letter tab digit) "A\t*")]
+ (testing "<*> - the third parser fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0505
+ (let [p1 (<*> letter tab tab tab tab tab (sym* \x))
+ s1 (parse p1 "A\t\t\t\t\t*")]
+ (testing "<*> - the seventh parser fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0510
+ (let [s1 (parse (<:> k/lower) "a")]
+ (testing "<:> - parses an item; consumes all input"
+ (is (empty? (:input s1)))
+ (is (= \a (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0515
+ (let [s1 (parse (<:> (<$> (partial apply str) (<*> (token* "end") space))) "end ")]
+ (testing "<:> - parses nested items; consumes all input"
+ (is (empty? (:input s1)))
+ (is (= "end " (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0520
+ (let [in "a1b3c4d5e7f8"
+ p1 (<*> letter digit)
+ s1 (parse (<:> (many p1)) in)]
+ (testing "<:> - parses six pairs; consumes all input"
+ (is (empty? (:input s1)))
+ (is (= '((\a \1) (\b \3) (\c \4) (\d \5) (\e \7) (\f \8)) (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0525
+ (let [s1 (parse (<:> k/lower) "*&!")]
+ (testing "<:> - fails with parsers consuming no input; consumes no input"
+ (is (= [\* \& \!] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-0530
+ (let [s1 (parse (<:> (<*> k/upper k/lower k/upper)) "Mi*")
+ em (k/get-msg-str (:error s1))]
+ (testing "<:> - fails with parsers consuming input; consumes no input"
+ (is (= [\M \i \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\*\nexpecting uppercase letter"
+ :cljs "unexpected \"*\"\nexpecting uppercase letter")
+ em)))))
+
+
+(deftest test-0535
+ (let [s1 (parse (<|> (<:> (>> digit letter)) digit) "1*")
+ em (k/get-msg-str (:error s1))]
+ (testing "<:> - verifies that it allows <|> to test the next choice"
+ (is (= [\*] (:input s1)))
+ (is (= \1 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0540
+ (let [s1 (parse (<|> (<:> letter) digit) "***")
+ em (k/get-msg-str (:error s1))]
+ (testing "<:> - verifies that it carries over the error msg"
+ (is (= [\* \* \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\*\nexpecting letter or digit"
+ :cljs "unexpected \"*\"\nexpecting letter or digit")
+ em)))))
+
+
+(deftest test-0545
+ (let [s1 (parse (many k/lower) "*")]
+ (testing "many - parses zero items"
+ (is (= [\*] (:input s1)))
+ (is (empty? (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0550
+ (let [s1 (parse (many k/lower) "a*")]
+ (testing "many - parses one item"
+ (is (= [\*] (:input s1)))
+ (is (= [\a] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0555
+ (let [s1 (parse (many (optional letter)) "ABCDEGFHIJK*")]
+ (testing "many - skips optional items; consumes input though value is empty"
+ (is (= [\*] (:input s1)))
+ (is (= (seq "ABCDEGFHIJK") (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0560
+ (let [in "a1b3c4d5e7f8"
+ p1 (<*> letter digit)
+ s1 (parse (many p1) in)]
+ (testing "many - parses six compound items"
+ (is (empty? (:input s1)))
+ (is (= '((\a \1) (\b \3) (\c \4) (\d \5) (\e \7) (\f \8)) (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0560-05
+ (let [s1 (parse (many k/lower) "*")]
+ (testing "many - collects the result in a vector; parses zero items"
+ (is (= [\*] (:input s1)))
+ (is (empty? (:value s1)))
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0560-10
+ (let [s1 (parse (many k/lower) "a*")]
+ (testing "many - collects the result in a vector; parses one item"
+ (is (= [\*] (:input s1)))
+ (is (= [\a] (:value s1)))
+
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0565
+ (let [s1 (parse (<|> (many k/lower) (sym* \*)) "*")]
+ (testing "many - consumes no input and succeeds; <|> returns its value"
+ (is (= [\*] (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0570
+ (let [in "a1b3c4d5ee"
+ p1 (<*> letter digit)
+ s1 (parse (many p1) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "many - parses four compound items, then fails in the next compound item"
+ (is (= [\e] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\e\nexpecting digit"
+ :cljs "unexpected \"e\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0575
+ (let [s1 (parse (many1 k/lower) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "many1 - fails with zero items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\*\nexpecting lowercase letter"
+ :cljs "unexpected \"*\"\nexpecting lowercase letter")
+ em)))))
+
+
+(deftest test-0580
+ (let [s1 (parse (many1 k/lower) "a*")]
+ (testing "many1 - parses one item"
+ (is (= [\*] (:input s1)))
+ (is (= [\a] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0580-05
+ (let [s1 (parse (many1 k/lower) "a*")]
+ (testing "many1 - collects the result in a vector; parses one item"
+ (is (= [\*] (:input s1)))
+ (is (= [\a] (:value s1)))
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0585
+ (let [in "a1b3c4d5e7f8"
+ p1 (<*> letter digit)
+ s1 (parse (many1 p1) in)]
+ (testing "many1 - parses six compound items"
+ (is (empty? (:input s1)))
+ (is (= '((\a \1) (\b \3) (\c \4) (\d \5) (\e \7) (\f \8)) (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0590
+ (let [s1 (parse (<|> (many1 k/lower) (sym* \*)) "w*")]
+ (testing "many1 - consumes input; <|> returns its value"
+ (is (= [\*] (:input s1)))
+ (is (= [\w] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0595
+ (let [s1 (parse (<|> (many1 digit) k/upper) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "many1 - fails; passes on empty, errors to <|>"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit or uppercase letter"
+ :cljs "unexpected \"*\"\nexpecting digit or uppercase letter")
+ em)))))
+
+
+(deftest test-0600
+ (let [s1 (parse (<|> (many1 digit) k/upper) "A")]
+ (testing "many1 - fails; passes on empty, are cleared in <|>"
+ (is (empty? (:input s1)))
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0605
+ (let [in "a1b3c4d5ee"
+ p1 (<*> letter digit)
+ s1 (parse (many1 p1) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "many1 - parses four compound items, then fails in the next compound item"
+ (is (= [\e] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\e\nexpecting digit"
+ :cljs "unexpected \"e\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0610
+ (let [s1 (parse (optional (<*> k/upper digit)) "U2*")]
+ (testing "optional - parses an optional item"
+ (is (= [\*] (:input s1)))
+ (is (= [\U \2] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0615
+ (let [s1 (parse (optional (<*> k/upper digit)) "u2*")]
+ (testing "optional - fails consuming no input"
+ (is (= [\u \2 \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0620
+ (let [s1 (parse (optional (<*> k/upper digit)) "UP*")
+ em (k/get-msg-str (:error s1))]
+ (testing "optional - fails consuming input"
+ (is (= [\P \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\P\nexpecting digit"
+ :cljs "unexpected \"P\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0625
+ (let [p1 (<$> (partial apply str) (<*> (optional k/upper) (sym* \*)))
+ s1 (parse p1 "U*")]
+ (testing "optional - skips the optional char"
+ (is (empty? (:input s1)))
+ (is (= "U*" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0630
+ (let [s1 (parse (option "XY" (<*> k/upper digit)) "U2*")]
+ (testing "option - parses an item"
+ (is (= [\*] (:input s1)))
+ (is (= [\U \2] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0635
+ (let [s1 (parse (option "XY" (<*> k/upper digit)) "u2*")]
+ (testing "option - fails without consuming input; produces optional value"
+ (is (= [\u \2 \*] (:input s1)))
+ (is (= "XY" (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0640
+ (let [s1 (parse (option "XY" (<*> k/upper digit)) "UP*")
+ em (k/get-msg-str (:error s1))]
+ (testing "option - fails consuming input"
+ (is (= [\P \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\P\nexpecting digit"
+ :cljs "unexpected \"P\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0640-05
+ (let [s1 (parse (skip (sym* \*)) "*")]
+ (testing "skip - skips a star"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0640-10
+ (let [s1 (parse (skip letter digit) "U2")]
+ (testing "skip - skips a letter and a digit"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0640-15
+ (let [s1 (parse (skip (sym* \*) letter digit (sym* \*)) "*U2*")]
+ (testing "skip - skips a star, a letter, a digit, and a star"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0645
+ (let [s1 (parse (skip-many letter) "*")]
+ (testing "skip-many - skips zero letters"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0650
+ (let [s1 (parse (skip-many (<*> letter digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "skip-many - skips zero compound items; <*> fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0655
+ (let [s1 (parse (skip-many (<*> digit k/lower)) "0x*")]
+ (testing "skip-many - skips one compound item"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0660
+ (let [s1 (parse (skip-many letter) "abcdefghijk*")]
+ (testing "skip-many - skips letters"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0665
+ (let [s1 (parse (skip-many (<*> digit k/lower)) "0x1y2z*")]
+ (testing "skip-many - skips three compound items; consumes no more input"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0670
+ (let [s1 (parse (>> (skip-many (optional digit)) (sym* \*)) "0123456789*")]
+ (testing "skip-many - skips optional items; then consumes more input"
+ (is (empty? (:input s1)))
+ (is (= \* (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0675
+ (let [s1 (parse (skip-many1 letter) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "skip-many1 - fails with zero letters"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\*\nexpecting letter"
+ :cljs "unexpected \"*\"\nexpecting letter")
+ em)))))
+
+
+(deftest test-0680
+ (let [s1 (parse (skip-many1 (<*> letter digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "skip-many1 - skips zero compound items; <*> fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit") em)))))
+
+
+(deftest test-0685
+ (let [s1 (parse (skip-many1 (<*> digit k/lower)) "0x*")]
+ (testing "skip-many1 - skips one compound item"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0690
+ (let [s1 (parse (skip-many1 letter) "abcdefghijk*")]
+ (testing "skip-many1 - skips letters"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0695
+ (let [s1 (parse (skip-many1 (<*> digit k/lower)) "0x1y2z*")]
+ (testing "skip-many1 - skips three compound items; consumes no more input"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0700
+ (let [s1 (parse (>> (skip-many1 (optional digit)) (sym* \*)) "0123456789*")]
+ (testing "skip-many1 - skips optional items; then consumes more input"
+ (is (empty? (:input s1)))
+ (is (= \* (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0705
+ (let [s1 (parse (sep-by (sym* \,) digit) "*")]
+ (testing "sep-by - there are no separated items"
+ (is (= [\*] (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0710
+ (let [s1 (parse (sep-by (sym* \,) (>> letter digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "sep-by - there are no separated compound items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0715
+ (let [s1 (parse (sep-by (sym* \,) digit) "0*")]
+ (testing "sep-by - one item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [\0] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0720
+ (let [s1 (parse (sep-by (sym* \,) (<*> k/upper digit)) "U2*")]
+ (testing "sep-by - one compound item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [[\U \2]] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0725
+ (let [s1 (parse (sep-by (sym* \,) (>> letter digit)) "U2,*")
+ em (k/get-msg-str (:error s1))]
+ (testing "sep-by - there is only one item and the separator"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting letter"
+ :cljs "unexpected \"*\"\nexpecting letter")
+ em)))))
+
+
+(deftest test-0730
+ (let [s1 (parse (sep-by (sym* \,) digit) "0,1*")]
+ (testing "sep-by - two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0730-05
+ (let [s1 (parse (sep-by (sym* \,) digit) "0,1*")]
+ (testing "sep-by - collects the result in a vector; two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0735
+ (let [s1 (parse (sep-by (sym* \,) (>> (sym* \+) digit)) "+0,+1*")]
+ (testing "sep-by - two compound items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0740
+ (let [p1 (sep-by (many k/white-space) (many letter))
+ s1 (parse p1 "one two \t\t three")]
+ (testing "sep-by - three compound items"
+ (is (empty? (:input s1)))
+ (is (= (list (seq "one") (seq "two") (seq "three")) (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0745
+ (let [s1 (parse (sep-by1 (sym* \,) digit) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "sep-by1 - there are no separated items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0750
+ (let [s1 (parse (sep-by1 (sym* \,) (>> letter digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "sep-by1 - there are no separated compound items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0755
+ (let [s1 (parse (sep-by1 (sym* \,) digit) "0*")]
+ (testing "sep-by1 - one item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [\0] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0760
+ (let [s1 (parse (sep-by1 (sym* \,) (<*> k/upper digit)) "U2*")]
+ (testing "sep-by1 - one compound item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [[\U \2]] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0765
+ (let [s1 (parse (sep-by1 (sym* \,) (>> letter digit)) "U2,*")
+ em (k/get-msg-str (:error s1))]
+ (testing "sep-by1 - there is only one item and the separator"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting letter"
+ :cljs "unexpected \"*\"\nexpecting letter")
+ em)))))
+
+
+(deftest test-0770
+ (let [s1 (parse (sep-by1 (sym* \,) digit) "0,1*")]
+ (testing "sep-by1 - two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0770-05
+ (let [s1 (parse (sep-by1 (sym* \,) digit) "0,1*")]
+ (testing "sep-by1 - collects the result in a vector; two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0775
+ (let [s1 (parse (sep-by1 (sym* \,) (>> (sym* \+) digit)) "+0,+1*")]
+ (testing "sep-by1 - two compound items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0780
+ (let [p1 (sep-by1 (many k/white-space) (many letter))
+ s1 (parse p1 "one two \t\t three")]
+ (testing "sep-by1 - three compound items"
+ (is (empty? (:input s1)))
+ (is (= (list (seq "one") (seq "two") (seq "three")) (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0785
+ (let [s1 (parse (sep-by1 (sym* \|) (>> k/upper digit)) "A1|B2|C3|DD,*")
+ em (k/get-msg-str (:error s1))]
+ (testing "sep-by1 - compound item fails after reading several items"
+ (is (= [\D \, \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\D\nexpecting digit"
+ :cljs "unexpected \"D\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0790
+ (let [s1 (parse (end-by (sym* \,) digit) "*")]
+ (testing "end-by - there are no separated items"
+ (is (= [\*] (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0800
+ (let [s1 (parse (end-by (sym* \,) (>> letter digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "end-by - there are no separated compound items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0805
+ (let [s1 (parse (end-by (sym* \,) digit) "0*")
+ em (k/get-msg-str (:error s1))]
+ (testing "end-by - one item; with no separator it fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting \\,"
+ :cljs "unexpected \"*\"\nexpecting \",\"")
+ em)))))
+
+
+(deftest test-0810
+ (let [s1 (parse (end-by (sym* \,) (<*> k/upper digit)) "U2*")
+ em (k/get-msg-str (:error s1))]
+ (testing "end-by - one compound item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting \\,"
+ :cslj "unexpected \"*\"\nexpecting \",\"")
+ em)))))
+
+
+(deftest test-0815
+ (let [s1 (parse (end-by (sym* \,) (>> letter digit)) "U2,*")]
+ (testing "end-by - there is one item that ends with a separator"
+ (is (= [\*] (:input s1)))
+ (is (= [\2] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0820
+ (let [s1 (parse (end-by (sym* \,) digit) "0,1,*")]
+ (testing "end-by - two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0820-05
+ (let [s1 (parse (end-by (sym* \,) digit) "0,1,*")]
+ (testing "end-by - collects the result in a vector; two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0825
+ (let [s1 (parse (end-by (sym* \,) (>> (sym* \+) digit)) "+0,+1,*")]
+ (testing "end-by - two compound items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0830
+ (let [p1 (end-by (many k/white-space) (many letter))
+ s1 (parse p1 "one two \t\t three\n")]
+ (testing "end-by - three compound items"
+ (is (empty? (:input s1)))
+ (is (= (list (seq "one") (seq "two") (seq "three")) (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0835
+ (let [s1 (parse (end-by1 (sym* \,) digit) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "end-by1 - there are no separated items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0840
+ (let [s1 (parse (end-by1 (sym* \,) (>> letter digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "end-by1 - there are no separated compound items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0845
+ (let [s1 (parse (end-by1 (sym* \,) digit) "0*")
+ em (k/get-msg-str (:error s1))]
+ (testing "end-by1 - one item; with no separator it fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting \\,"
+ :cljs "unexpected \"*\"\nexpecting \",\"")
+ em)))))
+
+
+(deftest test-0850
+ (let [s1 (parse (end-by1 (sym* \,) (<*> k/upper digit)) "U2*")
+ em (k/get-msg-str (:error s1))]
+ (testing "end-by1 - one compound item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting \\,"
+ :cljs "unexpected \"*\"\nexpecting \",\"")
+ em)))))
+
+
+(deftest test-0855
+ (let [s1 (parse (end-by1 (sym* \,) (>> letter digit)) "U2,*")]
+ (testing "end-by1 - there is one item and the separator"
+ (is (= [\*] (:input s1)))
+ (is (= [\2] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0860
+ (let [s1 (parse (end-by1 (sym* \,) digit) "0,1,*")]
+ (testing "end-by1 - two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0860-05
+ (let [s1 (parse (end-by1 (sym* \,) digit) "0,1,*")]
+ (testing "end-by1 - collects the result in a vector; two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0865
+ (let [s1 (parse (end-by1 (sym* \,) (>> (sym* \+) digit)) "+0,+1,*")]
+ (testing "end-by1 - two compound items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0870
+ (let [p1 (end-by1 (many k/white-space) (many letter))
+ s1 (parse p1 "one two \t\t three\n")]
+ (testing "end-by1 - three compound items"
+ (is (empty? (:input s1)))
+ (is (= (list (seq "one") (seq "two") (seq "three")) (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0880
+ (let [s1 (parse (end-by1 (sym* \|) (>> k/upper digit)) "A1|B2|C3|DD,*")
+ em (k/get-msg-str (:error s1))]
+ (testing "end-by1 - compound item fails after reading several items"
+ (is (= [\D \, \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\D\nexpecting digit"
+ :cljs "unexpected \"D\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0885
+ (let [s1 (parse (sep-end-by (sym* \,) digit) "*")]
+ (testing "sep-end-by - there are no separated items"
+ (is (= [\*] (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0890
+ (let [s1 (parse (sep-end-by (sym* \,) (>> letter digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "sep-end-by - there are no separated compound items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0895
+ (let [s1 (parse (sep-end-by (sym* \,) digit) "0*")]
+ (testing "sep-end-by - one item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [\0] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0900
+ (let [s1 (parse (sep-by (sym* \,) (<*> k/upper digit)) "U2*")]
+ (testing "sep-by - one compound item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [[\U \2]] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0905
+ (let [s1 (parse (sep-end-by (sym* \,) (>> letter digit)) "U2,*")]
+ (testing "sep-end-by - one item ended by the separator"
+ (is (= [\*] (:input s1)))
+ (is (= [\2] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0910
+ (let [s1 (parse (sep-end-by (sym* \,) digit) "0,1*")]
+ (testing "sep-end-by - two simple items separated by ,"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0910-05
+ (let [s1 (parse (sep-end-by (sym* \,) digit) "0,1*")]
+ (testing "sep-end-by - collects the result in a vector; two simple items separated by ,"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+(deftest test-0915
+ (let [s1 (parse (sep-end-by (sym* \,) (>> (sym* \+) digit)) "+0,+1,*")]
+ (testing "sep-end-by - two compound items separated and ended by ,"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0920
+ (let [p1 (sep-end-by (many1 k/white-space) (<*> letter letter letter))
+ s1 (parse p1 "one two\t \tsix\n")]
+ (testing "sep-end-by - three compound items; using many1 to avoid an SO"
+ (is (empty? (:input s1)))
+ (is (= (list (seq "one") (seq "two") (seq "six")) (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0925
+ (let [s1 (parse (sep-end-by1 (sym* \,) digit) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "sep-end-by1 - there are no separated items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0930
+ (let [s1 (parse (sep-end-by1 (sym* \,) (>> letter digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "sep-end-by1 - there are no separated compound items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0935
+ (let [s1 (parse (sep-end-by1 (sym* \,) digit) "0*")]
+ (testing "sep-end-by1 - one item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [\0] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0940
+ (let [s1 (parse (sep-end-by1 (sym* \,) (<*> k/upper digit)) "U2*")]
+ (testing "sep-end-by1 - one compound item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [[\U \2]] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0950
+ (let [s1 (parse (sep-end-by1 (sym* \,) (>> letter digit)) "U2,*")]
+ (testing "sep-end-by1 - one compound item ended by the separator"
+ (is (= [\*] (:input s1)))
+ (is (= [\2] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0960
+ (let [s1 (parse (sep-end-by1 (sym* \,) digit) "0,1*")]
+ (testing "sep-end-by1 - two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0965
+ (let [s1 (parse (sep-end-by1 (sym* \,) (>> (sym* \+) digit)) "+0,+1,*")]
+ (testing "sep-end-by1 - two compound items ended by the separator"
+ (is (= [\*] (:input s1)))
+ (is (= [\0 \1] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0970
+ (let [p1 (sep-end-by1 k/white-space (<*> letter letter letter))
+ s1 (parse p1 "one two\tsix\n")]
+ (testing "sep-end-by1 - three compound items"
+ (is (empty? (:input s1)))
+ (is (= (list (seq "one") (seq "two") (seq "six")) (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0970-05
+ (let [p1 (sep-end-by1 k/white-space (<*> letter letter letter))
+ s1 (parse p1 "one two\tsix\n")]
+ (testing "sep-end-by1 - collects the result in a vector; three compound items"
+ (is (empty? (:input s1)))
+ (is (= (list (seq "one") (seq "two") (seq "six")) (:value s1)))
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0970-10
+ (let [p1 (sep-end-by1 k/white-space (many1 letter))
+ s1 (parse p1 "one")]
+ (testing "sep-end-by1 - collects the result in a vector; one compound item"
+ (is (empty? (:input s1)))
+ (is (= [(seq "one")] (:value s1)))
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0975
+ (let [s1 (parse (sep-end-by1 (sym* \|) (>> k/upper digit)) "A1|B2|C3|DD,*")
+ em (k/get-msg-str (:error s1))]
+ (testing "sep-end-by1 - compound item fails after reading several items"
+ (is (= [\D \, \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\D\nexpecting digit"
+ :cljs "unexpected \"D\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0980
+ (let [s1 (parse (between (sym* \{) (sym* \}) digit) "{0}*")]
+ (testing "between - one item"
+ (is (= [\*] (:input s1)))
+ (is (= \0 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0980-05
+ (let [s1 (parse (between (sym* \:) digit) ":0:*")]
+ (testing "between - with same delimiter - one item"
+ (is (= [\*] (:input s1)))
+ (is (= \0 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0980-10
+ (let [s1 (parse (between (sym* \|) (many digit)) "|5005|*")]
+ (testing "between - with same delimiter - multiple items"
+ (is (= [\*] (:input s1)))
+ (is (= [\5 \0 \0 \5] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0985
+ (let [p1 (>>= letter
+ (fn [x] (>>= (many alpha-num)
+ (fn [y] (return (cons x y))))))
+ s1 (parse (between (sym* \{) (sym* \}) p1) "{abc101z}*")]
+ (testing "between - one compound item"
+ (is (= [\*] (:input s1)))
+ (is (= (seq "abc101z") (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0990
+ (let [s1 (parse (between (sym* \{) (sym* \}) digit) "(0}*")
+ em (k/get-msg-str (:error s1))]
+ (testing "between - the open parser fails"
+ (is (= [\( \0 \} \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\(\nexpecting \\{"
+ :cljs "unexpected \"(\"\nexpecting \"{\"")
+ em)))))
+
+
+(deftest test-0995
+ (let [s1 (parse (between (sym* \{) (sym* \}) digit) "{0)*")
+ em (k/get-msg-str (:error s1))]
+ (testing "between - the close parser fails"
+ (is (= [\) \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\)\nexpecting \\}"
+ :cljs "unexpected \")\"\nexpecting \"}\"")
+ em)))))
+
+
+(deftest test-1000
+ (let [s1 (parse (times 0 digit) "0*")]
+ (testing "times - zero items"
+ (is (= [\0 \*] (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1001
+ (let [s1 (parse (times 1 letter) "x")]
+ (testing "times - one item"
+ (is (= [] (:input s1)))
+ (is (= [\x] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1005
+ (let [s1 (parse (times 3 (>> k/any-char letter)) "*a@b$c")]
+ (testing "times - three items"
+ (is (empty? (:input s1)))
+ (is (= [\a \b \c] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1005-05
+ (let [s1 (parse (times 3 (>> k/any-char letter)) "*a@b$c")]
+ (testing "times - collects the result in a vector; three items"
+ (is (empty? (:input s1)))
+ (is (= [\a \b \c] (:value s1)))
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1010
+ (let [s1 (parse (times 3 (>> k/any-char letter)) "*a@b$$")
+ em (k/get-msg-str (:error s1))]
+ (testing "times - two items, then fails"
+ (is (= [\$] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\$\nexpecting letter"
+ :cljs "unexpected \"$\"\nexpecting letter")
+ em)))))
+
+
+(deftest test-1015
+ (let [s1 (parse (<$> count (k/look-ahead (many digit))) "12345678")]
+ (testing "look-ahead - succeeds consuming input"
+ (is (= (seq "12345678") (:input s1)))
+ (is (= 8 (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1020
+ (let [s1 (parse (k/look-ahead (many digit)) "YYZ")]
+ (testing "look-ahead - succeeds consuming no input"
+ (is (= [\Y \Y \Z] (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1025
+ (let [s1 (parse (k/look-ahead digit) "*")]
+ (testing "look-ahead - fails consuming no input"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1030
+ (let [s1 (parse (k/look-ahead (>> letter digit)) "A*")]
+ (testing "look-ahead - fails consuming no input"
+ (is (= [\A \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1030-05
+ (let [s1 (parse (k/predict (sym* \=)) "=10")]
+ (testing "predict - if p succeeds it consumes no input"
+ (is (= [\= \1 \0] (:input s1)))
+ (is (= \= (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1030-10
+ (let [s1 (parse (k/predict (sym* \=)) "<10")]
+ (testing "predict - if p succeeds it consumes no input"
+ (is (= [\< \1 \0] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-1035
+ (let [s1 (parse (k/not-followed-by digit) "**")]
+ (testing "not-followed-by - succeeds as digit fails"
+ (is (= [\* \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1040
+ (let [s1 (parse (k/not-followed-by (>> letter letter digit)) "xy**")]
+ (testing "not-followed-by - succeeds as compound item fails"
+ (is (= [\x \y \* \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1045
+ (let [s1 (parse (k/not-followed-by (<*> k/upper digit)) "U2*")
+ em (k/get-msg-str (:error s1))]
+ (testing "not-followed-by - fails as the parse succeeds"
+ (is (= [\U \2 \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected [\\U \\2]"
+ :cljs "unexpected [\"U\" \"2\"]")
+ em)))))
+
+
+(deftest test-1050
+ (let [s1 (parse (>> k/upper k/upper k/upper eof) "YYZ")]
+ (testing "eof - there's nothing left"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1055
+ (let [s1 (parse eof "")]
+ (testing "eof - there's nothing to begin with"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1060
+ (let [s1 (parse (<*> k/upper digit eof) "U2*")
+ em (k/get-msg-str (:error s1))]
+ (testing "eof - fails because the input isn't empty"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= "unexpected *\nexpecting end of input" em)))))
+
+
+(deftest test-1065
+ (let [s1 (parse (k/many-till digit letter) "123456A")]
+ (testing "many-till - parses several numbers, then a letter"
+ (is (empty? (:input s1)))
+ (is (= (seq "123456") (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1065-05
+ (let [s1 (parse (k/many-till digit letter) "123456A")]
+ (testing "many-till - collects the result in a vector; several numbers and a letter"
+ (is (empty? (:input s1)))
+ (is (= (seq "123456") (:value s1)))
+ (is (vector? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1070
+ (let [s1 (parse (k/many-till digit letter) "A*")]
+ (testing "many-till - just the end parser"
+ (is (= [\*] (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1075
+ (let [p1 (>> (token* ""))))
+ s1 (parse p1 "")]
+ (testing "many-till - reads a space between xml comments"
+ (is (empty? (:input s1)))
+ (is (= [\space] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1080
+ (let [p1 (>> (token* ""))))
+ s1 (parse p1 "")]
+ (testing "many-till - reads a word between xml comments"
+ (is (empty? (:input s1)))
+ (is (= (seq "foobar") (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-1085
+ (let [s1 (parse (k/many-till digit letter) "*A")
+ em (k/get-msg-str (:error s1))]
+ (testing "many-till - fails parsing the prefix"
+ (is (= [\* \A] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\*\nexpecting letter or digit"
+ :cljs "unexpected \"*\"\nexpecting letter or digit")
+ em)))))
+
+
+(deftest test-1090
+ (let [s1 (parse (k/many-till digit letter) "12345*A")
+ em (k/get-msg-str (:error s1))]
+ (testing "many-till - parses several prefixes and then fails"
+ (is (= [\* \A] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting letter or digit"
+ :cljs "unexpected \"*\"\nexpecting letter or digit")
+ em)))))
+
+
+(deftest test-1095
+ (let [s1 (parse (k/many-till digit (>> k/upper (sym* \X))) "12345A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "many-till - parses the prefix, then fails reading the end parser"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting \\X"
+ :cljs "unexpected \"*\"\nexpecting \"X\"")
+ em)))))
+
+
+(deftest test-1113
+ (let [s1 (parse (<+> letter) "a")]
+ (testing "<+> - cats from one parser"
+ (is (empty? (:input s1)))
+ (is (= "a" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1114
+ (let [s1 (parse (<+> (times 3 (sym* \S))) "SSS")]
+ (testing "<+> - cats from one parser"
+ (is (empty? (:input s1)))
+ (is (= "SSS" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1115
+ (let [s1 (parse (<+> (sym* \-) digit) "-1")]
+ (testing "<+> - cats from two parsers"
+ (is (empty? (:input s1)))
+ (is (= "-1" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1120
+ (let [s1 (parse (<+> (sym* \-) digit (sym* \;)) "-1;")]
+ (testing "<+> - cats from three parsers"
+ (is (empty? (:input s1)))
+ (is (= "-1;" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1125
+ (let [p1 (<+> letter (>> (sym* \|) letter) (>> (sym* \|) digit))
+ s1 (parse p1 "X|Y|9")]
+ (testing "<+> - cats from filtering parsers"
+ (is (empty? (:input s1)))
+ (is (= "XY9" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1130
+ (let [in "ABC012"
+ p1 (<+> (<*> letter letter letter) (<*> digit digit digit))
+ s1 (parse p1 in)]
+ (testing "<+> - cats from compound parsers"
+ (is (empty? (:input s1)))
+ (is (= "ABC012" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1135
+ (let [s1 (parse (<+> letter digit) "*")]
+ (testing "<+> - the first parser fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1)))))
+
+
+(deftest test-1140
+ (let [s1 (parse (<+> letter digit) "A*")]
+ (testing "<+> - the second parser fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1145
+ (let [s1 (parse (<+> letter tab digit) "A\t*")]
+ (testing "<+> - the third parser fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1150
+ (let [p1 (<+> letter tab tab tab tab tab (sym* \x))
+ s1 (parse p1 "A\t\t\t\t\t*")]
+ (testing "<+> - the seventh parser fails"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1150-05
+ (let [s1 (parse (k/search dec-num) "Now I have 20 dollars")]
+ (testing "search - a simple number"
+ (is (= (seq " dollars") (:input s1)))
+ (is (= 20 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1150-10
+ (let [s1 (parse (many (k/search dec-num)) "Now I have 20 dollars, or 2 tens")]
+ (testing "search - multiple numbers"
+ (is (empty? (:input s1)))
+ (is (= [20 2] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1150-15
+ (let [s1 (parse (many (k/search (<|> dec-num (token* "dollars")))) "Now I have 20 dollars")]
+ (testing "search - multiple choices, multiple times"
+ (is (empty? (:input s1)))
+ (is (= [20 "dollars"] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+;; +-------------------------------------------------------------+
+;; | Parser state. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-1155
+ (let [p1 (>> (k/put-state 0)
+ (skip-many
+ (bind [x k/any-char]
+ (if (= x \newline) (k/modify-state inc) (return nil)))))
+ s1 (parse p1 "aaa\nbbb\nccc\nddd\nfff\nggg\nhhh\n\niii\njjj\n\nkkk")]
+ (testing "put-state, modify-state"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (= 11 (:user s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1160
+ (let [p1 (>> (skip (k/put-state 0)
+ (skip-many
+ (bind [x k/any-char]
+ (if (= x \newline) (k/modify-state inc) (return nil)))))
+ k/get-state)
+ s1 (parse p1 "aaa\nbbb\nccc\nddd\nfff\nggg\nhhh\n\niii\njjj\n\nkkk")]
+ (testing "put-state, get-state; get user state as the parser's value"
+ (is (empty? (:input s1)))
+ (is (= 11 (:value s1)))
+ (is (:ok s1))
+ (is (= 11 (:user s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1165
+ (let [in "ABC"
+ p1 (<+> letter letter letter)
+ p2 (>> (k/set-input "XYZ") p1)
+ s1 (parse (<*> p1 p2) in)]
+ (testing "set-input"
+ (is (empty? (:input s1)))
+ (is (= ["ABC" "XYZ"] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1170
+ (let [in "ABC"
+ p1 (<+> letter letter letter)
+ p2 (>> (skip (k/set-input "XY0")
+ (k/set-position (k/make-pos "include"))) p1)
+ s1 (parse (<*> p1 p2) in)
+ em (k/get-msg-str (:error s1))
+ ip (:pos s1)]
+ (testing "set-input, set-position"
+ (is (= [\0] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= "include" (:src ip)))
+ (is (= 1 (:line ip)))
+ (is (= 3 (:col ip)))
+ (is (= #?(:clj "unexpected \\0\nexpecting letter"
+ :cljs "unexpected \"0\"\nexpecting letter")
+ em)))))
+
+
+(deftest test-1175
+ (let [in "ABC"
+ p1 (<+> letter letter letter)
+ p2 (>> (skip (k/set-input "WXYZ")
+ (k/set-position (k/make-pos "include"))) k/get-position)
+ s1 (parse (>> p1 p2) in)
+ v1 (:value s1)]
+ (testing "set-input, set-position, get-position"
+ (is (= (seq "WXYZ") (:input s1)))
+ (is (= "include" (:src v1)))
+ (is (= 1 (:line v1)))
+ (is (= 1 (:col v1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1180
+ (let [in "ABC"
+ p1 (<+> letter letter letter)
+ p2 (>> (k/set-input "XYZ") k/get-input)
+ s1 (parse (>> p1 p2) in)]
+ (testing "set-input, get-input"
+ (is (= [\X \Y \Z] (:input s1)))
+ (is (= [\X \Y \Z] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+;; +-------------------------------------------------------------+
+;; | Numeric parsers. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-1185
+ (let [s1 (parse dec-num "747")]
+ (testing "dec-num - reads a simple integer"
+ (is (empty? (:input s1)))
+ (is (= 747 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1190
+ (let [s1 (parse dec-num "747-600")]
+ (testing "dec-num - reads a simple integer, delimited"
+ (is (= [\- \6 \0 \0] (:input s1)))
+ (is (= 747 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1195
+ (let [s1 (parse (>> k/upper dec-num) "A380aircraft")]
+ (testing "dec-num - reads an integer, delimited"
+ (is (= (seq "aircraft") (:input s1)))
+ (is (= 380 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1200
+ (let [s1 (parse dec-num "987654321987654321000|")]
+ (testing "dec-num - reads an integer, delimited"
+ (is (= [\|] (:input s1)))
+ (is (= 987654321987654321000N (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1205
+ (let [s1 (parse k/oct-num "0747")]
+ (testing "oct-num - reads a simple octal number"
+ (is (empty? (:input s1)))
+ (is (= 0747 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1210
+ (let [s1 (parse k/oct-num "0747-600")]
+ (testing "oct-num - reads a simple octal number, delimited"
+ (is (= [\- \6 \0 \0] (:input s1)))
+ (is (= 0747 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1215
+ (let [s1 (parse (>> k/upper k/oct-num) "B767aircraft")]
+ (testing "oct-num - reads an octal number, delimited"
+ (is (= (seq "aircraft") (:input s1)))
+ (is (= 0767 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1220
+ (let [s1 (parse k/oct-num "76543217654321000000|")]
+ (testing "oct-num - reads an octal number, delimited"
+ (is (= [\|] (:input s1)))
+ (is (= 076543217654321000000N (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1225
+ (let [s1 (parse k/hex-num "747")]
+ (testing "hex-num - reads a simple hex number"
+ (is (empty? (:input s1)))
+ (is (= 0x747 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1230
+ (let [s1 (parse k/hex-num "747-600")]
+ (testing "hex-num - reads a simple hex number, delimited"
+ (is (= [\- \6 \0 \0] (:input s1)))
+ (is (= 0x747 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1235
+ (let [s1 (parse (>> k/upper k/hex-num) "A380plane")]
+ (testing "hex-num - reads a hex number, delimited"
+ (is (= (seq "plane") (:input s1)))
+ (is (= 0x380 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1240
+ (let [s1 (parse k/hex-num "ABCDEF987654321987654321000|")]
+ (testing "hex-num - reads a hex number, delimited"
+ (is (= [\|] (:input s1)))
+ (is (= 0xABCDEF987654321987654321000N (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1245
+ (let [s1 (parse k/float-num "100")]
+ (testing "float-num - reads a simple floating-point number"
+ (is (empty? (:input s1)))
+ (is (= 100.0 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1250
+ (let [s1 (parse k/float-num "3.1415927")]
+ (testing "float-num - reads a simple floating-point number"
+ (is (empty? (:input s1)))
+ (is (= 3.1415927 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1255
+ (let [s1 (parse k/float-num "9.8m/s")]
+ (testing "float-num - reads a simple floating-point number, delimited"
+ (is (= [\m \/ \s] (:input s1)))
+ (is (= 9.8 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1260
+ (let [s1 (parse k/float-num "0.00343ms")]
+ (testing "float-num - reads a floating-point number, delimited"
+ (is (= [\m \s] (:input s1)))
+ (is (= 0.00343 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-1265
+ (let [s1 (parse k/float-num "98765432.19876543555666|")]
+ (testing "float-num - reads a floating-point number, delimited"
+ (is (= [\|] (:input s1)))
+ (is (= 9.876543219876544E7 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
diff --git a/src/test/clojure/blancas/kern/test_lexer.clj b/src/test/clojure/blancas/kern/test_lexer.clj
deleted file mode 100644
index 85f68a6..0000000
--- a/src/test/clojure/blancas/kern/test_lexer.clj
+++ /dev/null
@@ -1,2074 +0,0 @@
-;; Copyright (c) 2013 Armando Blancas. All rights reserved.
-;; The use and distribution terms for this software are covered by the
-;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-;; which can be found in the file epl-v10.html at the root of this distribution.
-;; By using this software in any fashion, you are agreeing to be bound by
-;; the terms of this license.
-;; You must not remove this notice, or any other, from this software.
-
-(ns blancas.kern.test-lexer
- (:use [blancas.kern.core]
- [blancas.kern.lexer.basic]
- [clojure.test]
- [midje.sweet :exclude (expect one-of)])
- (:require [blancas.kern.lexer :as lex]))
-
-;; Private functions from kern.core
-
-(def get-msg-str (ns-resolve 'blancas.kern.core 'get-msg-str))
-
-
-;; Utility functions.
-
-(defn- get-class
- "Returns the class name of the parser state's value."
- [s] (.getName (class (:value s))))
-
-
-;; +-------------------------------------------------------------+
-;; | Basic lexers. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-0000
- (let [s1 (parse (>> trim eof) " \t\t\n")]
- (fact "trim - blank, tab, eol, then eof"
- (:value s1) => nil
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0005
- (let [s1 (parse (>> trim (many digit)) "123")]
- (fact "trim - no whitespace, it's optional"
- (:value s1) => [\1 \2 \3]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0010
- (let [s1 (parse (>> trim (many1 letter)) " \t\n\t\t ABC")]
- (fact "trim - some whitespace before letters"
- (:value s1) => [\A \B \C]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0015
- (let [s1 (parse (>> (lexeme (sym* \space)) eof) " \t\t\n")]
- (fact "lexeme - a blank, then tab, eol; then eof"
- (:value s1) => nil
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0020
- (let [s1 (parse (lexeme (many digit)) "123")]
- (fact "lexeme - no whitespace, it's optional"
- (:value s1) => [\1 \2 \3]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0025
- (let [s1 (parse (lexeme (many1 letter)) "ABC \t\n\t\t")]
- (fact "lexeme - some whitespace after letters"
- (:value s1) => [\A \B \C]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0030
- (let [s1 (parse new-line "\nfoo")]
- (fact "new-line - parses a new line and stops"
- (:value s1) => \newline
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\f \o \o]
- (:empty s1) => false)))
-
-
-(deftest test-0035
- (let [s1 (parse new-line "\n\t\t foo")]
- (fact "new-line - skip a new line and any other whitespace that follows"
- (:value s1) => \newline
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\f \o \o]
- (:empty s1) => false)))
-
-
-(deftest test-0040
- (let [s1 (parse new-line "\r\nfoo")]
- (fact "new-line - parses a Windows new-line and stops"
- (:value s1) => \newline
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\f \o \o]
- (:empty s1) => false)))
-
-
-(deftest test-0045
- (let [s1 (parse new-line "foo")
- em (get-msg-str (:error s1))]
- (fact "new-line - fails when there's no new-line"
- (:input s1) => [\f \o \o]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\f\nexpecting new line")))
-
-
-(deftest test-0050
- (let [s1 (parse (one-of "+-*/") "+ \n\t4;")]
- (fact "one-of - parses one operator"
- (:value s1) => \+
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\4 \;]
- (:empty s1) => false)))
-
-
-(deftest test-0055
- (let [s1 (parse (one-of "+-*/") "3 + 4;")
- em (get-msg-str (:error s1))]
- (fact "one-of - fails when there's no such operators"
- (:input s1) => (seq "3 + 4;")
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\3")))
-
-
-(deftest test-0060
- (let [s1 (parse (none-of "+-*/") "> \n\t4;")]
- (fact "none-of - parses none of these operators"
- (:value s1) => \>
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\4 \;]
- (:empty s1) => false)))
-
-
-(deftest test-0065
- (let [s1 (parse (none-of "+-*/") "+ 4;")
- em (get-msg-str (:error s1))]
- (fact "none-of - fails when there's one of these operators"
- (:input s1) => (seq "+ 4;")
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\+")))
-
-
-(deftest test-0070
- (let [in "program := foo."
- s1 (parse (token "program") in)]
- (fact "token - parses a specific word, then trims whitespaces"
- (:input s1) => (seq ":= foo.")
- (:value s1) => "program"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0075
- (let [in "program:= foo."
- s1 (parse (token "program") in)]
- (fact "token - parses a specific word"
- (:input s1) => (seq ":= foo.")
- (:value s1) => "program"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0080
- (let [in "foo\t (bar)\n\nbaz"
- s1 (parse (>>= (token "foo")
- (fn [a]
- (>>= (token "(bar)")
- (fn [b]
- (>>= (token "baz")
- (fn [c]
- (return [a b c])))))))
- in)]
- (fact "token - three in a row ignoring whitespaces"
- (:input s1) => empty?
- (:value s1) => ["foo" "(bar)" "baz"])))
-
-
-(deftest test-0085
- (let [in "goat"
- s1 (parse (token "goal") in)
- em (get-msg-str (:error s1))]
- (fact "token - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected goat\nexpecting goal")))
-
-
-(deftest test-0090
- (let [in "function f()"
- s1 (parse (token "function" "procedure") in)]
- (fact "token - parses one of multiple word choices"
- (:input s1) => [\f \( \)]
- (:value s1) => "function"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0095
- (let [in "procedure f()"
- s1 (parse (token "function" "procedure") in)]
- (fact "token - parses one of multiple word choices"
- (:input s1) => [\f \( \)]
- (:value s1) => "procedure"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0100
- (let [in "goat"
- s1 (parse (token "goal" "gol" "gal" "moat") in)
- em (get-msg-str (:error s1))]
- (fact "token - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected goat\nunexpected goa\nexpecting goal, gol, gal or moat")))
-
-
-(deftest test-0105
- (let [in "program \t\t foo()"
- s1 (parse (word "program") in)]
- (fact "word - parses a specific, delimited word"
- (:input s1) => [\f \o \o \( \)]
- (:value s1) => "program"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0110
- (let [in "else{}"
- s1 (parse (word "else") in)]
- (fact "word - parses a specific, delimited word"
- (:input s1) => [\{ \}]
- (:value s1) => "else"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0115
- (let [in "procedure"
- s1 (parse (word "proc") in)
- em (get-msg-str (:error s1))]
- (fact "word - fails because is not delimited"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected e\nexpecting end of proc")))
-
-
-(deftest test-0120
- (let [in "foobar()"
- s1 (parse identifier in)]
- (fact "identifier - parses a basic identifier"
- (:input s1) => [\( \)]
- (:value s1) => "foobar"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0125
- (let [in "total_45 := 0;"
- s1 (parse identifier in)]
- (fact "identifier - parses a basic identifier"
- (:input s1) => [\: \= \space \0 \;]
- (:value s1) => "total_45"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0130
- (let [in "4privateUse"
- s1 (parse identifier in)
- em (get-msg-str (:error s1))]
- (fact "identifier - fails with invalid starting char"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\4\nexpecting letter or \\_")))
-
-
-(deftest test-0135
- (let [in "'a' \t\t|;"
- s1 (parse char-lit in)]
- (fact "char-lit - parses a character literal"
- (:input s1) => [\| \;]
- (:value s1) => \a
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0140
- (let [in "'\\n' \t\t|;"
- s1 (parse char-lit in)]
- (fact "char-lit - parses an escaped character literal"
- (:input s1) => [\| \;]
- (:value s1) => \newline
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0145
- (let [in "'\\t' \t\t|;"
- s1 (parse char-lit in)]
- (fact "char-lit - parses an escaped character literal"
- (:input s1) => [\| \;]
- (:value s1) => \tab
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0150
- (let [in "'u2"
- s1 (parse char-lit in)
- em (get-msg-str (:error s1))]
- (fact "char-lit - fails with a missing closing quote"
- (:input s1) => [\2]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\2\nexpecting end of character literal")))
-
-
-(deftest test-0155
- (let [in "u2"
- s1 (parse char-lit in)
- em (get-msg-str (:error s1))]
- (fact "char-lit - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\u\nexpecting character literal")))
-
-
-(deftest test-0160
- (let [in "\"now is the time\" \t\t|;"
- s1 (parse string-lit in)]
- (fact "string-lit - parses a simple string literal"
- (:input s1) => [\| \;]
- (:value s1) => "now is the time"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0165
- (let [in "\"now\\nis\\tthe\\ttime\" \t\t|;"
- s1 (parse string-lit in)]
- (fact "string-lit - parses a string with escaped chars"
- (:input s1) => [\| \;]
- (:value s1) => "now\nis\tthe\ttime"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0170
- (let [in "\"now is the time"
- s1 (parse string-lit in)
- em (get-msg-str (:error s1))]
- (fact "string-lit - fails with a string that is not terminated"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected end of input\nexpecting end of string literal")))
-
-
-(deftest test-0175
- (let [in "45 + foobar"
- s1 (parse string-lit in)
- em (get-msg-str (:error s1))]
- (fact "string-lit - fails; not a string"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\4\nexpecting string literal")))
-
-
-(deftest test-0180
- (let [in "+100"
- s1 (parse dec-lit in)]
- (fact "dec-lit - parses a redundant positive sign"
- (:input s1) => empty?
- (:value s1) => 100
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0185
- (let [in "123456789"
- s1 (parse dec-lit in)]
- (fact "dec-lit - parses an integer"
- (:input s1) => empty?
- (:value s1) => 123456789
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0190
- (let [in "1000000000N"
- s1 (parse dec-lit in)]
- (fact "dec-lit - parses a BigInt"
- (:input s1) => empty?
- (:value s1) => 1000000000N
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0195
- (let [in "-747"
- s1 (parse dec-lit in)]
- (fact "dec-lit - parses a negative int"
- (:input s1) => empty?
- (:value s1) => -747
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0200
- (let [in "9999999999999999999"
- s1 (parse dec-lit in)
- c1 (get-class s1)]
- (fact "dec-lit - promotes a decimal to a BigInt"
- (:input s1) => empty?
- (:value s1) => 9999999999999999999N
- (:ok s1) => true
- (:empty s1) => false
- c1 => "clojure.lang.BigInt")))
-
-(deftest test-0205
- (let [in "100NA"
- s1 (parse dec-lit in)
- em (get-msg-str (:error s1))]
- (fact "dec-lit - fails; no letter can follow N"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected A\nexpecting decimal literal")))
-
-
-(deftest test-0210
- (let [in "100e"
- s1 (parse dec-lit in)
- em (get-msg-str (:error s1))]
- (fact "dec-lit - fails; no letter can follow the last digit"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected e\nexpecting decimal literal")))
-
-
-(deftest test-0215
- (let [in "99."
- s1 (parse dec-lit in)
- em (get-msg-str (:error s1))]
- (fact "dec-lit - fails; the last digit can't be followed by a dot"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected .\nexpecting decimal literal")))
-
-
-(deftest test-0220
- (let [in "0"
- s1 (parse oct-lit in)]
- (fact "oct-lit - zero should be a valid octal number"
- (:input s1) => empty?
- (:value s1) => 0
- (:ok s1) => true
- (:empty s1) => true)))
-
-
-(deftest test-0225
- (let [in "+0100"
- s1 (parse oct-lit in)]
- (fact "oct-lit - parses a redundant positive sign"
- (:input s1) => empty?
- (:value s1) => 64
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0230
- (let [in "012345676543210"
- s1 (parse oct-lit in)]
- (fact "oct-lit - parses an integer"
- (:input s1) => empty?
- (:value s1) => 012345676543210
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0235
- (let [in "03777N"
- s1 (parse oct-lit in)]
- (fact "oct-lit - parses a BigInt"
- (:input s1) => empty?
- (:value s1) => 03777N
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0240
- (let [in "-0747"
- s1 (parse oct-lit in)]
- (fact "oct-lit - parses a negative int"
- (:input s1) => empty?
- (:value s1) => -0747
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0245
- (let [in "055555555555555555555N"
- s1 (parse oct-lit in)
- c1 (get-class s1)]
- (fact "oct-lit - promotes a decimal to a BigInt"
- (:input s1) => empty?
- (:value s1) => 055555555555555555555N
- (:ok s1) => true
- (:empty s1) => false
- c1 => "clojure.lang.BigInt")))
-
-(deftest test-0250
- (let [in "0100NA"
- s1 (parse oct-lit in)
- em (get-msg-str (:error s1))]
- (fact "oct-lit - fails; no letter can follow N"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected A\nexpecting octal literal")))
-
-
-(deftest test-0255
- (let [in "0100e"
- s1 (parse oct-lit in)
- em (get-msg-str (:error s1))]
- (fact "oct-lit - fails; no letter can follow the last digit"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected e\nexpecting octal literal")))
-
-
-(deftest test-0260
- (let [in "077."
- s1 (parse oct-lit in)
- em (get-msg-str (:error s1))]
- (fact "oct-lit - fails; the last digit can't be followed by a dot"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected .\nexpecting octal literal")))
-
-
-(deftest test-0265
- (let [in "0x0"
- s1 (parse hex-lit in)]
- (fact "hex-lit - parses a zero"
- (:input s1) => empty?
- (:value s1) => 0
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0270
- (let [in "0XABCDEF"
- s1 (parse hex-lit in)]
- (fact "hex-lit - uses all capial letters"
- (:input s1) => empty?
- (:value s1) => 0xabcdef
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0275
- (let [in "0xabcdef"
- s1 (parse hex-lit in)]
- (fact "hex-lit - uses all capial letters"
- (:input s1) => empty?
- (:value s1) => 0XABCDEF
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0280
- (let [in "+0x100"
- s1 (parse hex-lit in)]
- (fact "hex-lit - parses a redundant positive sign"
- (:input s1) => empty?
- (:value s1) => 0x100
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0285
- (let [in "0xCAFEBABE"
- s1 (parse hex-lit in)]
- (fact "hex-lit - parses an integer"
- (:input s1) => empty?
- (:value s1) => 0xCAFEBABE
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0290
- (let [in "0x00008B55CABA0000N"
- s1 (parse hex-lit in)]
- (fact "hex-lit - parses a BigInt"
- (:input s1) => empty?
- (:value s1) => 0x00008B55CABA0000N
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0295
- (let [in "-0x0F0E"
- s1 (parse hex-lit in)]
- (fact "hex-lit - parses a negative int"
- (:input s1) => empty?
- (:value s1) => -0x0F0E
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0300
- (let [in "0x8000FA7770000B3400400200A"
- s1 (parse hex-lit in)
- c1 (get-class s1)]
- (fact "hex-lit - promotes a decimal to a BigInt"
- (:input s1) => empty?
- (:value s1) => 0x8000FA7770000B3400400200AN
- (:ok s1) => true
- (:empty s1) => false
- c1 => "clojure.lang.BigInt")))
-
-(deftest test-0305
- (let [in "0x100NA"
- s1 (parse hex-lit in)
- em (get-msg-str (:error s1))]
- (fact "hex-lit - fails; no letter can follow N"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected A\nexpecting hex literal")))
-
-
-(deftest test-0310
- (let [in "0x100x"
- s1 (parse hex-lit in)
- em (get-msg-str (:error s1))]
- (fact "hex-lit - fails; no letter can follow the last digit"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected x\nexpecting hex literal")))
-
-
-(deftest test-0315
- (let [in "0x77."
- s1 (parse hex-lit in)
- em (get-msg-str (:error s1))]
- (fact "hex-lit - fails; the last digit can't be followed by a dot"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected .\nexpecting hex literal")))
-
-
-(deftest test-0320
- (let [in "0"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a zero"
- (:input s1) => empty?
- (:value s1) => 0.0
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0325
- (let [in "0.0"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a zero"
- (:input s1) => empty?
- (:value s1) => 0.0
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0330
- (let [in "+100.00"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a redundant positive sign"
- (:input s1) => empty?
- (:value s1) => 100.00
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0335
- (let [in "1558.95"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a floating-point number"
- (:input s1) => empty?
- (:value s1) => 1558.95
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0340
- (let [in "1558.955e12"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a floating-point number with an exponent"
- (:input s1) => empty?
- (:value s1) => 1558.955e12
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0345
- (let [in "1558.9558e-12"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a floating-point number with an exponent"
- (:input s1) => empty?
- (:value s1) => 1558.9558e-12
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0350
- (let [in "1558.9558e+12"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a floating-point number with an exponent"
- (:input s1) => empty?
- (:value s1) => 1558.9558e+12
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0355
- (let [in "-1558.9558e-12"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a negative floating-point number with an exponent"
- (:input s1) => empty?
- (:value s1) => -1558.9558e-12
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0360
- (let [in "1558e12"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a number with no fractional part and an exponent"
- (:input s1) => empty?
- (:value s1) => 1558e12
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0365
- (let [in "3.1415927M"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a BigDecimal"
- (:input s1) => empty?
- (:value s1) => 3.1415927M
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0370
- (let [in "-199.95"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a negative floating-point number"
- (:input s1) => empty?
- (:value s1) => -199.95
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0370-05
- (let [in "999"
- s1 (parse float-lit in)]
- (fact "float-lit - parses a round integer as a floating-point number"
- (:input s1) => empty?
- (:value s1) => 999.0
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0370-10
- (let [in "999"
- s1 (parse float-lit in)]
- (fact "float-lit - regression test: number should not be long"
- (:value s1) =not=> 999)))
-
-
-(deftest test-0375
- (let [in "99.95MA"
- s1 (parse float-lit in)
- em (get-msg-str (:error s1))]
- (fact "float-lit - fails; no letter can follow M"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected A\nexpecting floating-point literal")))
-
-
-(deftest test-0380
- (let [in "99.95X"
- s1 (parse float-lit in)
- em (get-msg-str (:error s1))]
- (fact "float-lit - fails; no letter can follow the last digit"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected X\nexpecting floating-point literal")))
-
-
-(deftest test-0385
- (let [in ".9999"
- s1 (parse float-lit in)
- em (get-msg-str (:error s1))]
- (fact "float-lit - fails; cannot start with a dot"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\.\nexpecting floating-point literal")))
-
-
-(deftest test-0390
- (let [in "true"
- s1 (parse bool-lit in)]
- (fact "bool-lit - true"
- (:input s1) => empty?
- (:value s1) => true
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0395
- (let [in "false"
- s1 (parse bool-lit in)]
- (fact "bool-lit - false"
- (:input s1) => empty?
- (:value s1) => false
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0400
- (let [in "true \t \t)"
- s1 (parse bool-lit in)]
- (fact "bool-lit - true with whitespace"
- (:input s1) => [\)]
- (:value s1) => true
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0405
- (let [in "false\n\t\t :"
- s1 (parse bool-lit in)]
- (fact "bool-lit - false with whitespace"
- (:input s1) => [\:]
- (:value s1) => false
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0410
- (let [in "nil"
- s1 (parse nil-lit in)]
- (fact "nil-lit - nil"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0415
- (let [in "null"
- s1 (parse nil-lit in)]
- (fact "nil-lit - null"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0420
- (let [in "nil \t \t)"
- s1 (parse nil-lit in)]
- (fact "nil-lit - nil with whitespace"
- (:input s1) => [\)]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0425
- (let [in "null\n\t\t :"
- s1 (parse nil-lit in)]
- (fact "nil-lit - null with whitespace"
- (:input s1) => [\:]
- (:value s1) => nil
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0430
- (let [in "(true)"
- s1 (parse (parens bool-lit) in)]
- (fact "parens - true"
- (:input s1) => empty?
- (:value s1) => true
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0435
- (let [in "()"
- s1 (parse (parens (many dec-lit)) in)]
- (fact "parens - nothing"
- (:input s1) => empty?
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0440
- (let [in "( 11 22 33 44 55 )"
- s1 (parse (parens (many1 dec-lit)) in)]
- (fact "parens - true"
- (:input s1) => empty?
- (:value s1) => [11 22 33 44 55]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0445
- (let [in "11 22 33)"
- s1 (parse (parens (many1 dec-lit)) in)
- em (get-msg-str (:error s1))]
- (fact "parens - fails; no starting paren"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\1\nexpecting \\(")))
-
-
-(deftest test-0450
- (let [in "(11 22 33 ;"
- s1 (parse (parens (many1 dec-lit)) in)
- em (get-msg-str (:error s1))]
- (fact "parens - fails; no ending paren"
- (:input s1) => [\;]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\;\nexpecting \\)")))
-
-
-(deftest test-0455
- (let [in "()"
- s1 (parse (parens dec-lit) in)
- em (get-msg-str (:error s1))]
- (fact "parens - fails; missing value"
- (:input s1) => [\)]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\)\nexpecting decimal literal")))
-
-
-(deftest test-0460
- (let [in "{true}"
- s1 (parse (braces bool-lit) in)]
- (fact "braces - true"
- (:input s1) => empty?
- (:value s1) => true
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0465
- (let [in "{}"
- s1 (parse (braces (many dec-lit)) in)]
- (fact "braces - nothing"
- (:input s1) => empty?
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0470
- (let [in "{ 11 22 33 44 55 }"
- s1 (parse (braces (many1 dec-lit)) in)]
- (fact "braces - true"
- (:input s1) => empty?
- (:value s1) => [11 22 33 44 55]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0475
- (let [in "11 22 33}"
- s1 (parse (braces (many1 dec-lit)) in)
- em (get-msg-str (:error s1))]
- (fact "braces - fails; no starting brace"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\1\nexpecting \\{")))
-
-
-(deftest test-0480
- (let [in "{11 22 33 ;"
- s1 (parse (braces (many1 dec-lit)) in)
- em (get-msg-str (:error s1))]
- (fact "braces - fails; no ending brace"
- (:input s1) => [\;]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\;\nexpecting \\}")))
-
-
-(deftest test-0485
- (let [in "{}"
- s1 (parse (braces dec-lit) in)
- em (get-msg-str (:error s1))]
- (fact "braces - fails; missing value"
- (:input s1) => [\}]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\}\nexpecting decimal literal")))
-
-
-(deftest test-0490
- (let [in ""
- s1 (parse (angles bool-lit) in)]
- (fact "angles - true"
- (:input s1) => empty?
- (:value s1) => true
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0495
- (let [in "<>"
- s1 (parse (angles (many dec-lit)) in)]
- (fact "angles - nothing"
- (:input s1) => empty?
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0500
- (let [in "< 11 22 33 44 55 >"
- s1 (parse (angles (many1 dec-lit)) in)]
- (fact "angles - true"
- (:input s1) => empty?
- (:value s1) => [11 22 33 44 55]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0505
- (let [in "11 22 33>"
- s1 (parse (angles (many1 dec-lit)) in)
- em (get-msg-str (:error s1))]
- (fact "angles - fails; no starting angle bracket"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\1\nexpecting \\<")))
-
-
-(deftest test-0510
- (let [in "<11 22 33 ;"
- s1 (parse (angles (many1 dec-lit)) in)
- em (get-msg-str (:error s1))]
- (fact "angles - fails; no ending angle bracket"
- (:input s1) => [\;]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\;\nexpecting \\>")))
-
-
-(deftest test-0515
- (let [in "<>"
- s1 (parse (angles dec-lit) in)
- em (get-msg-str (:error s1))]
- (fact "angles - fails; missing value"
- (:input s1) => [\>]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\>\nexpecting decimal literal")))
-
-
-(deftest test-0520
- (let [in "[true]"
- s1 (parse (brackets bool-lit) in)]
- (fact "brackets - true"
- (:input s1) => empty?
- (:value s1) => true
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0525
- (let [in "[]"
- s1 (parse (brackets (many dec-lit)) in)]
- (fact "brackets - nothing"
- (:input s1) => empty?
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0530
- (let [in "[ 11 22 33 44 55 ]"
- s1 (parse (brackets (many1 dec-lit)) in)]
- (fact "brackets - true"
- (:input s1) => empty?
- (:value s1) => [11 22 33 44 55]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0535
- (let [in "11 22 33]"
- s1 (parse (brackets (many1 dec-lit)) in)
- em (get-msg-str (:error s1))]
- (fact "brackets - fails; no starting bracket"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\1\nexpecting \\[")))
-
-
-(deftest test-0540
- (let [in "[11 22 33 ;"
- s1 (parse (brackets (many1 dec-lit)) in)
- em (get-msg-str (:error s1))]
- (fact "brackets - fails; no ending bracket"
- (:input s1) => [\;]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\;\nexpecting \\]")))
-
-
-(deftest test-0545
- (let [in "[]"
- s1 (parse (brackets dec-lit) in)
- em (get-msg-str (:error s1))]
- (fact "brackets - fails; missing value"
- (:input s1) => [\]]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\]\nexpecting decimal literal")))
-
-
-(deftest test-0550
- (let [in ";\n\n"
- s1 (parse semi in)]
- (fact "semi"
- (:input s1) => empty?
- (:value s1) => \;
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0555
- (let [in "+"
- s1 (parse semi in)
- em (get-msg-str (:error s1))]
- (fact "semi - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\+\nexpecting \\;")))
-
-
-(deftest test-0560
- (let [in ",\n\n"
- s1 (parse comma in)]
- (fact "comma"
- (:input s1) => empty?
- (:value s1) => \,
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0565
- (let [in "+"
- s1 (parse comma in)
- em (get-msg-str (:error s1))]
- (fact "comma - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\+\nexpecting \\,")))
-
-
-(deftest test-0570
- (let [in ":\n\n"
- s1 (parse colon in)]
- (fact "colon"
- (:input s1) => empty?
- (:value s1) => \:
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0575
- (let [in "+"
- s1 (parse colon in)
- em (get-msg-str (:error s1))]
- (fact "colon - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\+\nexpecting \\:")))
-
-
-(deftest test-0580
- (let [in ".\n\n"
- s1 (parse dot in)]
- (fact "comma"
- (:input s1) => empty?
- (:value s1) => \.
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0585
- (let [in "+"
- s1 (parse dot in)
- em (get-msg-str (:error s1))]
- (fact "dot - fails"
- (:input s1) => (seq in)
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\+\nexpecting \\.")))
-
-
-(deftest test-0590
- (let [s1 (parse (semi-sep digit) "*")]
- (fact "semi-sep - there are no separated items"
- (:input s1) => [\*]
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-0595
- (let [s1 (parse (semi-sep (>> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "semi-sep - there are no separated compound items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0600
- (let [s1 (parse (semi-sep digit) "0*")]
- (fact "semi-sep - one item, no separator"
- (:input s1) => [\*]
- (:value s1) => [\0]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0605
- (let [s1 (parse (semi-sep (<*> upper digit)) "U2*")]
- (fact "semi-sep - one compound item, no separator"
- (:input s1) => [\*]
- (:value s1) => [[\U \2]]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0610
- (let [s1 (parse (semi-sep (>> letter digit)) "U2;*")
- em (get-msg-str (:error s1))]
- (fact "semi-sep - there is only one item and the separator"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting letter")))
-
-
-(deftest test-0615
- (let [s1 (parse (semi-sep dec-lit) "550; 101*")]
- (fact "semi-sep - two simple items"
- (:input s1) => [\*]
- (:value s1) => [550 101]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0620
- (let [s1 (parse (semi-sep hex-lit) "+0xFADE ; -0x7800 *")]
- (fact "semi-sep - two compound items"
- (:input s1) => [\*]
- (:value s1) => [0xFADE -0x7800]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0625
- (let [p1 (semi-sep identifier)
- s1 (parse p1 "one ;\n two ; \t\t three")]
- (fact "semi-sep - three compound items"
- (:input s1) => empty?
- (:value s1) => ["one" "two" "three"]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0630
- (let [s1 (parse (semi-sep1 digit) "*")
- em (get-msg-str (:error s1))]
- (fact "semi-sep1 - there are no separated items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0635
- (let [s1 (parse (semi-sep1 (>> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "semi-sep1 - there are no separated compound items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0640
- (let [s1 (parse (semi-sep1 dec-lit) "747*")]
- (fact "semi-sep1 - one item, no separator"
- (:input s1) => [\*]
- (:value s1) => [747]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0645
- (let [s1 (parse (semi-sep1 (<*> upper digit)) "U2*")]
- (fact "semi-sep1 - one compound item, no separator"
- (:input s1) => [\*]
- (:value s1) => [[\U \2]]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0650
- (let [s1 (parse (semi-sep1 identifier) "U2;*")
- em (get-msg-str (:error s1))]
- (fact "semi-sep1 - there is only one item and the separator"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting letter or \\_")))
-
-
-(deftest test-0655
- (let [s1 (parse (semi-sep1 dec-lit) "100;200*")]
- (fact "semi-sep1 - two simple items"
- (:input s1) => [\*]
- (:value s1) => [100 200]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0660
- (let [s1 (parse (semi-sep1 dec-lit) "-100 \t \t;\n +200*")]
- (fact "semi-sep1 - two compound items with whitespace"
- (:input s1) => [\*]
- (:value s1) => [-100 200]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0665
- (let [p1 (semi-sep1 identifier)
- s1 (parse p1 "one ;\n\n two \t\t;\n\t three")]
- (fact "semi-sep1 - three compound items"
- (:input s1) => empty?
- (:value s1) => ["one" "two" "three"]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0670
- (let [s1 (parse (semi-sep1 (>> upper digit)) "A1; B2; \tC3;DD;*")
- em (get-msg-str (:error s1))]
- (fact "semi-sep1 - compound item fails after reading several items"
- (:input s1) => [\D \; \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\D\nexpecting digit")))
-
-
-(deftest test-0675
- (let [s1 (parse (comma-sep digit) "*")]
- (fact "comma-sep - there are no separated items"
- (:input s1) => [\*]
- (:value s1) => []
- (:ok s1) => true
- (:empty s1) => true
- (:error s1) => nil)))
-
-
-(deftest test-0680
- (let [s1 (parse (comma-sep (>> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "comma-sep - there are no separated compound items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0685
- (let [s1 (parse (comma-sep digit) "0*")]
- (fact "comma-sep - one item, no separator"
- (:input s1) => [\*]
- (:value s1) => [\0]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0690
- (let [s1 (parse (comma-sep (<*> upper digit)) "U2*")]
- (fact "comma-sep - one compound item, no separator"
- (:input s1) => [\*]
- (:value s1) => [[\U \2]]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0695
- (let [s1 (parse (comma-sep (>> letter digit)) "U2,*")
- em (get-msg-str (:error s1))]
- (fact "comma-sep - there is only one item and the separator"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting letter")))
-
-
-(deftest test-0700
- (let [s1 (parse (comma-sep dec-lit) "550, 101*")]
- (fact "comma-sep - two simple items"
- (:input s1) => [\*]
- (:value s1) => [550 101]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0705
- (let [s1 (parse (comma-sep hex-lit) "+0xFADE , -0x7800 *")]
- (fact "comma-sep - two compound items"
- (:input s1) => [\*]
- (:value s1) => [0xFADE -0x7800]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0710
- (let [p1 (comma-sep identifier)
- s1 (parse p1 "one ,\n two , \t\t three")]
- (fact "comma-sep - three compound items"
- (:input s1) => empty?
- (:value s1) => ["one" "two" "three"]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0715
- (let [s1 (parse (comma-sep1 digit) "*")
- em (get-msg-str (:error s1))]
- (fact "comma-sep1 - there are no separated items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0720
- (let [s1 (parse (comma-sep1 (>> letter digit)) "A*")
- em (get-msg-str (:error s1))]
- (fact "comma-sep1 - there are no separated compound items"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting digit")))
-
-
-(deftest test-0725
- (let [s1 (parse (comma-sep1 dec-lit) "747*")]
- (fact "comma-sep1 - one item, no separator"
- (:input s1) => [\*]
- (:value s1) => [747]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0730
- (let [s1 (parse (comma-sep1 (<*> upper digit)) "U2*")]
- (fact "comma-sep1 - one compound item, no separator"
- (:input s1) => [\*]
- (:value s1) => [[\U \2]]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0735
- (let [s1 (parse (comma-sep1 identifier) "U2,*")
- em (get-msg-str (:error s1))]
- (fact "comma-sep1 - there is only one item and the separator"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting letter or \\_")))
-
-
-(deftest test-0740
- (let [s1 (parse (comma-sep1 dec-lit) "100,200*")]
- (fact "comma-sep1 - two simple items"
- (:input s1) => [\*]
- (:value s1) => [100 200]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0745
- (let [s1 (parse (comma-sep1 dec-lit) "-100 \t \t,\n +200*")]
- (fact "comma-sep1 - two compound items with whitespace"
- (:input s1) => [\*]
- (:value s1) => [-100 200]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0750
- (let [p1 (comma-sep1 identifier)
- s1 (parse p1 "one ,\n\n two \t\t,\n\t three")]
- (fact "comma-sep1 - three compound items"
- (:input s1) => empty?
- (:value s1) => ["one" "two" "three"]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0755
- (let [s1 (parse (comma-sep1 (>> upper digit)) "A1, B2, \tC3,DD,*")
- em (get-msg-str (:error s1))]
- (fact "comma-sep1 - compound item fails after reading several items"
- (:input s1) => [\D \, \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\D\nexpecting digit")))
-
-
-(deftest test-0760
- (let [s1 (parse char-lit "'z'")]
- (fact "char-lit"
- (:value s1) => \z
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0765
- (let [s1 (parse char-lit "'\\b'")]
- (fact "char-lit"
- (:value s1) => \backspace
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0770
- (let [s1 (parse char-lit "'\\t'")]
- (fact "char-lit"
- (:value s1) => \tab
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0775
- (let [s1 (parse char-lit "'\\n'")]
- (fact "char-lit"
- (:value s1) => \newline
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0780
- (let [s1 (parse char-lit "'\\f'")]
- (fact "char-lit"
- (:value s1) => \formfeed
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0785
- (let [s1 (parse char-lit "'\\r'")]
- (fact "char-lit"
- (:value s1) => \return
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0790
- (let [s1 (parse char-lit "'\\''")]
- (fact "char-lit"
- (:value s1) => \'
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0795
- (let [s1 (parse char-lit "'\\\"'")]
- (fact "char-lit"
- (:value s1) => \"
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0800
- (let [s1 (parse char-lit "'\\\\'")]
- (fact "char-lit"
- (:value s1) => \\
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0805
- (let [s1 (parse char-lit "'\\/'")]
- (fact "char-lit"
- (:value s1) => \/
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-(deftest test-0810
- (let [in "'a "
- s1 (parse char-lit in)
- em (get-msg-str (:error s1))]
- (fact "char-lit - fails without the closing quote"
- (:input s1) => [\space]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\space\nexpecting end of character literal")))
-
-
-(deftest test-0815
- (let [in "'\\n "
- s1 (parse char-lit in)
- em (get-msg-str (:error s1))]
- (fact "char-lit - fails without the closing quote"
- (:input s1) => [\space]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\space\nexpecting end of character literal")))
-
-
-(deftest test-0820
- (let [in "\"\\bnow\\tis\\nthe\\ftime\\r\" \t\t|;"
- s1 (parse string-lit in)]
- (fact "string-lit - parses a string with multiple escaped characters"
- (:input s1) => [\| \;]
- (:value s1) => "\bnow\tis\nthe\ftime\r"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-;; +-------------------------------------------------------------+
-;; | Custom lexers. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-0820-05
- (let [rec (lex/make-parsers (assoc lex/shell-style :line-continuation (sym* \?)))]
- (lex/with-parsers rec
- (let [in "foo bar foobar ?\n\t\tbaz"
- s1 (parse (many1 lex/identifier) in)]
- (fact "trim - line continuation with a ?"
- (:input s1) => empty?
- (:value s1) => ["foo" "bar" "foobar" "baz"]
- (:ok s1) => true
- (:empty s1) => false)))))
-
-
-(deftest test-0825
- (let [rec (lex/make-parsers (assoc lex/c-style :case-sensitive false))]
- (lex/with-parsers rec
- (let [in "WhIlE (..."
- s1 (parse (lex/word "while") in)]
- (fact "word - non-case-sensitive"
- (:input s1) => [\( \. \. \.]
- (:value s1) => "while"
- (:ok s1) => true
- (:empty s1) => false)))))
-
-
-(deftest test-0830
- (let [rec (lex/make-parsers (assoc lex/c-style :nested-comments true))]
- (lex/with-parsers rec
- (let [in "foo /***outter /* inner comment */ end of outer***/"
- s1 (parse lex/identifier in)]
- (fact "word - nested comments"
- (:input s1) => empty?
- (:value s1) => "foo"
- (:ok s1) => true
- (:empty s1) => false)))))
-
-
-(deftest test-0845
- (let [rec (lex/make-parsers (assoc lex/c-style :reserved-names ["foo" "bar"]))]
- (lex/with-parsers rec
- (let [in "foobar * baz"
- s1 (parse lex/identifier in)]
- (fact "word - valid word, not a reserved word"
- (:value s1) => "foobar"
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\* \space \b \a \z]
- (:empty s1) => false)))))
-
-
-(deftest test-0850
- (let [rec (lex/make-parsers (assoc lex/c-style :reserved-names ["foo" "bar"]))]
- (lex/with-parsers rec
- (let [in "foo * bar"
- s1 (parse lex/identifier in)
- em (get-msg-str (:error s1))]
- (fact "word - fails on a reserved word"
- (:input s1) => [\f \o \o \space \* \space \b \a \r]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "foo is a reserved name")))))
-
-
-(deftest test-0855
- (let [rec (lex/make-parsers (assoc lex/c-style
- :case-sensitive false
- :reserved-names ["foo" "bar"]))]
- (lex/with-parsers rec
- (let [in "FOO * bar"
- s1 (parse lex/identifier in)
- em (get-msg-str (:error s1))]
- (fact "word - fails on a reserved word"
- (:input s1) => [\F \O \O \space \* \space \b \a \r]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "FOO is a reserved name")))))
-
-
-(deftest test-0860
- (let [rec (lex/make-parsers (assoc lex/basic-def :leading-sign false))]
- (lex/with-parsers rec
- (let [in "5005"
- s1 (parse lex/dec-lit in)]
- (fact "dec-lit - regular case, no leading sign."
- (:input s1) => empty?
- (:value s1) => 5005
- (:ok s1) => true
- (:empty s1) => false)))))
-
-
-(deftest test-0865
- (let [rec (lex/make-parsers (assoc lex/basic-def :leading-sign false))]
- (lex/with-parsers rec
- (let [in "0xCAFE"
- s1 (parse lex/hex-lit in)]
- (fact "hex-lit - regular case, no leading sign."
- (:input s1) => empty?
- (:value s1) => 0xCAFE
- (:ok s1) => true
- (:empty s1) => false)))))
-
-
-(deftest test-0870
- (let [rec (lex/make-parsers (assoc lex/basic-def :leading-sign false))]
- (lex/with-parsers rec
- (let [in "-5005"
- s1 (parse lex/dec-lit in)]
- (fact "dec-lit - with leading sign it fails."
- (:input s1) => (seq "-5005")
- (:value s1) => nil
- (:ok s1) => false)))))
-
-
-(deftest test-0875
- (let [rec (lex/make-parsers (assoc lex/basic-def :leading-sign false))]
- (lex/with-parsers rec
- (let [in "+3.1416"
- s1 (parse lex/float-lit in)]
- (fact "float-lit - with leading sign it fails."
- (:input s1) => (seq "+3.1416")
- (:value s1) => nil
- (:ok s1) => false)))))
-
-
-;; +-------------------------------------------------------------+
-;; | Repeating Patterns. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-0900
- (let [s1 (parse identifier "f")]
- (fact "identifier -- state must not be empty"
- (:value s1) => "f"
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0905
- (let [s1 (parse (many identifier) "f")]
- (fact "identifier -- many should work with a single-letter id"
- (:value s1) => ["f"]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0910
- (let [s1 (parse (comma-sep identifier) "f")]
- (fact "multiple identifier"
- (:value s1) => ["f"]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0915
- (let [s1 (parse (many (sym \Q)) "QQQ")]
- (fact "multiple symbols"
- (:value s1) => [\Q \Q \Q]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0920
- (let [s1 (parse (many (one-of "abc")) "a b c")]
- (fact "many one-of"
- (:value s1) => [\a \b \c]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0925
- (let [s1 (parse (many (none-of "abc")) "xyz")]
- (fact "many none-of"
- (:value s1) => [\x \y \z]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0930
- (let [s1 (parse (many (token "abc")) "abcabc abc")]
- (fact "many token"
- (:value s1) => ["abc" "abc" "abc"]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0935
- (let [s1 (parse (many0 (token "abc")) "xxx")]
- (fact "many0, nothing match but empty is cleared"
- (:value s1) => []
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => (seq "xxx")
- (:empty s1) => false)))
-
-
-(deftest test-0940
- (let [s1 (parse (many (field " ")) "now is the time")]
- (fact "many field"
- (:value s1) => ["now" "is" "the" "time"]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0945
- (let [s1 (parse (many (field " ")) "x y")]
- (fact "many token"
- (:value s1) => ["x" "y"]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0950
- (let [s1 (parse (many dec-lit) "0")]
- (fact "many dec-lit"
- (:value s1) => [0]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0955
- (let [s1 (parse (many oct-lit) "01")]
- (fact "many oct-lit"
- (:value s1) => [1]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0960
- (let [s1 (parse (many hex-lit) "0x1")]
- (fact "many hex-lit"
- (:value s1) => [1]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0965
- (let [s1 (parse (many float-lit) "1")]
- (fact "many float-lit"
- (:value s1) => [1.0]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
diff --git a/src/test/clojure/blancas/kern/test_lexer.cljc b/src/test/clojure/blancas/kern/test_lexer.cljc
new file mode 100644
index 0000000..63b1c11
--- /dev/null
+++ b/src/test/clojure/blancas/kern/test_lexer.cljc
@@ -0,0 +1,2145 @@
+;; Copyright (c) 2013 Armando Blancas. All rights reserved.
+;; The use and distribution terms for this software are covered by the
+;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this distribution.
+;; By using this software in any fashion, you are agreeing to be bound by
+;; the terms of this license.
+;; You must not remove this notice, or any other, fro-m this software.
+
+(ns blancas.kern.test-lexer
+ (:require [blancas.kern.core :as k :refer [parse >> >>= <*>]]
+ [blancas.kern.lexer.basic :as lex-basic]
+ [clojure.test :refer [deftest is testing]]
+ [blancas.kern.lexer :as lex])
+ #?(:cljs (:require-macros [blancas.kern.lexer :as lex])))
+
+;; Utility functions.
+
+(defn- get-class
+ "Returns the class name of the parser state's value."
+ [s] (str (type (:value s))))
+
+
+;; +-------------------------------------------------------------+
+;; | Basic lexers. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-0000
+ (let [s1 (parse (>> lex-basic/trim k/eof) " \t\t\n")]
+ (testing "trim - blank, tab, eol, then eof"
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0005
+ (let [s1 (parse (>> lex-basic/trim (k/many k/digit)) "123")]
+ (testing "trim - no whitespace, it's optional"
+ (is (= [\1 \2 \3] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0010
+ (let [s1 (parse (>> lex-basic/trim (k/many1 k/letter)) " \t\n\t\t ABC")]
+ (testing "trim - some whitespace before letters"
+ (is (= [\A \B \C] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0015
+ (let [s1 (parse (>> (lex-basic/lexeme (k/sym* \space)) k/eof) " \t\t\n")]
+ (testing "lexeme - a blank, then tab, eol; then eof"
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0020
+ (let [s1 (parse (lex-basic/lexeme (k/many k/digit)) "123")]
+ (testing "lexeme - no whitespace, it's optional"
+ (is (= [\1 \2 \3] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0025
+ (let [s1 (parse (lex-basic/lexeme (k/many1 k/letter)) "ABC \t\n\t\t")]
+ (testing "lexeme - some whitespace after letters"
+ (is (= [\A \B \C] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0030
+ (let [s1 (parse lex-basic/new-line "\nfoo")]
+ (testing "new-line - parses a new line and stops"
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\f \o \o] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0035
+ (let [s1 (parse lex-basic/new-line "\n\t\t foo")]
+ (testing "new-line - skip a new line and any other whitespace that follows"
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\f \o \o] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0040
+ (let [s1 (parse lex-basic/new-line "\r\nfoo")]
+ (testing "new-line - parses a Windows new-line and stops"
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\f \o \o] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0045
+ (let [s1 (parse lex-basic/new-line "foo")
+ em (k/get-msg-str (:error s1))]
+ (testing "new-line - fails when there's no new-line"
+ (is (= [\f \o \o] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\f\nexpecting new line"
+ :cljs "unexpected \"f\"\nexpecting new line")
+ em)))))
+
+
+(deftest test-0050
+ (let [s1 (parse (lex-basic/one-of "+-*/") "+ \n\t4;")]
+ (testing "one-of - parses one operator"
+ (is (= \+ (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\4 \;] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0055
+ (let [s1 (parse (lex-basic/one-of "+-*/") "3 + 4;")
+ em (k/get-msg-str (:error s1))]
+ (testing "one-of - fails when there's no such operators"
+ (is (= (seq "3 + 4;") (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\3"
+ :cljs "unexpected \"3\"")
+ em)))))
+
+
+(deftest test-0060
+ (let [s1 (parse (lex-basic/none-of "+-*/") "> \n\t4;")]
+ (testing "none-of - parses none of these operators"
+ (is (= \> (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\4 \;] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0065
+ (let [s1 (parse (lex-basic/none-of "+-*/") "+ 4;")
+ em (k/get-msg-str (:error s1))]
+ (testing "none-of - fails when there's one of these operators"
+ (is (= (seq "+ 4;") (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\+"
+ :cljs "unexpected \"+\"")
+ em)))))
+
+
+(deftest test-0070
+ (let [in "program := foo."
+ s1 (parse (lex-basic/token "program") in)]
+ (testing "token - parses a specific word, then trims whitespaces"
+ (is (= (seq ":= foo.") (:input s1)))
+ (is (= "program" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0075
+ (let [in "program:= foo."
+ s1 (parse (lex-basic/token "program") in)]
+ (testing "token - parses a specific word"
+ (is (= (seq ":= foo.") (:input s1)))
+ (is (= "program" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0080
+ (let [in "foo\t (bar)\n\nbaz"
+ s1 (parse (>>= (lex-basic/token "foo")
+ (fn [a]
+ (>>= (lex-basic/token "(bar)")
+ (fn [b]
+ (>>= (lex-basic/token "baz")
+ (fn [c]
+ (k/return [a b c])))))))
+ in)]
+ (testing "token - three in a row ignoring whitespaces"
+ (is (empty? (:input s1)))
+ (is (= ["foo" "(bar)" "baz"]))) (:value s1)))
+
+
+(deftest test-0085
+ (let [in "goat"
+ s1 (parse (lex-basic/token "goal") in)
+ em (k/get-msg-str (:error s1))]
+ (testing "token - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected goat\nexpecting goal" em)))))
+
+
+(deftest test-0090
+ (let [in "function f()"
+ s1 (parse (lex-basic/token "function" "procedure") in)]
+ (testing "token - parses one of multiple word choices"
+ (is (= [\f \( \)] (:input s1)))
+ (is (= "function" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0095
+ (let [in "procedure f()"
+ s1 (parse (lex-basic/token "function" "procedure") in)]
+ (testing "token - parses one of multiple word choices"
+ (is (= [\f \( \)] (:input s1)))
+ (is (= "procedure" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0100
+ (let [in "goat"
+ s1 (parse (lex-basic/token "goal" "gol" "gal" "moat") in)
+ em (k/get-msg-str (:error s1))]
+ (testing "token - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected goat\nunexpected goa\nexpecting goal, gol, gal or moat" em)))))
+
+
+(deftest test-0105
+ (let [in "program \t\t foo()"
+ s1 (parse (lex-basic/word "program") in)]
+ (testing "word - parses a specific, delimited word"
+ (is (= [\f \o \o \( \)] (:input s1)))
+ (is (= "program" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0110
+ (let [in "else{}"
+ s1 (parse (lex-basic/word "else") in)]
+ (testing "word - parses a specific, delimited word"
+ (is (= [\{ \}] (:input s1)))
+ (is (= "else" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0115
+ (let [in "procedure"
+ s1 (parse (lex-basic/word "proc") in)
+ em (k/get-msg-str (:error s1))]
+ (testing "word - fails because is not delimited"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected e\nexpecting end of proc" em)))))
+
+
+(deftest test-0120
+ (let [in "foobar()"
+ s1 (parse lex-basic/identifier in)]
+ (testing "identifier - parses a basic identifier"
+ (is (= [\( \)] (:input s1)))
+ (is (= "foobar" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0125
+ (let [in "total_45 := 0;"
+ s1 (parse lex-basic/identifier in)]
+ (testing "identifier - parses a basic identifier"
+ (is (= [\: \= \space \0 \;] (:input s1)))
+ (is (= "total_45" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0130
+ (let [in "4privateUse"
+ s1 (parse lex-basic/identifier in)
+ em (k/get-msg-str (:error s1))]
+ (testing "identifier - fails with invalid starting char"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\4\nexpecting letter or \\_"
+ :cljs "unexpected \"4\"\nexpecting letter or \"_\"")
+ em)))))
+
+
+(deftest test-0135
+ (let [in "'a' \t\t|;"
+ s1 (parse lex-basic/char-lit in)]
+ (testing "char-lit - parses a character literal"
+ (is (= [\| \;] (:input s1)))
+ (is (= \a (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0140
+ (let [in "'\\n' \t\t|;"
+ s1 (parse lex-basic/char-lit in)]
+ (testing "char-lit - parses an escaped character literal"
+ (is (= [\| \;] (:input s1)))
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+
+(deftest test-0145
+ (let [in "'\\t' \t\t|;"
+ s1 (parse lex-basic/char-lit in)]
+ (testing "char-lit - parses an escaped character literal"
+ (is (= [\| \;] (:input s1)))
+ (is (= \tab (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0150
+ (let [in "'u2"
+ s1 (parse lex-basic/char-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "char-lit - fails with a missing closing quote"
+ (is (= [\2] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\2\nexpecting end of character literal"
+ :cljs "unexpected \"2\"\nexpecting end of character literal")
+ em)))))
+
+
+(deftest test-0155
+ (let [in "u2"
+ s1 (parse lex-basic/char-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "char-lit - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\u\nexpecting character literal"
+ :cljs "unexpected \"u\"\nexpecting character literal")
+ em)))))
+
+
+(deftest test-0160
+ (let [in "\"now is the time\" \t\t|;"
+ s1 (parse lex-basic/string-lit in)]
+ (testing "string-lit - parses a simple string literal"
+ (is (= [\| \;] (:input s1)))
+ (is (= "now is the time" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0165
+ (let [in "\"now\\nis\\tthe\\ttime\" \t\t|;"
+ s1 (parse lex-basic/string-lit in)]
+ (testing "string-lit - parses a string with escaped chars"
+ (is (= [\| \;] (:input s1)))
+ (is (= "now\nis\tthe\ttime" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0170
+ (let [in "\"now is the time"
+ s1 (parse lex-basic/string-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "string-lit - fails with a string that is not terminated"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= "unexpected end of input\nexpecting end of string literal" em)))))
+
+
+(deftest test-0175
+ (let [in "45 + foobar"
+ s1 (parse lex-basic/string-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "string-lit - fails; not a string"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\4\nexpecting string literal"
+ :cljs "unexpected \"4\"\nexpecting string literal") em)))))
+
+
+(deftest test-0180
+ (let [in "+100"
+ s1 (parse lex-basic/dec-lit in)]
+ (testing "dec-lit - parses a redundant positive sign"
+ (is (empty? (:input s1)))
+ (is (= 100 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0185
+ (let [in "123456789"
+ s1 (parse lex-basic/dec-lit in)]
+ (testing "dec-lit - parses an integer"
+ (is (empty? (:input s1)))
+ (is (= 123456789 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0190
+ (let [in "1000000000N"
+ s1 (parse lex-basic/dec-lit in)]
+ (testing "dec-lit - parses a BigInt"
+ (is (empty? (:input s1)))
+ (is (= 1000000000N (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0195
+ (let [in "-747"
+ s1 (parse lex-basic/dec-lit in)]
+ (testing "dec-lit - parses a negative int"
+ (is (empty? (:input s1)))
+ (is (= -747 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0200
+ (let [in "9999999999999999999"
+ s1 (parse lex-basic/dec-lit in)
+ c1 (get-class s1)]
+ (testing "dec-lit - promotes a decimal to a BigInt"
+ (is (empty? (:input s1)))
+ (is (= 9999999999999999999N (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (= c1 #?(:clj "class clojure.lang.BigInt" :cljs "function Number() { [native code] }"))))))
+
+(deftest test-0205
+ (let [in "100NA"
+ s1 (parse lex-basic/dec-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "dec-lit - fails; no letter can follow N"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected A\nexpecting decimal literal" em)))))
+
+
+(deftest test-0210
+ (let [in "100e"
+ s1 (parse lex-basic/dec-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "dec-lit - fails; no letter can follow the last digit"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected e\nexpecting decimal literal" em)))))
+
+
+(deftest test-0215
+ (let [in "99."
+ s1 (parse lex-basic/dec-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "dec-lit - fails; the last digit can't be followed by a dot"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected .\nexpecting decimal literal" em)))))
+
+
+(deftest test-0220
+ (let [in "0"
+ s1 (parse lex-basic/oct-lit in)]
+ (testing "oct-lit - zero should be a valid octal number"
+ (is (empty? (:input s1)))
+ (is (= 0 (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1)))))
+
+
+(deftest test-0225
+ (let [in "+0100"
+ s1 (parse lex-basic/oct-lit in)]
+ (testing "oct-lit - parses a redundant positive sign"
+ (is (empty? (:input s1)))
+ (is (= 64 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0230
+ (let [in "012345676543210"
+ s1 (parse lex-basic/oct-lit in)]
+ (testing "oct-lit - parses an integer"
+ (is (empty? (:input s1)))
+ (is (= 012345676543210 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0235
+ (let [in "03777N"
+ s1 (parse lex-basic/oct-lit in)]
+ (testing "oct-lit - parses a BigInt"
+ (is (empty? (:input s1)))
+ (is (= 03777N (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0240
+ (let [in "-0747"
+ s1 (parse lex-basic/oct-lit in)]
+ (testing "oct-lit - parses a negative int"
+ (is (empty? (:input s1)))
+ (is (= -0747 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0245
+ (let [in "055555555555555555555N"
+ s1 (parse lex-basic/oct-lit in)
+ c1 (get-class s1)]
+ (testing "oct-lit - promotes a decimal to a BigInt"
+ (is (empty? (:input s1)))
+ (is (= 055555555555555555555N (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (= c1 #?(:clj "class clojure.lang.BigInt" :cljs "function Number() { [native code] }"))))))
+
+(deftest test-0250
+ (let [in "0100NA"
+ s1 (parse lex-basic/oct-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "oct-lit - fails; no letter can follow N"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected A\nexpecting octal literal" em)))))
+
+
+(deftest test-0255
+ (let [in "0100e"
+ s1 (parse lex-basic/oct-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "oct-lit - fails; no letter can follow the last digit"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected e\nexpecting octal literal" em)))))
+
+
+(deftest test-0260
+ (let [in "077."
+ s1 (parse lex-basic/oct-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "oct-lit - fails; the last digit can't be followed by a dot"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected .\nexpecting octal literal" em)))))
+
+
+(deftest test-0265
+ (let [in "0x0"
+ s1 (parse lex-basic/hex-lit in)]
+ (testing "hex-lit - parses a zero"
+ (is (empty? (:input s1)))
+ (is (= 0 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0270
+ (let [in "0XABCDEF"
+ s1 (parse lex-basic/hex-lit in)]
+ (testing "hex-lit - uses all capial letters"
+ (is (empty? (:input s1)))
+ (is (= 0xabcdef (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0275
+ (let [in "0xabcdef"
+ s1 (parse lex-basic/hex-lit in)]
+ (testing "hex-lit - uses all capial letters"
+ (is (empty? (:input s1)))
+ (is (= 0XABCDEF (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0280
+ (let [in "+0x100"
+ s1 (parse lex-basic/hex-lit in)]
+ (testing "hex-lit - parses a redundant positive sign"
+ (is (empty? (:input s1)))
+ (is (= 0x100 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0285
+ (let [in "0xCAFEBABE"
+ s1 (parse lex-basic/hex-lit in)]
+ (testing "hex-lit - parses an integer"
+ (is (empty? (:input s1)))
+ (is (= 0xCAFEBABE (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0290
+ (let [in "0x00008B55CABA0000N"
+ s1 (parse lex-basic/hex-lit in)]
+ (testing "hex-lit - parses a BigInt"
+ (is (empty? (:input s1)))
+ (is (= 0x00008B55CABA0000N (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0295
+ (let [in "-0x0F0E"
+ s1 (parse lex-basic/hex-lit in)]
+ (testing "hex-lit - parses a negative int"
+ (is (empty? (:input s1)))
+ (is (= -0x0F0E (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0300
+ (let [in "0x8000FA7770000B3400400200A"
+ s1 (parse lex-basic/hex-lit in)
+ c1 (get-class s1)]
+ (testing "hex-lit - promotes a decimal to a BigInt"
+ (is (empty? (:input s1)))
+ (is (= 0x8000FA7770000B3400400200AN (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (= c1 #?(:clj "class clojure.lang.BigInt" :cljs "function Number() { [native code] }"))))))
+
+(deftest test-0305
+ (let [in "0x100NA"
+ s1 (parse lex-basic/hex-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "hex-lit - fails; no letter can follow N"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected A\nexpecting hex literal" em)))))
+
+
+(deftest test-0310
+ (let [in "0x100x"
+ s1 (parse lex-basic/hex-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "hex-lit - fails; no letter can follow the last digit"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected x\nexpecting hex literal" em)))))
+
+
+(deftest test-0315
+ (let [in "0x77."
+ s1 (parse lex-basic/hex-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "hex-lit - fails; the last digit can't be followed by a dot"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected .\nexpecting hex literal" em)))))
+
+
+(deftest test-0320
+ (let [in "0"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a zero"
+ (is (empty? (:input s1)))
+ (is (= 0.0 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0325
+ (let [in "0.0"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a zero"
+ (is (empty? (:input s1)))
+ (is (= 0.0 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0330
+ (let [in "+100.00"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a redundant positive sign"
+ (is (empty? (:input s1)))
+ (is (= 100.00 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0335
+ (let [in "1558.95"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a floating-point number"
+ (is (empty? (:input s1)))
+ (is (= 1558.95 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0340
+ (let [in "1558.955e12"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a floating-point number with an exponent"
+ (is (empty? (:input s1)))
+ (is (= 1558.955e12 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0345
+ (let [in "1558.9558e-12"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a floating-point number with an exponent"
+ (is (empty? (:input s1)))
+ (is (= 1558.9558e-12 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0350
+ (let [in "1558.9558e+12"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a floating-point number with an exponent"
+ (is (empty? (:input s1)))
+ (is (= 1558.9558e+12 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0355
+ (let [in "-1558.9558e-12"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a negative floating-point number with an exponent"
+ (is (empty? (:input s1)))
+ (is (= -1558.9558e-12 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0360
+ (let [in "1558e12"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a number with no fractional part and an exponent"
+ (is (empty? (:input s1)))
+ (is (= 1558e12 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0365
+ (let [in "3.1415927M"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a BigDecimal"
+ (is (empty? (:input s1)))
+ (is (= 3.1415927M (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0370
+ (let [in "-199.95"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a negative floating-point number"
+ (is (empty? (:input s1)))
+ (is (= -199.95 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0370-05
+ (let [in "999"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - parses a round integer as a floating-point number"
+ (is (empty? (:input s1)))
+ (is (= 999.0 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0370-10
+ (let [in "999"
+ s1 (parse lex-basic/float-lit in)]
+ (testing "float-lit - regression test: number should not be long"
+ (not (= 999 (:value s1))))))
+
+
+(deftest test-0375
+ (let [in "99.95MA"
+ s1 (parse lex-basic/float-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "float-lit - fails; no letter can follow M"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected A\nexpecting floating-point literal" em)))))
+
+
+(deftest test-0380
+ (let [in "99.95X"
+ s1 (parse lex-basic/float-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "float-lit - fails; no letter can follow the last digit"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "unexpected X\nexpecting floating-point literal" em)))))
+
+
+(deftest test-0385
+ (let [in ".9999"
+ s1 (parse lex-basic/float-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "float-lit - fails; cannot start with a dot"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\.\nexpecting floating-point literal"
+ :cljs "unexpected \".\"\nexpecting floating-point literal")
+ em)))))
+
+
+(deftest test-0390
+ (let [in "true"
+ s1 (parse lex-basic/bool-lit in)]
+ (testing "bool-lit - true"
+ (is (empty? (:input s1)))
+ (is (:value s1))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0395
+ (let [in "false"
+ s1 (parse lex-basic/bool-lit in)]
+ (testing "bool-lit - false"
+ (is (empty? (:input s1)))
+ (is (false? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0400
+ (let [in "true \t \t)"
+ s1 (parse lex-basic/bool-lit in)]
+ (testing "bool-lit - true with whitespace"
+ (is (= [\)] (:input s1)))
+ (is (:value s1))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0405
+ (let [in "false\n\t\t :"
+ s1 (parse lex-basic/bool-lit in)]
+ (testing "bool-lit - false with whitespace"
+ (is (= [\:] (:input s1)))
+ (is (false? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0410
+ (let [in "nil"
+ s1 (parse lex-basic/nil-lit in)]
+ (testing "nil-lit - nil"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0415
+ (let [in "null"
+ s1 (parse lex-basic/nil-lit in)]
+ (testing "nil-lit - null"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0420
+ (let [in "nil \t \t)"
+ s1 (parse lex-basic/nil-lit in)]
+ (testing "nil-lit - nil with whitespace"
+ (is (= [\)] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0425
+ (let [in "null\n\t\t :"
+ s1 (parse lex-basic/nil-lit in)]
+ (testing "nil-lit - null with whitespace"
+ (is (= [\:] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0430
+ (let [in "(true)"
+ s1 (parse (lex-basic/parens lex-basic/bool-lit) in)]
+ (testing "parens - true"
+ (is (empty? (:input s1)))
+ (is (:value s1))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0435
+ (let [in "()"
+ s1 (parse (lex-basic/parens (k/many lex-basic/dec-lit)) in)]
+ (testing "parens - nothing"
+ (is (empty? (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0440
+ (let [in "( 11 22 33 44 55 )"
+ s1 (parse (lex-basic/parens (k/many1 lex-basic/dec-lit)) in)]
+ (testing "parens - true"
+ (is (empty? (:input s1)))
+ (is (= [11 22 33 44 55] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0445
+ (let [in "11 22 33)"
+ s1 (parse (lex-basic/parens (k/many1 lex-basic/dec-lit)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "parens - fails; no starting paren"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\1\nexpecting \\("
+ :cljs "unexpected \"1\"\nexpecting \"(\"")
+ em)))))
+
+
+(deftest test-0450
+ (let [in "(11 22 33 ;"
+ s1 (parse (lex-basic/parens (k/many1 lex-basic/dec-lit)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "parens - fails; no ending paren"
+ (is (= [\;] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\;\nexpecting \\)"
+ :cljs "unexpected \";\"\nexpecting \")\"")
+ em)))))
+
+
+(deftest test-0455
+ (let [in "()"
+ s1 (parse (lex-basic/parens lex-basic/dec-lit) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "parens - fails; missing value"
+ (is (= [\)] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\)\nexpecting decimal literal"
+ :cljs "unexpected \")\"\nexpecting decimal literal")
+ em)))))
+
+
+(deftest test-0460
+ (let [in "{true}"
+ s1 (parse (lex-basic/braces lex-basic/bool-lit) in)]
+ (testing "braces - true"
+ (is (empty? (:input s1)))
+ (is (:value s1))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0465
+ (let [in "{}"
+ s1 (parse (lex-basic/braces (k/many lex-basic/dec-lit)) in)]
+ (testing "braces - nothing"
+ (is (empty? (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0470
+ (let [in "{ 11 22 33 44 55 }"
+ s1 (parse (lex-basic/braces (k/many1 lex-basic/dec-lit)) in)]
+ (testing "braces - true"
+ (is (empty? (:input s1)))
+ (is (= [11 22 33 44 55] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0475
+ (let [in "11 22 33}"
+ s1 (parse (lex-basic/braces (k/many1 lex-basic/dec-lit)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "braces - fails; no starting brace"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\1\nexpecting \\{"
+ :cljs "unexpected \"1\"\nexpecting \"{\"")
+ em)))))
+
+
+(deftest test-0480
+ (let [in "{11 22 33 ;"
+ s1 (parse (lex-basic/braces (k/many1 lex-basic/dec-lit)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "braces - fails; no ending brace"
+ (is (= [\;] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\;\nexpecting \\}"
+ :cljs "unexpected \";\"\nexpecting \"}\"")
+ em)))))
+
+
+(deftest test-0485
+ (let [in "{}"
+ s1 (parse (lex-basic/braces lex-basic/dec-lit) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "braces - fails; missing value"
+ (is (= [\}] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\}\nexpecting decimal literal"
+ :cljs "unexpected \"}\"\nexpecting decimal literal")
+ em)))))
+
+
+(deftest test-0490
+ (let [in ""
+ s1 (parse (lex-basic/angles lex-basic/bool-lit) in)]
+ (testing "angles - true"
+ (is (empty? (:input s1)))
+ (is (:value s1))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0495
+ (let [in "<>"
+ s1 (parse (lex-basic/angles (k/many lex-basic/dec-lit)) in)]
+ (testing "angles - nothing"
+ (is (empty? (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0500
+ (let [in "< 11 22 33 44 55 >"
+ s1 (parse (lex-basic/angles (k/many1 lex-basic/dec-lit)) in)]
+ (testing "angles - true"
+ (is (empty? (:input s1)))
+ (is (= [11 22 33 44 55] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0505
+ (let [in "11 22 33>"
+ s1 (parse (lex-basic/angles (k/many1 lex-basic/dec-lit)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "angles - fails; no starting angle bracket"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\1\nexpecting \\<"
+ :cljs "unexpected \"1\"\nexpecting \"<\"")
+ em)))))
+
+
+(deftest test-0510
+ (let [in "<11 22 33 ;"
+ s1 (parse (lex-basic/angles (k/many1 lex-basic/dec-lit)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "angles - fails; no ending angle bracket"
+ (is (= [\;] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\;\nexpecting \\>"
+ :cljs "unexpected \";\"\nexpecting \">\"")
+ em)))))
+
+
+(deftest test-0515
+ (let [in "<>"
+ s1 (parse (lex-basic/angles lex-basic/dec-lit) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "angles - fails; missing value"
+ (is (= [\>] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\>\nexpecting decimal literal"
+ :cljs "unexpected \">\"\nexpecting decimal literal")
+ em)))))
+
+
+(deftest test-0520
+ (let [in "[true]"
+ s1 (parse (lex-basic/brackets lex-basic/bool-lit) in)]
+ (testing "brackets - true"
+ (is (empty? (:input s1)))
+ (is (:value s1))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0525
+ (let [in "[]"
+ s1 (parse (lex-basic/brackets (k/many lex-basic/dec-lit)) in)]
+ (testing "brackets - nothing"
+ (is (empty? (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0530
+ (let [in "[ 11 22 33 44 55 ]"
+ s1 (parse (lex-basic/brackets (k/many1 lex-basic/dec-lit)) in)]
+ (testing "brackets - true"
+ (is (empty? (:input s1)))
+ (is (= [11 22 33 44 55] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0535
+ (let [in "11 22 33]"
+ s1 (parse (lex-basic/brackets (k/many1 lex-basic/dec-lit)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "brackets - fails; no starting bracket"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\1\nexpecting \\["
+ :cljs "unexpected \"1\"\nexpecting \"[\"")
+ em)))))
+
+
+(deftest test-0540
+ (let [in "[11 22 33 ;"
+ s1 (parse (lex-basic/brackets (k/many1 lex-basic/dec-lit)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "brackets - fails; no ending bracket"
+ (is (= [\;] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\;\nexpecting \\]"
+ :cljs "unexpected \";\"\nexpecting \"]\"")
+ em)))))
+
+
+(deftest test-0545
+ (let [in "[]"
+ s1 (parse (lex-basic/brackets lex-basic/dec-lit) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "brackets - fails; missing value"
+ (is (= [\]] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\]\nexpecting decimal literal"
+ :cljs "unexpected \"]\"\nexpecting decimal literal")
+ em)))))
+
+
+(deftest test-0550
+ (let [in ";\n\n"
+ s1 (parse lex-basic/semi in)]
+ (testing "semi"
+ (is (empty? (:input s1)))
+ (is (= \; (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0555
+ (let [in "+"
+ s1 (parse lex-basic/semi in)
+ em (k/get-msg-str (:error s1))]
+ (testing "semi - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\+\nexpecting \\;"
+ :cljs "unexpected \"+\"\nexpecting \";\"")
+ em)))))
+
+
+(deftest test-0560
+ (let [in ",\n\n"
+ s1 (parse lex-basic/comma in)]
+ (testing "comma"
+ (is (empty? (:input s1)))
+ (is (= \, (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0565
+ (let [in "+"
+ s1 (parse lex-basic/comma in)
+ em (k/get-msg-str (:error s1))]
+ (testing "comma - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\+\nexpecting \\,"
+ :cljs "unexpected \"+\"\nexpecting \",\"")
+ em)))))
+
+
+(deftest test-0570
+ (let [in ":\n\n"
+ s1 (parse lex-basic/colon in)]
+ (testing "colon"
+ (is (empty? (:input s1)))
+ (is (= \: (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0575
+ (let [in "+"
+ s1 (parse lex-basic/colon in)
+ em (k/get-msg-str (:error s1))]
+ (testing "colon - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\+\nexpecting \\:"
+ :cljs "unexpected \"+\"\nexpecting \":\"")
+ em)))))
+
+
+(deftest test-0580
+ (let [in ".\n\n"
+ s1 (parse lex-basic/dot in)]
+ (testing "comma"
+ (is (empty? (:input s1)))
+ (is (= \. (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0585
+ (let [in "+"
+ s1 (parse lex-basic/dot in)
+ em (k/get-msg-str (:error s1))]
+ (testing "dot - fails"
+ (is (= (seq in) (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\+\nexpecting \\."
+ :cljs "unexpected \"+\"\nexpecting \".\"")
+ em)))))
+
+
+(deftest test-0590
+ (let [s1 (parse (lex-basic/semi-sep k/digit) "*")]
+ (testing "semi-sep - there are no separated items"
+ (is (= [\*] (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0595
+ (let [s1 (parse (lex-basic/semi-sep (>> k/letter k/digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "semi-sep - there are no separated compound items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0600
+ (let [s1 (parse (lex-basic/semi-sep k/digit) "0*")]
+ (testing "semi-sep - one item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [\0] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0605
+ (let [s1 (parse (lex-basic/semi-sep (<*> k/upper k/digit)) "U2*")]
+ (testing "semi-sep - one compound item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [[\U \2]] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0610
+ (let [s1 (parse (lex-basic/semi-sep (>> k/letter k/digit)) "U2;*")
+ em (k/get-msg-str (:error s1))]
+ (testing "semi-sep - there is only one item and the separator"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting letter"
+ :cljs "unexpected \"*\"\nexpecting letter")
+ em)))))
+
+
+(deftest test-0615
+ (let [s1 (parse (lex-basic/semi-sep lex-basic/dec-lit) "550; 101*")]
+ (testing "semi-sep - two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [550 101] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0620
+ (let [s1 (parse (lex-basic/semi-sep lex-basic/hex-lit) "+0xFADE ; -0x7800 *")]
+ (testing "semi-sep - two compound items"
+ (is (= [\*] (:input s1)))
+ (is (= [0xFADE -0x7800] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0625
+ (let [p1 (lex-basic/semi-sep lex-basic/identifier)
+ s1 (parse p1 "one ;\n two ; \t\t three")]
+ (testing "semi-sep - three compound items"
+ (is (empty? (:input s1)))
+ (is (= ["one" "two" "three"] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0630
+ (let [s1 (parse (lex-basic/semi-sep1 k/digit) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "semi-sep1 - there are no separated items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0635
+ (let [s1 (parse (lex-basic/semi-sep1 (>> k/letter k/digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "semi-sep1 - there are no separated compound items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0640
+ (let [s1 (parse (lex-basic/semi-sep1 lex-basic/dec-lit) "747*")]
+ (testing "semi-sep1 - one item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [747] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0645
+ (let [s1 (parse (lex-basic/semi-sep1 (<*> k/upper k/digit)) "U2*")]
+ (testing "semi-sep1 - one compound item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [[\U \2]] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0650
+ (let [s1 (parse (lex-basic/semi-sep1 lex-basic/identifier) "U2;*")
+ em (k/get-msg-str (:error s1))]
+ (testing "semi-sep1 - there is only one item and the separator"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting letter or \\_"
+ :cljs "unexpected \"*\"\nexpecting letter or \"_\"")
+ em)))))
+
+
+(deftest test-0655
+ (let [s1 (parse (lex-basic/semi-sep1 lex-basic/dec-lit) "100;200*")]
+ (testing "semi-sep1 - two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [100 200] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0660
+ (let [s1 (parse (lex-basic/semi-sep1 lex-basic/dec-lit) "-100 \t \t;\n +200*")]
+ (testing "semi-sep1 - two compound items with whitespace"
+ (is (= [\*] (:input s1)))
+ (is (= [-100 200] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0665
+ (let [p1 (lex-basic/semi-sep1 lex-basic/identifier)
+ s1 (parse p1 "one ;\n\n two \t\t;\n\t three")]
+ (testing "semi-sep1 - three compound items"
+ (is (empty? (:input s1)))
+ (is (= ["one" "two" "three"] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0670
+ (let [s1 (parse (lex-basic/semi-sep1 (>> k/upper k/digit)) "A1; B2; \tC3;DD;*")
+ em (k/get-msg-str (:error s1))]
+ (testing "semi-sep1 - compound item fails after reading several items"
+ (is (= [\D \; \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\D\nexpecting digit"
+ :cljs "unexpected \"D\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0675
+ (let [s1 (parse (lex-basic/comma-sep k/digit) "*")]
+ (testing "comma-sep - there are no separated items"
+ (is (= [\*] (:input s1)))
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (:empty s1))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0680
+ (let [s1 (parse (lex-basic/comma-sep (>> k/letter k/digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "comma-sep - there are no separated compound items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0685
+ (let [s1 (parse (lex-basic/comma-sep k/digit) "0*")]
+ (testing "comma-sep - one item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [\0] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0690
+ (let [s1 (parse (lex-basic/comma-sep (<*> k/upper k/digit)) "U2*")]
+ (testing "comma-sep - one compound item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [[\U \2]] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0695
+ (let [s1 (parse (lex-basic/comma-sep (>> k/letter k/digit)) "U2,*")
+ em (k/get-msg-str (:error s1))]
+ (testing "comma-sep - there is only one item and the separator"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting letter"
+ :cljs "unexpected \"*\"\nexpecting letter")
+ em)))))
+
+
+(deftest test-0700
+ (let [s1 (parse (lex-basic/comma-sep lex-basic/dec-lit) "550, 101*")]
+ (testing "comma-sep - two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [550 101] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0705
+ (let [s1 (parse (lex-basic/comma-sep lex-basic/hex-lit) "+0xFADE , -0x7800 *")]
+ (testing "comma-sep - two compound items"
+ (is (= [\*] (:input s1)))
+ (is (= [0xFADE -0x7800] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0710
+ (let [p1 (lex-basic/comma-sep lex-basic/identifier)
+ s1 (parse p1 "one ,\n two , \t\t three")]
+ (testing "comma-sep - three compound items"
+ (is (empty? (:input s1)))
+ (is (= ["one" "two" "three"] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0715
+ (let [s1 (parse (lex-basic/comma-sep1 k/digit) "*")
+ em (k/get-msg-str (:error s1))]
+ (testing "comma-sep1 - there are no separated items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0720
+ (let [s1 (parse (lex-basic/comma-sep1 (>> k/letter k/digit)) "A*")
+ em (k/get-msg-str (:error s1))]
+ (testing "comma-sep1 - there are no separated compound items"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting digit"
+ :cljs "unexpected \"*\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0725
+ (let [s1 (parse (lex-basic/comma-sep1 lex-basic/dec-lit) "747*")]
+ (testing "comma-sep1 - one item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [747] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0730
+ (let [s1 (parse (lex-basic/comma-sep1 (<*> k/upper k/digit)) "U2*")]
+ (testing "comma-sep1 - one compound item, no separator"
+ (is (= [\*] (:input s1)))
+ (is (= [[\U \2]] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0735
+ (let [s1 (parse (lex-basic/comma-sep1 lex-basic/identifier) "U2,*")
+ em (k/get-msg-str (:error s1))]
+ (testing "comma-sep1 - there is only one item and the separator"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting letter or \\_"
+ :cljs "unexpected \"*\"\nexpecting letter or \"_\"")
+ em)))))
+
+
+(deftest test-0740
+ (let [s1 (parse (lex-basic/comma-sep1 lex-basic/dec-lit) "100,200*")]
+ (testing "comma-sep1 - two simple items"
+ (is (= [\*] (:input s1)))
+ (is (= [100 200] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0745
+ (let [s1 (parse (lex-basic/comma-sep1 lex-basic/dec-lit) "-100 \t \t,\n +200*")]
+ (testing "comma-sep1 - two compound items with whitespace"
+ (is (= [\*] (:input s1)))
+ (is (= [-100 200] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0750
+ (let [p1 (lex-basic/comma-sep1 lex-basic/identifier)
+ s1 (k/parse p1 "one ,\n\n two \t\t,\n\t three")]
+ (testing "comma-sep1 - three compound items"
+ (is (empty? (:input s1)))
+ (is (= ["one" "two" "three"] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0755
+ (let [s1 (parse (lex-basic/comma-sep1 (>> k/upper k/digit)) "A1, B2, \tC3,DD,*")
+ em (k/get-msg-str (:error s1))]
+ (testing "comma-sep1 - compound item fails after reading several items"
+ (is (= [\D \, \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\D\nexpecting digit"
+ :cljs "unexpected \"D\"\nexpecting digit")
+ em)))))
+
+
+(deftest test-0760
+ (let [s1 (parse lex-basic/char-lit "'z'")]
+ (testing "char-lit"
+ (is (= \z (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0765
+ (let [s1 (parse lex-basic/char-lit "'\\b'")]
+ (testing "char-lit"
+ (is (= \backspace (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0770
+ (let [s1 (parse lex-basic/char-lit "'\\t'")]
+ (testing "char-lit"
+ (is (= \tab (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0775
+ (let [s1 (parse lex-basic/char-lit "'\\n'")]
+ (testing "char-lit"
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0780
+ (let [s1 (parse lex-basic/char-lit "'\\f'")]
+ (testing "char-lit"
+ (is (= \formfeed (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0785
+ (let [s1 (parse lex-basic/char-lit "'\\r'")]
+ (testing "char-lit"
+ (is (= \return (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0790
+ (let [s1 (parse lex-basic/char-lit "'\\''")]
+ (testing "char-lit"
+ (is (= \' (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0795
+ (let [s1 (parse lex-basic/char-lit "'\\\"'")]
+ (testing "char-lit"
+ (is (= \" (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0800
+ (let [s1 (parse lex-basic/char-lit "'\\\\'")]
+ (testing "char-lit"
+ (is (= \\ (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0805
+ (let [s1 (parse lex-basic/char-lit "'\\/'")]
+ (testing "char-lit"
+ (is (= \/ (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+(deftest test-0810
+ (let [in "'a "
+ s1 (parse lex-basic/char-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "char-lit - fails without the closing quote"
+ (is (= [\space] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\space\nexpecting end of character literal"
+ :cljs "unexpected \" \"\nexpecting end of character literal")
+ em)))))
+
+
+(deftest test-0815
+ (let [in "'\\n "
+ s1 (parse lex-basic/char-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "char-lit - fails without the closing quote"
+ (is (= [\space] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\space\nexpecting end of character literal"
+ :cljs "unexpected \" \"\nexpecting end of character literal")
+ em)))))
+
+
+(deftest test-0820
+ (let [in "\"\\bnow\\tis\\nthe\\ftime\\r\" \t\t|;"
+ s1 (parse lex-basic/string-lit in)]
+ (testing "string-lit - parses a string with multiple escaped characters"
+ (is (= [\| \;] (:input s1)))
+ (is (= "\bnow\tis\nthe\ftime\r" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+;; +-------------------------------------------------------------+
+;; | Custom lexers. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-0820-05
+ (let [rec (lex/make-parsers (assoc lex/shell-style-def :line-continuation (k/sym* \?)))]
+ (lex/with-parsers rec
+ (let [in "foo bar foobar ?\n\t\tbaz"
+ s1 (parse (k/many1 lex/identifier) in)]
+ (testing "trim - line continuation with a ?"
+ (is (empty? (:input s1)))
+ (is (= ["foo" "bar" "foobar" "baz"] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))))
+
+
+(deftest test-0825
+ (let [rec (lex/make-parsers (assoc lex/c-style-def :case-sensitive false))]
+ (lex/with-parsers rec
+ (let [in "WhIlE (..."
+ s1 (parse (lex/word "while") in)]
+ (testing "word - non-case-sensitive"
+ (is (= [\( \. \. \.] (:input s1)))
+ (is (= "while" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))))
+
+
+(deftest test-0830
+ (let [rec (lex/make-parsers (assoc lex/c-style-def :nested-comments true))]
+ (lex/with-parsers rec
+ (let [in "foo /***outter /* inner comment */ end of outer***/"
+ s1 (parse lex/identifier in)]
+ (testing "word - nested comments"
+ (is (empty? (:input s1)))
+ (is (= "foo" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))))
+
+
+(deftest test-0845
+ (let [rec (lex/make-parsers (assoc lex/c-style-def :reserved-names ["foo" "bar"]))]
+ (lex/with-parsers rec
+ (let [in "foobar * baz"
+ s1 (parse lex/identifier in)]
+ (testing "word - valid word, not a reserved word"
+ (is (= "foobar" (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\* \space \b \a \z] (:input s1)))
+ (is (false? (:empty s1))))))))
+
+
+(deftest test-0850
+ (let [rec (lex/make-parsers (assoc lex/c-style-def :reserved-names ["foo" "bar"]))]
+ (lex/with-parsers rec
+ (let [in "foo * bar"
+ s1 (parse lex/identifier in)
+ em (k/get-msg-str (:error s1))]
+ (testing "word - fails on a reserved word"
+ (is (= [\f \o \o \space \* \space \b \a \r] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "foo is a reserved name" em)))))))
+
+
+(deftest test-0855
+ (let [rec (lex/make-parsers (assoc lex/c-style-def
+ :case-sensitive false
+ :reserved-names ["foo" "bar"]))]
+ (lex/with-parsers rec
+ (let [in "FOO * bar"
+ s1 (parse lex/identifier in)
+ em (k/get-msg-str (:error s1))]
+ (testing "word - fails on a reserved word"
+ (is (= [\F \O \O \space \* \space \b \a \r] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= "FOO is a reserved name" em)))))))
+
+
+(deftest test-0860
+ (let [rec (lex/make-parsers (assoc lex/basic-def :leading-sign false))]
+ (lex/with-parsers rec
+ (let [in "5005"
+ s1 (parse lex/dec-lit in)]
+ (testing "dec-lit - regular case, no leading sign."
+ (is (empty? (:input s1)))
+ (is (= 5005 (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))))
+
+
+(deftest test-0865
+ (let [rec (lex/make-parsers (assoc lex/basic-def :leading-sign false))]
+ (lex/with-parsers rec
+ (let [in "0xCAFE"
+ s1 (parse lex/hex-lit in)]
+ (testing "hex-lit - regular case, no leading sign."
+ (is (empty? (:input s1)))
+ (is (= 0xCAFE (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))))
+
+
+(deftest test-0870
+ (let [rec (lex/make-parsers (assoc lex/basic-def :leading-sign false))]
+ (lex/with-parsers rec
+ (let [in "-5005"
+ s1 (parse lex/dec-lit in)]
+ (testing "dec-lit - with leading sign it fails."
+ (is (= (seq "-5005") (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1))))))))
+
+
+(deftest test-0875
+ (let [rec (lex/make-parsers (assoc lex/basic-def :leading-sign false))]
+ (lex/with-parsers rec
+ (let [in "+3.1416"
+ s1 (parse lex/float-lit in)]
+ (testing "float-lit - with leading sign it fails."
+ (is (= (seq "+3.1416") (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1))))))))
+
+
+;; +-------------------------------------------------------------+
+;; | Repeating Patterns. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-0900
+ (let [s1 (parse lex-basic/identifier "f")]
+ (testing "identifier -- state must not be empty"
+ (is (= "f" (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0905
+ (let [s1 (parse (k/many lex-basic/identifier) "f")]
+ (testing "identifier -- many should work with a single-letter id"
+ (is (= ["f"] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0910
+ (let [s1 (parse (lex-basic/comma-sep lex-basic/identifier) "f")]
+ (testing "multiple identifier"
+ (is (= ["f"] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0915
+ (let [s1 (parse (k/many (lex-basic/sym \Q)) "QQQ")]
+ (testing "multiple symbols"
+ (is (= [\Q \Q \Q] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0920
+ (let [s1 (parse (k/many (lex-basic/one-of "abc")) "a b c")]
+ (testing "many one-of"
+ (is (= [\a \b \c] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0925
+ (let [s1 (parse (k/many (lex-basic/none-of "abc")) "xyz")]
+ (testing "many none-of"
+ (is (= [\x \y \z] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0930
+ (let [s1 (parse (k/many (lex-basic/token "abc")) "abcabc abc")]
+ (testing "many token"
+ (is (= ["abc" "abc" "abc"] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0935
+ (let [s1 (parse (k/many0 (lex-basic/token "abc")) "xxx")]
+ (testing "many0, nothing match but empty is cleared"
+ (is (= [] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= (seq "xxx") (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0940
+ (let [s1 (parse (k/many (lex-basic/field " ")) "now is the time")]
+ (testing "many field"
+ (is (= ["now" "is" "the" "time"] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0945
+ (let [s1 (parse (k/many (lex-basic/field " ")) "x y")]
+ (testing "many token"
+ (is (= ["x" "y"] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0950
+ (let [s1 (parse (k/many lex-basic/dec-lit) "0")]
+ (testing "many dec-lit"
+ (is (= [0] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0955
+ (let [s1 (parse (k/many lex-basic/oct-lit) "01")]
+ (testing "many oct-lit"
+ (is (= [1] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0960
+ (let [s1 (parse (k/many lex-basic/hex-lit) "0x1")]
+ (testing "many hex-lit"
+ (is (= [1] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0965
+ (let [s1 (parse (k/many lex-basic/float-lit) "1")]
+ (testing "many float-lit"
+ (is (= [1.0] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
diff --git a/src/test/clojure/blancas/kern/test_lexer_c.clj b/src/test/clojure/blancas/kern/test_lexer_c.clj
deleted file mode 100644
index f8fcf0e..0000000
--- a/src/test/clojure/blancas/kern/test_lexer_c.clj
+++ /dev/null
@@ -1,423 +0,0 @@
-;; Copyright (c) 2013 Armando Blancas. All rights reserved.
-;; The use and distribution terms for this software are covered by the
-;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-;; which can be found in the file epl-v10.html at the root of this distribution.
-;; By using this software in any fashion, you are agreeing to be bound by
-;; the terms of this license.
-;; You must not remove this notice, or any other, from this software.
-
-(ns blancas.kern.test-lexer-c
- (:use [blancas.kern.core]
- [blancas.kern.lexer.c-style]
- [clojure.test]
- [midje.sweet :exclude (expect one-of)]))
-
-;; Private functions from kern.core
-
-(def get-msg-str (ns-resolve 'blancas.kern.core 'get-msg-str))
-
-
-;; +-------------------------------------------------------------+
-;; | Java-style lexers. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-0000
- (let [s1 (parse (>> trim eof) " \t\t\n")]
- (fact "trim - blank, tab, eol, then eof"
- (:value s1) => nil
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0005
- (let [s1 (parse (>> trim (many digit)) "123")]
- (fact "trim - no whitespace, it's optional"
- (:value s1) => [\1 \2 \3]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0010
- (let [s1 (parse (>> trim (many1 letter)) " /* comment */ \t\n\t\t ABC")]
- (fact "trim - whitespace before letters"
- (:value s1) => [\A \B \C]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0015
- (let [s1 (parse (>> (lexeme (sym* \space)) eof) " \t\t\n")]
- (fact "lexeme - a blank, then tab, eol; then eof"
- (:value s1) => nil
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0020
- (let [s1 (parse (lexeme (many digit)) "123")]
- (fact "lexeme - no whitespace, it's optional"
- (:value s1) => [\1 \2 \3]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0025
- (let [s1 (parse (lexeme (many1 letter)) "ABC /* that's it */ \t\n\t\t")]
- (fact "lexeme - whitespace and comments after letters"
- (:value s1) => [\A \B \C]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0030
- (let [s1 (parse (lexeme (many1 letter)) "foo // and the rest is history\nbar")]
- (fact "trim - single-line comment"
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\b \a \r]
- (:empty s1) => false)))
-
-
-(deftest test-0035
- (let [in "foo // variable\n// that's all\n// for now\nbar"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - skips over multiple single-line comments"
- (:input s1) => [\b \a \r]
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0040
- (let [in "foo /* var foo\n that's all\n for now */\nbar"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - skips over multiple multi-line comment"
- (:input s1) => [\b \a \r]
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0045
- (let [in "foo/********this is a comment**********/"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - skips over multiple multi-line comment"
- (:input s1) => empty?
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0050
- (let [in "foo/****** this is a comment*****"
- s1 (parse (lexeme (many1 letter)) in)
- em (get-msg-str (:error s1))]
- (fact "lexeme - fails looking for end of comment"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected end of input\nexpecting end of comment")))
-
-
-(deftest test-0055
- (let [in "foo/******* this is a /* CAN I NEST? */ comment ********/"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - Won't da nested comment; but this works and stops at 'comment'"
- (:input s1) => (seq "comment ********/")
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0060
- (let [s1 (parse char-lit "'z'")]
- (fact "char-lit"
- (:value s1) => \z
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0065
- (let [s1 (parse char-lit "'\\b'")]
- (fact "char-lit"
- (:value s1) => \backspace
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0070
- (let [s1 (parse char-lit "'\\t'")]
- (fact "char-lit"
- (:value s1) => \tab
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0075
- (let [s1 (parse char-lit "'\\n'")]
- (fact "char-lit"
- (:value s1) => \newline
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0080
- (let [s1 (parse char-lit "'\\f'")]
- (fact "char-lit"
- (:value s1) => \formfeed
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0085
- (let [s1 (parse char-lit "'\\r'")]
- (fact "char-lit"
- (:value s1) => \return
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0090
- (let [s1 (parse char-lit "'\\''")]
- (fact "char-lit"
- (:value s1) => \'
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0095
- (let [s1 (parse char-lit "'\\\"'")]
- (fact "char-lit"
- (:value s1) => \"
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0100
- (let [s1 (parse char-lit "'\\\\'")]
- (fact "char-lit"
- (:value s1) => \\
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0105
- (let [s1 (parse char-lit "'\\/'")]
- (fact "char-lit"
- (:value s1) => \/
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0110
- (let [s1 (parse char-lit "'\\u0041'")]
- (fact "char-lit"
- (:value s1) => \A
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0115
- (let [s1 (parse char-lit "'\\101'")]
- (fact "char-lit"
- (:value s1) => \A
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0120
- (let [in "'a "
- s1 (parse char-lit in)
- em (get-msg-str (:error s1))]
- (fact "char-lit - fails without the closing quote"
- (:input s1) => [\space]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\space\nexpecting end of character literal")))
-
-
-(deftest test-0125
- (let [in "'\\u2'"
- s1 (parse char-lit in)
- em (get-msg-str (:error s1))]
- (fact "char-lit - fails: incomplete unicode number"
- (:input s1) => [\']
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\'\nexpecting hexadecimal digit")))
-
-
-(deftest test-0130
- (let [in "'\\00*"
- s1 (parse char-lit in)
- em (get-msg-str (:error s1))]
- (fact "char-lit - fails: octal numbers are assumed; that's acually char \0"
- (:input s1) => [\0 \*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\0\nexpecting end of character literal")))
-
-
-(deftest test-0135
- (let [s1 (parse char-lit "'\\?'")]
- (fact "char-lit"
- (:value s1) => \?
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0140
- (let [s1 (parse char-lit "'\\a'")]
- (fact "char-lit"
- (:value s1) => (char 7)
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0145
- (let [s1 (parse char-lit "'\\v'")]
- (fact "char-lit"
- (:value s1) => (char 11)
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0150
- (let [s1 (parse char-lit "'\\0'")]
- (fact "char-lit"
- (:value s1) => (char 0)
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0155
- (let [s1 (parse char-lit "'\\x41'")]
- (fact "char-lit"
- (:value s1) => \A
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0160
- (let [s1 (parse char-lit "'\\U00000041'")]
- (fact "char-lit"
- (:value s1) => \A
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0165
- (let [in "\"\\bnow\\tis\\nthe\\ftime\\r\" \t\t|;"
- s1 (parse string-lit in)]
- (fact "string-lit - parses a simple string literal"
- (:input s1) => [\| \;]
- (:value s1) => "\bnow\tis\nthe\ftime\r"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0170
- (let [in "\"null-terminated\\0\";"
- s1 (parse string-lit in)]
- (fact "string-lit - parses a null-terminated string"
- (:input s1) => [\;]
- (:value s1) => "null-terminated\u0000"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0175
- (let [in "\"\\\\null-terminated\\?\";"
- s1 (parse string-lit in)]
- (fact "string-lit - parses a backslash and a question mark"
- (:input s1) => [\;]
- (:value s1) => "\\null-terminated?"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0180
- (let [in "\"\\tnow is \\u0074\\u0068\\u0065 time\" \t\t|;"
- s1 (parse string-lit in)]
- (fact "string-lit - parses unicode characters"
- (:input s1) => [\| \;]
- (:value s1) => "\tnow is the time"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0185
- (let [in "\"now is \\164\\150\\145 time\" /* the */|;"
- s1 (parse string-lit in)]
- (fact "string-lit - parses octal characters"
- (:input s1) => [\| \;]
- (:value s1) => "now is the time"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0190
- (let [in "\"now is \\x74\\x68\\x65 time\" \t\t|;"
- s1 (parse string-lit in)]
- (fact "string-lit - parses hex characters"
- (:input s1) => [\| \;]
- (:value s1) => "now is the time"
- (:ok s1) => true
- (:empty s1) => false)))
diff --git a/src/test/clojure/blancas/kern/test_lexer_c.cljc b/src/test/clojure/blancas/kern/test_lexer_c.cljc
new file mode 100644
index 0000000..1f1674a
--- /dev/null
+++ b/src/test/clojure/blancas/kern/test_lexer_c.cljc
@@ -0,0 +1,425 @@
+;; Copyright (c) 2013 Armando Blancas. All rights reserved.
+;; The use and distribution terms for this software are covered by the
+;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this distribution.
+;; By using this software in any fashion, you are agreeing to be bound by
+;; the terms of this license.
+;; You must not remove this notice, or any other, from this software.
+
+(ns blancas.kern.test-lexer-c
+ (:require [blancas.kern.core :as k :refer [parse >>]]
+ [blancas.kern.lexer.c-style :as lex]
+ [clojure.test :refer [deftest is testing]]))
+
+;; +-------------------------------------------------------------+
+;; | Java-style lexers. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-0000
+ (let [s1 (parse (>> lex/trim k/eof) " \t\t\n")]
+ (testing "trim - blank, tab, eol, then eof"
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0005
+ (let [s1 (parse (>> lex/trim (k/many k/digit)) "123")]
+ (testing "trim - no whitespace, it's optional"
+ (is (= [\1 \2 \3] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0010
+ (let [s1 (parse (>> lex/trim (k/many1 k/letter)) " /* comment */ \t\n\t\t ABC")]
+ (testing "trim - whitespace before letters"
+ (is (= [\A \B \C] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0015
+ (let [s1 (parse (>> (lex/lexeme (k/sym* \space)) k/eof) " \t\t\n")]
+ (testing "lexeme - a blank, then tab, eol; then eof"
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0020
+ (let [s1 (parse (lex/lexeme (k/many k/digit)) "123")]
+ (testing "lexeme - no whitespace, it's optional"
+ (is (= [\1 \2 \3] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0025
+ (let [s1 (parse (lex/lexeme (k/many1 k/letter)) "ABC /* that's it */ \t\n\t\t")]
+ (testing "lexeme - whitespace and comments after letters"
+ (is (= [\A \B \C] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0030
+ (let [s1 (parse (lex/lexeme (k/many1 k/letter)) "foo // and the rest is history\nbar")]
+ (testing "trim - single-line comment"
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\b \a \r] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0035
+ (let [in "foo // variable\n// that's all\n// for now\nbar"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - skips over multiple single-line comments"
+ (is (= [\b \a \r] (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0040
+ (let [in "foo /* var foo\n that's all\n for now */\nbar"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - skips over multiple multi-line comment"
+ (is (= [\b \a \r] (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0045
+ (let [in "foo/********this is a comment**********/"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - skips over multiple multi-line comment"
+ (is (empty? (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0050
+ (let [in "foo/****** this is a comment*****"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "lexeme - fails looking for end of comment"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected end of input\nexpecting end of comment"
+ :cljs "unexpected end of input\nexpecting end of comment")
+ em)))))
+
+
+(deftest test-0055
+ (let [in "foo/******* this is a /* CAN I NEST? */ comment ********/"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - Won't da nested comment; but this works and stops at 'comment'"
+ (is (= (seq "comment ********/") (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0060
+ (let [s1 (parse lex/char-lit "'z'")]
+ (testing "char-lit"
+ (is (= \z (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0065
+ (let [s1 (parse lex/char-lit "'\\b'")]
+ (testing "char-lit"
+ (is (= \backspace (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0070
+ (let [s1 (parse lex/char-lit "'\\t'")]
+ (testing "char-lit"
+ (is (= \tab (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0075
+ (let [s1 (parse lex/char-lit "'\\n'")]
+ (testing "char-lit"
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0080
+ (let [s1 (parse lex/char-lit "'\\f'")]
+ (testing "char-lit"
+ (is (= \formfeed (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0085
+ (let [s1 (parse lex/char-lit "'\\r'")]
+ (testing "char-lit"
+ (is (= \return (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0090
+ (let [s1 (parse lex/char-lit "'\\''")]
+ (testing "char-lit"
+ (is (= \' (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0095
+ (let [s1 (parse lex/char-lit "'\\\"'")]
+ (testing "char-lit"
+ (is (= \" (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0100
+ (let [s1 (parse lex/char-lit "'\\\\'")]
+ (testing "char-lit"
+ (is (= \\ (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0105
+ (let [s1 (parse lex/char-lit "'\\/'")]
+ (testing "char-lit"
+ (is (= \/ (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0110
+ (let [s1 (parse lex/char-lit "'\\u0041'")]
+ (testing "char-lit"
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0115
+ (let [s1 (parse lex/char-lit "'\\101'")]
+ (testing "char-lit"
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0120
+ (let [in "'a "
+ s1 (parse lex/char-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "char-lit - fails without the closing quote"
+ (is (= [\space] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\space\nexpecting end of character literal"
+ :cljs "unexpected \" \"\nexpecting end of character literal")
+ em)))))
+
+
+(deftest test-0125
+ (let [in "'\\u2'"
+ s1 (parse lex/char-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "char-lit - fails: incomplete unicode number"
+ (is (= [\'] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\'\nexpecting hexadecimal digit"
+ :clsj "unexpected \"'\"\nexpecting hexadecimal digit")
+ em)))))
+
+
+(deftest test-0130
+ (let [in "'\\00*"
+ s1 (parse lex/char-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "char-lit - fails: octal numbers are assumed; that's acually char \0"
+ (is (= [\0 \*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\0\nexpecting end of character literal"
+ :cljs "unexpected \"0\"\nexpecting end of character literal")
+ em)))))
+
+
+(deftest test-0135
+ (let [s1 (parse lex/char-lit "'\\?'")]
+ (testing "char-lit"
+ (is (= \? (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0140
+ (let [s1 (parse lex/char-lit "'\\a'")]
+ (testing "char-lit"
+ (is (= (char 7) (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0145
+ (let [s1 (parse lex/char-lit "'\\v'")]
+ (testing "char-lit"
+ (is (= (char 11) (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0150
+ (let [s1 (parse lex/char-lit "'\\0'")]
+ (testing "char-lit"
+ (is (= (char 0) (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0155
+ (let [s1 (parse lex/char-lit "'\\x41'")]
+ (testing "char-lit"
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0160
+ (let [s1 (parse lex/char-lit "'\\U00000041'")]
+ (testing "char-lit"
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0165
+ (let [in "\"\\bnow\\tis\\nthe\\ftime\\r\" \t\t|;"
+ s1 (parse lex/string-lit in)]
+ (testing "string-lit - parses a simple string literal"
+ (is (= [\| \;] (:input s1)))
+ (is (= "\bnow\tis\nthe\ftime\r" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0170
+ (let [in "\"null-terminated\\0\";"
+ s1 (parse lex/string-lit in)]
+ (testing "string-lit - parses a null-terminated string"
+ (is (= [\;] (:input s1)))
+ (is (= "null-terminated\u0000" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0175
+ (let [in "\"\\\\null-terminated\\?\";"
+ s1 (parse lex/string-lit in)]
+ (testing "string-lit - parses a backslash and a question mark"
+ (is (= [\;] (:input s1)))
+ (is (= "\\null-terminated?" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0180
+ (let [in "\"\\tnow is \\u0074\\u0068\\u0065 time\" \t\t|;"
+ s1 (parse lex/string-lit in)]
+ (testing "string-lit - parses unicode characters"
+ (is (= [\| \;] (:input s1)))
+ (is (= "\tnow is the time" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0185
+ (let [in "\"now is \\164\\150\\145 time\" /* the */|;"
+ s1 (parse lex/string-lit in)]
+ (testing "string-lit - parses octal characters"
+ (is (= [\| \;] (:input s1)))
+ (is (= "now is the time" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0190
+ (let [in "\"now is \\x74\\x68\\x65 time\" \t\t|;"
+ s1 (parse lex/string-lit in)]
+ (testing "string-lit - parses hex characters"
+ (is (= [\| \;] (:input s1)))
+ (is (= "now is the time" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
diff --git a/src/test/clojure/blancas/kern/test_lexer_haskell.clj b/src/test/clojure/blancas/kern/test_lexer_haskell.clj
deleted file mode 100644
index 730523c..0000000
--- a/src/test/clojure/blancas/kern/test_lexer_haskell.clj
+++ /dev/null
@@ -1,301 +0,0 @@
-;; Copyright (c) 2013 Armando Blancas. All rights reserved.
-;; The use and distribution terms for this software are covered by the
-;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-;; which can be found in the file epl-v10.html at the root of this distribution.
-;; By using this software in any fashion, you are agreeing to be bound by
-;; the terms of this license.
-;; You must not remove this notice, or any other, from this software.
-
-(ns blancas.kern.test-lexer-haskell
- (:use [blancas.kern.core]
- [blancas.kern.lexer.haskell-style]
- [clojure.test]
- [midje.sweet :exclude (expect one-of)]))
-
-;; Private functions from kern.core
-
-(def get-msg-str (ns-resolve 'blancas.kern.core 'get-msg-str))
-
-
-;; +-------------------------------------------------------------+
-;; | Haskell-style lexers. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-0000
- (let [s1 (parse (>> trim eof) " \t\t\n")]
- (fact "trim - blank, tab, eol, then eof"
- (:value s1) => nil
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0005
- (let [s1 (parse (>> trim (many digit)) "123")]
- (fact "trim - no whitespace, it's optional"
- (:value s1) => [\1 \2 \3]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0010
- (let [s1 (parse (>> trim (many1 letter)) " {- comment -} \t\n\t\t ABC")]
- (fact "trim - whitespace before letters"
- (:value s1) => [\A \B \C]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0015
- (let [s1 (parse (>> (lexeme (sym* \space)) eof) " \t\t\n")]
- (fact "lexeme - a blank, then tab, eol; then eof"
- (:value s1) => nil
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0020
- (let [s1 (parse (lexeme (many digit)) "123")]
- (fact "lexeme - no whitespace, it's optional"
- (:value s1) => [\1 \2 \3]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0025
- (let [s1 (parse (lexeme (many1 letter)) "ABC {- that's it -} \t\n\t\t")]
- (fact "lexeme - whitespace and comments after letters"
- (:value s1) => [\A \B \C]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0030
- (let [s1 (parse (lexeme (many1 letter)) "foo -- and the rest is history\nbar")]
- (fact "trim - single-line comment"
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\b \a \r]
- (:empty s1) => false)))
-
-
-(deftest test-0035
- (let [in "foo -- variable\n-- that's all\n-- for now\nbar"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - skips over multiple single-line comments"
- (:input s1) => [\b \a \r]
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0040
- (let [in "foo {- var foo\n that's all\n for now -}\nbar"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - skips over multiple multi-line comment"
- (:input s1) => [\b \a \r]
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0045
- (let [in "foo{-----this is a comment------}"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - skips over multiple multi-line comment"
- (:input s1) => empty?
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0050
- (let [in "foo{-----this is {---- inner comment ----} an outer comment------}"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - skips nested comments"
- (:input s1) => empty?
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0055
- (let [in "foo{---outer {---- inner {---- most inner ----} less inner ----} outer ----}"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - skips nested comments"
- (:input s1) => empty?
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0060
- (let [in "foo{-----this is a comment------"
- s1 (parse (lexeme (many1 letter)) in)
- em (get-msg-str (:error s1))]
- (fact "lexeme - fails looking for end of comment"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected end of input\nexpecting end of comment")))
-
-
-(deftest test-0065
- (let [in "foo{-----this is a {- NESTED comment------}"
- s1 (parse (lexeme (many1 letter)) in)
- em (get-msg-str (:error s1))]
- (fact "lexeme - fails looking for end of a nested comment"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected end of input\nexpecting end of comment")))
-
-
-(deftest test-0070
- (let [s1 (parse char-lit "'z'")]
- (fact "char-lit"
- (:value s1) => \z
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0075
- (let [s1 (parse char-lit "'\\b'")]
- (fact "char-lit"
- (:value s1) => \backspace
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0080
- (let [s1 (parse char-lit "'\\t'")]
- (fact "char-lit"
- (:value s1) => \tab
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0085
- (let [s1 (parse char-lit "'\\n'")]
- (fact "char-lit"
- (:value s1) => \newline
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0090
- (let [s1 (parse char-lit "'\\f'")]
- (fact "char-lit"
- (:value s1) => \formfeed
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0095
- (let [s1 (parse char-lit "'\\r'")]
- (fact "char-lit"
- (:value s1) => \return
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0100
- (let [s1 (parse char-lit "'\\''")]
- (fact "char-lit"
- (:value s1) => \'
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0105
- (let [s1 (parse char-lit "'\\\"'")]
- (fact "char-lit"
- (:value s1) => \"
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0110
- (let [s1 (parse char-lit "'\\\\'")]
- (fact "char-lit"
- (:value s1) => \\
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0115
- (let [s1 (parse char-lit "'\\/'")]
- (fact "char-lit"
- (:value s1) => \/
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0120
- (let [s1 (parse char-lit "'\\x0041'")]
- (fact "char-lit"
- (:value s1) => \A
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0125
- (let [s1 (parse char-lit "'\\o101'")]
- (fact "char-lit"
- (:value s1) => \A
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0130
- (let [s1 (parse char-lit "'\\90'")]
- (fact "char-lit"
- (:value s1) => \Z
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
diff --git a/src/test/clojure/blancas/kern/test_lexer_haskell.cljc b/src/test/clojure/blancas/kern/test_lexer_haskell.cljc
new file mode 100644
index 0000000..d4cb383
--- /dev/null
+++ b/src/test/clojure/blancas/kern/test_lexer_haskell.cljc
@@ -0,0 +1,295 @@
+;; Copyright (c) 2013 Armando Blancas. All rights reserved.
+;; The use and distribution terms for this software are covered by the
+;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this distribution.
+;; By using this software in any fashion, you are agreeing to be bound by
+;; the terms of this license.
+;; You must not remove this notice, or any other, from this software.
+
+(ns blancas.kern.test-lexer-haskell
+ (:require [blancas.kern.core :as k :refer [parse >>]]
+ [blancas.kern.lexer.haskell-style :as lex]
+ [clojure.test :refer [deftest is testing]]))
+
+;; +-------------------------------------------------------------+
+;; | Haskell-style lexers. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-0000
+ (let [s1 (parse (>> lex/trim k/eof) " \t\t\n")]
+ (testing "trim - blank, tab, eol, then eof"
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0005
+ (let [s1 (parse (>> lex/trim (k/many k/digit)) "123")]
+ (testing "trim - no whitespace, it's optional"
+ (is (= [\1 \2 \3] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0010
+ (let [s1 (parse (>> lex/trim (k/many1 k/letter)) " {- comment -} \t\n\t\t ABC")]
+ (testing "trim - whitespace before letters"
+ (is (= [\A \B \C] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0015
+ (let [s1 (parse (>> (lex/lexeme (k/sym* \space)) k/eof) " \t\t\n")]
+ (testing "lexeme - a blank, then tab, eol; then eof"
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0020
+ (let [s1 (parse (lex/lexeme (k/many k/digit)) "123")]
+ (testing "lexeme - no whitespace, it's optional"
+ (is (= [\1 \2 \3] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0025
+ (let [s1 (parse (lex/lexeme (k/many1 k/letter)) "ABC {- that's it -} \t\n\t\t")]
+ (testing "lexeme - whitespace and comments after letters"
+ (is (= [\A \B \C] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0030
+ (let [s1 (parse (lex/lexeme (k/many1 k/letter)) "foo -- and the rest is history\nbar")]
+ (testing "trim - single-line comment"
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\b \a \r] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0035
+ (let [in "foo -- variable\n-- that's all\n-- for now\nbar"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - skips over multiple single-line comments"
+ (is (= [\b \a \r] (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0040
+ (let [in "foo {- var foo\n that's all\n for now -}\nbar"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - skips over multiple multi-line comment"
+ (is (= [\b \a \r] (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0045
+ (let [in "foo{-----this is a comment------}"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - skips over multiple multi-line comment"
+ (is (empty? (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0050
+ (let [in "foo{-----this is {---- inner comment ----} an outer comment------}"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - skips nested comments"
+ (is (empty? (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0055
+ (let [in "foo{---outer {---- inner {---- most inner ----} less inner ----} outer ----}"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - skips nested comments"
+ (is (empty? (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0060
+ (let [in "foo{-----this is a comment------"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "lexeme - fails looking for end of comment"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= "unexpected end of input\nexpecting end of comment" em)))))
+
+
+(deftest test-0065
+ (let [in "foo{-----this is a {- NESTED comment------}"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "lexeme - fails looking for end of a nested comment"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= "unexpected end of input\nexpecting end of comment" em)))))
+
+
+(deftest test-0070
+ (let [s1 (parse lex/char-lit "'z'")]
+ (testing "char-lit"
+ (is (= \z (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0075
+ (let [s1 (parse lex/char-lit "'\\b'")]
+ (testing "char-lit"
+ (is (= \backspace (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0080
+ (let [s1 (parse lex/char-lit "'\\t'")]
+ (testing "char-lit"
+ (is (= \tab (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0085
+ (let [s1 (parse lex/char-lit "'\\n'")]
+ (testing "char-lit"
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0090
+ (let [s1 (parse lex/char-lit "'\\f'")]
+ (testing "char-lit"
+ (is (= \formfeed (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0095
+ (let [s1 (parse lex/char-lit "'\\r'")]
+ (testing "char-lit"
+ (is (= \return (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0100
+ (let [s1 (parse lex/char-lit "'\\''")]
+ (testing "char-lit"
+ (is (= \' (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0105
+ (let [s1 (parse lex/char-lit "'\\\"'")]
+ (testing "char-lit"
+ (is (= \" (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0110
+ (let [s1 (parse lex/char-lit "'\\\\'")]
+ (testing "char-lit"
+ (is (= \\ (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0115
+ (let [s1 (parse lex/char-lit "'\\/'")]
+ (testing "char-lit"
+ (is (= \/ (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0120
+ (let [s1 (parse lex/char-lit "'\\x0041'")]
+ (testing "char-lit"
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0125
+ (let [s1 (parse lex/char-lit "'\\o101'")]
+ (testing "char-lit"
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0130
+ (let [s1 (parse lex/char-lit "'\\90'")]
+ (testing "char-lit"
+ (is (= \Z (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
diff --git a/src/test/clojure/blancas/kern/test_lexer_java.clj b/src/test/clojure/blancas/kern/test_lexer_java.clj
deleted file mode 100644
index 12ceb7d..0000000
--- a/src/test/clojure/blancas/kern/test_lexer_java.clj
+++ /dev/null
@@ -1,343 +0,0 @@
-;; Copyright (c) 2013 Armando Blancas. All rights reserved.
-;; The use and distribution terms for this software are covered by the
-;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-;; which can be found in the file epl-v10.html at the root of this distribution.
-;; By using this software in any fashion, you are agreeing to be bound by
-;; the terms of this license.
-;; You must not remove this notice, or any other, from this software.
-
-(ns blancas.kern.test-lexer-java
- (:use [blancas.kern.core]
- [blancas.kern.lexer.java-style]
- [clojure.test]
- [midje.sweet :exclude (expect one-of)]))
-
-;; Private functions from kern.core
-
-(def get-msg-str (ns-resolve 'blancas.kern.core 'get-msg-str))
-
-
-;; +-------------------------------------------------------------+
-;; | Java-style lexers. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-0000
- (let [s1 (parse (>> trim eof) " \t\t\n")]
- (fact "trim - blank, tab, eol, then eof"
- (:value s1) => nil
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0005
- (let [s1 (parse (>> trim (many digit)) "123")]
- (fact "trim - no whitespace, it's optional"
- (:value s1) => [\1 \2 \3]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0010
- (let [s1 (parse (>> trim (many1 letter)) " /* comment */ \t\n\t\t ABC")]
- (fact "trim - whitespace before letters"
- (:value s1) => [\A \B \C]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0015
- (let [s1 (parse (>> (lexeme (sym* \space)) eof) " \t\t\n")]
- (fact "lexeme - a blank, then tab, eol; then eof"
- (:value s1) => nil
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0020
- (let [s1 (parse (lexeme (many digit)) "123")]
- (fact "lexeme - no whitespace, it's optional"
- (:value s1) => [\1 \2 \3]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0025
- (let [s1 (parse (lexeme (many1 letter)) "ABC /* that's it */ \t\n\t\t")]
- (fact "lexeme - whitespace and comments after letters"
- (:value s1) => [\A \B \C]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0030
- (let [s1 (parse (lexeme (many1 letter)) "foo // and the rest is history\nbar")]
- (fact "trim - single-line comment"
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\b \a \r]
- (:empty s1) => false)))
-
-
-(deftest test-0035
- (let [in "foo // variable\n// that's all\n// for now\nbar"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - skips over multiple single-line comments"
- (:input s1) => [\b \a \r]
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0040
- (let [s1 (parse (lexeme (many1 letter)) "foo // and the rest is history")]
- (fact "trim - single-line comment at end of input"
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0045
- (let [in "foo /* var foo\n that's all\n for now */\nbar"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - skips over multiple multi-line comment"
- (:input s1) => [\b \a \r]
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0050
- (let [in "foo/********this is a comment**********/"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - skips over multiple multi-line comment"
- (:input s1) => empty?
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false
- (:error s1) => nil)))
-
-
-(deftest test-0055
- (let [in "foo/****** this is a comment*****"
- s1 (parse (lexeme (many1 letter)) in)
- em (get-msg-str (:error s1))]
- (fact "lexeme - fails looking for end of comment"
- (:input s1) => empty?
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected end of input\nexpecting end of comment")))
-
-
-(deftest test-0060
- (let [in "foo/******* this is a /* CAN I NEST? */ comment ********/"
- s1 (parse (lexeme (many1 letter)) in)]
- (fact "lexeme - Won't da nested comment; but this works and stops at 'comment'"
- (:input s1) => (seq "comment ********/")
- (:value s1) => [\f \o \o]
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0066
- (let [s1 (parse char-lit "'z'")]
- (fact "char-lit"
- (:value s1) => \z
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0070
- (let [s1 (parse char-lit "'\\b'")]
- (fact "char-lit"
- (:value s1) => \backspace
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0075
- (let [s1 (parse char-lit "'\\t'")]
- (fact "char-lit"
- (:value s1) => \tab
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0080
- (let [s1 (parse char-lit "'\\n'")]
- (fact "char-lit"
- (:value s1) => \newline
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0085
- (let [s1 (parse char-lit "'\\f'")]
- (fact "char-lit"
- (:value s1) => \formfeed
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0090
- (let [s1 (parse char-lit "'\\r'")]
- (fact "char-lit"
- (:value s1) => \return
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0095
- (let [s1 (parse char-lit "'\\''")]
- (fact "char-lit"
- (:value s1) => \'
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0100
- (let [s1 (parse char-lit "'\\\"'")]
- (fact "char-lit"
- (:value s1) => \"
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0105
- (let [s1 (parse char-lit "'\\\\'")]
- (fact "char-lit"
- (:value s1) => \\
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0110
- (let [s1 (parse char-lit "'\\/'")]
- (fact "char-lit"
- (:value s1) => \/
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0115
- (let [s1 (parse char-lit "'\\u0041'")]
- (fact "char-lit"
- (:value s1) => \A
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0120
- (let [s1 (parse char-lit "'\\101'")]
- (fact "char-lit"
- (:value s1) => \A
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0125
- (let [in "'a "
- s1 (parse char-lit in)
- em (get-msg-str (:error s1))]
- (fact "char-lit - fails without the closing quote"
- (:input s1) => [\space]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\space\nexpecting end of character literal")))
-
-
-(deftest test-0130
- (let [in "'\\u2'"
- s1 (parse char-lit in)
- em (get-msg-str (:error s1))]
- (fact "char-lit - fails: incomplete unicode number"
- (:input s1) => [\']
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\'\nexpecting hexadecimal digit")))
-
-
-(deftest test-0135
- (let [in "'\\50*"
- s1 (parse char-lit in)
- em (get-msg-str (:error s1))]
- (fact "char-lit - fails: incomplete octal number"
- (:input s1) => [\*]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => false
- em => "unexpected \\*\nexpecting end of character literal")))
-
-
-(deftest test-0140
- (let [in "\"\\bnow\\tis\\nthe\\ftime\\r\" \t\t|;"
- s1 (parse string-lit in)]
- (fact "string-lit - parses a simple string literal"
- (:input s1) => [\| \;]
- (:value s1) => "\bnow\tis\nthe\ftime\r"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0145
- (let [in "\"\\tnow is \\u0074\\u0068\\u0065 time\" \t\t|;"
- s1 (parse string-lit in)]
- (fact "string-lit - parses unicode characters"
- (:input s1) => [\| \;]
- (:value s1) => "\tnow is the time"
- (:ok s1) => true
- (:empty s1) => false)))
-
-
-(deftest test-0150
- (let [in "\"now is \\164\\150\\145 time\" /* the */|;"
- s1 (parse string-lit in)]
- (fact "string-lit - parses octal characters"
- (:input s1) => [\| \;]
- (:value s1) => "now is the time"
- (:ok s1) => true
- (:empty s1) => false)))
diff --git a/src/test/clojure/blancas/kern/test_lexer_java.cljc b/src/test/clojure/blancas/kern/test_lexer_java.cljc
new file mode 100644
index 0000000..16672a5
--- /dev/null
+++ b/src/test/clojure/blancas/kern/test_lexer_java.cljc
@@ -0,0 +1,343 @@
+;; Copyright (c) 2013 Armando Blancas. All rights reserved.
+;; The use and distribution terms for this software are covered by the
+;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this distribution.
+;; By using this software in any fashion, you are agreeing to be bound by
+;; the terms of this license.
+;; You must not remove this notice, or any other, from this software.
+
+(ns blancas.kern.test-lexer-java
+ (:require [blancas.kern.core :as k :refer [parse >>]]
+ [blancas.kern.lexer.java-style :as lex]
+ [clojure.test :refer [deftest is testing]]))
+
+;; +-------------------------------------------------------------+
+;; | Java-style lexers. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-0000
+ (let [s1 (parse (>> lex/trim k/eof) " \t\t\n")]
+ (testing "trim - blank, tab, eol, then eof"
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0005
+ (let [s1 (parse (>> lex/trim (k/many k/digit)) "123")]
+ (testing "trim - no whitespace, it's optional"
+ (is (= [\1 \2 \3] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0010
+ (let [s1 (parse (>> lex/trim (k/many1 k/letter)) " /* comment */ \t\n\t\t ABC")]
+ (testing "trim - whitespace before letters"
+ (is (= [\A \B \C] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0015
+ (let [s1 (parse (>> (lex/lexeme (k/sym* \space)) k/eof) " \t\t\n")]
+ (testing "lexeme - a blank, then tab, eol; then eof"
+ (is (nil? (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0020
+ (let [s1 (parse (lex/lexeme (k/many k/digit)) "123")]
+ (testing "lexeme - no whitespace, it's optional"
+ (is (= [\1 \2 \3] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0025
+ (let [s1 (parse (lex/lexeme (k/many1 k/letter)) "ABC /* that's it */ \t\n\t\t")]
+ (testing "lexeme - whitespace and comments after letters"
+ (is (= [\A \B \C] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0030
+ (let [s1 (parse (lex/lexeme (k/many1 k/letter)) "foo // and the rest is history\nbar")]
+ (testing "trim - single-line comment"
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\b \a \r] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0035
+ (let [in "foo // variable\n// that's all\n// for now\nbar"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - skips over multiple single-line comments"
+ (is (= [\b \a \r] (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0040
+ (let [s1 (parse (lex/lexeme (k/many1 k/letter)) "foo // and the rest is history")]
+ (testing "trim - single-line comment at end of input"
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0045
+ (let [in "foo /* var foo\n that's all\n for now */\nbar"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - skips over multiple multi-line comment"
+ (is (= [\b \a \r] (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0050
+ (let [in "foo/********this is a comment**********/"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - skips over multiple multi-line comment"
+ (is (empty? (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1)))
+ (is (nil? (:error s1))))))
+
+
+(deftest test-0055
+ (let [in "foo/****** this is a comment*****"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)
+ em (k/get-msg-str (:error s1))]
+ (testing "lexeme - fails looking for end of comment"
+ (is (empty? (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= "unexpected end of input\nexpecting end of comment" em)))))
+
+
+(deftest test-0060
+ (let [in "foo/******* this is a /* CAN I NEST? */ comment ********/"
+ s1 (parse (lex/lexeme (k/many1 k/letter)) in)]
+ (testing "lexeme - Won't da nested comment; but this works and stops at 'comment'"
+ (is (= (seq "comment ********/") (:input s1)))
+ (is (= [\f \o \o] (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0066
+ (let [s1 (parse lex/char-lit "'z'")]
+ (testing "char-lit"
+ (is (= \z (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0070
+ (let [s1 (parse lex/char-lit "'\\b'")]
+ (testing "char-lit"
+ (is (= \backspace (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0075
+ (let [s1 (parse lex/char-lit "'\\t'")]
+ (testing "char-lit"
+ (is (= \tab (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0080
+ (let [s1 (parse lex/char-lit "'\\n'")]
+ (testing "char-lit"
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0085
+ (let [s1 (parse lex/char-lit "'\\f'")]
+ (testing "char-lit"
+ (is (= \formfeed (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0090
+ (let [s1 (parse lex/char-lit "'\\r'")]
+ (testing "char-lit"
+ (is (= \return (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0095
+ (let [s1 (parse lex/char-lit "'\\''")]
+ (testing "char-lit"
+ (is (= \' (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0100
+ (let [s1 (parse lex/char-lit "'\\\"'")]
+ (testing "char-lit"
+ (is (= \" (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0105
+ (let [s1 (parse lex/char-lit "'\\\\'")]
+ (testing "char-lit"
+ (is (= \\ (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0110
+ (let [s1 (parse lex/char-lit "'\\/'")]
+ (testing "char-lit"
+ (is (= \/ (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0115
+ (let [s1 (parse lex/char-lit "'\\u0041'")]
+ (testing "char-lit"
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0120
+ (let [s1 (parse lex/char-lit "'\\101'")]
+ (testing "char-lit"
+ (is (= \A (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0125
+ (let [in "'a "
+ s1 (parse lex/char-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "char-lit - fails without the closing quote"
+ (is (= [\space] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\space\nexpecting end of character literal"
+ :cljs "unexpected \" \"\nexpecting end of character literal")
+ em)))))
+
+
+(deftest test-0130
+ (let [in "'\\u2'"
+ s1 (parse lex/char-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "char-lit - fails: incomplete unicode number"
+ (is (= [\'] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\'\nexpecting hexadecimal digit"
+ :cljs "unexpected \"'\"\nexpecting hexadecimal digit")
+ em)))))
+
+
+(deftest test-0135
+ (let [in "'\\50*"
+ s1 (parse lex/char-lit in)
+ em (k/get-msg-str (:error s1))]
+ (testing "char-lit - fails: incomplete octal number"
+ (is (= [\*] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (false? (:empty s1)))
+ (is (= #?(:clj "unexpected \\*\nexpecting end of character literal"
+ :cljs "unexpected \"*\"\nexpecting end of character literal")
+ em)))))
+
+
+(deftest test-0140
+ (let [in "\"\\bnow\\tis\\nthe\\ftime\\r\" \t\t|;"
+ s1 (parse lex/string-lit in)]
+ (testing "string-lit - parses a simple string literal"
+ (is (= [\| \;] (:input s1)))
+ (is (= "\bnow\tis\nthe\ftime\r" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0145
+ (let [in "\"\\tnow is \\u0074\\u0068\\u0065 time\" \t\t|;"
+ s1 (parse lex/string-lit in)]
+ (testing "string-lit - parses unicode characters"
+ (is (= [\| \;] (:input s1)))
+ (is (= "\tnow is the time" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0150
+ (let [in "\"now is \\164\\150\\145 time\" /* the */|;"
+ s1 (parse lex/string-lit in)]
+ (testing "string-lit - parses octal characters"
+ (is (= [\| \;] (:input s1)))
+ (is (= "now is the time" (:value s1)))
+ (is (:ok s1))
+ (is (false? (:empty s1))))))
diff --git a/src/test/clojure/blancas/kern/test_lexer_shell.clj b/src/test/clojure/blancas/kern/test_lexer_shell.clj
deleted file mode 100644
index 8aebd02..0000000
--- a/src/test/clojure/blancas/kern/test_lexer_shell.clj
+++ /dev/null
@@ -1,153 +0,0 @@
-;; Copyright (c) 2013 Armando Blancas. All rights reserved.
-;; The use and distribution terms for this software are covered by the
-;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
-;; which can be found in the file epl-v10.html at the root of this distribution.
-;; By using this software in any fashion, you are agreeing to be bound by
-;; the terms of this license.
-;; You must not remove this notice, or any other, from this software.
-
-(ns blancas.kern.test-lexer-shell
- (:use [blancas.kern.core]
- [blancas.kern.lexer.shell-style]
- [clojure.test]
- [midje.sweet :exclude (expect one-of)]))
-
-;; Private functions from kern.core
-
-(def get-msg-str (ns-resolve 'blancas.kern.core 'get-msg-str))
-
-
-;; +-------------------------------------------------------------+
-;; | Shell-style lexers. |
-;; +-------------------------------------------------------------+
-
-
-(deftest test-0000
- (let [s1 (parse (>> trim new-line) " \t\t\n")]
- (fact "trim - blank, tab, eol, then a new line (separately)"
- (:value s1) => \newline
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0005
- (let [s1 (parse (>> trim (many digit)) "123")]
- (fact "trim - no whitespace, it's optional"
- (:value s1) => [\1 \2 \3]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0010
- (let [s1 (parse (>> (skip trim new-line) (many1 letter)) " \t\t\nABC")]
- (fact "trim - some whitespace before letters"
- (:value s1) => [\A \B \C]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0015
- (let [s1 (parse (<*> (lexeme (sym* \space)) new-line eof) " \t\t\n")]
- (fact "lexeme - a blank, then tab, eol; then eof"
- (:value s1) => [\space \newline nil]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0020
- (let [s1 (parse (lexeme (many digit)) "123")]
- (fact "lexeme - no whitespace, it's optional"
- (:value s1) => [\1 \2 \3]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0025
- (let [s1 (parse (lexeme (many1 letter)) "ABC \t\t\t")]
- (fact "lexeme - some whitespace after letters"
- (:value s1) => [\A \B \C]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0030
- (let [s1 (parse new-line "\nfoo")]
- (fact "new-line - parses a new line and stops"
- (:value s1) => \newline
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\f \o \o]
- (:empty s1) => false)))
-
-
-(deftest test-0035
- (let [s1 (parse new-line "\n\t\t foo")]
- (fact "new-line - skip a new line and any other whitespace that follows"
- (:value s1) => \newline
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\f \o \o]
- (:empty s1) => false)))
-
-
-(deftest test-0040
- (let [s1 (parse new-line "\r\nfoo")]
- (fact "new-line - parses a Windows new-line and stops"
- (:value s1) => \newline
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\f \o \o]
- (:empty s1) => false)))
-
-
-(deftest test-0045
- (let [s1 (parse new-line "foo")
- em (get-msg-str (:error s1))]
- (fact "new-line - fails when there's no new-line"
- (:input s1) => [\f \o \o]
- (:value s1) => nil
- (:ok s1) => false
- (:empty s1) => true
- em => "unexpected \\f\nexpecting new line")))
-
-
-(deftest test-0050
- (let [s1 (parse (lexeme (many digit)) "123 # and the rest is history...")]
- (fact "lexeme - skip over a line comment"
- (:value s1) => [\1 \2 \3]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
-
-
-(deftest test-0055
- (let [s1 (parse identifier "init.phase-123_last=")]
- (fact "lexeme - identifier with - and ."
- (:value s1) => "init.phase-123_last"
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => [\=]
- (:empty s1) => false)))
-
-
-(deftest test-0060
- (let [s1 (parse (many1 identifier) "abc def ghi \\\nxyz")]
- (fact "lexeme - line continuation; no new line to skip"
- (:value s1) => ["abc" "def" "ghi" "xyz"]
- (:ok s1) => true
- (:error s1) => nil
- (:input s1) => empty?
- (:empty s1) => false)))
diff --git a/src/test/clojure/blancas/kern/test_lexer_shell.cljc b/src/test/clojure/blancas/kern/test_lexer_shell.cljc
new file mode 100644
index 0000000..c431277
--- /dev/null
+++ b/src/test/clojure/blancas/kern/test_lexer_shell.cljc
@@ -0,0 +1,150 @@
+;; Copyright (c) 2013 Armando Blancas. All rights reserved.
+;; The use and distribution terms for this software are covered by the
+;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
+;; which can be found in the file epl-v10.html at the root of this distribution.
+;; By using this software in any fashion, you are agreeing to be bound by
+;; the terms of this license.
+;; You must not remove this notice, or any other, from this software.
+
+(ns blancas.kern.test-lexer-shell
+ (:require [blancas.kern.core :as k :refer [parse >> <*>]]
+ [blancas.kern.lexer.shell-style :as lex]
+ [clojure.test :refer [deftest is testing]]))
+
+
+;; +-------------------------------------------------------------+
+;; | Shell-style lexers. |
+;; +-------------------------------------------------------------+
+
+
+(deftest test-0000
+ (let [s1 (parse (>> lex/trim lex/new-line) " \t\t\n")]
+ (testing "trim - blank, tab, eol, then a new line (separately)"
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0005
+ (let [s1 (parse (>> lex/trim (k/many k/digit)) "123")]
+ (testing "trim - no whitespace, it's optional"
+ (is (= [\1 \2 \3] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0010
+ (let [s1 (parse (>> (k/skip lex/trim lex/new-line) (k/many1 k/letter)) " \t\t\nABC")]
+ (testing "trim - some whitespace before letters"
+ (is (= [\A \B \C] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0015
+ (let [s1 (parse (<*> (lex/lexeme (k/sym* \space)) lex/new-line k/eof) " \t\t\n")]
+ (testing "lexeme - a blank, then tab, eol; then eof"
+ (is (= [\space \newline nil] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0020
+ (let [s1 (parse (lex/lexeme (k/many k/digit)) "123")]
+ (testing "lexeme - no whitespace, it's optional"
+ (is (= [\1 \2 \3] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0025
+ (let [s1 (parse (lex/lexeme (k/many1 k/letter)) "ABC \t\t\t")]
+ (testing "lexeme - some whitespace after letters"
+ (is (= [\A \B \C] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0030
+ (let [s1 (parse lex/new-line "\nfoo")]
+ (testing "new-line - parses a new line and stops"
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\f \o \o] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0035
+ (let [s1 (parse lex/new-line "\n\t\t foo")]
+ (testing "new-line - skip a new line and any other whitespace that follows"
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\f \o \o] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0040
+ (let [s1 (parse lex/new-line "\r\nfoo")]
+ (testing "new-line - parses a Windows new-line and stops"
+ (is (= \newline (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\f \o \o] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0045
+ (let [s1 (parse lex/new-line "foo")
+ em (k/get-msg-str (:error s1))]
+ (testing "new-line - fails when there's no new-line"
+ (is (= [\f \o \o] (:input s1)))
+ (is (nil? (:value s1)))
+ (is (false? (:ok s1)))
+ (is (:empty s1))
+ (is (= #?(:clj "unexpected \\f\nexpecting new line"
+ :cljs "unexpected \"f\"\nexpecting new line")
+ em)))))
+
+
+(deftest test-0050
+ (let [s1 (parse (lex/lexeme (k/many k/digit)) "123 # and the rest is history...")]
+ (testing "lexeme - skip over a line comment"
+ (is (= [\1 \2 \3] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0055
+ (let [s1 (parse lex/identifier "init.phase-123_last=")]
+ (testing "lexeme - identifier with - and ."
+ (is (= "init.phase-123_last" (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (= [\=] (:input s1)))
+ (is (false? (:empty s1))))))
+
+
+(deftest test-0060
+ (let [s1 (parse (k/many1 lex/identifier) "abc def ghi \\\nxyz")]
+ (testing "lexeme - line continuation; no new line to skip"
+ (is (= ["abc" "def" "ghi" "xyz"] (:value s1)))
+ (is (:ok s1))
+ (is (nil? (:error s1)))
+ (is (empty? (:input s1)))
+ (is (false? (:empty s1))))))