Skip to content

Instantly share code, notes, and snippets.

@cgrand
Last active February 8, 2017 12:26
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cgrand/83078ec052f3f406e5afdf46a7af13f7 to your computer and use it in GitHub Desktop.
Save cgrand/83078ec052f3f406e5afdf46a7af13f7 to your computer and use it in GitHub Desktop.
;; warm up: balancing
=> (s/def ::balanced
(s/* (s/cat :open #{'<} :children ::balanced :close #{'>})))
:user/balanced
=> (s/conform ::balanced '[< < > < > > < >])
[{:open <, :children [{:open <, :close >} {:open <, :close >}], :close >} {:open <, :close >}]
=> (s/conform ::balanced '[< < > < < > > > < >])
[{:open <, :children [{:open <, :close >} {:open <, :children [{:open <, :close >}], :close >}], :close >} {:open <, :close >}]
;; infix to prefix
(def to-sexpr
(s/conformer
(fn [[k x]]
(case k
:single x
:expr (map #(% x) [:op :lhs :rhs])))))
(s/def ::sum
(s/&
(s/alt
:single ::product
:expr (s/cat :lhs ::product :op '#{+ -} :rhs ::sum))
to-sexpr))
(s/def ::product
(s/&
(s/alt
:single number?
:expr (s/cat :lhs number? :op '#{* /} :rhs ::product))
to-sexpr))
;;;;;;
=> (s/conform ::sum '[1 * 4 + 2 * 3])
(+ (* 1 4) (* 2 3))
=> (s/conform ::sum '[1 * 4 + 2 + 5 * 3])
(+ (* 1 4) (+ 2 (* 5 3)))
;; the truth is that I didn't manage to add parenthized expressions and still have conformers.
;; if I leave conformers out I can easily add parenthized expressions
(s/def ::sum
(s/alt
:single ::product
:expr (s/cat :lhs ::product :op '#{+ -} :rhs ::sum)))
(s/def ::product
(s/alt
:expr (s/cat :lhs number? :op '#{* /} :rhs ::product)
:single #_number? ::parens))
(s/def ::parens
(s/alt
:expr (s/cat :lp #{\(} :expr ::sum :rp #{\)})
:single number?))
=> (s/conform ::sum '[1 * \( 4 + 5 \) + 2 * 3])
[:expr
{:lhs
[:expr
{:lhs 1,
:op *,
:rhs
[:single
[:expr
{:lp \(,
:expr
[:expr
{:lhs [:single [:single 4]],
:op +,
:rhs [:single [:single [:single 5]]]}],
:rp \)}]]}],
:op +,
:rhs [:single [:expr {:lhs 2, :op *, :rhs [:single [:single 3]]}]]}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment