home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
- %{
-
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- #ifndef TEST
- #include "ed.h"
- #include <debug/syms.h>
- #endif
- #define YYSTYPE long
-
-
- #ifdef TEST
- unsigned long syms_name2val (char *);
- int main (int, char **);
- int undefined_symbol = 0;
- #define valid_addr(x,y) 0
- #define read_child (void)
- #endif
- int evaluate (char *, long *, char **);
- static int yylex ();
- static void yyerror (char *);
-
- static long result;
- static char *input;
- static char *error;
-
- %}
-
- %token NUM
-
- %left OP_LOR '|' '^'
- %left OP_LAND '&'
- %nonassoc OP_EQ '<' '>' OP_NE OP_LE OP_GE
- %left OP_SHL OP_SHR
- %left '+' '-'
- %left '*' '/' '%'
- %left ':'
- %left OP_NEG OP_LNOT OP_NOT
-
- %start main
-
- %%
-
- main
- : expr { result = $1; }
-
- expr
- : NUM { $$ = $1; }
- | expr OP_LOR expr { $$ = $1 || $3; }
- | expr OP_LAND expr { $$ = $1 && $3; }
- | expr '|' expr { $$ = $1 | $3; }
- | expr '&' expr { $$ = $1 & $3; }
- | expr '^' expr { $$ = $1 ^ $3; }
- | expr OP_EQ expr { $$ = $1 == $3; }
- | expr '>' expr { $$ = $1 > $3; }
- | expr '<' expr { $$ = $1 < $3; }
- | expr OP_GE expr { $$ = $1 >= $3; }
- | expr OP_LE expr { $$ = $1 <= $3; }
- | expr OP_NE expr { $$ = $1 != $3; }
- | expr OP_SHL expr { $$ = (unsigned)$1 << $3; }
- | expr OP_SHR expr { $$ = (unsigned)$1 >> $3; }
- | expr '+' expr { $$ = $1 + $3; }
- | expr '-' expr { $$ = $1 - $3; }
- | expr '*' expr { $$ = $1 * $3; }
- | expr '/' expr
- { if ($3) $$ = $1 / $3; else yyerror ("Division by zero"); }
- | expr '%' expr
- { if ($3) $$ = $1 % $3; else yyerror ("Division by zero"); }
- | '-' expr %prec OP_NEG { $$ = -$2; }
- | '!' expr %prec OP_LNOT { $$ = !$2; }
- | '~' expr %prec OP_NOT { $$ = ~$2; }
- | '(' expr ')' { $$ = $2; }
- | '[' expr ']'
- { if (valid_addr ($2, 4))
- { long l; read_child ($2, &l, 4); $$ = l; }
- else
- yyerror ("Error reading child");
- }
- | expr ':' NUM
- { switch ($3) {
- case 1: $$ = ($1 & 0xff); break;
- case 2: $$ = ($1 & 0xffff); break;
- case 4: $$ = ($1 & 0xffffffff); break;
- default: yyerror ("Invalid resizing");
- }}
- ;
-
- %%
-
- static int
- yylex ()
- {
- char *p, save;
- int i;
- static struct {
- char c1, c2;
- int token;
- } twochars[] = {
- { '=', '=', OP_EQ },
- { '>', '=', OP_GE },
- { '<', '=', OP_LE },
- { '!', '=', OP_NE },
- { '&', '&', OP_LAND},
- { '|', '|', OP_LOR },
- { '<', '<', OP_SHL},
- { '>', '>', OP_SHR}};
-
- while (isspace (*input)) input++;
- switch (*input)
- {
- case '0' ... '9':
- case 'a' ... 'z':
- case 'A' ... 'Z':
- case '%':
- case '_':
- case '#':
- case '.':
- p = input++;
- while (isalnum (*input)
- || *input == '_' || *input == '#' || *input == '.')
- input++;
- save = *input;
- *input = 0;
- yylval = (long) syms_name2val (p);
- if (undefined_symbol)
- {
- static char buf[80];
- sprintf (buf, "Undefined symbol `%s'", p);
- yyerror (buf);
- }
- *input = save;
- return NUM;
- case '\'':
- if (input[1] == '\\' && input[2] && input[3] == '\'')
- {
- static char escaped[] = "e\et\tb\bn\nr\r\\\\''";
- for (i = 0; escaped[i]; i += 2)
- if (input[2] == escaped[i])
- {
- input += 4;
- yylval = escaped[i + 1];
- return NUM;
- }
- yyerror ("Unrecognized escaped character");
- }
- else if (input[1] && input[2] == '\'')
- {
- yylval = input[1];
- input += 3;
- }
- else
- yyerror ("Unterminated character constant");
- return NUM;
- case 0:
- return 0;
- default:
- for (i = 0; i < sizeof (twochars) / sizeof (twochars[0]); i++)
- if (*input == twochars[i].c1 && input[1] == twochars[i].c2)
- {
- input += 2;
- return twochars[i].token;
- }
- return *input++;
- }
- }
-
- int
- evaluate (char *exp, long *res, char **errtxt)
- {
- int err;
-
- input = exp;
- error = 0;
- err = yyparse ();
- *res = result;
- *errtxt = error;
- undefined_symbol = 0;
- return err || error;
- }
-
- static void
- yyerror (char *s)
- {
- if (!error) error = s;
- }
-
-
- #ifdef TEST
-
- unsigned long
- syms_name2val (char *p)
- {
- return strtoul(p, 0, 0);
- }
-
- int
- main (int argc, char **argv)
- {
- long res;
- int i, err;
- char *errtxt;
-
- for (i = 1; i < argc; i++)
- {
- err = evaluate (argv[i], &res, &errtxt);
- if (err)
- printf ("`%s' -> %s\n", argv[i], errtxt);
- else
- printf ("`%s' -> %ld\n", argv[i], res);
- }
- return 0;
- }
- #endif
-