This example demonstrates rule schemata.

	frown Tuple.lg

Try

	expr (lexer "(a, b, (c, d), ((e, f), g))") :: Maybe Expr

> module Tuple
> where
> import Char
>
> data Expr                     =  Id String
>                               |  Call String [Expr]
>                               |  Tuple [Expr]
>                                  deriving (Show)
>
> type Result                   =  Maybe
>
> %{
>
> Terminal                      =         Ident {String}
>                               |  "(" =  LPar
>                               |  ")" =  RPar
>                               |  "," =  Comma;
>
> :: expr {Expr};
> expr {Id s}                   :  Ident {s};
>      {Tuple es}               |  "(", sepBy expr "," {es}, ")";

Schemes (predefined).

> {-
> sepBy x sep {[a]}             <- x {a}, sep;
> sepBy x sep {[]}              :  ;
>             {as}              |  sepBy1 x sep {as};
>
> sepBy1 x sep {[a]}            <- x {a}, sep;
> sepBy1 x sep {s []}           :  sepBy1' x sep {s};
>
> sepBy1' x sep {[a] -> [a]}    <- x {a}, sep;
> sepBy1' x sep
>     {\ as -> a : as}          :  x {a};
>     {\ as -> s (a : as)}      |  sepBy1' x sep {s}, sep, x {a};
> -}

> }%
>
> frown ts                      =  fail "syntax error"
> 

> data Terminal                 =  Ident String | LPar | RPar | Comma
>                                  deriving (Show)
>
> lexer                         :: String -> [Terminal]
> lexer []                      =  []
> lexer ('(' : cs)              =  LPar  : lexer cs
> lexer (')' : cs)              =  RPar  : lexer cs
> lexer (',' : cs)              =  Comma : lexer cs
> lexer (c : cs)
>     | isAlpha c               =  let (n, cs') = span isAlphaNum cs
>                                  in  Ident (c : n) : lexer cs'
>     | otherwise               =  lexer cs
