/* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ #ifndef NORSCID static char rcs_lex[] = "$Id$" ; #endif /* This file contains the new lexical analizer */ typedef struct { char *name; int token, classvalue,length; } Key; Key keywords [] ={ "abs", FUNCTION, ABSSYM, 0, "and", ANDSYM, ANDSYM, 0, "asc", FUNCTION, ASCSYM, 0, "as", ASSYM, 0, 0, "atn", FUNCTION, ATNSYM, 0, "auto", ILLEGAL, 0, 0, "base", BASESYM, 0, 0, "call", CALLSYM, 0, 0, "cdbl", FUNCTION, CDBLSYM, 0, "chain", ILLEGAL, 0, 0, "chr", FUNCTION, CHRSYM, 0, "cint", FUNCTION, CINTSYM, 0, "clear", CLEARSYM, 0, 0, "cload", ILLEGAL, 0, 0, "close", CLOSESYM, 0, 0, "common", ILLEGAL, 0, 0, "cont", ILLEGAL, 0, 0, "cos", FUNCTION, COSSYM, 0, "csng", FUNCTION, CSNGSYM, 0, "csave", ILLEGAL, 0, 0, "cvi", FUNCTION, CVISYM, 0, "cvs", FUNCTION, CVSSYM, 0, "cvd", FUNCTION, CVDSYM, 0, "data", DATASYM, 0, 0, "defint", DEFINTSYM, 0, 0, "defsng", DEFSNGSYM, 0, 0, "defdbl", DEFDBLSYM, 0, 0, "defstr", DEFSTRSYM, 0, 0, "def", DEFSYM, 0, 0, "delete", ILLEGAL, 0, 0, "dim", DIMSYM, 0, 0, "edit", ILLEGAL, 0, 0, "else", ELSESYM, 0, 0, "end", ENDSYM, 0, 0, "eof", FUNCTION, EOFSYM, 0, "eqv", EQVSYM, EQVSYM, 0, "erase", ILLEGAL, 0, 0, "error", ERRORSYM, 0, 0, "err", ERRSYM, 0, 0, "erl", ERLSYM, 0, 0, "exp", FUNCTION, EXPSYM, 0, "field", FIELDSYM, 0, 0, "fix", FUNCTION, FIXSYM, 0, "for", FORSYM, 0, 0, "fre", FUNCTION, FRESYM, 0, "get", GETSYM, 0, 0, "gosub", GOSUBSYM, 0, 0, "goto", GOTOSYM, 0, 0, "hex", FUNCTION, HEXSYM, 0, "if", IFSYM, 0, 0, "imp", IMPSYM, IMPSYM, 0, "inkey", INKEYSYM, 0, 0, "input", INPUTSYM, 0, 0, "inp", FUNCTION, INPSYM, 0, "instr", FUNCTION, INSTRSYM, 0, "int", FUNCTION, INTSYM, 0, "kill", ILLEGAL, 0, 0, "left", FUNCTION, LEFTSYM, 0, "len", FUNCTION, LENSYM, 0, "let", LETSYM, 0, 0, "line", LINESYM, 0, 0, "list", LISTSYM, 0, 0, "llist", ILLEGAL, 0, 0, "load", LOADSYM, 0, 0, "loc", FUNCTION, LOCSYM, 0, "log", FUNCTION, LOGSYM, 0, "lpos", FUNCTION, LPOSSYM, 0, "lprint", ILLEGAL, 0, 0, "lset", LSETSYM, 0, 0, "merge", MERGESYM, 0, 0, "mid", MIDSYM, 0, 0, "mki", FUNCTION, MKISYM, 0, "mks", FUNCTION, MKSSYM, 0, "mkd", FUNCTION, MKDSYM, 0, "mod", MODSYM, 0, 0, "name", ILLEGAL, 0, 0, "new", ILLEGAL, 0, 0, "next", NEXTSYM, 0, 0, "not", NOTSYM, 0, 0, "null", ILLEGAL, 0, 0, "on", ONSYM, 0, 0, "oct", FUNCTION, OCTSYM, 0, "open", OPENSYM, 0, 0, "option", OPTIONSYM, 0, 0, "or", ORSYM, ORSYM, 0, "out", FUNCTION, OUTSYM, 0, "peek", PEEKSYM, 0, 0, "poke", POKESYM, 0, 0, "print", PRINTSYM, 0, 0, "pos", FUNCTION, POSSYM, 0, "put", PUTSYM, 0, 0, "randomize", RANDOMIZESYM, 0, 0, "read", READSYM, 0, 0, "rem", REMSYM, 0, 0, "renum", ILLEGAL, 0, 0, "ren", ILLEGAL, 0, 0, "restore", RESTORESYM, 0, 0, "resume", ILLEGAL, 0, 0, "return", RETURNSYM, 0, 0, "right", FUNCTION, RIGHTSYM, 0, "rnd", FUNCTION, RNDSYM, 0, "run", ILLEGAL, 0, 0, "save", ILLEGAL, 0, 0, "step", STEPSYM, 0, 0, "sgn", FUNCTION, SGNSYM, 0, "sin", FUNCTION, SINSYM, 0, "space", FUNCTION, SPACESYM, 0, "spc", FUNCTION, SPCSYM, 0, "sqr", FUNCTION, SQRSYM, 0, "stop", STOPSYM, 0, 0, "string", FUNCTION, STRINGSYM, 0, "str", FUNCTION, STRSYM, 0, "swap", SWAPSYM, 0, 0, "tab", FUNCTION, TABSYM, 0, "tan", FUNCTION, TANSYM, 0, "then", THENSYM, 0, 0, "to", TOSYM, 0, 0, "tron", TRONOFFSYM, TRONSYM, 0, "troff", TRONOFFSYM, TROFFSYM, 0, "using", USINGSYM, 0, 0, "usr", FUNCTION, USRSYM, 0, "val", FUNCTION, VALSYM, 0, "varptr", FUNCTION, VARPTRSYM, 0, "wait", ILLEGAL, 0, 0, "while", WHILESYM, 0, 0, "wend", WENDSYM, 0, 0, "width", ILLEGAL, 0, 0, "write", WRITESYM, 0, 0, "xor", XORSYM, XORSYM, 0, 0, 0, 0, 0 }; /* Keyword index table */ int kex[27]; /* Initialize the keyword table */ fillkex() { Key *k; int i; for(k=keywords;k->name;k++) k->length= strlen(k->name); k=keywords; for(i=0;k->name && i<='z'-'a';i++) { for(;k->name && *k->namename!=i+'a') continue; kex[*k->name-'a']=k-keywords; for(;k->name && *k->name==i+'a';k++); kex[*(k-1)->name-'a'+1]=k-keywords; } if (debug) { for(i=0;i<27;i++) print("%c:%d\n",'a'+i,kex[i]); } } #include /* Get each line separately into the buffer */ /* Lines too long are terminated and flagged illegal */ #define MAXLINELENGTH 1024 char inputline[MAXLINELENGTH]; /* current source line */ char *cptr; /* next character to decode */ int yylineno=0; /* source line counter */ #define GETSBUFSIZE 1024 char fgets_buf[GETSBUFSIZE]; char *our_fgets(buffer,n_char,stream) char *buffer; int n_char; File *stream; { /* Read one line or n_char */ static int characters_left = 0; static char *internal_bufp = fgets_buf; char *external_bufp; external_bufp = buffer; /* Moves through the external buffer */ while ( 1 ) { if ( characters_left ) { /* There is still something buffered */ if ( n_char > 1 ) { /* More characters have to be copied */ if ( *internal_bufp == '\n' ) { *external_bufp++ = *internal_bufp++; characters_left--; *external_bufp = '\0'; return(buffer); /* One line is read */ } else { *external_bufp++ = *internal_bufp++; characters_left--; n_char--; /* One character is copied */ } } else { /* Enough characters read */ *external_bufp = '\0'; return(buffer); } } else { /* Read new block */ sys_read(stream,fgets_buf,GETSBUFSIZE,&characters_left); internal_bufp = fgets_buf; /* Move pointer back to the beginning */ if ( characters_left == 0 ) { /* Nothing read */ if ( external_bufp == buffer ) { *external_bufp = '\0'; return(0); /* EOF */ } else { /* Something was already copied */ *external_bufp = '\0'; return(buffer); } } } } } extern char *strchr(); getline() { /* get next input line */ if ( our_fgets(inputline,MAXLINELENGTH,yyin) == 0) return(FALSE); yylineno ++; if ( strchr(inputline,'\n') == 0) error("source line too long"); inputline[MAXLINELENGTH-1]=0; if ( listing) fprint(STDERR, inputline); cptr= inputline; return(TRUE); } typechar() { switch(*cptr) { case '$': cptr++; return( STRINGTYPE); case '%': cptr++; return( INTTYPE); case '!': cptr++; return( FLOATTYPE); case '#': cptr++; return( DOUBLETYPE); } return(0); } /* symbols in Microsoft are significant for the first 40 characters */ #define SIGNIFICANT 40 char name[SIGNIFICANT+1]; lookup() { Key *k; Symbol *Sym; char *c; int i, typech; sval= name; for(c=cptr; *c && isalnum(*c);c++) if ( isupper(*c) ) *c= tolower(*c); for (k= keywords+kex[*cptr-'a']; k->name != 0 && *(k->name)== *cptr;k++) if ( strncmp(cptr,k->name,k->length)==0) { /* if ( isalnum( *(cptr+k->length) )) *//* EHB */ if ( isalnum( *(cptr+k->length) ) && /* EHB */ k->token == FUNCTION) /* EHB */ continue; /* keywords door delimiters gescheiden */ cptr += k->length; yylval.integer= k->classvalue; if (debug) print("lookup:%d %d\n", k->classvalue,k->token); if ( k->token == FUNCTION) { /* stripp type character */ typech=typechar(); } /* illegals + rem */ if ( k->token == REMSYM || k->token==ILLEGAL) while ( *cptr && *cptr!=':' && *cptr!='\n') cptr++; return( k->token); } /* Is it a function name ? */ c=cptr; /* Identifier found, update the symbol table */ i=0; while (( isalnum(*c) || *c == '.') && i < SIGNIFICANT) name[i++]= *c++; while (isalnum(*c) || *c == '.') c++; /* skip rest */ name[i]=0; cptr=c; Sym= srchsymbol(name); yylval.Sptr = Sym; typech= typechar(); if (Sym->symtype!=DEFAULTTYPE) { if (typech && typech!=Sym->symtype && wflag) warning("type re-declared,ignored"); } if ( typech) Sym->symtype=typech; if (debug) print("lookup:%d Identifier\n",Sym); if ( (name[0]=='f' || name[0]=='F') && (name[1]=='n' || name[1]=='N') ) return(FUNCTID); return(IDENTIFIER); } /* Parsing unsigned numbers */ readconstant() { /* read HEX and OCTAL numbers */ char *c; cptr++; if ( *cptr == 'H' || *cptr=='h') { /* HEX */ cptr++; c=cptr; while ( isdigit(*cptr) || (*cptr>='a' && *cptr<='f' ) || (*cptr>='A' && *cptr<='F' ) ) cptr++; (void) sscanf(c,"%x",&ival); } else if ( *cptr == 'O' || *cptr == 'o') { /* OCTAL */ cptr++; c=cptr; while ( isdigit(*cptr) ) cptr++; (void) sscanf(c,"%o",&ival); } else error("H or O expected"); return(INTVALUE); } #ifdef ____ /* Computes base to the power exponent. This was not done in the old compiler */ double powr(base,exp) double base; int exp; { int i; double result; int abs_exp; if ( exp < 0 ) abs_exp = -exp; else abs_exp = exp; result = 1.0; for ( i = 1; i <= abs_exp; i++ ) { result = result * base; } if ( exp < 0 ) return ( 1.0 / result ); else return ( result ); } #endif number() { long i1; int overflow = 0; register char *c; static char numbuf[256]; register char *d = numbuf; dval = numbuf; i1=0; c=cptr; while (*c == '0') c++; while (isdigit(*c)){ i1= i1*10 + *c-'0'; if (i1 < 0) overflow = 1; if (d < &numbuf[255]) *d++ = *c; c++; } if (d == numbuf) *d++ = '0'; cptr=c; if ( *c != '.' && *c != 'e' && *c != 'E' && *c != 'd' && *c != 'D' ){ if ( i1> MAXINT || i1= 4 */ #define CHUNKSIZE 123 scanstring() { int i,length=0; char firstchar = *cptr; char buffer[CHUNKSIZE],*bufp = buffer; /* generate label here */ if (! in_data) yylval.integer= genemlabel(); if ( *cptr== '"') cptr++; sval= cptr; while ( *cptr !='"') { switch(*cptr) { case 0: case '\n': #ifdef YYDEBUG if (yydebug) print("STRVALUE\n"); #endif if ( firstchar == '"') error("non-terminated string"); return(STRVALUE); /* case '\'': case '\\': *bufp++ = '\\'; *bufp++ = *cptr; if ( bufp >= buffer + CHUNKSIZE - 4 ) { if (! in_data) C_con_scon(buffer,(arith)(bufp-buffer)); bufp = buffer; } break; */ default: *bufp++ = *cptr; if ( bufp >= buffer + CHUNKSIZE - 4 ) { if (! in_data) C_con_scon(buffer,(arith)(bufp-buffer)); bufp = buffer; } } cptr++; length++; } *cptr = 0; *bufp++ = 0; cptr++; if (! in_data) { C_con_scon(buffer,(arith)(bufp-buffer)); i=yylval.integer; yylval.integer= genemlabel(); C_rom_dlb((label)i,(arith)0); C_rom_icon("9999",(arith)BEMINTSIZE); C_rom_icon(itoa(length),(arith)BEMINTSIZE); } #ifdef YYDEBUG if (yydebug) print("STRVALUE found\n"); #endif return(STRVALUE); } yylex() { char *c; /* Here is the big switch */ c= cptr; switch(*c){ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': return(lookup()); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': return(number()); case '\'': /* comment at end of line */ while ( *cptr != '\n' && *cptr) cptr++; case '\n': cptr++; return(EOLN); case 0: #ifdef YYDEBUG if ( yydebug) print("end of buffer"); #endif return(0); case '"': return(scanstring()); /* handle double operators */ case ' ': case '\t': cptr++; return(yylex()); case '&': return(readconstant()); case '?': cptr++; return(PRINTSYM); case '>': if ( *(c+1)=='='){ c++; c++; cptr=c; yylval.integer= GESYM; return(RELOP); } yylval.integer= '>'; cptr++; return(RELOP); case '<': if ( *(c+1)=='='){ c++; c++; cptr=c; yylval.integer=LESYM; return(RELOP); } else if ( *(c+1)=='>'){ c++; c++; cptr=c; yylval.integer=NESYM; return(RELOP); } yylval.integer= '<'; cptr++; return(RELOP); } return(*cptr++); }