home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / debug / fsdb / expr.y < prev    next >
Encoding:
Text File  |  1995-03-30  |  4.5 KB  |  216 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. %{
  3.  
  4. #include <ctype.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #ifndef TEST
  8. #include "ed.h"
  9. #include <debug/syms.h>
  10. #endif
  11. #define YYSTYPE long
  12.  
  13.  
  14. #ifdef TEST
  15. unsigned long syms_name2val (char *);
  16. int main (int, char **);
  17. int undefined_symbol = 0;
  18. #define valid_addr(x,y) 0
  19. #define read_child (void)
  20. #endif
  21. int evaluate (char *, long *, char **);
  22. static int yylex ();
  23. static void yyerror (char *);
  24.  
  25. static long result;
  26. static char *input;
  27. static char *error;
  28.  
  29. %}
  30.  
  31. %token NUM
  32.  
  33. %left OP_LOR '|' '^'
  34. %left OP_LAND '&'
  35. %nonassoc OP_EQ '<' '>' OP_NE OP_LE OP_GE
  36. %left OP_SHL OP_SHR
  37. %left '+' '-'
  38. %left '*' '/' '%'
  39. %left ':'
  40. %left OP_NEG OP_LNOT OP_NOT
  41.  
  42. %start main
  43.  
  44. %%
  45.  
  46. main
  47.     : expr                          { result = $1; }
  48.  
  49. expr
  50.     : NUM                { $$ = $1; }
  51.     | expr OP_LOR expr        { $$ = $1 || $3; }
  52.     | expr OP_LAND expr        { $$ = $1 && $3; }
  53.     | expr '|' expr            { $$ = $1 | $3; }
  54.     | expr '&' expr            { $$ = $1 & $3; }
  55.     | expr '^' expr            { $$ = $1 ^ $3; }
  56.     | expr OP_EQ expr        { $$ = $1 == $3; }
  57.     | expr '>' expr            { $$ = $1 > $3; }
  58.     | expr '<' expr            { $$ = $1 < $3; }
  59.     | expr OP_GE expr        { $$ = $1 >= $3; }
  60.     | expr OP_LE expr        { $$ = $1 <= $3; }
  61.     | expr OP_NE expr        { $$ = $1 != $3; }
  62.     | expr OP_SHL expr        { $$ = (unsigned)$1 << $3; }
  63.     | expr OP_SHR expr        { $$ = (unsigned)$1 >> $3; }
  64.     | expr '+' expr            { $$ = $1 + $3; }
  65.     | expr '-' expr            { $$ = $1 - $3; }
  66.     | expr '*' expr            { $$ = $1 * $3; }
  67.     | expr '/' expr
  68.       { if ($3) $$ = $1 / $3; else yyerror ("Division by zero"); }
  69.     | expr '%' expr
  70.       { if ($3) $$ = $1 % $3; else yyerror ("Division by zero"); }
  71.     | '-' expr %prec OP_NEG        { $$ = -$2; }
  72.     | '!' expr %prec OP_LNOT    { $$ = !$2; }
  73.     | '~' expr %prec OP_NOT        { $$ = ~$2; }
  74.     | '(' expr ')'            { $$ = $2; }
  75.     | '[' expr ']'
  76.       { if (valid_addr ($2, 4))
  77.           { long l; read_child ($2, &l, 4); $$ = l; }
  78.         else
  79.           yyerror ("Error reading child");
  80.       }
  81.     | expr ':' NUM
  82.       { switch ($3) {
  83.       case 1: $$ = ($1 & 0xff); break;
  84.       case 2: $$ = ($1 & 0xffff); break;
  85.       case 4: $$ = ($1 & 0xffffffff); break;
  86.       default: yyerror ("Invalid resizing");
  87.       }}
  88.     ;
  89.  
  90. %%
  91.  
  92. static int
  93. yylex ()
  94. {
  95.   char *p, save;
  96.   int i;
  97.   static struct {
  98.     char c1, c2;
  99.     int token;
  100.   } twochars[] = {
  101.     { '=', '=', OP_EQ },
  102.     { '>', '=', OP_GE },
  103.     { '<', '=', OP_LE },
  104.     { '!', '=', OP_NE },
  105.     { '&', '&', OP_LAND},
  106.     { '|', '|', OP_LOR },
  107.     { '<', '<', OP_SHL},
  108.     { '>', '>', OP_SHR}};
  109.  
  110.   while (isspace (*input)) input++;
  111.   switch (*input)
  112.     {
  113.     case '0' ... '9':
  114.     case 'a' ... 'z':
  115.     case 'A' ... 'Z':
  116.     case '%':
  117.     case '_':
  118.     case '#':
  119.     case '.':
  120.       p = input++;
  121.       while (isalnum (*input)
  122.          || *input == '_' || *input == '#' || *input == '.')
  123.     input++;
  124.       save = *input;
  125.       *input = 0;
  126.       yylval = (long) syms_name2val (p);
  127.       if (undefined_symbol)
  128.     {
  129.       static char buf[80];
  130.       sprintf (buf, "Undefined symbol `%s'", p);
  131.       yyerror (buf);
  132.     }
  133.       *input = save;
  134.       return NUM;
  135.     case '\'':
  136.       if (input[1] == '\\' && input[2] && input[3] == '\'')
  137.     {
  138.       static char escaped[] = "e\et\tb\bn\nr\r\\\\''";
  139.       for (i = 0; escaped[i]; i += 2)
  140.         if (input[2] == escaped[i])
  141.           {
  142.         input += 4;
  143.         yylval = escaped[i + 1];
  144.         return NUM;
  145.           }
  146.       yyerror ("Unrecognized escaped character");
  147.     }
  148.       else if (input[1] && input[2] == '\'')
  149.     {
  150.       yylval = input[1];
  151.       input += 3;
  152.     }
  153.       else
  154.     yyerror ("Unterminated character constant");
  155.       return NUM;
  156.     case 0:
  157.       return 0;
  158.     default:
  159.       for (i = 0; i < sizeof (twochars) / sizeof (twochars[0]); i++)
  160.     if (*input == twochars[i].c1 && input[1] == twochars[i].c2)
  161.       {
  162.         input += 2;
  163.         return twochars[i].token;
  164.       }
  165.       return *input++;
  166.     }
  167. }
  168.  
  169. int
  170. evaluate (char *exp, long *res, char **errtxt)
  171. {
  172.   int err;
  173.  
  174.   input = exp;
  175.   error = 0;
  176.   err = yyparse ();
  177.   *res = result;
  178.   *errtxt = error;
  179.   undefined_symbol = 0;
  180.   return err || error;
  181. }
  182.  
  183. static void
  184. yyerror (char *s)
  185. {
  186.   if (!error) error = s;
  187. }
  188.  
  189.  
  190. #ifdef TEST
  191.  
  192. unsigned long
  193. syms_name2val (char *p)
  194. {
  195.   return strtoul(p, 0, 0);
  196. }
  197.  
  198. int
  199. main (int argc, char **argv)
  200. {
  201.   long res;
  202.   int i, err;
  203.   char *errtxt;
  204.  
  205.   for (i = 1; i < argc; i++)
  206.     {
  207.       err = evaluate (argv[i], &res, &errtxt);
  208.       if (err)
  209.     printf ("`%s' -> %s\n", argv[i], errtxt);
  210.       else
  211.     printf ("`%s' -> %ld\n", argv[i], res);
  212.     }
  213.   return 0;
  214. }
  215. #endif
  216.