%{

#include <stdio.h>
#include "sactions.h"
#include "type.h"
#include "misc1.h"
#include "setexpr.h"
#include "symmap.h"
#include "list.h"

extern int lineno;           /* Imported from scanner---use sparingly. */
extern int current_mod_name; /* Name of module currently being parsed. */

%}

%union {
  Type    typeval;
  List    list;
  Decl    decl;
  Setexpr setexpr;
  Var     variable;
  Method  method;
  int     symbol;
  int     lineno;
}

%type <typeval>  type dataType procType returns
%type <list>     typeList typeUnion idList declList methodList
%type <setexpr>  raises exceptionSet methodSet
%type <decl>     decl
%type <variable> var
%type <method>   method

#<token.yh  -- Get token definitions.

%%

program: moduleStar;

module: 
    moduleHeader '=' globalStar BEGN stmt END ID
 |  moduleHeader '=' globalStar END ID
 |  moduleHeader '=' ID '[' typeList ']'
 |  error '=' globalStar BEGN stmt END ID
 |  error '=' globalStar END ID
 |  error '=' ID '[' typeList ']'
;

moduleHeader: 
    MODULE ID                   { moduleHeader($1, $2); }
 |  MODULE ID '[' mfpList ']'
;

mfp:
    ID
 |  ID WITH '{' mfpDeclList '}'
;

mfpDecl:
    ID ':' type
 |  STRINGLIT ':' type
 |  ID
;
    
global:
    TYPE typeDeclStar
 |  VAR declInitStar
 |  EXCEPTION exSetDeclStar
 |  routineDecl
 |  error TYPE typeDeclStar
 |  error VAR declInitStar
 |  error EXCEPTION exSetDeclStar
 |  error routineDecl
;


typeDecl:
    ID '=' type                { typeDecl($2, $1, $3); }
 |  ID '=' ENUM '[' idList ']' { typeDecl($2, $1, t_create(T_ENUM, $5)); }
;

declInit:
    decl
 |  ID GETS exp
 |  ID ':' type GETS exp
;

decl:
    ID ':' type                   { $$ = decl_create($1, $3); }
 |  ID                            { $$ = decl_create($1, tc_int); }
;

exSetDecl:
    ID '=' exceptionSet
;

routineDecl:
    FUNC ID signature '=' stmt
 |  PROC ID signature '=' stmt
 |  APROC ID signature '=' OPENA stmt CLOSEA
;


globalStar:
    /* empty */
 |  globalStar global
;

typeDeclStar:
    /* empty */
 |  typeDeclStar typeDecl
;

declInitStar:
    /* empty */
 |  declInitStar declInit
;

exSetDeclStar:
    /* empty */
 |  exSetDeclStar exSetDecl
;

moduleStar:
    /* empty */
 |  moduleStar module
;


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

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

mfpList:
    mfp
 |  mfpList ',' mfp
;

mfpDeclList:
    mfpDecl
 |  mfpDeclList ',' mfpDecl
;

declInitList:
    declInit
 |  declInitList ',' declInit
;

#<type.yh -- Include type productions.
#<expr.yh -- Include expression productions.
#<stmt.yh
