#include <stdio.h>
#include <ctype.h>
#include "stable.h"
#include "cgram.h"
#include "tokens.h"

int nspace;	/* # of bytes left in block */
char *spacep;	/* start of free space block */
SYMB *symbs;	/* head offree symb list */
SYMB *symbols;

char *calloc(int,int);
SYMB *
getsymb(char *str){
	SYMB *sp;
	int i;
	if((sp=symbs)==0){
		symbs=sp=(SYMB *)calloc(STSIZE,sizeof(SYMB));
		for(i=STSIZE-1 ; i>0 ; i--){
			sp->left= &sp[1]; /* initialize as a link list */
			sp=sp->left;
			}
		sp=symbs;
		}
	symbs=symbs->left;
	sp->left=0;
	i=strlen(str);
	if(i>nspace){
		spacep=calloc(1,1024);
		nspace=1024;
		}
	strcpy(spacep,str);
	sp->name=spacep;
	spacep+=i;
	nspace-=i;
	return(sp);
	}
SYMB **symtp;
SYMB *
find(SYMB *p, char *cp){
	int i;
	while(1){
		i=strcmp(cp,p->name);
		if(i==0)return(p);
		symtp= (i<0 ? &p->left : &p->right);
		if(*symtp == (SYMB *)0)return(0);
		p= *symtp;
		}
	}
char *kwords[] = { "if","int","char","float","else","continue","case",
	"return","while","break","for","switch","default","do",0};
int kwordn[] = { IF,INT,CHAR,FLOAT,ELSE,CONTINUE,CASE,
	RETURN,WHILE,BREAK,FOR,SWITCH,DEFAULT,DO,0};
char *ops="=<>+-&|!*/%^~?:,;()[]{}";
int retval[] = {ASG,LT,GT,PLUS,MINUS,BAND,BOR,LNOT,AST,DIV,MOD,BXOR,
	BNOT,QUEST,COLON,COMMA,SEMI,LPAR,RPAR,LBRK,RBRK,LBRC,RBRC};
int retdval[] = {EQU,SHL,SHR,INC,DEC,LAND,LOR};
int lineno=1;
yylex(){
	char c,*cp;
	int i;
	SYMB *sp;
	char temp[80];
	int retv;
	while(isspace(c=getchar()))
		if(c=='\n')lineno++;
	if(c==EOF)return (EOF);
	i=((int)strchr(ops,c))-(int)ops;
	if(i>=0){
		yylval=retval[i];
		if(i>11)return(yylval);
		c=getchar();
		if((c==ops[i]) && (i<7)){
			yylval=retdval[i];
			if(i!=1 && i!=2)return(yylval);
			c=getchar();
			}
		if(c!='='){
			ungetc(c,stdin);
			return(yylval);
			}
		return(++yylval);
		}
	if(isalpha(c)){
		cp=temp;
		*cp++ =c;
		while(isalnum(c=getchar()) || c=='_') *cp++ = c;
		ungetc(c,stdin);
		*cp=0;
		for(i=0 ; kwords[i] ; i++)
			if(!strcmp(temp,kwords[i]))return(kwordn[i]);
		symtp= &symbols;
		sp=(SYMB *)0;
		if(*symtp)sp=find(*symtp,temp);
		if(sp==(SYMB *)0) *symtp=sp=getsymb(temp);
		yylval=(int)sp;
		return(ID);
		}
	}
#if 0
int yylval;
main(){
	int i;
	while((i=yylex())!=EOF){
		if(i==0)continue;
		printf("%s",tokens[i]);
		switch(i){
		case CONST:
			printf(" - %d\n",yylval);
			break;
		case STR:
		case ID:
			printf(" - %s\n",((SYMB *)yylval)->name);
			break;
		default:
			printf("\n");
			break;
			}
		}
	}
yyerror(char *str){
	fprintf(stderr,"Error: %s on line %d\n",str,lineno);
	}
#endif

