9 Expr = Or | Or '?' Expr ':' Expr
10 Or = And | Or '||' And
11 And = Eq | And '&&' Eq
12 Eq = Rel | Eq '==' Rel | Eq '!=' Rel
13 Rel = Add | Rel '<=' Add | Rel '>=' Add | Rel '<' Add | Rel '>' Add
14 Add = Mul | Add '+' Mul | Add '-' Mul
15 Mul = Prim | Mul '*' Prim | Mul '/' Prim | Mul '%' Prim
16 Prim = '(' Expr ')' | '!' Prim | decimal | 'n'
20 recursive descent expression evaluator with stack depth limit.
21 for binary operators an operator-precedence parser is used.
22 eval* functions store the result of the parsed subexpression
23 and return a pointer to the next non-space character.
32 static const char *skipspace(const char *s
)
34 while (isspace(*s
)) s
++;
38 static const char *evalexpr(struct st
*st
, const char *s
, int d
);
40 static const char *evalprim(struct st
*st
, const char *s
, int d
)
43 if (--d
< 0) return "";
46 st
->r
= strtoul(s
, &e
, 10);
47 if (e
== s
|| st
->r
== -1) return "";
52 return skipspace(s
+1);
55 s
= evalexpr(st
, s
+1, d
);
56 if (*s
!= ')') return "";
57 return skipspace(s
+1);
60 s
= evalprim(st
, s
+1, d
);
67 static int binop(struct st
*st
, int op
, unsigned long left
)
69 unsigned long a
= left
, b
= st
->r
;
71 case 0: st
->r
= a
||b
; return 0;
72 case 1: st
->r
= a
&&b
; return 0;
73 case 2: st
->r
= a
==b
; return 0;
74 case 3: st
->r
= a
!=b
; return 0;
75 case 4: st
->r
= a
>=b
; return 0;
76 case 5: st
->r
= a
<=b
; return 0;
77 case 6: st
->r
= a
>b
; return 0;
78 case 7: st
->r
= a
<b
; return 0;
79 case 8: st
->r
= a
+b
; return 0;
80 case 9: st
->r
= a
-b
; return 0;
81 case 10: st
->r
= a
*b
; return 0;
82 case 11: if (b
) {st
->r
= a
%b
; return 0;} return 1;
83 case 12: if (b
) {st
->r
= a
/b
; return 0;} return 1;
88 static const char *parseop(struct st
*st
, const char *s
)
90 static const char opch
[11] = "|&=!><+-*%/";
91 static const char opch2
[6] = "|&====";
95 /* note: >,< are accepted with or without = */
96 if (i
<6 && s
[1] == opch2
[i
]) {
110 static const char *evalbinop(struct st
*st
, const char *s
, int minprec
, int d
)
112 static const char prec
[14] = {1,2,3,3,4,4,4,4,5,5,6,6,6,0};
116 s
= evalprim(st
, s
, d
);
120 st->r (left hand side value) and st->op are now set,
121 get the right hand side or back out if op has low prec,
122 if op was missing then prec[op]==0
125 if (prec
[op
] <= minprec
)
128 s
= evalbinop(st
, s
, prec
[op
], d
);
129 if (binop(st
, op
, left
))
134 static const char *evalexpr(struct st
*st
, const char *s
, int d
)
139 s
= evalbinop(st
, s
, 0, d
);
143 s
= evalexpr(st
, s
+1, d
);
147 s
= evalexpr(st
, s
+1, d
);
148 st
->r
= a
? b
: st
->r
;
152 unsigned long __pleval(const char *s
, unsigned long n
)
156 s
= evalexpr(&st
, s
, 100);
157 return *s
== ';' ? st
.r
: -1;