aboutsummaryrefslogtreecommitdiff
path: root/parse.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-02-11 23:09:00 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-02-11 23:09:00 -0500
commitddd9f6e5d542fca3186558e4d6603c4b05967121 (patch)
treedc70fdf5b0efecf30058c704ca10d7808c543fdf /parse.c
parent7d6af5f4c7663bddf4dad4a58c770dbdd299e022 (diff)
Fix operator precedence and boolification
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c74
1 files changed, 37 insertions, 37 deletions
diff --git a/parse.c b/parse.c
index 6488b2c5..37c33eb4 100644
--- a/parse.c
+++ b/parse.c
@@ -30,16 +30,17 @@ extern void builtin_fail(const char *fmt, ...);
#define STUB_PARSER(name) PARSER(name) { (void)ctx; (void)pos; return NULL; }
int op_tightness[] = {
- [BINOP_POWER]=1,
- [BINOP_MULT]=2, [BINOP_DIVIDE]=2, [BINOP_MOD]=2, [BINOP_MOD1]=2,
- [BINOP_PLUS]=3, [BINOP_MINUS]=3,
- [BINOP_CONCAT]=4,
+ [BINOP_POWER]=9,
+ [BINOP_MULT]=8, [BINOP_DIVIDE]=8, [BINOP_MOD]=8, [BINOP_MOD1]=8,
+ [BINOP_PLUS]=7, [BINOP_MINUS]=7,
+ [BINOP_CONCAT]=6,
[BINOP_LSHIFT]=5, [BINOP_RSHIFT]=5,
- [BINOP_MIN]=6, [BINOP_MAX]=6,
- [BINOP_EQ]=7, [BINOP_NE]=7,
- [BINOP_LT]=8, [BINOP_LE]=8, [BINOP_GT]=8, [BINOP_GE]=8,
- [BINOP_AND]=9, [BINOP_OR]=9, [BINOP_XOR]=9,
+ [BINOP_MIN]=4, [BINOP_MAX]=4,
+ [BINOP_EQ]=3, [BINOP_NE]=3,
+ [BINOP_LT]=2, [BINOP_LE]=2, [BINOP_GT]=2, [BINOP_GE]=2,
+ [BINOP_AND]=1, [BINOP_OR]=1, [BINOP_XOR]=1,
};
+#define MAX_TIGHTNESS 9
static const char *keywords[] = {
"yes", "xor", "while", "use", "then", "struct", "stop", "skip", "return",
@@ -1172,39 +1173,38 @@ static ast_t *parse_infix_expr(parse_ctx_t *ctx, const char *pos, int min_tightn
if (!lhs) return NULL;
spaces(&pos);
- binop_e op = match_binary_operator(&pos);
- if (op == BINOP_UNKNOWN || op_tightness[op] < min_tightness)
- return lhs;
+ for (binop_e op; (op=match_binary_operator(&pos)) != BINOP_UNKNOWN && op_tightness[op] >= min_tightness; spaces(&pos)) {
+ ast_t *key = NULL;
+ if (op == BINOP_MIN || op == BINOP_MAX) {
+ key = NewAST(ctx->file, pos, pos, Var, .name=op == BINOP_MIN ? "_min_" : "_max_");
+ for (bool progress = true; progress; ) {
+ ast_t *new_term;
+ progress = (false
+ || (new_term=parse_index_suffix(ctx, key))
+ || (new_term=parse_field_suffix(ctx, key))
+ || (new_term=parse_fncall_suffix(ctx, key, NORMAL_FUNCTION))
+ );
+ if (progress) key = new_term;
+ }
+ if (key->tag == Var) key = NULL;
+ else pos = key->end;
- ast_t *key = NULL;
- if (op == BINOP_MIN || op == BINOP_MAX) {
- key = NewAST(ctx->file, pos, pos, Var, .name=op == BINOP_MIN ? "_min_" : "_max_");
- for (bool progress = true; progress; ) {
- ast_t *new_term;
- progress = (false
- || (new_term=parse_index_suffix(ctx, key))
- || (new_term=parse_field_suffix(ctx, key))
- || (new_term=parse_fncall_suffix(ctx, key, NORMAL_FUNCTION))
- );
- if (progress) key = new_term;
}
- if (key->tag == Var) key = NULL;
- else pos = key->end;
+ spaces(&pos);
+ ast_t *rhs = parse_infix_expr(ctx, pos, op_tightness[op] + 1);
+ if (!rhs) break;
+ pos = rhs->end;
+
+ if (op == BINOP_MIN) {
+ return NewAST(ctx->file, lhs->start, rhs->end, Min, .lhs=lhs, .rhs=rhs, .key=key);
+ } else if (op == BINOP_MAX) {
+ return NewAST(ctx->file, lhs->start, rhs->end, Max, .lhs=lhs, .rhs=rhs, .key=key);
+ } else {
+ lhs = NewAST(ctx->file, lhs->start, rhs->end, BinaryOp, .lhs=lhs, .op=op, .rhs=rhs);
+ }
}
- spaces(&pos);
- ast_t *rhs = parse_infix_expr(ctx, pos, op_tightness[op]);
- if (!rhs) return lhs;
- pos = rhs->end;
-
- switch (op) {
- case BINOP_MIN:
- return NewAST(ctx->file, lhs->start, rhs->end, Min, .lhs=lhs, .rhs=rhs, .key=key);
- case BINOP_MAX:
- return NewAST(ctx->file, lhs->start, rhs->end, Max, .lhs=lhs, .rhs=rhs, .key=key);
- default:
- return NewAST(ctx->file, lhs->start, rhs->end, BinaryOp, .lhs=lhs, .rhs=rhs, .op=op);
- }
+ return lhs;
}
ast_t *parse_expr(parse_ctx_t *ctx, const char *pos) {