blob: 38ff4d5e6b91ae06c8da9995e92c4dc4d663a52a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
(ns lux.reader
(:require [clojure.string :as string]
[clojure.core.match :as M :refer [matchv]]
clojure.core.match.array
[lux.base :as & :refer [|do return* return fail fail* |let]]))
;; [Utils]
(defn ^:private with-line [body]
(fn [state]
(matchv ::M/objects [(&/get$ &/$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$ &/$SOURCE (&/V "lux;Some" more) state)
meta)
[["Yes" [meta ["lux;Some" line-meta]]]]
(return* (&/set$ &/$SOURCE (&/V "lux;Some" (&/|cons line-meta more)) state)
meta))
)))
;; [Exports]
(defn read-regex [regex]
(with-line
(fn [file-name line-num column-num ^String line]
(if-let [[^String 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 ^String line]
(if-let [[^String 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) (&/T 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 [^String text]
(with-line
(fn [file-name line-num column-num ^String 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)))))))
(def current-line
(fn [state]
(matchv ::M/objects [(&/get$ &/$SOURCE state)]
[["lux;None" _]]
(fail* "[Reader Error] No source code.")
[["lux;Some" ["lux;Nil" _]]]
(fail* "[Reader Error] EOF")
[["lux;Some" ["lux;Cons" [["lux;Meta" [_ line]]
more]]]]
(return* state line)
)))
|