open Lexer

type syntree = Term    of char list
            | NonTerm of char list
            | Param   of char list
            | Opt     of syntree
            | Rep     of syntree
            | TermRep of syntree * syntree
            | OptRep  of syntree
            | OrList  of syntree list
            | Con     of syntree * syntree

let analyse str =

 let rec rexp s =
   let mid = parser [< 'MID >] -> () in
   let rec restrexp e1 = parser
     [< _ = mid; e2 = andrexp; e = restrexp
          (match e1
            with OrList l -> OrList (l @ [e2])
               | _ -> OrList [e1; e2]
          )
     >] -> e
   | [< >] -> e1
 in match s with parser [< e1 = andrexp; e2 = restrexp e1 >] -> e2

 and andrexp s =
   let rec restand e1 = parser
     [< e2 = reprexp; e = restand (Con (e1, e2)) >] -> e
   | [< >] -> e1
 in match s with parser [< e1 = reprexp; e2 = restand e1 >] -> e2

 and reprexp = parser
     [< 'LSPAR; e = rexp; 'RSPAR >] -> Opt e
   | [< 'PLUS; e = plusexp >] -> e
   | [< 'LAPAR; e = rexp; 'RAPAR >] -> OptRep e
   | [< e = atom >] -> e

 and plusexp = parser
     [< 'TERM l; 'LAPAR; e = rexp; 'RAPAR >] -> TermRep (e, Term l)
   | [< 'LAPAR; e = rexp; 'RAPAR >] -> Rep e

 and atom = parser
     [< 'NONTERM l >] -> NonTerm l
   | [< 'TERM l >] -> Term l
   | [< 'PARAM l >] -> Param l
   | [< 'LPAR; e = rexp; 'RPAR >] -> e

in rexp (lexer str)