Skip to content

Instantly share code, notes, and snippets.

@BRonen
Created October 4, 2025 00:58
Show Gist options
  • Save BRonen/a5527f4b4e8a7f31d94c8619844c39ba to your computer and use it in GitHub Desktop.
Save BRonen/a5527f4b4e8a7f31d94c8619844c39ba to your computer and use it in GitHub Desktop.
infix math dsl macro to clojure
(defmacro infix-math-dsl [form]
(letfn [(parse [x]
(cond
(number? x)
{:node :number :value x}
(symbol? x)
(let [s (str x)]
(if (contains? #{"+" "-" "*" "/"} s)
{:node :op :value x}
{:node :ident :value s}))
(list? x)
{:node :list :value (mapv parse x)}
:else
{:node :error :value (pr-str x)}))
(evaluate [node]
(case (:node node)
:number (:value node)
:string (:value node)
:ident (symbol (:value node))
:list
(if (-> node :value count (not= 3))
(throw (ex-info (str "Parse error: " (-> node :value count)) {:node node}))
(let [value (:value node)
left (evaluate (nth value 0))
op (:value (nth value 1))
right (evaluate (nth value 2))]
`(~op ~left ~right)))
:op (throw (ex-info "Unexpected operator node" {:node node}))
:error (throw (ex-info (:value node)))))]
(-> form parse evaluate)))
(infix-math-dsl (1 + (2 - 3))) ;; => 0
(macroexpand '(infix-math-dsl (1 + (2 - 3)))) ;; => (+ 1 (- 2 3))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment