www.pudn.com > ANSI_C_OOP.rar > parse.c
#include#include #include #include #include #include #include #include "parse.h" /* defines NUMBER */ #include "value.h" #include "mathlib.h" #include "Var.h" /* * reserved words */ #include "Name.h" #include "Name.r" static void initNames (void) { static const struct Name names [] = { { 0, "let", LET }, { 0 } }; const struct Name * np; for (np = names; np -> name; ++ np) install(np); } /* * scanner */ #define ALNUM "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ "abcdefghijklmnopqrstuvwxyz" \ "_" "0123456789" static enum tokens token; /* current input symbol */ static double number; /* if NUMBER: numerical value */ static enum tokens scan (const char * buf) /* return token = next input symbol */ { static const char * bp; if (buf) bp = buf; /* new input line */ while (isspace(* bp & 0xff)) ++ bp; if (isdigit(* bp & 0xff) || * bp == '.') { errno = 0; token = NUMBER, number = strtod(bp, (char **) & bp); if (errno == ERANGE) error("bad value: %s", strerror(errno)); } else if (isalpha(* bp & 0xff) || * bp == '_') { char buf [BUFSIZ]; int len = strspn(bp, ALNUM); if (len >= BUFSIZ) error("name too long: %-.10s...", bp); strncpy(buf, bp, len), buf[len] = '\0', bp += len; token = screen(buf); } else token = * bp ? * bp ++ : 0; return token; } /* * factor : + factor * - factor * NUMBER * CONST * VAR * MATH ( sum ) * ( sum ) */ static void * sum (void); static void * factor (void) { void * result; switch (token) { case '+': scan(0); return factor(); case '-': scan(0); return new(Minus, factor()); default: error("bad factor: '%c' 0x%x", token, token); case NUMBER: result = new(Value, number); break; case CONST: case VAR: result = symbol; break; case MATH: { const struct Name * fp = symbol; if (scan(0) != '(') error("expecting ("); scan(0); result = new(Math, fp, sum()); if (token != ')') error("expecting )"); break; } case '(': scan(0); result = sum(); if (token != ')') error("expecting )"); } scan(0); return result; } /* * product : factor { *|/ factor }... */ static void * product (void) { void * result = factor(); const void * type; for (;;) { switch (token) { case '*': type = Mult; break; case '/': type = Div; break; default: return result; } scan(0); result = new(type, result, factor()); } } /* * sum : product { +|- product }... */ static void * sum (void) { void * result = product(); const void * type; for (;;) { switch (token) { case '+': type = Add; break; case '-': type = Sub; break; default: return result; } scan(0); result = new(type, result, product()); } } /* * stmt : let VAR = sum * sum */ static void * stmt (void) { void * result; switch (token) { case LET: if (scan(0) != VAR) error("bad assignment"); result = symbol; if (scan(0) != '=') error("expecting ="); scan(0); return new(Assign, result, sum()); default: return sum(); } } /* * stmt \n ... */ static jmp_buf onError; int main (void) { volatile int errors = 0; char buf [BUFSIZ]; initNames(); initConst(); initMath(); if (setjmp(onError)) ++ errors; while (fgets(buf, sizeof buf, stdin)) if (scan(buf)) { void * e = stmt(); if (token) error("trash after sum"); process(e); delete(e); } return errors > 0; } void error (const char * fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap), putc('\n', stderr); va_end(ap); longjmp(onError, 1); }