/* Operators: ==, != (left-associative) */ static ASTNode *parse_comparison(Parser *p) { ASTNode *expr = parse_relational(p); loop: switch (peek_id(p)) { case TOK_EQUAL: /* == */ accept(p); ignore_eols(p); expr = ast_create_2(AST_IS_EQUAL, expr, parse_comparison(p)); goto loop; case TOK_NOT_EQUAL: /* != */ accept(p); ignore_eols(p); expr = ast_create_2(AST_IS_NOT_EQUAL, expr, parse_comparison(p)); goto loop; } return expr; }
/* 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; }
/* Operators: =, +=, -=, /=, *= (right-associative) */ static ASTNode *parse_assign(Parser *p) { ASTNode *expr = parse_comparison(p); switch (peek_id(p)) { case TOK_ASSIGN: accept(p); ignore_eols(p); expr = ast_create_2(AST_ASSIGN, expr, parse_assign(p)); break; } return expr; }