/* Lexer for formula answers Copyright (C) 1992-2000 Michigan State University The CAPA system is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The CAPA system is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the CAPA system; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, you have permission to link this program with the TtH/TtM library and distribute executables, as long as you follow the requirements of the GNU GPL in regard to all of the software in the executable aside from TtH/TtM. */ /* =========================================================== */ /* capaFormulaLexer.c created by Isaac Tsai @ Feb 1999 */ /* =========================================================== */ #include /* isspace() */ #include /* sscanf() */ #include "capaParser.h" #define YYSTYPE Symbol_p #include "capaFormula.h" #include "capaToken.h" /* --------------- Global variables ------------------------- */ extern int Func_idx; extern Symbol FuncStack[MAX_FUNC_NEST]; extern char Fbuf[ONE_K]; /* lexer input buffer */ extern int Fidx; /* lexer input char index */ extern Symbol_p fml_lval; /* lexical variable used in parser */ /* ---- Token value returned from this lexer ---------------- */ /* --------------- Global variables ------------------------ */ /* scan a F_NUMBER token */ double f_get_float() { double num; int ii=0, len; char num_str[QUARTER_K]; num_str[ii]=0; while( isspace(Fbuf[Fidx]) ) { Fidx++; } if( Fbuf[Fidx] == '+' || Fbuf[Fidx] == '-' ) { num_str[ii++] = Fbuf[Fidx++]; } while( isdigit(Fbuf[Fidx]) || Fbuf[Fidx] == '.' ) { num_str[ii++] = Fbuf[Fidx++]; } if( Fbuf[Fidx] == 'E' || Fbuf[Fidx] == 'e' ) { /* a number followed immediately by e or E */ if( Fbuf[Fidx+1] == '+' || Fbuf[Fidx+1] == '-' || isdigit(Fbuf[Fidx+1]) ) { /* e or E followed immediately by a digit */ num_str[ii++] = Fbuf[Fidx++]; num_str[ii++] = Fbuf[Fidx++]; while( isdigit(Fbuf[Fidx]) ) { num_str[ii++] = Fbuf[Fidx++]; } } } num_str[ii] = 0; /* terminate the str */ len = strlen(num_str); if(len > 0 ) { sscanf(num_str,"%lg", &num); } else { num = 1.0; } return (num); } char * f_get_id() { char *var_p; int ii=0, len; char id_str[QUARTER_K]; id_str[ii]=0; while( isspace(Fbuf[Fidx]) ) { Fidx++; } if( isalpha( Fbuf[Fidx] ) ) { id_str[ii++] = Fbuf[Fidx++]; } while( isalnum(Fbuf[Fidx]) || Fbuf[Fidx] == '_' ) { id_str[ii++] = Fbuf[Fidx++]; } id_str[ii] = 0; /* terminate the str */ len = strlen(id_str); var_p = (char *)capa_malloc( (len+1), sizeof(char)); strcpy(var_p,id_str); return (var_p); } int f_peek_next_token() { int idx; idx = Fidx; while( isspace(Fbuf[idx]) ) { idx++; } return (Fbuf[idx]); } /* ======================================================= */ int fml_lex() { char *id_p; int c; if( Fbuf[Fidx] == 0 ) { /* printf("EoI\n"); */ return (EOF); } while( isspace(Fbuf[Fidx]) ) { Fidx++; } if( isalpha(Fbuf[Fidx]) ) { id_p = f_get_id(); c = f_peek_next_token(); if( c == '(' ) { (FuncStack[Func_idx]).s_type = FUNCTION_ID; (FuncStack[Func_idx]).s_name = id_p; Func_idx++; return (F_ID); } else { fml_lval = find_formula_id(id_p); capa_mfree((char *)id_p); if( fml_lval == NULL) { return (F_ERROR); } else { return (V_ID); } } } if( isdigit(Fbuf[Fidx]) || Fbuf[Fidx] == '.' ) { fml_lval = (Symbol *) capa_malloc(1, sizeof(Symbol)); /* *** */ fml_lval->s_real = f_get_float(); fml_lval->s_type = R_CONSTANT; return (F_NUMBER); } if( Fbuf[Fidx] == '(' ) { Fidx++; return (F_LPAR); } if( Fbuf[Fidx] == ')' ) { Fidx++; return (F_RPAR); } if( Fbuf[Fidx] == '+' ) { Fidx++; return (F_PLUS); } if( Fbuf[Fidx] == '-' ) { Fidx++; return (F_MINUS); } if( Fbuf[Fidx] == '*' ) { Fidx++; return (F_MULT); } if( Fbuf[Fidx] == '/' ) { Fidx++; return (F_DIV); } if( Fbuf[Fidx] == '%' ) { Fidx++; return (F_MOD); } if( Fbuf[Fidx] == '^' ) { Fidx++; return (F_POW); } if( Fbuf[Fidx] == ',' ) { Fidx++; return (F_COMMA); } return (F_ERROR); }