Skip to content

Instantly share code, notes, and snippets.

@wgb
Last active August 29, 2015 14:07
Show Gist options
  • Save wgb/7431a00f2ac1f96b595e to your computer and use it in GitHub Desktop.
Save wgb/7431a00f2ac1f96b595e to your computer and use it in GitHub Desktop.
Expression Parser
(require '[clojure.string :as str])
;; In this use case, a valid expression won't have an even number of lexemes
(defn valid-length? [lexemes]
(odd? (count lexemes)))
(defn valid-paren-count? [lexemes]
(let [opens (filter #(= "(" %) lexemes)
closes (filter #(= ")" %) lexemes)]
(= (count opens) (count closes))))
(defn pre-validate [lexemes]
(and (valid-length? lexemes)
(valid-paren-count? lexemes)))
(def valid-sequences
{:term [:factor :expr-begin]
:factor [:term :expr-end]
:expr-begin [:factor]
:expr-end [:term]})
(defn term? [lexeme]
(= lexeme "+"))
(defn factor? [lexeme]
(or (not (clojure.string/blank? (re-matches #"[A-Z]" check)))
(not (clojure.string/blank? (re-matches #"[0-9]" check)))))
(defn expr-begin? [lexeme]
(= lexeme "("))
(defn expr-end? [lexeme]
(= lexeme ")"))
(defn lexeme-type [lexeme]
(cond
(term? lexeme) :term
(factor? lexeme) :factor
(expr-begin? lexeme) :expr-begin
(expr-end? lexeme) :expr-end
:else nil))
(defn valid? [prev curr]
(when (and prev curr)
(let [valid-continuances (prev valid-sequences)]
(contains? valid-continuances curr))))
(defn validate-expression [lexemes]
(if (pre-validate lexemes)
(not-any? false? (reduce (fn [a lexeme]
(if (empty? a)
(if-not (factor? lexeme)
(conj a false)
(conj a lexeme))
(let [prev (lexeme-type (last a))
curr (lexeme-type lexeme)]
(if (valid? prev curr)
(conj a lexeme)
(conj a false)))))
[]
lexemes))
false))
(defn validate-expressions [expressions]
(doseq [lexemes expressions]
(if (validate-expression lexemes)
(println "Accept")
(println "Reject"))))
(defn split-line [line]
"Splits a line of text into a sequence of strings"
(str/split line #" "))
(defn read-lines [filename]
"Reads a file and returns a sequence made up of a vector for each line"
(with-open [reader (clojure.java.io/reader filename)]
(for [line (doall (line-seq reader))]
(split-line line))))
(defn parse-all [filename]
(let [lines (read-lines filename)]
(validate-expressions lines)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment