


%{
/* Achtung, dieser Parser vergeudet speicher in rauhen megen ...*/
    /* 25-09-94 * rewritten */
    /* 30-09-94 * shortened */



/*
	> BISON -y -d Yacc.y
	> Dcc y.tab.c -mD -c
*/


#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "node.h"

#include "y.tab.h"

#ifdef __SASC
#define alloca malloc
#else
#include <alloca.h>
#endif

#define PTR void *



int yyerror (const char *x);
int yyparse (void);
int yylex   (void);
static void __yy_bcopy(char *, char *, int);

int errors = 0;
extern int   lineno;
extern char *filename;
#define errorout(text) fprintf (stderr, "`%s',%d: %s\n", filename, lineno, text, ++errors)

%}

/* signs */
%token RBRA	/* %{ */
%token EBRA	/* %[ */
%token RKET	/* %} */
%token EKET	/* %[ */
%token ASS	/* =  */
%token SEMI	/* ;  */
%token ADD	/* += */

%token SBRA	/* }  */ /* added 04-11-94 */
%token SKET	/* {  */
%token SSBRA	/* {{ */
%token SSKET	/* }} */
%token KOMMA	/* ,  */

/* qualifier */
%token PROJECT
%token GLOBAL
%token CONST
%token HIDDEN
%token INTERNAL
%token GENERIC
%token TEMPORARY

/* fixed names */
%token TYPES
%token NEEDED
%token GENTYPE
%token DEFAULT
%token HELP

/* free text */
%token LABEL
%token VALUE

/* LEX - communcation */
%token NEWFILE
%token BLOCKSTART

%start parts_list

%%

parts_list : BLOCKSTART assignment_list parts_list
	   |
	   ;

assignment_list : /*  */
		| base_ass assignment_list
		;

base_ass : type base_ass
	 |	assignment
	 ;

type : CONST	    { NODE_access (CA_CONST);   } /* benutzer kann nur lesen */
     | HIDDEN	    { NODE_access (CA_HIDDEN);  } /* benutzer kann nur schreiben */
     | INTERNAL     { NODE_access (CA_INTERNAL);} /* dem benutzer nicht zugaenglich */

     | GENERIC	    { NODE_spc	(CS_GENERIC);   } /* muss erzeugt werden */
     | GLOBAL	    { NODE_spc	(CS_GLOBAL);    } /* globales object */
     | PROJECT	    { NODE_spc	(CS_PROJECT);   } /* kann bei jedem project variieren */
     | TEMPORARY    { NODE_spc	(CS_TEMPORARY); } /* kann unzugaenglich sein */

     | GENTYPE	    { NODE_type ((PTR)$1);      } /* generischer Typ */
     ;

assignment : lval {NODE_PUSH((PTR)$1, 1);} ASS {NODE_CLEAR();} body { NODE_POP(); } /* Assignment - vorhandenen Inhalt loeschen */
	   | lval {NODE_PUSH((PTR)$1, 1);} ADD                 body { NODE_POP(); } /* Append  */
	   | lval {NODE_PUSH((PTR)$1, 1);} SEMI                     { NODE_POP(); } /* Just name it ... */
	   | SEMI
	/* | error { errorout ("Fehlerhaftes Assignment"); } SEMI */
	   ;

body : RBRA  assignment_list  RKET
     | SBRA  assignment_list  SKET
     | SSBRA  VALUE	     SSKET { NODE_TEXT((PTR)$2); }
     | EBRA   VALUE	      EKET { NODE_TEXT((PTR)$2); }
     | lval   SEMI		   { NODE_TEXT((PTR)$1); }
     | VALUE   /* "%% ...\n" */    { NODE_TEXT((PTR)$1); }
  /* | error  { errorout ("Fehlerhafte Rechte Seite"); } SEMI */
     ;

lval : DEFAULT { $$ = 0;  }
     | TYPES   { $$ = 1;  }
     | NEEDED  { $$ = 2;  }
     | LABEL   { $$ = $1; } /* string ist von LEX.l dupliziert worden! */
     | HELP    { $$ = $1; } /* string ist von LEX.l dupliziert worden! */
  /* | error { errorout ("Fehlerhafte Linke Seite"); } SEMI */
     ;

%%





int yyerror (const char *x)
{
    extern int lineno;
    extern void NODE_TREE(void *, void *);

    fprintf (stderr, "%s\n (file `%s', line %ld)\n", x, filename, lineno);
    {
	char *comment = NULL;
	switch (yychar) {
#define tk(x)    case x: comment =  #x; break;
#define tkl(x,n) case x: comment =   n; break;
	tk( EOF )
	tkl( RBRA, "openbracket" )
	tkl( EBRA, "openbracket" )
	tkl( RKET, "closebracket" )
	tkl( EKET, "closebracket" )
	tkl( ASS,  "assignmentoperator" )
	tkl( SEMI, "semicolon" )
	tkl( ADD,  "addoperator" )
	tk( PROJECT )
	tk( GLOBAL )
	tk( CONST )
	tk( HIDDEN )
	tk( INTERNAL )
	tk( GENERIC )
	tk( TEMPORARY )
	tk( GENTYPE )
	tk( TYPES )
	tk( NEEDED )
	tk( DEFAULT )
	tk( LABEL )
	tk( VALUE )
	tk( NEWFILE )
	tk( BLOCKSTART )
	} /* switch */
	if (comment)
	    printf ("probably unexpected %s %s\n", comment, (yychar == LABEL)? yylval: "");
    }
    NODE_TREE(NULL, NULL);
    // exit (-1);
    return 0;
} /* yyerror */

