[Haskell-beginners] Attribute Grammar and Type signature with Happy

Stephen Tetley stephen.tetley at gmail.com
Thu May 27 16:08:35 EDT 2010


Hello Julien

I've worked out type signatures below for both examples in the Happy
docs. I'm afraid, I've no idea what what the type signatures actually
mean, I worked them out simply by hacking.

I'd rather suggest the AG system within Happy is best avoided, as it
seems like a proof of concept that didn't get fleshed out. UUAG I
would highly recommend - its a well maintained and documented AG
system for Haskell, that has been used for real compilers (Helium,
UHC/EHC).

{
module ABCParser where
}

%tokentype { Char }

%token a { 'a' }
%token b { 'b' }
%token c { 'c' }
%token newline { '\n' }

%attributetype { Attrs a }
%attribute value { a }
%attribute len   { Int }

%name parse abcstring

%%

abcstring :: { Attrs [()] -> ([()], Attrs [Char]) }
abcstring
  : alist blist clist newline
       { $$ = $1 ++ $2 ++ $3
       ; $2.len = $1.len
       ; $3.len = $1.len
       }

alist :: { Attrs [()] -> ([()], Attrs [Char]) }
alist
  : a alist
       { $$ = $1 : $2
       ; $$.len = $2.len + 1
       }
  |    { $$ = []; $$.len = 0 }

blist :: { Attrs [()] -> ([()], Attrs [Char]) }
blist
  : b blist
       { $$ = $1 : $2
       ; $2.len = $$.len - 1
       }
  |    { $$ = []
       ; where failUnless ($$.len == 0) "blist wrong length"
       }

clist :: { Attrs [()] -> ([()], Attrs [Char]) }
clist
  : c clist
       { $$ = $1 : $2
       ; $2.len = $$.len - 1
       }
  |    { $$ = []
       ; where failUnless ($$.len == 0) "clist wrong length"
       }

{
happyError = error "parse error"
failUnless b msg = if b then () else error msg
}

-------------------------------

{
module BitsParser (parse) where
}

%tokentype { Char }

%token minus { '-' }
%token plus  { '+' }
%token one   { '1' }
%token zero  { '0' }
%token newline { '\n' }

%attributetype { Attrs }
%attribute value { Integer }
%attribute pos   { Int }

%name parse start

%%

start :: { Attrs -> ([()],Attrs) }
start
   : num newline { $$ = $1 }

num :: { Attrs -> ([()],Attrs) }
num
   : bits        { $$ = $1       ; $1.pos = 0 }
   | plus bits   { $$ = $2       ; $2.pos = 0 }
   | minus bits  { $$ = negate $2; $2.pos = 0 }

bits :: { Attrs -> ([()],Attrs) }
bits
   : bit         { $$ = $1
                 ; $1.pos = $$.pos
                 }

   | bits bit    { $$ = $1 + $2
                 ; $1.pos = $$.pos + 1
                 ; $2.pos = $$.pos
                 }
bit :: { Attrs -> ([()],Attrs) }
bit
   : zero        { $$ = 0 }
   | one         { $$ = 2^($$.pos) }

{
happyError = error "parse error"
}


More information about the Beginners mailing list