Skip to content

Instantly share code, notes, and snippets.

@mikedouglas
Created November 21, 2009 08:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikedouglas/240050 to your computer and use it in GitHub Desktop.
Save mikedouglas/240050 to your computer and use it in GitHub Desktop.
(ns parser.core)
(declare bind)
;; succeeds w/o consuming input
(defn result [v]
(fn [inp] [[v inp]]))
;; always fails
(defn zero []
(fn [inp] []))
;; consumes first char, otherwise fails
(defn item []
(fn [inp]
(if (seq inp)
[[(first inp) (apply str (rest inp))]]
[])))
(defn bind [p f]
(fn [inp]
(apply concat
(for [[v p-inp] (p inp)]
((f v) p-inp)))))
;; consumes first char if (pred char), otherwise fails
(defn sat [pred]
(bind (item) (fn [x]
(if (pred x)
(result x)
(zero)))))
;; par-seq definition using `bind`
(defn par-seq [p q]
(bind p (fn [x]
(bind q (fn [y]
(result [x y]))))))
;; combines two parsers
(defn plus [p q]
(fn [inp] (into (p inp) (q inp))))
(defn par-char [x]
(sat (fn [y] (= x y))))
(defn par-digit []
(sat (fn [x] (java.lang.Character/isDigit x))))
(defn par-lower []
(sat (fn [x] (java.lang.Character/isLowerCase x))))
(defn par-upper []
(sat (fn [x] (java.lang.Character/isUpperCase x))))
(defn par-letter []
(plus (par-upper) (par-lower)))
(defn par-alphanum []
(plus (par-letter) (par-digit)))
(defn par-word []
(let [ne-word (bind (par-letter) (fn [x]
(bind (par-word) (fn [xs]
(result (apply str (cons x xs)))))))]
(plus (ne-word) (result ""))))
((par-word) "hello")
;; results in:
;; Wrong number of args passed to: core$bind--2546$fn
;; [Thrown class java.lang.IllegalArgumentException]
;;
;; Restarts:
;; 0: [ABORT] Return to SLIME's top level.
;;
;; Backtrace:
;; 0: clojure.lang.AFn.throwArity(AFn.java:449)
;; 1: clojure.lang.AFn.invoke(AFn.java:48)
;; 2: parser.core$par_word__2979.invoke(NO_SOURCE_FILE:1)
;; 3: parser.core$eval__3139.invoke(NO_SOURCE_FILE:1)
;; 4: clojure.lang.Compiler.eval(Compiler.java:4532)
;; 5: clojure.core$eval__3990.invoke(core.clj:1728)
;; --more--
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment