home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************/
- /* Lexik **/
- /*********************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "t_lex.h" /* header */
-
- char *T_TOKENSET[]=TOKENSET; /* the tokens */
- int T_TOKENTYP[]=TOKENTYP; /* type of tokens */
-
- static long t_lexflags=0L; /* Lex-Flags */
-
- LEX t_lexx; /* global hand-over */
- /* variable */
- /* use pointer only */
-
- char t_wert[LEX_MAXWERT]; /* char memory */
- int t_lcounter; /* line counter */
- int t_pcounter; /* char pointer */
- char t_actstr[LEX_MAXWERT]; /* chars already read */
- int t_err; /* error no. */
-
- /* function for setting filepointer and flags */
- /* returns current filepointer, if fep==NULL; */
- /* else sets and returns current filepointer */
- FILE *t_setfep(FILE *fep, long flags)
- {
- static FILE *cur_fep=NULL;
- int i,j;
- char *s;
-
- for(i=0;*T_TOKENSET[i];i++)
- for(j=0,s=T_TOKENSET[i];j<strlen(s);j++)
- *(s+j)=(char)toupper(*(s+j));
-
-
- if(fep!=NULL) cur_fep=fep;
- t_lexflags=flags;
- return(cur_fep);
- }
-
-
- /* Lex-function: parameter: fep: pointer to readable file */
- /* force: force expected type */
- /* use "t_lex(fep,NO_FORCE)" for unforced lex */
- /* returns: pointer to t_lex or NULL, */
- /* if syntax error */
- LEX *t_lex(FILE *fep, int force)
- #define uget {ungetc(c,fep);t_pcounter-=1;\
- if(ct2 && !isspace(c)) t_actstr[--ct2]=0;}
- {
- int c,i,d,k,typ,space;
- long n,offs;
- double r;
- static FILE *fps=NULL;
- static int ct,ct2;
- static int lpushf=0;
- T_NODE *tnode;
- LEX *lex;
-
- if(force==LEX_PUSH) { lpushf=1; return(&t_lexx); }
- if(lpushf) { lpushf-=1; return(&t_lexx); }
-
- t_lexx.typ=EOLX; t_lexx.wert.n.i=0; t_lexx.wert.c="";
- t_err=-1; t_actstr[0]=(char)0;
- ct2=0;
-
- if(fep==NULL) fep=t_setfep(NULL,t_lexflags);
- if(fep==NULL) return((LEX *)NULL);
- if(fps!=fep)
- {
- t_lcounter=t_pcounter=1;
- fps=fep;
- }
- t_err=0;
-
- if(force!=NO_FORCE) switch(force)
- {
- case LEX_SPACE:
- t_lexx.typ=LEX_SPACE;
- break;
- case LEX_RCHAR:
- t_lexx.typ=LEX_RCHAR;
- break;
- default: lex=t_lex(fep,NO_FORCE);
- if((lex==(LEX *)NULL) || (lex->typ==force)) return(lex);
- t_err=3;
- return((LEX *)NULL);
- }
-
-
- for(space=0;;)
- {
- c=getc(fep);
-
- if(isprint(c))
- {
- t_pcounter+=1;
- if(!isspace(c) && t_lexx.typ!=LEX_COM && ct2<LEX_MAXWERT-1)
- {
- t_actstr[ct2++]=(char)c;
- t_actstr[ct2]=(char)0;
- }
- }
- if(c=='\n') /* Line end */
- {
- t_pcounter=1;
- if(t_lexflags&1) t_lcounter=1;
- else t_lcounter+=1;
- }
-
- switch(t_lexx.typ)
- {
- case LEX_UNDEF:
- case LEX_SPACE:
- case EOLX:
- if(c==EOF)
- {
- t_lexx.typ=EOLX; t_lexx.wert.n.i=0; t_lexx.wert.c="";
- return (&t_lexx);
- }
- if((t_lexflags&1) && (c=='\n'))
- {
- t_lexx.typ=EOLN; return(&t_lexx);
- }
- if(isspace(c) || !isprint(c)) { space=1; continue; }
- /* Space elim. */
- if(c=='/')
- {
- d=getc(fep);
- if(d!='*') ungetc(d,fep);
- else
- {
- typ=t_lexx.typ;
- t_lexx.typ=LEX_COM;
- t_err=2;
- space=1;
- continue;
- }
- }
-
- if(t_lexx.typ==LEX_SPACE)
- {
- uget;
- if(space) return(&t_lexx);
- else return((LEX *)NULL);
- }
-
- if(isdigit(c) || (force==ZAHL) || (force==REAL))
- { /* Zahl */
- uget;
- offs=ftell(fep);
- if(force==ZAHL) k=fscanf(fep,"%i",&n);
- else if(force==REAL) k=fscanf(fep,"%lG",&r);
- else
- {
- k=fscanf(fep,"%lG",&r);
- if((r> 32767) ||
- (r<-32767) ||
- ((double)((int)r)!=r)) force=REAL;
- else
- {
- n=(int)(r);
- force=ZAHL;
- }
- }
- offs=ftell(fep)-offs; t_pcounter+=(int)(offs);
- if(!k || (k==EOF)) { t_err=4; return((LEX *)NULL); }
- if(force==ZAHL)
- {
- t_lexx.wert.n.i=(int)n;
- sprintf(t_wert,"%d",(int)n);
- }
- else
- {
- t_lexx.wert.n.r=r;
- sprintf(t_wert,"%G",r);
- }
- t_lexx.typ=force;
- return(&t_lexx);
- }
-
- if(strchr(CHRSET,c)) /* Einzelzeichen */
- {
- t_lexx.wert.n.i=t_lexx.typ=c;
- return(&t_lexx);
- }
-
- if(isalpha(c)) /* Bezeichner */
- {
- t_lexx.typ=KW;
- t_lexx.wert.c=t_wert;
- t_wert[0]=(char)c;
- t_wert[1]=0;
- ct=1;
- continue;
- }
- t_lexx.typ=LEX_UNDEF;
- t_err=-1;
- continue;
-
- case LEX_COM:
- if(c==EOF) { t_err=2; return((LEX *)NULL); }
- if(c=='*')
- {
- d=getc(fep);
- if(d!='/') ungetc(d,fep);
- else
- {
- if((typ==LEX_SPACE) || (typ==LEX_UNDEF))
- t_lexx.typ=typ;
- else t_lexx.typ=EOLX;
- t_pcounter+=1;
- t_err=-1;
- continue;
- }
- }
- continue;
-
- case KW: if(isalpha(c)||isdigit(c)||c=='_')
- {
- t_wert[ct++]=(char)c;
- if(ct==LEX_MAXWERT)
- { t_err=1; return((LEX *)NULL); }
- t_wert[ct]=0;
- continue;
- }
- else
- {
- if(t_lexflags&2)
- for(i=0;i<strlen(t_wert);i++)
- t_wert[i]=(char) toupper(t_wert[i]);
- t_wert[ct++]=(char)c;
- t_wert[ct]=(char)0;
- if(ct>=LEX_MAXWERT)
- { t_err=1; return((LEX *)NULL); }
-
- /*** Check including last char */
- for(i=0;*T_TOKENSET[i] &&
- strcmp(T_TOKENSET[i],t_wert) &&
- !isspace(c);i++);
- if(!(*T_TOKENSET[i]) || isspace(c))
- { /*** Nothing found -> check last char alone */
- for(i=0;*T_TOKENSET[i] &&
- (*T_TOKENSET[i]!=(char)c) &&
- !isspace(c);i++);
- if(!(*T_TOKENSET[i]) || isspace(c))
- { /*** Nothing found -> check without last char */
- t_wert[--ct]=(char)0; uget;
- for(i=0;*T_TOKENSET[i]&&strcmp(T_TOKENSET[i],t_wert);i++);
- }
- }
-
- t_lexx.typ=T_TOKENTYP[i];
- if((tnode=t_symtable(t_wert))==(T_NODE *)NULL)
- { t_err=5; return((LEX *)NULL); }
- t_lexx.wert.n.i=tnode->n;
- return(&t_lexx);
- }
-
- case LEX_RCHAR:
- if(c!='\\')
- {
- t_lexx.wert.n.i=c;
- if(c==EOF) t_lexx.typ=EOLX;
- return(&t_lexx);
- }
- else t_lexx.typ='\\';
- continue;
- case '\\':
- t_lexx.wert.n.i=c;
- if(c==EOF) t_lexx.typ=EOLX;
- return(&t_lexx);
- }
- }
- }
-
-
- /********* String for error message *********************************/
- char t_msg[128+LEX_MAXWERT];
- char *t_pos(void)
- {
- sprintf(t_msg,"Text line %d, pos. %d, read '%.20s': ",
- t_lcounter, t_pcounter, *t_actstr ? t_actstr : t_wert);
- switch(t_err)
- {
- case 0: strcat(t_msg,"OK. ");
- break;
- case 1: strcat(t_msg,"Buffer too small. ");
- break;
- case 2: strcat(t_msg,"In comment. ");
- break;
- case 3: sprintf(t_msg+strlen(t_msg),
- "Unexpected type %d (value %d, string \"%s\") found.",
- t_lexx.typ,t_lexx.wert.n.i,t_lexx.wert.c);
- case 4: strcat(t_msg,"Could not scan integer/real number.");
- break;
- case 5: strcat(t_msg,"Symbol table error.");
- break;
- default: strcat(t_msg,"?");
- break;
- }
- return(t_msg);
- }
-
-
-
- static T_NODE *t_root=(T_NODE *)NULL;
- static int nn=1;
- static T_NODE *t_list[1024];
-
-
- /* simple symbol table manager, one symbol table only */
- /* input: string, returns: T_NODE, NULL on error */
- /* table contains any KW */
-
- T_NODE *t_symtable(char *str)
- {
- static T_NODE *last=(T_NODE *)NULL;
- T_NODE *next, *current;
- int v;
-
- next=t_root;
- while(next!=(T_NODE *)NULL)
- {
- current=next;
- v=strcmp(next->s,str);
- if(v==0) return(next);
- else if(v<0) next=next->l;
- else next=next->r;
- }
- if((next=(T_NODE *)malloc(sizeof(T_NODE)))==(T_NODE *)NULL)
- return((T_NODE *)NULL);
- next->l=next->r=next->nl=next->a=(T_NODE *)NULL;
- t_list[nn-1]=next;
- next->n=nn++;
-
- if(last!=(T_NODE *)NULL) last->nl=next;
- last=next;
-
- next->p=(void *)NULL;
- next->c=0;
- if((next->s=(char *)malloc(strlen(str)+1))==(char *)NULL)
- return((T_NODE *)NULL);
- strcpy(next->s,str);
-
- if(t_root!=(T_NODE *)NULL)
- {
- if(v==0) return(0);
- else if(v<0) current->l=next;
- else current->r=next;
- }
- else t_root=next;
- return(next);
- }
-
- /* finds symbol n, returns t_node */
- T_NODE *t_symfind(int n)
- {
- int i;
- T_NODE *tnode;
-
- if(n<1 || n>=nn) return((T_NODE *)NULL);
- if(n<=1024) return(t_list[n-1]);
- for(tnode=t_list[1023],i=1024;(i<n)&&(tnode!=(T_NODE *)NULL);i++)
- tnode=tnode->nl;
- if((i==n) && (tnode!=(T_NODE *)NULL)) return(tnode);
- return((T_NODE *)NULL);
- }
-
- /* performs action on all items with code */
- /* if code <0, performs action on all items */
- /* action will get T_NODE */
- /* returns: sum of action's returns */
- int t_symwalk(int code, int (*action)(T_NODE *))
- {
- T_NODE *t_node;
- int sum;
-
- for(t_node=t_root,sum=0;t_node!=(T_NODE *)NULL;t_node=t_node->nl)
- if((t_node->c==code) || (code<0))
- sum+=(*action)(t_node);
-
- return(sum);
- }
- /* performs action on tnodes and deletes any tnode and any tnode->p */
- /* returns number of deleted nodes */
- int t_symdel(void (*action)(T_NODE *))
- {
- T_NODE *t_node, *t_old;
- int n;
-
- t_node=t_root; n=0;
- while(t_node!=(T_NODE *)NULL)
- {
- t_old=t_node;
- t_node=t_node->nl;
- (*action)(t_old);
- if(t_old->p!=(void *)NULL) free(t_old->p);
- free(t_old);
- n+=1;
- }
- t_root=(T_NODE *)NULL; nn=1;
- return(n);
- }
-
- /* returns number for tokentyp n */
- int t_tokenval(int n)
- {
- int i;
- for(i=0;(T_TOKENTYP[i]!=n) && *(T_TOKENSET[i]);i++);
- return(i);
- }
-
- /* returns string for tokentyp n */
- char *t_tokenstr(int n)
- {
- int i;
- for(i=0;(T_TOKENTYP[i]!=n) && *(T_TOKENSET[i]);i++);
- return(T_TOKENSET[i]);
- }
-
- /* returns tokentyp for number n */
- int t_valtoken(int n)
- {
- int i;
- for(i=0;(i<n) && *(T_TOKENSET[i]);i++);
- return(T_TOKENTYP[i]);
- }
-
- /* returns string for number n */
- char *t_valstr(int n)
- {
- int i;
- for(i=0;(i<n) && *(T_TOKENSET[i]);i++);
- return(T_TOKENSET[i]);
- }
-