Recently, I have learned how to implement quasiquoters with antiquote capabilities, like printfQ
in the following piece of code:
main = do
let itemName = "apple"
price = 1.29
[printfQ| The price of #{itemName} is #{price}. |]
The ingredient string of the quasiquote will be passed to quoteExp printfQ :: String -> ExpQ
. So what we do is to parse the given String
, find names to be embedded "itemName"
and "price"
, apply varE . mkName
for each name, and build the ExpQ
.
Now suppose I'd like to extend this printfQ
to allow expression embedding as follows:
[printfQ| The price of #{itemNames !! i} is #{price + taxOf price}. |]
I can write the parser that detects two string"itemNames !! i"
and "price + taxOf price"
. But then I need a stronger version of varE . mkName
, a function of type String -> ExpQ
that turns those strings into ExpQ
, interpreting them as expressions referring to the namespace the printfQ
is used.
My question: is there any library function that does this string to AST conversion? Are there some easy ways to do this, or do I need to write an entire Haskell parser?
After taking a bath an excellent idea came to me:
Hey, if I need an entire Haskell parser, why not use an existing one?
After a couple of search in that line I found my answer: parseExp
from
http://hackage.haskell.org/package/haskell-src-meta-0.6.0.4/docs/Language-Haskell-Meta-Parse.html#v:parseExp .
I wrote a self-contained example for this:
https://github.com/nushio3/practice/tree/master/template-haskell/embed-expr