On Thu, Apr 05, 2007 at 12:14:52AM +0100, Joel Reymont wrote:
> Folks,
>
> I have very uniform Parsec code like this and I'm wondering if I can
> derive it using TemplateHaskell or DrIFT or some other tool. Any ideas?
>
> Note that
>
> 1) The reserved word matches the constructor
>
> 2) No arguments equals no parens
>
> 3) More than one argument is separated with a comma
>
> 4) For every invocation of numExpr, strExpr or boolExpr, the type of
> the constructor argument is NumExpr, StrExpr and BoolExpr respectively.
>
> This is just a handful of functions and I have to tackle about 100
> more, thus my asking :-).
>
> Thanks, Joel
Data.Derive can do this. In an attempt to avoid munging the relevent
files they are attached.
[EMAIL PROTECTED]:/tmp$ ghci -fth -v0 -i/usr/local/src/derive -e '$(
_derive_print_instance makeJoelR '"''"'Foo )' Sample.hs
instance JoelR Main.Foo
where parse = choice [(>>) (reserved ['A']) ((>>) (char '(') ((>>=) parse
(\a0 -> (>>) (char ')') (return (Main.A a1))))),
(>>) (reserved ['B']) ((>>) (char '(') ((>>=) parse
(\a0 -> (>>) (char ',') ((>>=) parse (\a1 -> (>>)
(char ')') (return (Main.B a1 a2))))))),
(>>) (reserved ['C']) (return Main.C)]
Not pretty code, but it will work. (Future plans include adding a
prefix -> infix translator to the optimizer.)
http://www.cs.york.ac.uk/fp/darcs/derive
Stefan
import Text.ParserCombinators.Parsec
import Data.Derive.JoelR
import Data.Derive.TH
class JoelR a where parse :: CharParser s a
data NumExpr = Dummy_ -- I don't know the constr
numExpr = undefined
instance JoelR NumExpr where parse = numExpr
data Foo = A NumExpr | B Foo Foo | C
module Data.Derive.JoelR where
import Data.Derive
import Data.Derive.Peephole
import Data.List
makeJoelR = Derivation drv "JoelR"
drv dat@(DataDef name arity ctors) =
simple_instance "JoelR" dat [funN "parse" [ sclause [] body ] ]
where
body = l1 "choice" $ lst [ clause con | con <- ctors ]
clause con = l1 "reserved" (lit (trim (ctorName con))) >>: args con (ctorArity con)
trim = reverse . takeWhile (/= '.') . reverse
args ct 0 = return' (ctp ct 'a')
args ct k = l1 "char" (lit '(') >>: args' ct k 0
args' ct remn seen = l0 "parse" >>=: (('a' : show seen) ->: args'' ct (remn-1) (seen+1))
args'' ct 0 seen = l1 "char" (lit ')') >>: return' (ctp ct 'a')
args'' ct k seen = l1 "char" (lit ',') >>: args' ct k seen
_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe