%{

open Fnlib Config Mixture Const Globals Location Types Asynt Asyntfn;

%}

%token ABSTRACTION ABSTYPE AND ANDALSO AS CASE DATATYPE DO ELSE END
%token EQTYPE EXCEPTION
%token FN FUN HANDLE IF IN INFIX INFIXR LET LOCAL
%token NONFIX OF OP ORELSE RAISE REC SIG SIGNATURE STRUCT STRUCTURE
%token THEN TYPE VAL WHILE WITH WITHTYPE

%token EQUALS
%token COMMA ARROW DARROW BAR STAR HASH
%token LBRACE RBRACE HASHLBRACKET LBRACKET RBRACKET LPAREN RPAREN
%token COLON SEMICOLON UNDERBAR DOTDOTDOT

%token OPEN PRIM_VAL PRIM_TYPE PRIM_EQTYPE PRIM_REFTYPE

%token <string> ID
%token <Const.QualifiedIdent> QUAL_ID QUAL_STAR

%token <int> ZDIGIT NZDIGIT ZPOSINT2 NZPOSINT2 NEGINT
%token <word> WORD
%token <char> CHAR
%token <real> REAL
%token <string> STRING

%token QUOTEL
%token <string> QUOTER QUOTEM

%token <string> TYVAR

%token EOF

%right    AND
%nonassoc DARROW
%nonassoc BAR
%nonassoc ELSE
%nonassoc DO
%nonassoc RAISE
%right    HANDLE
%right    ORELSE
%right    ANDALSO
%right    AS

%nonassoc COLON
%right    ARROW
%nonassoc ID EQUALS
%right    STAR

%start SigFile
%type <Asynt.Sig> SigFile

%type <bool> EOPh
%type <string> Ident EqIdent UnitName
%type <Location.Location * string> LocUnitName
%type <Asynt.IdInfo> OpIdent OpEqIdent TypeIdent LongTypeIdent
%type <Asynt.TyVar> TyVar
%type <string list> UnitName_seq1
%type <int> NumLabel Arity
%type <unit> SemiEof
%type <Mixture.Lab> Label
%type <Asynt.PrimValBind list> PrimValBind AndPrimValBind_opt
%type <Asynt.TypBind list> TypBind AndTypBind_opt
%type <Asynt.TypDesc list> TypDesc AndTypDesc_opt
%type <Asynt.DatBind list> DatBind AndDatBind_opt
%type <Asynt.ConBind list> ConBind BarConBind_opt
%type <Asynt.TypBind list option> WithType_opt
%type <Asynt.ExDesc list> ExDesc AndExDesc_opt
%type <Asynt.Ty option> OfTy_opt ColonTy_opt
%type <Asynt.Ty> Ty Ty_sans_STAR AtomicTy
%type <Asynt.Ty list> TupleTy TyComma_seq2
%type <Asynt.Ty Mixture.Row> TyRow_opt TyRow CommaTyRow_opt
%type <Asynt.TyVar list> TyVarSeq TyVarComma_seq1

%type <Asynt.Spec> Spec KWSpec
%type <Asynt.Spec list> KWSpec_seq
%type <Asynt.ValDesc list> ValDesc AndValDesc_opt

%%

Ident :
    ID          { $1 }
  | STAR        { "*" }
;

OpIdent :
    Ident       { mkIdInfo (mkLoc { qual="", id=$1 }) false }
  | OP Ident    { mkIdInfo (mkLoc { qual="", id=$2 }) true }
;

OpEqIdent :
    EqIdent     { mkIdInfo (mkLoc { qual="", id=$1 }) false }
  | OP Ident    { mkIdInfo (mkLoc { qual="", id=$2 }) true }
;

EqIdent :
    Ident       { $1 }
  | EQUALS      { "=" }
;

LocUnitName :
    UnitName    { mkLoc($1) }
;

UnitName :
    Ident       { normalizedUnitName $1 }
  | EQUALS      { "=" }
;

TypeIdent :
    ID          { mkIdInfo (mkLoc { qual="", id=$1 }) false }
;

LongTypeIdent :
    TypeIdent   { $1 }
  | QUAL_ID     { mkIdInfo (mkLoc $1) false }
;

TyVar :
    TYVAR    { mkIdInfo (mkLoc { qual="", id=$1 }) false }
;

UnitName_seq1 :
    UnitName UnitName_seq1      { $1 :: $2 }
  | UnitName                    { [$1] }
;

NumLabel :
    NZPOSINT2   { $1 }
  | NZDIGIT     { $1 }
;

Label :
    Ident       { STRINGlab $1 }
  | NumLabel    { INTlab $1 }
;

Arity :
    ZPOSINT2    { $1 }
  | NZPOSINT2   { $1 }
  | ZDIGIT      { $1 }
  | NZDIGIT     { $1 }
;

EOPh :
    SEMICOLON   { false }
  | EOF         { true }
;

SemiEof :
    SEMICOLON SemiEof   { }
  | EOF			{ }
;

PrimValBind :
    OpIdent COLON Ty EQUALS Arity STRING AndPrimValBind_opt
                        { ($1, $3, $5, $6) :: $7 }
;

AndPrimValBind_opt :
    AND PrimValBind     { $2 }
  | /* */               { [] }
;

TypBind :
    TyVarSeq TypeIdent  EQUALS Ty AndTypBind_opt
                        { ($1, $2, $4) :: $5 }
;

AndTypBind_opt :
    AND TypBind         { $2 }
  | /* */               { [] }
;

DatBind :
    TyVarSeq TypeIdent EQUALS ConBind AndDatBind_opt
                        { ($1, $2, $4) :: $5 }
;

AndDatBind_opt :
    AND DatBind         { $2 }
  | /* */               { [] }
;

ConBind :
    OpIdent OfTy_opt BarConBind_opt     { ConBind($1, $2) :: $3 }
;

BarConBind_opt :
    BAR ConBind         { $2 }
  | /* */               { [] }
;

WithType_opt :
    WITHTYPE TypBind    { SOME $2 }
  | /* */               { NONE }
;

ExDesc :
    OpIdent OfTy_opt AndExDesc_opt              { ($1,$2) :: $3 }
;

AndExDesc_opt :
    AND ExDesc          { $2 }
  | /* */               { [] }
;

ColonTy_opt :
    COLON Ty    { SOME $2 }
  | /* */       { NONE }

OfTy_opt :
    OF Ty       { SOME $2 }
  | /* */       { NONE }
;

Ty :
    TupleTy ARROW Ty    { mkLoc(FNty( tupleTy $1, $3)) }
  | TupleTy             { tupleTy $1 }
;

TupleTy :
    Ty_sans_STAR                { [$1] }
  | Ty_sans_STAR STAR TupleTy   { $1 :: $3 }
;

Ty_sans_STAR :
    LPAREN TyComma_seq2 RPAREN LongTypeIdent    { mkLoc(CONty($2, $4)) }
  | Ty_sans_STAR LongTypeIdent                  { mkLoc(CONty([$1], $2)) }
  | AtomicTy                                    { $1 }
;

TyComma_seq2 :
    Ty COMMA TyComma_seq2       { $1 :: $3 }
  | Ty COMMA Ty                 { [$1, $3] }
;

AtomicTy :
    LongTypeIdent               { mkLoc(CONty([], $1)) }
  | TyVar                       { mkLoc(TYVARty $1) }
  | LBRACE TyRow_opt RBRACE     { mkLoc(RECty $2) }
  | LPAREN Ty RPAREN            { $2 }
;

TyRow_opt :
    TyRow       { $1 }
  | /* */       { [] }
;

TyRow :
    Label COLON Ty CommaTyRow_opt       { ($1,$3)::$4 }
;

CommaTyRow_opt :
    COMMA TyRow         { $2 }
  | /* */               { [] }
;

TyVarSeq :
    TyVar                               { [$1] }
  | LPAREN TyVarComma_seq1 RPAREN       { $2 }
  | /* */                               { [] }
;

TyVarComma_seq1 :
    TyVar COMMA TyVarComma_seq1         { $1 :: $3 }
  | TyVar                               { [$1] }
;

SigFile :
    SIGNATURE LocUnitName EQUALS SIG KWSpec_seq END SemiEof
                        { NamedSig{locsigid = $2, specs = $5 } }
  | KWSpec_seq EOF	{ AnonSig $1 }
;

KWSpec_seq :
    KWSpec KWSpec_seq		{ $1 :: $2 }
  | SEMICOLON KWSpec_seq	{ $2 }
  | /* */			{ [] }
;

Spec :
    KWSpec Spec         { mkLoc(SEQspec($1, $2)) }
  | SEMICOLON Spec      { $2 }
  | /* */               { mkLoc(EMPTYspec) }
;

KWSpec :
    VAL ValDesc                 { mkLoc(VALspec $2) }
  | PRIM_VAL PrimValBind        { mkLoc(PRIM_VALspec $2) }
  | TYPE TypBind                { mkLoc(TYPEspec $2) }
  | TYPE TypDesc                { mkLoc(TYPEDESCspec(FALSEequ, $2)) }
  | EQTYPE TypDesc              { mkLoc(TYPEDESCspec(TRUEequ, $2)) }
  | PRIM_REFTYPE TypDesc        { mkLoc(TYPEDESCspec(REFequ, $2)) }
  | DATATYPE DatBind WithType_opt
                                { mkLoc(DATATYPEspec($2,$3)) }
  | EXCEPTION ExDesc            { mkLoc(EXCEPTIONspec $2) }
  | LOCAL Spec IN Spec END      { mkLoc(LOCALspec($2,$4)) }
  | OPEN UnitName_seq1          { mkLoc(OPENspec $2) }
;

ValDesc :
    OpEqIdent COLON Ty AndValDesc_opt
                        { ($1, $3) :: $4 }
;

AndValDesc_opt :
    AND ValDesc         { $2 }
  | /* */               { [] }
;

TypDesc :
    TyVarSeq TypeIdent AndTypDesc_opt
                        { ($1, $2) :: $3 }
;

AndTypDesc_opt :
    AND TypDesc         { $2 }
  | /* */               { [] }
;
