Add comparisons: >, <, ==, !=. They return 1 for true, 0 for false, and bind more loosely than addition.
We're adding a new precedence layer above the current expression. So:
1. Rename the current parseExpression (which loops on +/-) to parseAddSub. Update the recursive call inside parseFactor.
2. Add a new parseExpression on top that handles comparisons -- it calls parseAddSub for the left operand, then checks for a comparison operator, then calls parseAddSub again for the right.
For == and !=, check two characters: source[pos.*] and source[pos.* + 1].
testCase("5 > 3", 1);
testCase("2 > 7", 0);
testCase("3 == 3", 1);
testCase("3 != 3", 0);
Rename the old expression function to parseAddSub:
fn parseAddSub(source: [*]const u8, pos: *usize) i64 {
var val: i64 = parseTerm(source, pos);
while (source[pos.*] == '+' or source[pos.*] == '-') {
const op: u8 = source[pos.*];
pos.* += 1;
skipSpaces(source, pos);
const right: i64 = parseTerm(source, pos);
val = switch (op) {
'+' => val + right,
'-' => val - right,
else => val,
};
}
return val;
}
Then the new parseExpression on top:
fn parseExpression(source: [*]const u8, pos: *usize) i64 {
const left: i64 = parseAddSub(source, pos);
const c: u8 = source[pos.*];
if (c == '>') {
pos.* += 1;
skipSpaces(source, pos);
return if (left > parseAddSub(source, pos)) @as(i64, 1) else 0;
}
if (c == '<') {
pos.* += 1;
skipSpaces(source, pos);
return if (left < parseAddSub(source, pos)) @as(i64, 1) else 0;
}
if (c == '=' and source[pos.* + 1] == '=') {
pos.* += 2;
skipSpaces(source, pos);
return if (left == parseAddSub(source, pos)) @as(i64, 1) else 0;
}
if (c == '!' and source[pos.* + 1] == '=') {
pos.* += 2;
skipSpaces(source, pos);
return if (left != parseAddSub(source, pos)) @as(i64, 1) else 0;
}
return left;
}
Don't forget to update the recursive call in parseFactor -- when we see (, we recurse into parseExpression (the new top), not parseAddSub.