static bool parse_expr(ExprParseState *state) { /* Temporarily set the constant expression evaluation barrier */ int prev_last_jmp = state->last_jmp; int start = state->last_jmp = state->ops_count; CHECK_ERROR(parse_or(state)); if (state->token == TOKEN_IF) { /* Ternary IF expression in python requires swapping the * main body with condition, so stash the body opcodes. */ int size = state->ops_count - start; int bytes = size * sizeof(ExprOp); ExprOp *body = MEM_mallocN(bytes, "driver if body"); memcpy(body, state->ops + start, bytes); state->last_jmp = state->ops_count = start; state->stack_ptr--; /* Parse condition. */ if (!parse_next_token(state) || !parse_or(state) || state->token != TOKEN_ELSE || !parse_next_token(state)) { MEM_freeN(body); return false; } int jmp_else = parse_add_jump(state, OPCODE_JMP_ELSE); /* Add body back. */ memcpy(parse_alloc_ops(state, size), body, bytes); MEM_freeN(body); state->stack_ptr++; int jmp_end = parse_add_jump(state, OPCODE_JMP); /* Parse the else block. */ parse_set_jump(state, jmp_else); CHECK_ERROR(parse_expr(state)); parse_set_jump(state, jmp_end); } /* If no actual jumps happened, restore previous barrier */ else if (state->last_jmp == start) { state->last_jmp = prev_last_jmp; } return true; }
/* Parse STRING. On success, return the parsed expression tree. On error, set *ERROR to an error string (for free()) or NULL, and return NULL. (*ERROR == NULL is allowed to handle out-of-memory errors) */ struct expr * expr_parse(const char *string, char **error) { struct parsing p; struct expr *res; p.error = error; p.token_value = NULL; p.src = string; if (lex(&p) != 0) goto err; if (p.token == T_EOF) { *error = strdup("Empty expression"); goto err; } res = parse_or(&p); if (res != NULL && p.token != T_EOF) { expr_free(res); *error = NULL; asprintf(error, "Unexpected trailing token `%.*s'", p.token_len, p.token_start); goto err; } free(p.token_value); return res; err: free(p.token_value); return NULL; }
static struct expr * parse_inner() { if (token("prune")) { struct expr *e = mkexpr(EXPR_PRUNE); return e; } else if (token("print")) { struct expr *e = mkexpr(EXPR_PRINT); return e; } else if (token("!")) { struct expr *e = parse_cmp(); struct expr *not = mkexpr(EXPR_NOT); not->a.expr = e; return not; } else if (token("(")) { struct expr *e = parse_or(); if (token(")")) return e; parse_error("missing ) at '%.15s'", pos); return 0; } else { parse_error("unknown expression at '%.15s'", pos); return 0; } }
static struct expr * parse_expr(char *s) { pos = s; struct expr *e = parse_or(); if (*pos) parse_error("trailing garbage at '%.15s'", pos); return e; }
/* Parse a primary-expression string in *P. On success, return the parsed primary-expression. On error, set *P->ERROR to an error string (for free()) or NULL, and return NULL. */ static struct expr * parse_primary(struct parsing *p) { struct expr *e; switch (p->token) { case EO_NOT: { struct expr *res; if (lex(p) != 0) return NULL; e = parse_primary(p); if (e == NULL) return NULL; res = parser_malloc(p, sizeof(*res)); if (res == NULL) goto err_e; res->op = EO_NOT; res->v.sub[0] = e; return res; } case T_LEFT_PAREN: { if (lex(p) != 0) return NULL; e = parse_or(p); if (e == NULL) return NULL; if (p->token != T_RIGHT_PAREN) { *p->error = NULL; asprintf(p->error, "Right paren expected, got `%.*s'", p->token_len, p->token_start); goto err_e; } if (lex(p) != 0) goto err_e; return e; } case T_FIELD_ESCAPE: case T_STRING: return parse_comparison(p); default: *p->error = NULL; asprintf(p->error, "Unexpected token `%.*s'", p->token_len, p->token_start); return NULL; } abort(); /* Should never get here */ err_e: expr_free(e); return NULL; }
bool WhereMatcher::parse_and() { bool left = parse_or(); Token t = stream_get(); if(t.first == bool_and) { bool right = parse_and(); return left && right; } else { if (t.first != value_undefined_type) stream_unget(t); return left; } }
static bool parse_or(ExprParseState *state) { CHECK_ERROR(parse_and(state)); if (state->token == TOKEN_OR) { int jump = parse_add_jump(state, OPCODE_JMP_OR); CHECK_ERROR(parse_next_token(state) && parse_or(state)); parse_set_jump(state, jump); } return true; }