home *** CD-ROM | disk | FTP | other *** search
- /* EXPR_SEM.C
- Copyright (C) 1992 Keith L. Robertson All Rights Reserved
-
- Semantic actions used in the EXPR expression evaluator.
- */
- #include "expr_lex.h" // <types.h>
- #include <math.h>
- #include "pg_parse.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
-
- #define MAX_TABLE 20
- typedef struct {
- STRING name;
- FLOAT value;
- } IDENTIFIER_ENTRY;
-
- IDENTIFIER_ENTRY ident_table [MAX_TABLE] = {
- "pi", 3.14159265358979323846,
- "e", 2.7182818284590452354,
- };
-
-
- /****************************/
-
- VOID expr_print ()
- { printf ("\t%f\n", attr [0].val.f);
- }
-
-
- VOID finish_kill ()
- { printf ("\tDone.\n");
- }
-
- VOID kill_ident ()
- { SHORT id_index;
- STRING id_name = attr [0].name;
- CHAR msg [80];
-
- for (id_index = MAX_TABLE-1; 0 <= id_index; --id_index) {
- if (strcmp (ident_table [id_index].name, id_name) == 0) {
- free (ident_table [id_index].name);
- ident_table [id_index].name = 0;
- break;
- }
- }
- if (id_index < 0) {
- /* Report that it wasn't found. */
- sprintf (msg, " Identifier '%s' not found.", id_name);
- log_error (SEMANTIC, msg);
- }
- free (id_name);
- }
-
-
- VOID list ()
- { SHORT id_index;
- BOOL is_ident = 0;
- for (id_index = MAX_TABLE-1; 0 <= id_index; --id_index) {
- if (ident_table [id_index].name != 0) {
- printf ("\t%s\t%f\n", ident_table [id_index].name, ident_table [id_index].value);
- is_ident = 1;
- }
- }
- if (! is_ident) { printf ("\tNo identifiers are defined.\n"); }
- }
-
-
- VOID lisp ()
- { printf ("\tTh'ufferin' th'uccotash!\n\
- \tThum people get their kick'th from the th'rangetht thing'th.\n");
- if (! was_jumped (attr [1])) {
- printf ("\tI gueth I lithp and you th'tutter!\n");
- }
- }
-
-
- VOID session_help ()
- { printf ("\n\
- Enter a command to have it evaluated and its result printed:\n\
- All commands must end with a semicolon (;). Available commands:\n\
- An expression with NUMBERs, IDENTifiers, symbols: ( ) ^ * / + -\n\
- and functions '<fn>(<expr>)': arc/cos sin tan, exp log, abs sqrt ceil floor.\n\
- Use:\t\"IDENT = <expr> ;\"\tto define an identifier for use in expressions.\n\
- \t\"list ;\"\t\tto list all currently defined identifiers.\n\
- \t\"kill IDENT... ;\"\tto undefine a list of identifiers.\n\
- \t\"lisp [lisp];\"\t\tfor a silly message.\n\
- \t\"help ;\" or \"? ;\"\tto repeat this message.\n\
- \t\"exit ;\" or enter end-of-file (F6,Return) to exit.\n");
- }
-
-
- VOID session_error ()
- { log_error (SYNTAX, "error in expression");
- /* Read to end of command. */
- skip_to_token (SEMICOLON);
- }
-
-
- #if 0
- /********
- Example usage of skip_to_bittok().
- Let's say these are all the high-level uses of Expr:
- Assign_statement --> IDENT ':=' Expr ';'
- While_statement --> WHILE Expr DO Statement
- If_statement --> IF Expr THEN Statement
- There are NUM_TOKENS tokens, ';' is token 1 (right after EOS, token 0),
- DO is token 22, and THEN is token 23.
- If there's a syntax error in an Expr, we want to print a message and
- skip to the end of the Expr.
- 'log_error' prints the position where the error was detected,
- so we rarely need much description as to what token was expected.
- ********/
-
- VOID expr_error ()
- { static USHORT expr_ends [(NUM_TOKENS + 8 - 1) / 8]
- = { 0x0002, 0x00C0, };
- log_error (SYNTAX, "Error in expression.");
- skip_to_bittok (expr_ends);
- }
- #endif
-
-
- VOID expr_assign ()
- { SHORT id_index;
- STRING id_name = attr [0].name;
-
- /* Try and find ident name in table. */
- id_index = MAX_TABLE-1;
- while ((0 <= id_index) &&
- (strcmp (ident_table [id_index].name, id_name) != 0)) {
- --id_index;
- }
-
- if (id_index < 0) {
- /* Ident being assigned isn't in the table. Create it. */
-
- /* First try and find an empty spot. */
- id_index = MAX_TABLE-1;
- while ((0 <= id_index) && (ident_table [id_index].name != 0)) {
- --id_index;
- }
-
- if (0 <= id_index) {
- /* Found a spot for it; add ident in table. */
- ident_table [id_index].name = id_name;
- }
- }
-
- if (0 <= id_index) {
- /* Set ident value. */
- ident_table [id_index].value = attr [2].val.f;
- }
- else {
- log_error (SEMANTIC, "could not add identifier. Table is full.");
- }
-
- /* Value of assignment is value of expression. */
- attr [0].val.f = attr [2].val.f;
- }
-
-
- VOID expr_paren ()
- { attr [0].val.f = attr [1].val.f;
- }
-
-
- #define NUM_FUNCTIONS 12
- static CSTRING ftable [] = {
- "arccos", "arcsin", "arctan",
- "cos", "sin", "tan",
- "exp", "log", "abs",
- "sqrt", "ceil", "floor",
- };
-
- VOID function_call ()
- { SHORT fn_index = NUM_FUNCTIONS-1;
- STRING fn_name = strlwr (attr [0].name);
-
- while (fn_index >= 0 && strcmp (ftable[fn_index], fn_name) != 0) {
- --fn_index;
- }
-
- if (fn_index < 0) {
- CHAR msg [80];
- sprintf (msg, " Function '%s' is not defined.", fn_name);
- log_error (SEMANTIC, msg);
- attr [0].val.f = 0; // Return result of 0.
- }
- else {
- FLOAT res, arg = attr [2].val.f;
- switch (fn_index) {
- case 0: res = acos (arg); break;
- case 1: res = asin (arg); break;
- case 2: res = atan (arg); break;
- case 3: res = cos (arg); break;
- case 4: res = sin (arg); break;
- case 5: res = tan (arg); break;
- case 6: res = exp (arg); break;
- case 7: res = log (arg); break;
- case 8: res = fabs (arg); break;
- case 9: res = sqrt (arg); break;
- case 10: res = ceil (arg); break;
- case 11: res = floor (arg); break;
- }
- attr [0].val.f = res; // Return result.
- }
- }
-
-
- VOID unary ()
- { if (attr [0].token == MINUS) {
- attr [0].val.f = - attr [1].val.f;
- }
- else { attr [0].val.f = attr [1].val.f; }
- }
-
-
- VOID power ()
- { attr [0].val.f = pow (attr [0].val.f, attr [2].val.f);
- }
-
-
- VOID binary2 ()
- { if (attr [1].token == TIMES) {
- attr [0].val.f *= attr [2].val.f;
- }
- else { /* '/', DIVIDE */
- attr [0].val.f /= attr [2].val.f;
- }
- }
-
-
- VOID binary1 ()
- { if (attr [1].token == PLUS) {
- attr [0].val.f += attr [2].val.f;
- }
- else { /* '-', MINUS */
- attr [0].val.f -= attr [2].val.f;
- }
- }
-
-
- VOID look_up_ident ()
- { FLOAT val;
- CHAR msg [80];
- SHORT id_index;
- STRING id_name = attr [0].name;
-
- /* Try and find ident name in table. */
- id_index = MAX_TABLE-1;
- while ((0 <= id_index) &&
- (strcmp (ident_table [id_index].name, id_name) != 0)) {
- --id_index;
- }
-
- if (0 <= id_index) {
- /* Found it! Get its value. */
- val = ident_table [id_index].value;
- }
- else {
- /* Report that it wasn't found. */
- sprintf (msg, " Identifier '%s' not found.", id_name);
- log_error (SEMANTIC, msg);
- val = 0;
- }
- attr [0].val.f = val;
- free (id_name);
- }
-
-
- /****************************/
-
- INT main ()
- { INT id_index;
-
- /* Duplicate any predefined identifiers so */
- /* that kill() doesn't free static memory. */
- for (id_index = MAX_TABLE-1; 0 <= id_index; --id_index) {
- if (ident_table [id_index].name != 0) {
- ident_table [id_index].name = strdup (ident_table [id_index].name);
- }
- }
-
- session_help ();
- init_lexer ();
- ERROR_THRESHOLD = 0;
-
- parse ();
- return 0;
- }
-