mpick: add ternary (conditional) operator

pull/174/head
Duncaen 5 years ago committed by Leah Neukirchen
parent 3968f2ef03
commit 8f0b6e2117

@ -92,7 +92,8 @@ Unread messages.
.Nm .Nm
tests are given by the following EBNF: tests are given by the following EBNF:
.Bd -literal .Bd -literal
<expr> ::= <expr> || <expr> -- disjunction <expr> ::= <expr> ? <expr> : <expr> -- ternary operator
| <expr> || <expr> -- disjunction
| <expr> && <expr> -- conjunction | <expr> && <expr> -- conjunction
| ! <expr> -- negation | ! <expr> -- negation
| ( <expr> ) | ( <expr> )

@ -46,6 +46,7 @@
enum op { enum op {
EXPR_OR = 1, EXPR_OR = 1,
EXPR_AND, EXPR_AND,
EXPR_COND,
EXPR_NOT, EXPR_NOT,
EXPR_LT, EXPR_LT,
EXPR_LE, EXPR_LE,
@ -115,7 +116,7 @@ struct expr {
int64_t num; int64_t num;
regex_t *regex; regex_t *regex;
enum var var; enum var var;
} a, b; } a, b, c;
int extra; int extra;
}; };
@ -263,7 +264,7 @@ parse_op()
} }
static struct expr *parse_cmp(); static struct expr *parse_cmp();
static struct expr *parse_or(); static struct expr *parse_cond();
static struct expr * static struct expr *
parse_inner() parse_inner()
@ -285,7 +286,7 @@ parse_inner()
not->a.expr = e; not->a.expr = e;
return not; return not;
} else if (token("(")) { } else if (token("(")) {
struct expr *e = parse_or(); struct expr *e = parse_cond();
if (token(")")) if (token(")"))
return e; return e;
parse_error("missing ) at '%.15s'", pos); parse_error("missing ) at '%.15s'", pos);
@ -723,10 +724,33 @@ parse_or()
} }
static struct expr * static struct expr *
parse_expr(char *s) parse_cond()
{
struct expr *e1 = parse_or();
if (token("?")) {
struct expr *e2 = parse_or();
if (token(":")) {
struct expr *e3 = parse_cond();
struct expr *r = mkexpr(EXPR_COND);
r->a.expr = e1;
r->b.expr = e2;
r->c.expr = e3;
return r;
} else {
parse_error("expected : at '%.15s'", pos);
}
}
return e1;
}
static struct expr *
parse_expr()
{ {
pos = s; pos = s;
struct expr *e = parse_or(); struct expr *e = parse_cond();
if (*pos) if (*pos)
parse_error("trailing garbage at '%.15s'", pos); parse_error("trailing garbage at '%.15s'", pos);
return e; return e;
@ -942,6 +966,10 @@ eval(struct expr *e, struct mailinfo *m)
return eval(e->a.expr, m) || eval(e->b.expr, m); return eval(e->a.expr, m) || eval(e->b.expr, m);
case EXPR_AND: case EXPR_AND:
return eval(e->a.expr, m) && eval(e->b.expr, m); return eval(e->a.expr, m) && eval(e->b.expr, m);
case EXPR_COND:
return eval(e->a.expr, m)
? eval(e->b.expr, m)
: eval(e->c.expr, m);
case EXPR_NOT: case EXPR_NOT:
return !eval(e->a.expr, m); return !eval(e->a.expr, m);
return 1; return 1;

Loading…
Cancel
Save