Writing a DSLΒΆ
Let us make a calculator that would evaluate expressions like:
1 + 2
Dependencies:
[instaparse "1.4.10"]
[org.clojure/core.match "0.3.0-alpha5"]
Update required libs:
[instaparse.core :as insta]
[clojure.core.match :refer [match]]
Write the grammar as BNF (in the root of the project):
EXPR := NUMBER <ws*> OP <ws*> NUMBER
OP := ADD | SUB
ADD := "+"
SUB := "-"
NUMBER := #"[0-9]+"
ws := #'\s+' (* whitespace *)
Parse the grammar:
(def parse (->> (System/getProperty "user.dir")
(format "%s/grammar.bnf" )
slurp
insta/parser
))
Test it:
(parse "1 + 2")
;; [:EXPR [:NUMBER 1] [:OP [:ADD +]] [:NUMBER 3]]
Generate the ast:
(defn evaluate
"Convert parse tree to abstract syntax tree"
[parsed]
(match parsed [:EXPR [:NUMBER l] [:OP op] [:NUMBER r]] (+ (read-string l) (read-string r) ) ;; hardcode the operator
:else {:error (format "Matching rules incomplete for: %s" parsed)}
))
Evaluate:
(->> "1 + 2"
parse
evaluate)