%{
%}
typeArgument :
    | funtype {TypeArgumentUtils.ofFun s0}
    | flexibletype {Flexible s0}
    | subtype {s0}
funtype :
    | tupletype "->" funtype {s0::s2}
    | tupletype {[s0]}
tupletype :
    | apptype "*" tupletype {s0::s2}
    | apptype {[s0]}
apptype :
    | atomtype suffixTypes {TypeArgumentUtils.ofApp(s0,s1)}
atomtype :
    | "_" {Anon}
    | typar { TypeArgumentUtils.ofTypar s0 }
    | namedtype {match s0 with a,b -> Ctor(a,b)}
    | anonRecordType {s0}
    | "(" typeArgument ")" {s1}
    | struct "(" tupletype ")" {match TypeArgumentUtils.ofTuple s2 with Tuple(_,ls) -> Tuple(true,ls) | _ -> failwith "" }
    | struct anonRecordType {match s1 with AnonRecd(_,ls) -> AnonRecd(true,ls) |_->failwith""}
namedtype :
    | ctortype {s0,[]}
    | ctortype "<" typeArguments ">" {s0, s2}
ctortype :
    | longIdent { s0 }
suffixType:
    | ctortype {LongIdent s0}
    | ARRAY_TYPE_SUFFIX {ArrayTypeSuffix s0}
typeArguments :
    | typeArgument "," typeArguments {s0::s2}
    | typeArgument {[s0]}
anonRecordType :
    | "{|" recdFieldDeclList "|}" {AnonRecd(false, s1)}
recdFieldDeclList :
    | fieldDecl ";" recdFieldDeclList {s0::s2}
    | fieldDecl ";"? {[s0]}
fieldDecl :
    | IDENT ":" typeArgument {(s0,s2)}
suffixTypes :
    | suffixType suffixTypes {s0::s1}
    | (*empty*) {[]}
flexibletype :
    | "#" namedtype {match s1 with ctor,targs -> FlexibleCtor(ctor,targs)}
    | "#" "(" apptype ")" {TypeArgumentUtils.toBaseOrInterfaceType s2}
    | "#" "_" {FlexibleAnon}
subtype :
    | variabletype ":>" apptype { Subtype(s0,TypeArgumentUtils.toBaseOrInterfaceType s2) }
variabletype :
    | "_" {AnonTypar}
    | typar {s0}
typar :
    | QTYPAR {NamedTypar(false,s0)}
    | HTYPAR {NamedTypar(true,s0)}
longIdent :
    | IDENT "." longIdent {s0::s2}
    | IDENT {[s0]}
";"? :
    | ";" {}
    | (*empty*) {}

%%

%type<int> ARRAY_TYPE_SUFFIX
%type<string> IDENT HTYPAR QTYPAR
%type<TypeArgument> anonRecordType apptype atomtype subtype typeArgument
%type<string list> ctortype longIdent
%type<string*TypeArgument> fieldDecl
%type<BaseOrInterfaceType> flexibletype
%type<TypeArgument list list> funtype
%type<string list * TypeArgument list> namedtype
%type<(string*TypeArgument)list> recdFieldDeclList
%type<SuffixType> suffixType
%type<SuffixType list> suffixTypes
%type<TypeArgument list> tupletype typeArguments
%type<Typar> typar variabletype
