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 >
Internet Message Format  |  1987-04-02  |  3KB

  1. From erikb@cs.vu.nl Fri Apr  3 01:17:58 1987
  2. Path: seismo!mcvax!botter!erikb
  3. From: erikb@cs.vu.nl (Erik Baalbergen)
  4. Newsgroups: comp.os.minix
  5. Subject: expr(1) source
  6. Message-ID: <1133@botter.cs.vu.nl>
  7. Date: 3 Apr 87 06:17:58 GMT
  8. Sender: remote@cs.vu.nl
  9. Reply-To: erikb@cs.vu.nl (Erik Baalbergen)
  10. Distribution: world
  11. Organization: V.U. Informatica, Amsterdam
  12. Lines: 189
  13.  
  14. Here's the source for expr(1). Like test(1), this program was not part
  15. of the Minix distribution. Unfortunately, I didn't have time to implement
  16. the ':' operator. Maybe there's someone else out there who will do the job...
  17.  
  18. Erik Baalbergen
  19. -- cut here --
  20. /* expr(1)  --  author Erik Baalbergen */
  21.  
  22. /* expr accepts the following grammar:
  23.     expr ::= expr operator expr | "(" expr ")" ;
  24.   where the priority of the operators is taken care of.
  25.   The resulting value is printed on stdout.
  26.   Note that the ":"-operator is not implemented.
  27. */
  28.  
  29. #define EOI    0
  30. #define OR    1
  31. #define AND    2
  32. #define LT    3
  33. #define LE    4
  34. #define EQ    5
  35. #define NE    6
  36. #define GE    7
  37. #define GT    8
  38. #define PLUS    9
  39. #define MINUS    10
  40. #define TIMES    11
  41. #define DIV    12
  42. #define MOD    13
  43. #define COLON    14
  44. #define LPAREN    15
  45. #define RPAREN    16
  46. #define OPERAND    20
  47.  
  48. #define MAXPRIO    6
  49.  
  50. struct op {
  51.     char *op_text;
  52.     short op_num, op_prio;
  53. } ops[] = {
  54.     {"|",    OR,    6},
  55.     {"&",    AND,    5},
  56.     {"<",    LT,    4},
  57.     {"<=",    LE,    4},
  58.     {"=",    EQ,    4},
  59.     {"!=",    NE,    4},
  60.     {">=",    GE,    4},
  61.     {">",    GT,    4},
  62.     {"+",    PLUS,    3},
  63.     {"-",    MINUS,    3},
  64.     {"*",    TIMES,    2},
  65.     {"/",    DIV,    2},
  66.     {"%",    MOD,    2},
  67.     /* {":",    COLON,    1}, */
  68.     {"(",    LPAREN,    0},
  69.     {")",    RPAREN,    0},
  70.     {0, 0, 0}
  71. };
  72.  
  73. long eval(), expr();
  74. char *prog;
  75. char **ip;
  76. struct op *ip_op;
  77.  
  78. main(argc, argv)
  79.     char *argv[];
  80. {
  81.     long res;
  82.  
  83.     prog = argv[0];
  84.     ip = &argv[1];
  85.     res = expr(lex(*ip), MAXPRIO);
  86.     if (*++ip != 0)
  87.         syntax();
  88.     printf("%ld\n", res);
  89.     exit(0);
  90. }
  91.  
  92. lex(s)
  93.     register char *s;
  94. {
  95.     register struct op *op = ops;
  96.  
  97.     if (s == 0) {
  98.         ip_op = 0;
  99.         return EOI;
  100.     }
  101.     while (op->op_text) {
  102.         if (strcmp(s, op->op_text) == 0) {
  103.             ip_op = op;
  104.             return op->op_num;
  105.         }
  106.         op++;
  107.     }
  108.     ip_op = 0;
  109.     return OPERAND;
  110. }
  111.  
  112. long
  113. num(s)
  114.     register char *s;
  115. {
  116.     long l = 0;
  117.     long sign = 1;
  118.  
  119.     if (*s == '\0')
  120.         syntax();
  121.     if (*s == '-') {
  122.         sign = -1;
  123.         s++;
  124.     }
  125.     while (*s >= '0' && *s <= '9')
  126.         l = l * 10 + *s++ - '0';
  127.     if (*s != '\0')
  128.         syntax();
  129.     return sign * l;
  130. }
  131.  
  132. syntax()
  133. {
  134.     write(2, prog, strlen(prog));
  135.     write(2, ": syntax error\n", 15);
  136.     exit(1);
  137. }
  138.  
  139. long
  140. expr(n, prio)
  141. {
  142.     long res;
  143.  
  144.     if (n == EOI)
  145.         syntax();
  146.     if (n == LPAREN) {
  147.         res = expr(lex(*++ip), MAXPRIO);
  148.         if (lex(*++ip) != RPAREN)
  149.             syntax();
  150.         return res;
  151.     }
  152.     if (n != OPERAND)
  153.         syntax();
  154.     if (prio == 0)
  155.         return num(*ip);
  156.     res = expr(n, prio - 1);
  157.     while ((n = lex(*++ip)) && ip_op && ip_op->op_prio == prio)
  158.         res = eval(res, n, expr(lex(*++ip), prio - 1));
  159.     ip--;
  160.     return res;
  161. }
  162.  
  163. long
  164. eval(l1, op, l2)
  165.     long l1, l2;
  166. {
  167.     switch (op) {
  168.     case OR:
  169.         return l1 ? l1 : l2;
  170.     case AND:
  171.         return (l1 && l2) ? l1 : 0;
  172.     case LT:
  173.         return l1 < l2;
  174.     case LE:
  175.         return l1 <= l2;
  176.     case EQ:
  177.         return l1 == l2;
  178.     case NE:
  179.         return l1 != l2;
  180.     case GE:
  181.         return l1 >= l2;
  182.     case GT:
  183.         return l1 > l2;
  184.     case PLUS:
  185.         return l1 + l2;
  186.     case MINUS:
  187.         return l1 - l2;
  188.     case TIMES:
  189.         return l1 * l2;
  190.     case DIV:
  191.         return l1 / l2;
  192.     case MOD:
  193.         return l1 % l2;
  194.     }
  195.     fatal();
  196. }
  197.  
  198. fatal()
  199. {
  200.     write(2, "fatal\n", 6);
  201.     exit(1);
  202. }
  203.  
  204.  
  205.