home *** CD-ROM | disk | FTP | other *** search
- 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);
- }
-
-
-