/* 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 <ctype.h> /* isspace() */
#include <stdio.h> /* sscanf() */
#include <string.h>
#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);
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>