aboutsummaryrefslogtreecommitdiff
path: root/src/lux/reader.clj
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lux/reader.clj80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/lux/reader.clj b/src/lux/reader.clj
new file mode 100644
index 000000000..b4824261a
--- /dev/null
+++ b/src/lux/reader.clj
@@ -0,0 +1,80 @@
+(ns lux.reader
+ (:require [clojure.string :as string]
+ [clojure.core.match :as M :refer [matchv]]
+ clojure.core.match.array
+ [lux.base :as & :refer [exec return* return fail fail* |let]]))
+
+;; [Utils]
+(defn ^:private with-line [body]
+ (fn [state]
+ (matchv ::M/objects [(&/get$ "lux;source" state)]
+ [["lux;None" _]]
+ (fail* "[Reader Error] No source code.")
+
+ [["lux;Some" ["lux;Nil" _]]]
+ (fail* "[Reader Error] EOF")
+
+ [["lux;Some" ["lux;Cons" [["lux;Meta" [[file-name line-num column-num] line]]
+ more]]]]
+ (matchv ::M/objects [(body file-name line-num column-num line)]
+ [["No" msg]]
+ (fail* msg)
+
+ [["Yes" [meta ["lux;None" _]]]]
+ (return* (&/set$ "lux;source" (&/V "lux;Some" more) state)
+ meta)
+
+ [["Yes" [meta ["lux;Some" line-meta]]]]
+ (return* (&/set$ "lux;source" (&/V "lux;Some" (&/|cons line-meta more)) state)
+ meta))
+ )))
+
+;; [Exports]
+(defn read-regex [regex]
+ (with-line
+ (fn [file-name line-num column-num line]
+ (if-let [[match] (re-find regex line)]
+ (let [match-length (.length match)
+ line* (.substring line match-length)]
+ (&/V "Yes" (&/T (&/V "lux;Meta" (&/T (&/T file-name line-num column-num) match))
+ (if (empty? line*)
+ (&/V "lux;None" nil)
+ (&/V "lux;Some" (&/V "lux;Meta" (&/T (&/T file-name line-num (+ column-num match-length)) line*)))))))
+ (&/V "No" (str "[Reader Error] Pattern failed: " regex))))))
+
+(defn read-regex2 [regex]
+ (with-line
+ (fn [file-name line-num column-num line]
+ (if-let [[match tok1 tok2] (re-find regex line)]
+ (let [match-length (.length match)
+ line* (.substring line match-length)]
+ (&/V "Yes" (&/T (&/V "lux;Meta" (&/T (&/T file-name line-num column-num) [tok1 tok2]))
+ (if (empty? line*)
+ (&/V "lux;None" nil)
+ (&/V "lux;Some" (&/V "lux;Meta" (&/T (&/T file-name line-num (+ column-num match-length)) line*)))))))
+ (&/V "No" (str "[Reader Error] Pattern failed: " regex))))))
+
+(defn read-text [text]
+ (with-line
+ (fn [file-name line-num column-num line]
+ ;; (prn 'read-text text line)
+ (if (.startsWith line text)
+ (let [match-length (.length text)
+ line* (.substring line match-length)]
+ (&/V "Yes" (&/T (&/V "lux;Meta" (&/T (&/T file-name line-num column-num) text))
+ (if (empty? line*)
+ (&/V "lux;None" nil)
+ (&/V "lux;Some" (&/V "lux;Meta" (&/T (&/T file-name line-num (+ column-num match-length)) line*)))))))
+ (&/V "No" (str "[Reader Error] Text failed: " text))))))
+
+(defn from [file-name]
+ (let [lines (&/->list (string/split-lines (slurp file-name)))]
+ (&/|map (fn [line+line-num]
+ (|let [[line line-num] line+line-num]
+ (&/V "lux;Meta" (&/T (&/T file-name line-num 0)
+ line))))
+ (&/|filter (fn [line+line-num]
+ (|let [[line line-num] line+line-num]
+ (not (empty? line))))
+ (&/zip2 lines
+ (&/|range (&/|length lines)))))))