4.4. Example Attribute Grammars
Prev | Chapter 4. Attribute Grammars | Next

## 4.4. Example Attribute Grammars

The following two toy attribute grammars may prove instructive. The first is an attribute grammar for the classic context-sensitive grammar { a^n b^n c^n | n >= 0 }. It demonstrates the use of conditionals, inherited and synthesized attributes.

    {
    module ABCParser (parse) 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
       : alist blist clist newline
            { $$ = $1 ++ $2 ++ $3
            ; $2.len = $1.len
            ; $3.len = $1.len
            }

    alist
       : a alist
            { $$ = $1 : $2
            ; $$.len = $2.len + 1
            }
       |    { $$ = []; $$.len = 0 }

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

    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
    }

This grammar parses binary numbers and calculates their value. It demonstrates the use of inherited and synthesized attributes.

    {
    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
       : num newline { $$ = $1 }

    num
       : bits        { $$ = $1       ; $1.pos = 0 }
       | plus bits   { $$ = $2       ; $2.pos = 0 }
       | minus bits  { $$ = negate $2; $2.pos = 0 }

    bits
       : bit         { $$ = $1
                     ; $1.pos = $$.pos
                     }

       | bits bit    { $$ = $1 + $2
                     ; $1.pos = $$.pos + 1
                     ; $2.pos = $$.pos
                     }

    bit
       : zero        { $$ = 0 }
       | one         { $$ = 2^($$.pos) }

    {
    happyError = error "parse error"
    }

Prev | Up | Next
4.3. Limits of Happy Attribute Grammars | Home | Chapter 5. Invoking Happy