%{
# include "swbus.h"
# define YYSTYPE         yystype
# define putgrn(n)       (void)ITadd(n, gl)
# define class(nt)       { cls= 0; xxc= nt-1;   \
	       for (xc= 0; xc < nt; xc++, xxc--)    \
			     if (stpick(xc)->type != tNULL) \
		 cls += (1 << xxc);}
# define ndput(tp)   { stput(tp);   \
	       if (gn != NULL){gn->value0=  \
		  (CLR_TYPE)IAT_IT_add(gl, grnl); \
		  gl->size= 0;} \
	       gn= (sttype() == tNULL) ? NULL : sttop(); }
# define ndterm(tp, val) { stput (tp);  \
		       staclr (c_lexv, (CLR_TYPE)val.name); \
		       staclr (c_line, (CLR_TYPE)val.line);}

IT* gl;
TNODE*  gn;
int cls;
int xc;
int xxc;

/* KJT 22/01/23: added function prototypes */
int yyparse();

%}

%token LANGUAGE 260
%token SYNTAX 261
%token END_LANGUAGE 262
%token LID 263
%token RULE 264
%token ASSIGN 265
%token TAST 266
%token ATTRIBUTION 267
%token CONDITION 268
%token VISIT 269
%token END_RULE 270
%token NODE 271
%token UID 272
%token STRING 273
%token INCLUDE_LAG 274
%token END_INCLUDE 275
%token INCLUDE_RAG 276
%token ATTRIBUTES 277
%token CHAR 278
%token ID 279

%start language


%%

I1opt                   :
	 /* empty */
	{ ndput (tNULL); }
	;

I1opt                   :
	 lagh
	;

I2opt                   :
	 /* empty */
	{ ndput (tNULL); }
	;

I2opt                   :
	 ragh
	;

I3opt                   :
	 /* empty */
	{ ndput (tNULL); }
	;

I3opt                   :
	 attrs
	;

language                :
	 LANGUAGE language_id I1opt I2opt I3opt SYNTAX rules END_LANGUAGE
	{
	if (errorcount == 0)
	{
	 class(5);
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 ndput(tlanguage);
	 sttop()->value1= (CLR_TYPE)cls;
	 if (stpick(1)->type == tNULL)
	      {stswap(); stpop();}
	 else stsflink ();
	 putgrn(1);
	}
	}
	;

language_id             :
	 LID
	{
	if (errorcount == 0)
	{
	 ndput(tlanguage_id);
	 staclr (c_lexv, (CLR_TYPE)$1.name);
	 staclr (c_line, (CLR_TYPE)$1.line);
	 putgrn(2);
	}
	}
	;

I4repp                  :
	 rule
	;

I4repp                  :
	 I4repp rule
	{ if (errorcount == 0) stlrlink (); }
	;

rules                   :
	 I4repp
	{
	if (errorcount == 0)
	{
	 class(1);
	 ndput(trules);
	 sttop()->value1= (CLR_TYPE)cls;
	 if (stpick(1)->type == tNULL)
	      {stswap(); stpop();}
	 else stsflink ();
	 putgrn(3);
	}
	}
	;

rule                    :
	 RULE lhs ASSIGN rhs
	{
	if (errorcount == 0)
	{
	 class(2);
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 ndput(trule);
	 sttop()->value1= (CLR_TYPE)cls;
	 if (stpick(1)->type == tNULL)
	      {stswap(); stpop();}
	 else stsflink ();
	 putgrn(4);
	}
	}
	;

I5opt                   :
	 /* empty */
	{ ndput (tNULL); }
	;

I5opt                   :
	 TAST astset
	;

I6opt                   :
	 /* empty */
	{ ndput (tNULL); }
	;

I6opt                   :
	 ATTRIBUTION attrset
	;

I7opt                   :
	 /* empty */
	{ ndput (tNULL); }
	;

I7opt                   :
	 CONDITION condset
	;

I8opt                   :
	 /* empty */
	{ ndput (tNULL); }
	;

I8opt                   :
	 VISIT visitset
	;

rule                    :
	 RULE lhs ASSIGN rhs I5opt I6opt I7opt I8opt END_RULE
	{
	if (errorcount == 0)
	{
	 class(6);
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 ndput(trule);
	 sttop()->value1= (CLR_TYPE)cls;
	 if (stpick(1)->type == tNULL)
	      {stswap(); stpop();}
	 else stsflink ();
	 putgrn(5);
	}
	}
	;

lhs                     :
	 phyla
	{
	if (errorcount == 0)
	{
	 putgrn(6);
	}
	}
	;

lhs                     :
	 node
	{
	if (errorcount == 0)
	{
	 putgrn(7);
	}
	}
	;

rhs                     :
	/* empty */
	{
	if (errorcount == 0)
	{
  ndput (tNULL);
	 putgrn(8);
	}
	}
	;

rhs                     :
	 repp
	{
	if (errorcount == 0)
	{
	 putgrn(9);
	}
	}
	;

rhs                     :
	 repa
	{
	if (errorcount == 0)
	{
	 putgrn(10);
	}
	}
	;

rhs                     :
	 repp_sep
	{
	if (errorcount == 0)
	{
	 putgrn(11);
	}
	}
	;

rhs                     :
	 repa_sep
	{
	if (errorcount == 0)
	{
	 putgrn(12);
	}
	}
	;

rhs                     :
	 secuence
	{
	if (errorcount == 0)
	{
	 putgrn(13);
	}
	}
	;

repp                    :
	 '[' lhs '+' ']'
	{
	if (errorcount == 0)
	{
	 if (sttype() == tNULL){
		class(0);
		stpop();
	 }
	 else class(1);
	 ndput(trepp);
	 sttop()->value1= (CLR_TYPE)cls;
	 if (cls == 1) stsflink ();
	 putgrn(14);
	}
	}
	;

repa                    :
	 '[' lhs '*' ']'
	{
	if (errorcount == 0)
	{
	 if (sttype() == tNULL){
		class(0);
		stpop();
	 }
	 else class(1);
	 ndput(trepa);
	 sttop()->value1= (CLR_TYPE)cls;
	 if (cls == 1) stsflink ();
	 putgrn(15);
	}
	}
	;

repp_sep                :
	 '[' lhs '+' terminal ']'
	{
	if (errorcount == 0)
	{
	 class(2);
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 ndput(trepp_sep);
	 sttop()->value1= (CLR_TYPE)cls;
	 if (stpick(1)->type == tNULL)
	      {stswap(); stpop();}
	 else stsflink ();
	 putgrn(16);
	}
	}
	;

repa_sep                :
	 '[' lhs '*' terminal ']'
	{
	if (errorcount == 0)
	{
	 class(2);
	 if (sttype() == tNULL) stpop();
	 else if (stpick(1)->type == tNULL) {stswap(); stpop();}
	 else stlrlink();
	 ndput(trepa_sep);
	 sttop()->value1= (CLR_TYPE)cls;
	 if (stpick(1)->type == tNULL)
	      {stswap(); stpop();}
	 else stsflink ();
	 putgrn(17);
	}
	}
	;

I9repp                  :
	 term
	;

I9repp                  :
	 I9repp term
	{ if (errorcount == 0) stlrlink (); }
	;

secuence                :
	 I9repp
	{
	if (errorcount == 0)
	{
	 class(1);
	 ndput(tsecuence);
	 sttop()->value1= (CLR_TYPE)cls;
	 if (stpick(1)->type == tNULL)
	      {stswap(); stpop();}
	 else stsflink ();
	 putgrn(18);
	}
	}
	;

term                    :
	 phyla
	{
	if (errorcount == 0)
	{
	 putgrn(19);
	}
	}
	;

term                    :
	 node
	{
	if (errorcount == 0)
	{
	 putgrn(20);
	}
	}
	;

term                    :
	 terminal
	{
	if (errorcount == 0)
	{
	 putgrn(21);
	}
	}
	;

term                    :
	 '[' option ']'
	{
	if (errorcount == 0)
	{
	 putgrn(22);
	}
	}
	;

I10repp                 :
	 term
	;

I10repp                 :
	 I10repp term
	{ if (errorcount == 0) stlrlink (); }
	;

option                  :
	 I10repp
	{
	if (errorcount == 0)
	{
	 class(1);
	 ndput(toption);
	 sttop()->value1= (CLR_TYPE)cls;
	 if (stpick(1)->type == tNULL)
	      {stswap(); stpop();}
	 else stsflink ();
	 putgrn(23);
	}
	}
	;

phyla                   :
	 LID
	{
	if (errorcount == 0)
	{
	 ndput(tphyla);
	 staclr (c_lexv, (CLR_TYPE)$1.name);
	 staclr (c_line, (CLR_TYPE)$1.line);
	 putgrn(24);
	}
	}
	;

node                    :
	 NODE
	{
	if (errorcount == 0)
	{
	 ndput(tnode);
	 staclr (c_lexv, (CLR_TYPE)$1.name);
	 staclr (c_line, (CLR_TYPE)$1.line);
	 putgrn(25);
	}
	}
	;

terminal                :
	 UID
	{
	if (errorcount == 0)
	{
	 ndput(tterminal);
	 staclr (c_lexv, (CLR_TYPE)$1.name);
	 staclr (c_line, (CLR_TYPE)$1.line);
	 putgrn(26);
	}
	}
	;

terminal                :
	 STRING
	{
	if (errorcount == 0)
	{
	 ndput(tterminal);
	 staclr (c_lexv, (CLR_TYPE)$1.name);
	 staclr (c_line, (CLR_TYPE)$1.line);
	 putgrn(27);
	}
	}
	;

lagh                    :
	 INCLUDE_LAG laginc END_INCLUDE
	{
	if (errorcount == 0)
	{
	 putgrn(28);
	}
	}
	;

ragh                    :
	 INCLUDE_RAG raginc END_INCLUDE
	{
	if (errorcount == 0)
	{
	 putgrn(29);
	}
	}
	;

I11repp                 :
	 block
	;

I11repp                 :
	 I11repp block
	{ if (errorcount == 0) stlrlink (); }
	;

laginc                  :
	 I11repp
	{
	if (errorcount == 0)
	{
  stpop ();
  ndput(tlaginc);
  staclr (c_block, (CLR_TYPE)block);
	 putgrn(30);
	}
	}
	;

I12repp                 :
	 block
	;

I12repp                 :
	 I12repp block
	{ if (errorcount == 0) stlrlink (); }
	;

raginc                  :
	 I12repp
	{
	if (errorcount == 0)
	{
  stpop ();
  ndput(traginc);
  staclr (c_block, (CLR_TYPE)block);
	 putgrn(31);
	}
	}
	;

attrs                   :
	 ATTRIBUTES attr_list
	{
	if (errorcount == 0)
	{
	 putgrn(32);
	}
	}
	;

I13repp                 :
	 block
	;

I13repp                 :
	 I13repp block
	{ if (errorcount == 0) stlrlink (); }
	;

attr_list               :
	 I13repp
	{
	if (errorcount == 0)
	{
  stpop ();
  ndput(tattr_list);
  staclr (c_block, (CLR_TYPE)block);
	 putgrn(33);
	}
	}
	;

I14repp                 :
	 block
	;

I14repp                 :
	 I14repp block
	{ if (errorcount == 0) stlrlink (); }
	;

astset                  :
	 I14repp
	{
	if (errorcount == 0)
	{
  stpop ();
  ndput(tastset);
  staclr (c_block, (CLR_TYPE)block);
	 putgrn(34);
	}
	}
	;

I15repp                 :
	 block
	;

I15repp                 :
	 I15repp block
	{ if (errorcount == 0) stlrlink (); }
	;

attrset                 :
	 I15repp
	{
	if (errorcount == 0)
	{
  stpop ();
  ndput(tattrset);
  staclr (c_block, (CLR_TYPE)block);
	 putgrn(35);
	}
	}
	;

I16repp                 :
	 block
	;

I16repp                 :
	 I16repp block
	{ if (errorcount == 0) stlrlink (); }
	;

condset                 :
	 I16repp
	{
	if (errorcount == 0)
	{
  stpop ();
  ndput(tcondset);
  staclr (c_block, (CLR_TYPE)block);
	 putgrn(36);
	}
	}
	;

I17repp                 :
	 block
	;

I17repp                 :
	 I17repp block
	{ if (errorcount == 0) stlrlink (); }
	;

visitset                :
	 I17repp
	{
	if (errorcount == 0)
	{
  stpop ();
  ndput(tvisitset);
  staclr (c_block, (CLR_TYPE)block);
	 putgrn(37);
	}
	}
	;

block                   :
	 LID
	{
	if (errorcount == 0)
	{
	 ndput(tNULL);
	 putgrn(38);
	}
	}
	;

block                   :
	 ASSIGN
	{
	if (errorcount == 0)
	{
	 ndput(tNULL);
	 putgrn(39);
	}
	}
	;

block                   :
	 NODE
	{
	if (errorcount == 0)
	{
	 ndput(tNULL);
	 putgrn(40);
	}
	}
	;

block                   :
	 UID
	{
	if (errorcount == 0)
	{
	 ndput(tNULL);
	 putgrn(41);
	}
	}
	;

block                   :
	 STRING
	{
	if (errorcount == 0)
	{
	 ndput(tNULL);
	 putgrn(42);
	}
	}
	;

block                   :
	 CHAR
	{
	if (errorcount == 0)
	{
	 ndput(tNULL);
	 putgrn(43);
	}
	}
	;

block                   :
	 ID
	{
	if (errorcount == 0)
	{
	 ndput(tNULL);
	 putgrn(44);
	}
	}
	;

block                   :
	 '['
	{
	if (errorcount == 0)
	{
	 ndput(tNULL);
	 putgrn(45);
	}
	}
	;

block                   :
	 ']'
	{
	if (errorcount == 0)
	{
	 ndput(tNULL);
	 putgrn(46);
	}
	}
	;

block                   :
	 '+'
	{
	if (errorcount == 0)
	{
	 ndput(tNULL);
	 putgrn(47);
	}
	}
	;

block                   :
	 '*'
	{
	if (errorcount == 0)
	{
	 ndput(tNULL);
	 putgrn(48);
	}
	}
	;

%%

PRIVATE int
yylex ()
{
    token *tk;

   tk = gtk ();
   yylval = tk->yylval;
   return tk->type;
}

PUBLIC TNODE*
bast ()
{
   gl= ITcreate (4, 2, 1);
   gn= NULL;
   (void)yyparse();
   if (gn != NULL) gn->value0= (CLR_TYPE)IAT_IT_add(gl, grnl);
   return sttop();
}
