home *** CD-ROM | disk | FTP | other *** search
Lex Description | 1991-09-02 | 4.0 KB | 225 lines |
- %{
-
- #include <stdio.h>
- #include <math.h>
- #include "hc.h"
-
- char *bin(double n);
- char *oct(double n);
- char *rhex(double d);
- double do_call(int name, double arg);
- double do_power(double a, double b);
-
- void lr_save(double d);
- double lr_recall(int n);
-
- %}
-
- %union {
- double d;
- int i;
- }
-
- %token <i> LAST_RESULT
- %token <d> INUM
- %token <i> ID
-
- %type <d> expr
-
- %left '+' '-'
- %left '^'
- %left '|'
- %left '&'
- %left '<' '>'
- %left '*' '/' '%'
- %left UNARYMINUS '~'
- %right POWER
-
- %start lines
-
- %% /***********************************************************************/
-
- lines
- :
- | lines stmt '\n'
- ;
-
- stmt
- : expr {
- printf(" %lg %s %s %s\n",
- $1, rhex($1), oct($1), bin($1));
- lr_save($1);
- }
- | error '\n' { yyerrok; }
- | ID '=' expr { id_val[(long)$1] = $3; lr_save($3); }
- ;
-
- expr
- : INUM { $$ = $1; }
- | ID { $$ = id_val[$1]; }
- | LAST_RESULT { $$ = lr_recall($1); }
- | expr '+' expr { $$ = $1 + $3; }
- | expr '-' expr { $$ = $1 - $3; }
- | expr '*' expr { $$ = $1 * $3; }
- | expr '/' expr { $$ = $1 / $3; }
- | expr '%' expr { $$ = (long)$1 % (long)$3; }
- | expr '<' expr { $$ = ldexp($1, (long)$3); }
- | expr '>' expr { $$ = ldexp($1, -(long)$3); }
- | expr '&' expr { $$ = (long)$1 & (long)$3; }
- | expr '|' expr { $$ = (long)$1 | (long)$3; }
- | expr '^' expr { $$ = (long)$1 ^ (long)$3; }
- | expr POWER expr { $$ = do_power($1, $3); }
- | '-' expr %prec UNARYMINUS { $$ = - $2; }
- | '~' expr %prec UNARYMINUS { $$ = ~ (long)$2; }
- | '(' expr ')' { $$ = $2; }
- | ID '(' expr ')' { $$ = do_call($1, $3); }
- ;
-
- %%
-
- char *oct(double d)
- {
- long n;
- static char buf[30];
- if ((d > 0x7fffffff) || (d < -0x7fffffff))
- return "";
- n = (long)d;
- if (n)
- {
- sprintf(buf, "0%o", n);
- return buf;
- }
- else
- return "0";
- }
-
- char *bin(double d)
- {
- long n;
- static char buf[] = " xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx";
- int i;
- char *rv;
- char *bp = buf+5*8-1;
- if ((d > 0x7fffffff) || (d < -0x7fffffff))
- return "";
- n = (long)d;
- if (n == 0)
- return "0";
- for (i=31; i>=0; i--)
- {
- *bp-- = '0' + (n & 1);
- n >>= 1;
- if (i % 4 == 0)
- bp--;
- }
- rv = buf;
- for (i=0; i<7; i++)
- {
- if (strncmp(rv+1, "0000", 4))
- return rv+1;
- rv += 5;
- }
- return rv+1;
- }
-
- char *rhex(double d)
- {
- static char buf[] = "0x12345678.12345678 ";
- int dleft;
- char *cp, *lastdig;
- if ((d > 0x7fffffff) || (d < -0x7fffffff))
- return "<huge>";
- if ((d < 0) && (d != (long)d))
- d--;
- sprintf(buf, "0x%x", (long)d);
- cp = buf+strlen(buf);
- if (d < 0)
- {
- d -= (long)d;
- if (d) d += 1;
- }
- else
- {
- d -= (long)d;
- }
- dleft = 18 - strlen(buf);
- if (d == 0)
- return buf;
- lastdig = cp;
- *cp++ = '.';
- while (dleft)
- {
- d *= 16;
- *cp++ = "0123456789abcdef"[(long)d];
- if (d)
- lastdig = cp;
- d -= (long)d;
- dleft--;
- }
- *lastdig = 0;
- return buf;
- }
-
- typedef double (*FUNC)(double);
-
- struct {
- char *name;
- FUNC func;
- } funclist[] = {
- "sin", sin,
- "sinh", sinh,
- "cos", cos,
- "cosh", cosh,
- "tan", tan,
- "tanh", tanh,
- "asin", asin,
- "asinh", asinh,
- "acos", acos,
- "acosh", acosh,
- "atan", atan,
- "atanh", atanh,
- "exp", exp,
- "log", log,
- "pow10", pow10,
- "log10", log10,
- "pow2", pow2,
- "log2", log2,
- "sqrt", sqrt,
- 0,0
- };
-
- double do_call(int fp, double arg)
- {
- int i;
- for (i=0; funclist[i].name; i++)
- if (strcmp(funclist[i].name, id_name[fp]) == 0)
- return (funclist[i].func)(arg);
- printf("Unknown function `%s'\n", id_name[fp]);
- return 0;
- }
-
- double do_power(double a, double b)
- {
- return pow(a, b);
- }
-
- #define LAST_SIZE 10
- double last_result[LAST_SIZE];
- int last_idx;
-
- void lr_save(double d)
- {
- last_result[last_idx] = d;
- last_idx = (last_idx+LAST_SIZE-1) % LAST_SIZE;
- }
-
- double lr_recall(int n)
- {
- if (n > LAST_SIZE)
- {
- printf("Can't recall that far back\n");
- return 0;
- }
- return last_result[(last_idx+n)%LAST_SIZE];
- }
-