//parser for circuit description files *.d //daan hogema & paul wiegerynck TUG (c) 14 nov 2002 #ifndef D_PARSE_INCLUDED #include #include #include "string.h" #include "d_var.h" int d_parse_isnumber(int a) {//checks if character is number if(a>='0'&&a<='9')return(1); return(0); } int d_parse_isoperator(int a) {//checks if character is an operator character switch(a) { case'+':case'-':case'*':case'/':case'<':case'>':case'?':case':': case'!':case'=':case'^':case'&':case'|':case'%': return(a);break; } return(0); } int d_parse_iswhitespace(int a) { if(a>0&&a<=' ')return(1); return(0); } /////////////////////////////file preprocessor//////////////////////////// FILE *dp_fp=NULL; int dp_linenumber; char d_parse_getchar(void) { int i; char h[20]; int dp_addtoken(); //predeclaration i=fgetc(dp_fp); if(i==-1)return(0); if(i=='\n') { dp_linenumber++; sprintf(h,"\n%d",dp_linenumber); dp_addtoken(h); } if(i==0)i=' '; return((char)i); } #define d_parse_GET1() S_cfifo(d_parse_get1buffer,&d_parse_get1) #define D_PARSE_STRING (128) //bewere of signed chars!!! (128!=-128) char d_parse_stringbuffer[StringSize]=""; char d_parse_get1buffer[StringSize]; char d_parse_previous=' '; void d_parse_get1(void) { // raw file reading: // removes comments // precedes special tokens with' ' int i; i=d_parse_getchar(); if(!i) { return; } if(i=='/') //remove comments { i=d_parse_getchar(); if(i=='/') { while(i=d_parse_getchar(),i&&i!='\n'); } //comment ends on newline else if(i=='*') { char previous=0; while(i=d_parse_getchar()) { if(i=='/'&&previous=='*'){i=' ';break;} previous=i; } if(i==0)dd_syntax_expected("terminating */","end of file"); } else { S_cappend(d_parse_get1buffer,' ',StringSize); S_cappend(d_parse_get1buffer,'/',StringSize); d_parse_previous='/'; } } switch(i) //surround special tokens with space { case'}'://just for safety add ending ; of last statement in list S_cappend(d_parse_get1buffer,' ',StringSize); S_cappend(d_parse_get1buffer,';',StringSize); case'{':case';': case'(':case')':case',': S_cappend(d_parse_get1buffer,' ',StringSize); S_cappend(d_parse_get1buffer,i,StringSize); S_cappend(d_parse_get1buffer,' ',StringSize); d_parse_previous=' ';return; break; } //check for string constant - it will be temporarily stored if(i=='"') { S_clear(d_parse_stringbuffer); //S_cappend(d_parse_stringbuffer,D_PARSE_STRING,StringSize); //explicit string is coded by leading 128 while(i=d_parse_getchar(),i&&i!='"') { int k; opnieuw: if(i=='"')break; if(i=='\\') { i=d_parse_getchar(); switch(i) { case'\\':i='\\';break; case'n': i='\n';break; case't': i='\t';break; case'r': i='\r';break; case'"': i='"'; break; default: if(d_parse_isnumber(i)) { k=i-'0'; i=d_parse_getchar(); if(d_parse_isnumber(i)){k=8*k+i-'0';} else{S_cappend(d_parse_stringbuffer,k,StringSize); goto opnieuw;} i=d_parse_getchar(); if(d_parse_isnumber(i)){k=8*k+i-'0';} else{S_cappend(d_parse_stringbuffer,k,StringSize); goto opnieuw;} i=k; } break; } } S_cappend(d_parse_stringbuffer,i,StringSize); } S_cappend(d_parse_get1buffer,' ',StringSize); S_cappend(d_parse_get1buffer,D_PARSE_STRING,StringSize); d_parse_previous=' '; i=' '; } //isolation of operators from text if(d_parse_isoperator(i)) { int j; j=d_parse_previous; if(!( (j=='>' && i=='=') || (j=='<' && i=='=') || (j=='!' && i=='=') || (j=='=' && i=='=') || (j=='&' && i=='&') || (j=='|' && i=='|') || (j=='/' && i=='%') || (j=='&' && i=='*') )) S_cappend(d_parse_get1buffer,' ',StringSize); } else if(d_parse_isoperator(d_parse_previous)) { S_cappend(d_parse_get1buffer,' ',StringSize); } d_parse_previous=i; S_cappend(d_parse_get1buffer,i,StringSize); } char d_parse_token(char *s) { //gets next token from stream //skip white space unsigned char c; S_clear(s); while(c=d_parse_GET1() , d_parse_iswhitespace(c)); //check for string if(c==D_PARSE_STRING) { Copy(d_parse_stringbuffer,s);return(s[0]);} //get string or token do { S_cappend(s,c,StringSize); c=d_parse_GET1(); } while(c && !d_parse_iswhitespace(c)); return(s[0]); } ////////////////////// token buffers ////////////////////// struct dp_tokenbufferstruct //one per include file read { char *fn; struct S_tokenbufferstruct t; }; struct dp_tokenbufferstruct *tokenbuffer; //struct dp_tokenbufferstruct *actualtokenbuffer; int actualtbn; int tokenbuffer_number=0,tokenbuffer_arraysize=0; void dp_addtoken(char *token) { //add token to actualtokenbuffer S_addtoken(token, &(tokenbuffer[actualtbn].t)); } char *dp_tokenbuffer_filename(char *fn) { //attempts to open and buffer file fn //returns explicative string if fails char s[StringSize]; int i; for(i=0;i=0;i--) { int atb; //actual tokenbuffer char *hulps; atb=dp_stack[dp_level].tbn; hulps=tokenbuffer[atb].t.token[i]; if(hulps[0]=='\n'){line=atoi(hulps+1);break;} } return(line); } int d_parse_fileline(void) { //updates variables file_name and file_line int atb; if(dp_level<0)return(0); atb=dp_stack[dp_level].tbn; d_var_push("file.name",tokenbuffer[atb].fn); d_var_push_int("file.line",d_parse_line()); return(1); } #define d_parse_filename() (tokenbuffer[dp_stack[dp_level].tbn].fn) // returns actual filename int d_parse_tokenpos(void) {//returns actual tokenposition (next!) in file being read return(dp_stack[dp_level].actual); } char *d_parse_init(char *fn,int from) //causes tokenlist fn to be read from token from //add this in the include file stack //fn equal NULL means take filename that is actually being read //from negative means: take actual position in actual file //returns error explaining string if fails { int i,atb; char *e; dp_level++; if(dp_level>=DP_LEVELMAX)return("max nesting depth exceeded"); if(from<0) { from=dp_stack[dp_level-1].actual; } //printf("(init%d:%d)",dp_level,from); atb=dp_stack[dp_level-1].tbn; if(fn==NULL)fn=tokenbuffer[atb].fn; e=dp_tokenbuffer_filename(fn); if(e)return(e); dp_stack[dp_level].tbn=actualtbn; dp_stack[dp_level].actual=from; //actual is the # of the token to be read next d_parse_fileline(); return(0); } void d_parse_close(void) { //steps down one level in the include file stack dp_level--; if(dp_level<0)return; actualtbn=dp_stack[dp_level].tbn; //printf("(close%d:%d)",dp_level,dp_stack[dp_level].actual); d_parse_fileline(); }; ////////////////////////parser////////////////////////////////// char d_parse_string[StringSize],d_parse_char; int d_parse_previewed=0; char d_parse_next(void) //to be added: distinction between reserved tokens and the same between "" { int atb; //return previewed if preview was asked if(d_parse_previewed){d_parse_previewed=0;return(d_parse_char);} //gets next token from stream opnieuw: atb=dp_stack[dp_level].tbn; if(dp_stack[dp_level].actual>=tokenbuffer[atb].t.number) { S_clear(d_parse_string); d_parse_char='\0'; return(0); //end of file at file being read } S_copy(tokenbuffer[atb].t.token[dp_stack[dp_level].actual++], StringSize,d_parse_string); if(d_parse_string[0]=='\n')goto opnieuw; //token beginning with \n are line counters d_parse_char=d_parse_string[0]; //printf("(%s)",d_parse_string,dp_stack[dp_level].actual); fflush(stdout); return(d_parse_char); } char d_parse_preview(void) {//gets next token from stream without advancing in stream if(d_parse_previewed){d_parse_previewed=1;return(d_parse_char);} d_parse_next(); d_parse_previewed=1; return(d_parse_char); } #define D_PARSE_INCLUDED #endif