type:
    dataType { $$ = $1; }
 |  procType { $$ = $1; }
 |  type WITH methodSet            { $$ = t_setmethods($1, $3); }
;

dataType:
 /* Primative types, type equations and user-defined types. */
    var                            { $$ = t_create(T_EQU, $1); }
 |  ID '[' typeList ']' '.' ID     { $$ = fancyEquate($2, $1, $6); }

 /* Compound types */
 |  '(' ')'                        { $$ = tc_none; /* Only for signatures */}
 |  '(' typeList ')'               { $$ = tupleType($1, $2); }
 |  RECORD '[' declList']'         { $$ = compType($1, T_RECORD, $3); }
 |  '[' declList']'				   { $$ = compType($1, T_RECORD, $2); }
 |  SET '[' type ']'               { $$ = compType($1, T_SET, $3); }
 |  SET type                       { $$ = compType($1, T_SET, $2); }
 |  SEQ '[' type ']'               { $$ = compType($1, T_SEQ, $3); }
 |  SEQ type                       { $$ = compType($1, T_SEQ, $2); }
 |  UNION '[' typeList ']'         { $$ = compType($1, T_UNION, $3); }
 |  '(' typeUnion ')'              { $$ = compType($1, T_UNION, $2); }
;

procType:
 /* Procedural types */
    dataType ARROW type raises     { $$ = procType($2, T_FUNC, $1, $3, $4); }
 |  PROC dataType returns raises   { $$ = procType($1, T_PROC, $2, $3, $4); }
 |  APROC dataType returns raises  { $$ = procType($1, T_APROC, $2, $3, $4); }
;

returns:
    /* empty */                   { $$ = tc_none; }
 |  ARROW type                    { $$ = $2; }
;

raises:
    /* empty */                   { $$ = setex_create(sm_eq); }
 |  RAISES exceptionSet           { $$ = $2; }
;

method:
    ID GETS var                   { $$ = mthd_create($1, $3); }
 |  STRINGLIT GETS var            { $$ = mthd_create(current_mod_name, $3); }
;

var:
    ID                            { $$ = var_create(current_mod_name, $1); }
 |  ID '.' ID                     { $$ = var_create($1, $3); }
;


typeList:
    type                          { $$ = lst_cons( $1, NULL ); }
 |  typeList ',' type             { $$ = lst_append( $1, $3 ); }
;

typeUnion:
    type                          { $$ = lst_cons( $1, NULL ); }
 |  typeUnion '+' type             { $$ = lst_append( $1, $3 ); }
;

methodList:
    method                        { $$ = lst_cons($1, NULL); }
 |  methodList ',' method         { $$ = lst_append($1, $3); }
;



exceptionSet:
    ID                            { $$ = setex_ref(sm_eq, $1); }
 |  '{' idList '}'                { $$ = setex_itemlist(sm_eq, $2); }
 |  exceptionSet '+' exceptionSet { $$ = setex_uniond($1, $3); }
;

methodSet:
    '{' methodList '}'            { $$ = setex_itemlist(mthd_eq, $2); }
;
