home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1994 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1994.iso
/
netsrcs
/
v7_expr
< prev
next >
Wrap
Internet Message Format
|
1987-04-02
|
3KB
From erikb@cs.vu.nl Fri Apr 3 01:17:58 1987
Path: seismo!mcvax!botter!erikb
From: erikb@cs.vu.nl (Erik Baalbergen)
Newsgroups: comp.os.minix
Subject: expr(1) source
Message-ID: <1133@botter.cs.vu.nl>
Date: 3 Apr 87 06:17:58 GMT
Sender: remote@cs.vu.nl
Reply-To: erikb@cs.vu.nl (Erik Baalbergen)
Distribution: world
Organization: V.U. Informatica, Amsterdam
Lines: 189
Here's the source for expr(1). Like test(1), this program was not part
of the Minix distribution. Unfortunately, I didn't have time to implement
the ':' operator. Maybe there's someone else out there who will do the job...
Erik Baalbergen
-- cut here --
/* expr(1) -- author Erik Baalbergen */
/* expr accepts the following grammar:
expr ::= expr operator expr | "(" expr ")" ;
where the priority of the operators is taken care of.
The resulting value is printed on stdout.
Note that the ":"-operator is not implemented.
*/
#define EOI 0
#define OR 1
#define AND 2
#define LT 3
#define LE 4
#define EQ 5
#define NE 6
#define GE 7
#define GT 8
#define PLUS 9
#define MINUS 10
#define TIMES 11
#define DIV 12
#define MOD 13
#define COLON 14
#define LPAREN 15
#define RPAREN 16
#define OPERAND 20
#define MAXPRIO 6
struct op {
char *op_text;
short op_num, op_prio;
} ops[] = {
{"|", OR, 6},
{"&", AND, 5},
{"<", LT, 4},
{"<=", LE, 4},
{"=", EQ, 4},
{"!=", NE, 4},
{">=", GE, 4},
{">", GT, 4},
{"+", PLUS, 3},
{"-", MINUS, 3},
{"*", TIMES, 2},
{"/", DIV, 2},
{"%", MOD, 2},
/* {":", COLON, 1}, */
{"(", LPAREN, 0},
{")", RPAREN, 0},
{0, 0, 0}
};
long eval(), expr();
char *prog;
char **ip;
struct op *ip_op;
main(argc, argv)
char *argv[];
{
long res;
prog = argv[0];
ip = &argv[1];
res = expr(lex(*ip), MAXPRIO);
if (*++ip != 0)
syntax();
printf("%ld\n", res);
exit(0);
}
lex(s)
register char *s;
{
register struct op *op = ops;
if (s == 0) {
ip_op = 0;
return EOI;
}
while (op->op_text) {
if (strcmp(s, op->op_text) == 0) {
ip_op = op;
return op->op_num;
}
op++;
}
ip_op = 0;
return OPERAND;
}
long
num(s)
register char *s;
{
long l = 0;
long sign = 1;
if (*s == '\0')
syntax();
if (*s == '-') {
sign = -1;
s++;
}
while (*s >= '0' && *s <= '9')
l = l * 10 + *s++ - '0';
if (*s != '\0')
syntax();
return sign * l;
}
syntax()
{
write(2, prog, strlen(prog));
write(2, ": syntax error\n", 15);
exit(1);
}
long
expr(n, prio)
{
long res;
if (n == EOI)
syntax();
if (n == LPAREN) {
res = expr(lex(*++ip), MAXPRIO);
if (lex(*++ip) != RPAREN)
syntax();
return res;
}
if (n != OPERAND)
syntax();
if (prio == 0)
return num(*ip);
res = expr(n, prio - 1);
while ((n = lex(*++ip)) && ip_op && ip_op->op_prio == prio)
res = eval(res, n, expr(lex(*++ip), prio - 1));
ip--;
return res;
}
long
eval(l1, op, l2)
long l1, l2;
{
switch (op) {
case OR:
return l1 ? l1 : l2;
case AND:
return (l1 && l2) ? l1 : 0;
case LT:
return l1 < l2;
case LE:
return l1 <= l2;
case EQ:
return l1 == l2;
case NE:
return l1 != l2;
case GE:
return l1 >= l2;
case GT:
return l1 > l2;
case PLUS:
return l1 + l2;
case MINUS:
return l1 - l2;
case TIMES:
return l1 * l2;
case DIV:
return l1 / l2;
case MOD:
return l1 % l2;
}
fatal();
}
fatal()
{
write(2, "fatal\n", 6);
exit(1);
}