|
1 | 1 | (ns zetta.core |
2 | | - (:use [clojure.algo.monads |
3 | | - :only |
4 | | - [defmonad defmonadfn domonad with-monad m-seq]])) |
| 2 | + (:require [monads.macros :as monad-macro]) |
| 3 | + (:require [monads.core :as monad] |
| 4 | + [clojure.algo.monads |
| 5 | + :refer |
| 6 | + [defmonad defmonadfn domonad with-monad m-seq]]) |
| 7 | + ^:clj (:import [clojure.lang IFn])) |
5 | 8 |
|
6 | 9 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
7 | 10 | ;; |
|
99 | 102 | [input0 more0 input1 more1 f] |
100 | 103 | (f (concat input0 input1) (concat-more more0 more1))) |
101 | 104 |
|
| 105 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 106 | +;; |
| 107 | +;; ## Parser Monad implementation |
| 108 | +;; |
| 109 | +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 110 | + |
| 111 | +(declare always) |
| 112 | +(declare bind-parsers) |
| 113 | +(declare fail-parser) |
| 114 | +(declare join-parsers) |
| 115 | + |
| 116 | +(defrecord Parser [f] |
| 117 | + IFn |
| 118 | + ;; (invoke [this_ a] (println "1) ERROR: " a)) |
| 119 | + ;; (invoke [this_ a b] (println "2)ERROR: " a b)) |
| 120 | + ;; (invoke [this_ a b c] (println "3) ERROR: " a b c)) |
| 121 | + (invoke [this_ input0 more0 err-fn ok-fn] |
| 122 | + ;; (println "4)" input0 more0 err-fn ok-fn) |
| 123 | + (f input0 more0 err-fn ok-fn)) |
| 124 | + |
| 125 | + ^:clj |
| 126 | + (applyTo [this args] (clojure.lang.AFn/applyToHelper this args)) |
| 127 | + |
| 128 | + monad/Monad |
| 129 | + (do-result [self a] |
| 130 | + (always a)) |
| 131 | + |
| 132 | + (bind [self f] |
| 133 | + (bind-parsers self f)) |
| 134 | + |
| 135 | + monad/MonadZero |
| 136 | + (zero [_] |
| 137 | + (fail-parser "MonadZero/zero")) |
| 138 | + |
| 139 | + (plus-step [self ps] |
| 140 | + (reduce join-parsers self ps))) |
| 141 | + |
| 142 | + |
| 143 | + |
102 | 144 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
103 | 145 | ;; |
104 | 146 | ;; ## Basic parsers primitives |
|
120 | 162 | "Parser that will always fail, you may provide an error message msg that |
121 | 163 | will be shown on the final result." |
122 | 164 | [msg] |
123 | | - (fn failed-parser [input0 more0 err-fn _ok-fn] |
124 | | - #(err-fn input0 more0 [] (str "Failed reading: " msg)))) |
| 165 | + (Parser. |
| 166 | + (fn failed-parser [input0 more0 err-fn _ok-fn] |
| 167 | + #(err-fn input0 more0 [] (str "Failed reading: " msg))))) |
125 | 168 |
|
126 | 169 | (defn always |
127 | 170 | "Returns a parser that will always succeed, this parser will return the |
128 | 171 | parameter given." |
129 | 172 | [a] |
130 | | - (fn new-parser [input0 more0 err-fn ok-fn] |
131 | | - #(ok-fn input0 more0 a))) |
| 173 | + (Parser. |
| 174 | + (fn new-parser [input0 more0 _err-fn ok-fn] |
| 175 | + #(ok-fn input0 more0 a)))) |
132 | 176 |
|
133 | 177 | (defn bind-parsers |
134 | 178 | "Receives a parser and a continuation function, the result of the parser is |
|
141 | 185 | (bind-parsers (char \\a) (fn [achr] (always \"hello\"))) |
142 | 186 | " |
143 | 187 | [p f] |
144 | | - (fn parser-continuation [input0 more0 err-fn ok-fn0] |
145 | | - (letfn [ |
146 | | - (ok-fn [input1 more1 a] ((f a) input1 more1 err-fn ok-fn0))] |
147 | | - (p input0 more0 err-fn ok-fn)))) |
| 188 | + (Parser. |
| 189 | + (fn parser-continuation [input0 more0 err-fn ok-fn0] |
| 190 | + (letfn [(ok-fn [input1 more1 a] |
| 191 | + ((f a) input1 more1 err-fn ok-fn0))] |
| 192 | + (p input0 more0 err-fn ok-fn))))) |
148 | 193 |
|
149 | 194 | (defn join-parsers |
150 | 195 | "Merges two parsers together and returns a new parser that will execute |
|
156 | 201 | (join-parsers (char \\a) (char \\b)) |
157 | 202 | " |
158 | 203 | [p1 p2] |
159 | | - (fn m-plus-parser [input0 more0 err-fn0 ok-fn] |
160 | | - (letfn [ |
161 | | - (err-fn [input1 more1 _ _] |
162 | | - (p2 input1 more1 err-fn0 ok-fn))] |
163 | | - (p1 input0 more0 err-fn ok-fn)))) |
164 | | - |
165 | | -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
166 | | -;; |
167 | | -;; ## Parser Monad implementation |
168 | | -;; |
169 | | -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
170 | | - |
171 | | -(defmonad parser-m |
172 | | - [ m-result (fn result-fn [a] |
173 | | - (always a)) |
174 | | - |
175 | | - m-bind (fn bind-fn [p f] |
176 | | - (bind-parsers p f)) |
177 | | - |
178 | | - m-zero (fail-parser "m-zero") |
179 | | - |
180 | | - m-plus (fn m-plus-fn [p1 p2] |
181 | | - (join-parsers p1 p2))]) |
| 204 | + (Parser. |
| 205 | + (fn m-plus-parser [input0 more0 err-fn0 ok-fn] |
| 206 | + (letfn [ |
| 207 | + (err-fn [input1 more1 _ _] |
| 208 | + (p2 input1 more1 err-fn0 ok-fn))] |
| 209 | + (p1 input0 more0 err-fn ok-fn))))) |
182 | 210 |
|
183 | 211 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
184 | 212 | ;; |
185 | 213 | ;; ## Parser building macros |
186 | 214 | ;; |
187 | 215 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
188 | 216 |
|
| 217 | +(def parser-monad always) |
| 218 | +(def dummy-parser (parser-monad nil)) |
| 219 | + |
| 220 | +;; TODO: How do we translate this to ProtocolMonads? |
189 | 221 | (defmacro with-parser |
190 | 222 | "Allows the use of monadic functions m-bind and m-result which are |
191 | 223 | binded to the parser-m monad." |
|
196 | 228 | "Allows the use of 'domonad' statements with the m-bind and m-result |
197 | 229 | functions binded to the parser-m monad." |
198 | 230 | [steps result] |
199 | | - `(domonad parser-m ~steps ~result)) |
| 231 | + `(monad-macro/do always ~steps ~result)) |
200 | 232 |
|
201 | 233 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
202 | 234 | ;; |
|
216 | 248 | [input0 _more0 result] |
217 | 249 | (ResultDone. input0 result)) |
218 | 250 |
|
219 | | -(defn prompt |
| 251 | +(def prompt |
220 | 252 | "This is parser is used to return continuations (when there is not |
221 | 253 | enough input available for the parser to either succeed or fail)." |
222 | | - [input0 _more0 err-fn ok-fn] |
223 | | - (with-meta |
224 | | - (fn [new-input] |
225 | | - (if (empty? new-input) |
226 | | - (p-trampoline err-fn input0 complete) |
227 | | - (p-trampoline ok-fn (concat input0 (seq new-input)) incomplete))) |
228 | | - {:stop true})) |
| 254 | + (Parser. |
| 255 | + (fn prompt [input0 _more0 err-fn ok-fn] |
| 256 | + (with-meta |
| 257 | + (fn [new-input] |
| 258 | + (if (empty? new-input) |
| 259 | + (p-trampoline err-fn input0 complete) |
| 260 | + (p-trampoline ok-fn (concat input0 (seq new-input)) incomplete))) |
| 261 | + {:stop true})))) |
229 | 262 |
|
230 | 263 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
231 | 264 | ;; |
|
302 | 335 |
|
303 | 336 | Where `number` is a parser that will return a number from the parsed input." |
304 | 337 | [f & more] |
305 | | - (with-parser |
306 | | - (m-bind (m-seq more) (fn [params] |
307 | | - (m-result (apply f params)))))) |
| 338 | + (bind-parsers |
| 339 | + (monad/seq always more) |
| 340 | + (fn [params] |
| 341 | + (always (apply f params))))) |
308 | 342 |
|
309 | 343 | (def <|> |
310 | 344 | "Alias for join-parsers function." |
|
0 commit comments