%{

open FSharp.Xml.Light

%}
%token NEXT OR
%token <string>IDENT
%token PCDATA
%token STAR QUESTION PLUS
%token OPEN CLOSE
%token END

%right STAR QUESTION PLUS

%start dtd_element
%type <Dtd.dtd_child> dtd_element
%%

dtd_element:
    | dtd_full_seq END
        { $1 }
;
dtd_full_seq:
    | dtd_seq CLOSE dtd_op
        { $3 $1 }
    | dtd_seq CLOSE
        { $1 }
;
dtd_seq:
    | dtd_item NEXT dtd_children
        { Dtd.DTDChildren ($1 :: $3) }
    | dtd_item OR dtd_choice
        { Dtd.DTDChoice ($1 :: $3) }
    | dtd_item
        { $1 }
;
dtd_children:
    | dtd_item NEXT dtd_children
        { $1 :: $3 }
    | dtd_item
        { [$1] }
;
dtd_choice:
    | dtd_item OR dtd_choice
        { $1 :: $3 }
    | dtd_item
        { [$1] }
;
dtd_item:
    | OPEN dtd_full_seq
        { $2 }
    | dtd_member
        { $1 }
;
dtd_member:
    | IDENT dtd_op
        { $2 (Dtd.DTDTag $1) }
    | PCDATA dtd_op
        { $2 Dtd.DTDPCData }
    | IDENT
        { Dtd.DTDTag $1 }
    | PCDATA
        { Dtd.DTDPCData }
;
dtd_op:
    | dtd_op_item dtd_op
        { (fun x -> $2 ($1 x)) }
    | dtd_op_item 
        { $1 }
;
dtd_op_item:
    | STAR
        { (fun x -> Dtd.DTDZeroOrMore x) }
    | QUESTION
        { (fun x -> Dtd.DTDOptional x) }
    | PLUS
        { (fun x -> Dtd.DTDOneOrMore x) }
;