Given the following example "~a{b=1}&(a{b=1}|a{b=1})|a{b=1}|a{b=1}" I have written the following parser using Instaparse
((insta/parser
"
S = (group | exp)+
group = '~'? <'('> exp+ <')'> op?
exp = '~'? path <'='> (v | r) <'}'> op?
path = (p <'{'>)* p
op = '|' | '&'
<p> = #'[a-z]'
v = #'[a-z0-9]'
r = <'\\''> #'[^\\']*' <'\\''>
")
"~a{b=1}&(a{b=1}|a{b=1})|a{b=1}|a{b=1}")
Running the above output the following output
[:S
[:exp "~" [:path "a" "b"] [:v "1"] [:op "&"]]
[:group
[:exp [:path "a" "b"] [:v "1"] [:op "|"]]
[:exp [:path "a" "b"] [:v "1"] [:op "|"]]
[:exp [:path "a" "b"] [:v "1"]]
[:op "|"]]
[:exp [:path "a" "b"] [:v "1"]]]
However from this output I have a very hard time writing a transformation into Clojure expressions. To have a more straightforward transformation I would need something more like:
[:S
[:op "|"
[:op "&"
[:exp "~" [:path "a" "b"] [:v "1"]]
[:group
[:op "|"
[:exp [:path "a" "b"] [:v "1"]]
[:op "|"
[:exp [:path "a" "b"] [:v "1"]]
[:exp [:path "a" "b"] [:v "1"]]]]]]
[:exp [:path "a" "b"] [:v "1"]]]]
Given this structure it would be much easier to transform this in to Clojure.
How would your write a generic parser that can parse structures like the above and similar into an AST that can then be turned into Clojure code using a simple insta/transfrom?
I'd follow the example from Operator-precedence parser; this will give you "single"
and/orterms, but that should be easy to trim/optimize away in your following steps.E.g.