update: evaluateCondition now needs allocator
This commit is contained in:
parent
9e1e3c2039
commit
1e94763ba1
1 changed files with 114 additions and 0 deletions
114
src/renderer.zig
114
src/renderer.zig
|
|
@ -291,4 +291,118 @@ pub const Renderer = struct {
|
||||||
.null => false,
|
.null => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn evaluateCondition(self: *const Renderer, allocator: Allocator, expr: []const u8) RenderError!bool {
|
||||||
|
const trimmed = std.mem.trim(u8, expr, " \t\r\n");
|
||||||
|
if (trimmed.len == 0) return false;
|
||||||
|
|
||||||
|
var parts = std.mem.splitScalar(u8, trimmed, ' ');
|
||||||
|
|
||||||
|
// Coleta tokens não vazios
|
||||||
|
var tokens = std.ArrayList([]const u8){};
|
||||||
|
defer tokens.deinit(allocator);
|
||||||
|
|
||||||
|
while (parts.next()) |part| {
|
||||||
|
const t = std.mem.trim(u8, part, " \t\r\n");
|
||||||
|
if (t.len > 0) try tokens.append(allocator, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caso simples: só nome de variável
|
||||||
|
if (tokens.items.len == 1) {
|
||||||
|
const value = self.context.get(tokens.items[0]) orelse Value.null;
|
||||||
|
return isTruthy(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caso especial: "not variavel"
|
||||||
|
if (tokens.items.len == 2 and std.mem.eql(u8, tokens.items[0], "not")) {
|
||||||
|
const value = self.context.get(tokens.items[1]) orelse Value.null;
|
||||||
|
return !isTruthy(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caso com operadores de comparação: var op valor
|
||||||
|
if (tokens.items.len == 3) {
|
||||||
|
const left = tokens.items[0];
|
||||||
|
const op = tokens.items[1];
|
||||||
|
const right_str = tokens.items[2];
|
||||||
|
|
||||||
|
const left_value = self.context.get(left) orelse Value.null;
|
||||||
|
const right_value = parseLiteral(right_str);
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, op, ">")) return compare(left_value, right_value, .gt);
|
||||||
|
if (std.mem.eql(u8, op, "<")) return compare(left_value, right_value, .lt);
|
||||||
|
if (std.mem.eql(u8, op, ">=")) return compare(left_value, right_value, .ge);
|
||||||
|
if (std.mem.eql(u8, op, "<=")) return compare(left_value, right_value, .le);
|
||||||
|
if (std.mem.eql(u8, op, "==")) return compare(left_value, right_value, .eq);
|
||||||
|
if (std.mem.eql(u8, op, "!=")) return compare(left_value, right_value, .ne);
|
||||||
|
|
||||||
|
return error.InvalidSyntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caso mais complexo (and/or/not composto) - por enquanto erro
|
||||||
|
return error.UnsupportedExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Função auxiliar: converte string literal pra Value
|
||||||
|
fn parseLiteral(str: []const u8) Value {
|
||||||
|
const trimmed = std.mem.trim(u8, str, " \t\r\n\"'");
|
||||||
|
if (std.mem.eql(u8, trimmed, "true")) return Value{ .bool = true };
|
||||||
|
if (std.mem.eql(u8, trimmed, "false")) return Value{ .bool = false };
|
||||||
|
if (std.mem.eql(u8, trimmed, "null")) return Value.null;
|
||||||
|
|
||||||
|
if (std.fmt.parseInt(i64, trimmed, 10)) |n| return Value{ .int = n } else |_| {}
|
||||||
|
if (std.fmt.parseFloat(f64, trimmed)) |f| return Value{ .float = f } else |_| {}
|
||||||
|
|
||||||
|
return Value{ .string = trimmed };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Função auxiliar: truthy check
|
||||||
|
fn isTruthy(v: Value) bool {
|
||||||
|
return switch (v) {
|
||||||
|
.null => false,
|
||||||
|
.bool => |b| b,
|
||||||
|
.int => |i| i != 0,
|
||||||
|
.float => |f| f != 0.0,
|
||||||
|
.string => |s| s.len > 0,
|
||||||
|
.list => |l| l.len > 0,
|
||||||
|
.dict => |d| d.count() > 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Função auxiliar: comparação
|
||||||
|
fn compare(left: Value, right: Value, op: enum { gt, lt, ge, le, eq, ne, not }) bool {
|
||||||
|
// Implementação básica (expanda conforme necessário)
|
||||||
|
switch (left) {
|
||||||
|
.int => |l| switch (right) {
|
||||||
|
.int => |r| return switch (op) {
|
||||||
|
.gt => l > r,
|
||||||
|
.lt => l < r,
|
||||||
|
.ge => l >= r,
|
||||||
|
.le => l <= r,
|
||||||
|
.eq => l == r,
|
||||||
|
.ne, .not => l != r,
|
||||||
|
},
|
||||||
|
else => return false,
|
||||||
|
},
|
||||||
|
.float => |l| switch (right) {
|
||||||
|
.float => |r| return switch (op) {
|
||||||
|
.gt => l > r,
|
||||||
|
.lt => l < r,
|
||||||
|
.ge => l >= r,
|
||||||
|
.le => l <= r,
|
||||||
|
.eq => l == r,
|
||||||
|
.ne, .not => l != r,
|
||||||
|
},
|
||||||
|
else => return false,
|
||||||
|
},
|
||||||
|
.string => |l| switch (right) {
|
||||||
|
.string => |r| return switch (op) {
|
||||||
|
.eq => std.mem.eql(u8, l, r),
|
||||||
|
.ne, .not => !std.mem.eql(u8, l, r),
|
||||||
|
else => false,
|
||||||
|
},
|
||||||
|
else => return false,
|
||||||
|
},
|
||||||
|
else => return false,
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue