Skip to content

Instantly share code, notes, and snippets.

@pyrocat101
Last active August 29, 2015 14:00
Show Gist options
  • Save pyrocat101/11205476 to your computer and use it in GitHub Desktop.
Save pyrocat101/11205476 to your computer and use it in GitHub Desktop.
Regex Parser
(defn syntax-error []
(throw (ex-info "Syntax Error" {})))
(declare alt then star prime)
(defn expect [s c]
(if (not= (first s) c)
(syntax-error)
(rest s)))
(defn alt [s]
(let [[a s] (then s)]
(if (= (first s) "|")
(let [[b s*] (alt (rest s))]
[(list :alt a b) s*])
[a s])))
(defn then [s]
(let [[c s] (star s)]
(if (or (= (first s) "(")
(re-matches #"\w" (first s)))
(let [[d s*] (then s)]
[(list :then c d) s*])
[c s])))
(defn star [s]
(let [[p s] (prime s)
P [p]]
(println p)
(if (= (first s) "*")
[(cons :star P) (rest s)]
[(first P) s])))
(defn prime [s]
(if (re-matches #"\w" (first s))
(do
[(list :literal (first s)) (rest s)])
(do
(let [s* (expect s "(")
[r s**] (alt s*)
s*** (expect s** ")")]
[r s***]))))
(defn parse-regex [s]
(let [s (map str (lazy-cat s "\x00"))
[tree s*] (alt s)]
(if-not (= (first s*) "\x00")
(syntax-error)
tree)))
(parse-regex "a")
(parse-regex "abc")
(parse-regex "(ab)")
(parse-regex "(ab)*")
(parse-regex "(ab)*(c|d)*(e|f)")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment