home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / pgen_2 / expr_sem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-04  |  7.1 KB  |  294 lines

  1. /*    EXPR_SEM.C
  2.     Copyright (C) 1992    Keith L. Robertson    All Rights Reserved
  3.  
  4.     Semantic actions used in the EXPR expression evaluator.
  5. */
  6. #include "expr_lex.h"        // <types.h>
  7. #include <math.h>
  8. #include "pg_parse.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12.  
  13.  
  14. #define        MAX_TABLE    20
  15. typedef struct  {
  16.     STRING    name;
  17.     FLOAT    value;
  18. }    IDENTIFIER_ENTRY;
  19.  
  20. IDENTIFIER_ENTRY    ident_table [MAX_TABLE]    = {
  21.     "pi",    3.14159265358979323846,
  22.     "e",    2.7182818284590452354,
  23. };
  24.  
  25.  
  26. /****************************/
  27.  
  28. VOID    expr_print ()
  29. {   printf ("\t%f\n", attr [0].val.f);
  30. }
  31.  
  32.  
  33. VOID    finish_kill ()
  34. {   printf ("\tDone.\n");
  35. }
  36.  
  37. VOID    kill_ident ()
  38. {   SHORT    id_index;
  39.     STRING    id_name = attr [0].name;
  40.     CHAR    msg [80];
  41.  
  42.     for  (id_index = MAX_TABLE-1;  0 <= id_index;  --id_index)  {
  43.     if  (strcmp (ident_table [id_index].name, id_name) == 0)  {
  44.         free (ident_table [id_index].name);
  45.         ident_table [id_index].name = 0;
  46.         break;
  47.     }
  48.     }
  49.     if  (id_index < 0)  {
  50.     /* Report that it wasn't found. */
  51.     sprintf (msg, "  Identifier '%s' not found.", id_name);
  52.     log_error (SEMANTIC, msg);
  53.     }
  54.     free (id_name);
  55. }
  56.  
  57.  
  58. VOID    list ()
  59. {   SHORT    id_index;
  60.     BOOL    is_ident = 0;
  61.     for  (id_index = MAX_TABLE-1;  0 <= id_index;  --id_index)  {
  62.     if  (ident_table [id_index].name != 0)  {
  63.         printf ("\t%s\t%f\n", ident_table [id_index].name, ident_table [id_index].value);
  64.         is_ident = 1;
  65.     }
  66.     }
  67.     if  (! is_ident)  { printf ("\tNo identifiers are defined.\n"); }
  68. }
  69.  
  70.  
  71. VOID    lisp ()
  72. {   printf ("\tTh'ufferin' th'uccotash!\n\
  73. \tThum people get their kick'th from the th'rangetht thing'th.\n");
  74.     if  (! was_jumped (attr [1]))  {
  75.     printf ("\tI gueth I lithp and you th'tutter!\n");
  76.     }
  77. }
  78.  
  79.  
  80. VOID    session_help ()
  81. {   printf ("\n\
  82. Enter a command to have it evaluated and its result printed:\n\
  83.   All commands must end with a semicolon (;).  Available commands:\n\
  84.   An expression with NUMBERs, IDENTifiers, symbols:  ( ) ^ * / + -\n\
  85.   and functions '<fn>(<expr>)':  arc/cos sin tan, exp log, abs sqrt ceil floor.\n\
  86.   Use:\t\"IDENT = <expr> ;\"\tto define an identifier for use in expressions.\n\
  87. \t\"list ;\"\t\tto list all currently defined identifiers.\n\
  88. \t\"kill IDENT... ;\"\tto undefine a list of identifiers.\n\
  89. \t\"lisp [lisp];\"\t\tfor a silly message.\n\
  90. \t\"help ;\" or \"? ;\"\tto repeat this message.\n\
  91. \t\"exit ;\"  or enter end-of-file (F6,Return)  to exit.\n");
  92. }
  93.  
  94.  
  95. VOID    session_error ()
  96. {   log_error (SYNTAX, "error in expression");
  97.     /* Read to end of command. */
  98.     skip_to_token (SEMICOLON);
  99. }
  100.  
  101.  
  102. #if  0
  103. /********
  104.     Example usage of skip_to_bittok().
  105.     Let's say these are all the high-level uses of Expr:
  106.     Assign_statement    --> IDENT ':=' Expr ';'
  107.     While_statement        --> WHILE Expr DO Statement
  108.     If_statement        --> IF Expr THEN Statement
  109.     There are NUM_TOKENS tokens, ';' is token 1 (right after EOS, token 0),
  110.     DO is token 22, and THEN is token 23.
  111.     If there's a syntax error in an Expr, we want to print a message and
  112.     skip to the end of the Expr.
  113.     'log_error' prints the position where the error was detected,
  114.     so we rarely need much description as to what token was expected.
  115. ********/
  116.  
  117. VOID    expr_error ()
  118. {   static USHORT    expr_ends [(NUM_TOKENS + 8 - 1) / 8]
  119.     = { 0x0002, 0x00C0, };
  120.     log_error (SYNTAX, "Error in expression.");
  121.     skip_to_bittok (expr_ends);
  122. }
  123. #endif
  124.  
  125.  
  126. VOID    expr_assign ()
  127. {   SHORT    id_index;
  128.     STRING    id_name = attr [0].name;
  129.  
  130.     /* Try and find ident name in table. */
  131.     id_index = MAX_TABLE-1;
  132.     while  ((0 <= id_index)  &&
  133.         (strcmp (ident_table [id_index].name, id_name) != 0))  {
  134.     --id_index;
  135.     }
  136.  
  137.     if  (id_index < 0)  {
  138.     /* Ident being assigned isn't in the table.  Create it. */
  139.  
  140.     /* First try and find an empty spot. */
  141.     id_index = MAX_TABLE-1;
  142.     while  ((0 <= id_index)  &&  (ident_table [id_index].name != 0))  {
  143.         --id_index;
  144.     }
  145.  
  146.     if  (0 <= id_index)  {
  147.         /* Found a spot for it; add ident in table. */
  148.         ident_table [id_index].name = id_name;
  149.     }
  150.     }
  151.  
  152.     if  (0 <= id_index)  {
  153.     /* Set ident value. */
  154.     ident_table [id_index].value = attr [2].val.f;
  155.     }
  156.     else   {
  157.     log_error (SEMANTIC, "could not add identifier.  Table is full.");
  158.     }
  159.  
  160.     /* Value of assignment is value of expression. */
  161.     attr [0].val.f = attr [2].val.f;
  162. }
  163.  
  164.  
  165. VOID    expr_paren ()
  166. {   attr [0].val.f = attr [1].val.f;
  167. }
  168.  
  169.  
  170. #define        NUM_FUNCTIONS    12
  171. static CSTRING    ftable [] = {
  172.     "arccos",    "arcsin",    "arctan",
  173.     "cos",        "sin",        "tan",
  174.     "exp",        "log",        "abs",
  175.     "sqrt",        "ceil",        "floor",
  176. };
  177.  
  178. VOID    function_call ()
  179. {   SHORT    fn_index = NUM_FUNCTIONS-1;
  180.     STRING    fn_name = strlwr (attr [0].name);
  181.  
  182.     while  (fn_index >= 0  &&  strcmp (ftable[fn_index], fn_name) != 0)  {
  183.     --fn_index;
  184.     }
  185.  
  186.     if  (fn_index < 0)  {
  187.     CHAR    msg [80];
  188.     sprintf (msg, "  Function '%s' is not defined.", fn_name);
  189.     log_error (SEMANTIC, msg);
  190.     attr [0].val.f = 0;        // Return result of 0.
  191.     }
  192.     else   {
  193.     FLOAT    res,  arg = attr [2].val.f;
  194.     switch  (fn_index)  {
  195.     case  0:    res = acos (arg);    break;
  196.     case  1:    res = asin (arg);    break;
  197.     case  2:    res = atan (arg);    break;
  198.     case  3:    res = cos (arg);    break;
  199.     case  4:    res = sin (arg);    break;
  200.     case  5:    res = tan (arg);    break;
  201.     case  6:    res = exp (arg);    break;
  202.     case  7:    res = log (arg);    break;
  203.     case  8:    res = fabs (arg);    break;
  204.     case  9:    res = sqrt (arg);    break;
  205.     case 10:    res = ceil (arg);    break;
  206.     case 11:    res = floor (arg);    break;
  207.     }
  208.     attr [0].val.f = res;    // Return result.
  209.     }
  210. }
  211.  
  212.  
  213. VOID    unary ()
  214. {   if  (attr [0].token == MINUS)  {
  215.     attr [0].val.f = - attr [1].val.f;
  216.     }
  217.     else  { attr [0].val.f = attr [1].val.f; }
  218. }
  219.  
  220.  
  221. VOID    power ()
  222. {   attr [0].val.f = pow (attr [0].val.f, attr [2].val.f);
  223. }
  224.  
  225.  
  226. VOID    binary2 ()
  227. {   if  (attr [1].token == TIMES)  {
  228.     attr [0].val.f *= attr [2].val.f;
  229.     }
  230.     else   {    /* '/', DIVIDE */
  231.     attr [0].val.f /= attr [2].val.f;
  232.     }
  233. }
  234.  
  235.  
  236. VOID    binary1 ()
  237. {   if  (attr [1].token == PLUS)  {
  238.     attr [0].val.f += attr [2].val.f;
  239.     }
  240.     else   {    /* '-', MINUS */
  241.     attr [0].val.f -= attr [2].val.f;
  242.     }
  243. }
  244.  
  245.  
  246. VOID    look_up_ident ()
  247. {   FLOAT    val;
  248.     CHAR    msg [80];
  249.     SHORT    id_index;
  250.     STRING    id_name = attr [0].name;
  251.  
  252.     /* Try and find ident name in table. */
  253.     id_index = MAX_TABLE-1;
  254.     while  ((0 <= id_index)  &&
  255.         (strcmp (ident_table [id_index].name, id_name) != 0))  {
  256.     --id_index;
  257.     }
  258.  
  259.     if  (0 <= id_index)  {
  260.     /* Found it!  Get its value. */
  261.     val = ident_table [id_index].value;
  262.     }
  263.     else  {
  264.     /* Report that it wasn't found. */
  265.     sprintf (msg, "  Identifier '%s' not found.", id_name);
  266.     log_error (SEMANTIC, msg);
  267.     val = 0;
  268.     }
  269.     attr [0].val.f = val;
  270.     free (id_name);
  271. }
  272.  
  273.  
  274. /****************************/
  275.  
  276. INT    main ()
  277. {   INT        id_index;
  278.  
  279.     /* Duplicate any predefined identifiers so */
  280.     /* that kill() doesn't free static memory. */
  281.     for  (id_index = MAX_TABLE-1;  0 <= id_index;  --id_index)  {
  282.     if  (ident_table [id_index].name != 0)  {
  283.         ident_table [id_index].name = strdup (ident_table [id_index].name);
  284.     }
  285.     }
  286.  
  287.     session_help ();
  288.     init_lexer ();
  289.     ERROR_THRESHOLD = 0;
  290.  
  291.     parse ();
  292.     return  0;
  293. }
  294.