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
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to