%{
#include <stdio.h>
typedef char *CHAR_PTR;
#define YYSTYPE	CHAR_PTR
#define BLOCK_MARK	0
#define INT_DEC		1
#define CHAR_DEC	2
#define FLOAT_DEC	3
#define MAX_ENTRIES	100

struct symtab_type {
	int type;
	char name[80];
	int size;
};

int dec_type, symtop;
struct symtab_type symtab[MAX_ENTRIES];
%}
%token ID FLOAT INT MAIN CHAR CONST
%start program
%%

	program:
		MAIN '(' ')' block ;

	block:
		'{' { push_symbol(BLOCK_MARK, "*undefined*", 0); }
		dec_list { print_symtab(); } block_1 ID '=' CONST ';'
		'}' { while (pop_symbol()); print_symtab(); } ;

	block_1:
		|
		block ;

	dec_list:
		dec ';' |
		dec_list dec ';' ;

	type:
		INT { dec_type = INT_DEC; } |
		CHAR { dec_type = CHAR_DEC; } |
		FLOAT { dec_type = FLOAT_DEC; } ;

	dec:
		type id_list ;

	id_list:
		ID { push_symbol(dec_type, $1, 0); } |
		ID ',' id_list { push_symbol(dec_type, $1, 0); } |
		ID '[' CONST ']' { push_symbol(dec_type, $1, atoi($3)); } |
		ID '[' CONST ']' ',' id_list
			{ push_symbol(dec_type, $1, atoi($3)); } ;

%%
main()
{
	init_symtab();
	if (yyparse()) {
		printf("Unsuccessful parse.\n");
		return(1);
	}
	else {
		printf("Parse was successful.\n");
		return(0);
	}
}

init_symtab()
{
	int i;

	for (i = 0; i < MAX_ENTRIES; i++) {
		symtab[i].type = BLOCK_MARK;
		strcpy(symtab[i].name, "*undefined*");
		symtab[i].size = 0;
	}
	symtop = 0;
}

print_symtab()
{
	int i;

	printf("****** Start of Symbol Table ******\n");
	for (i = symtop; i > 0; i--)
		if (symtab[i].type == BLOCK_MARK)
			printf("=====> --- Block  Marker --- <=====\n");
		else {
			printf("       ");
			switch (symtab[i].type) {
				case INT_DEC:	printf("int     "); break;
				case CHAR_DEC:	printf("char    "); break;
				case FLOAT_DEC:	printf("float   "); break;
				default:	printf("Error!\n");
			}
			printf("%-15s", symtab[i].name);
			if (symtab[i].size > 0)
				printf("%d", symtab[i].size);
			printf("\n");
		}
	printf("****** End of Symbol Table   ******\n\n");
}

push_symbol(type, name, size)
int type, size;
char *name;
{
	if (symtop < MAX_ENTRIES - 1) {
		symtop++;
		symtab[symtop].type = type;
		strcpy(symtab[symtop].name, name);
		symtab[symtop].size = size;
	}
	else
		printf("Error- Stack overflow\n");
}

pop_symbol()
{
	int type = 0;

	if (symtop < 1)
		printf("Error- Stack underflow\n");
	else {
		type = symtab[symtop].type;
		symtop--;
	}
	return(type);
}
