Add equals operator to template engine
This commit is contained in:
parent
aee81e27b6
commit
4e3450de4e
2 changed files with 50 additions and 9 deletions
|
@ -15,6 +15,7 @@ pub fn main() !void {
|
||||||
.bar = .{ .x = "x" },
|
.bar = .{ .x = "x" },
|
||||||
.qux = false,
|
.qux = false,
|
||||||
.quxx = true,
|
.quxx = true,
|
||||||
|
.quxx2 = true,
|
||||||
.maybe_foo = @as(?[]const u8, "foo"),
|
.maybe_foo = @as(?[]const u8, "foo"),
|
||||||
.maybe_bar = @as(?[]const u8, null),
|
.maybe_bar = @as(?[]const u8, null),
|
||||||
.x = "y",
|
.x = "y",
|
||||||
|
@ -168,6 +169,7 @@ fn EvaluateExpression(
|
||||||
.arg_deref => |names| Deref(Args, names),
|
.arg_deref => |names| Deref(Args, names),
|
||||||
.capture_deref => |names| Deref(Captures, names),
|
.capture_deref => |names| Deref(Captures, names),
|
||||||
.context_deref => |names| Deref(Context, names),
|
.context_deref => |names| Deref(Context, names),
|
||||||
|
.equals => bool,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +183,16 @@ fn evaluateExpression(
|
||||||
.arg_deref => |names| deref(args, names),
|
.arg_deref => |names| deref(args, names),
|
||||||
.capture_deref => |names| deref(captures, names),
|
.capture_deref => |names| deref(captures, names),
|
||||||
.context_deref => |names| deref(context, names),
|
.context_deref => |names| deref(context, names),
|
||||||
|
.equals => |eql| {
|
||||||
|
const lhs = evaluateExpression(eql.lhs, args, captures, context);
|
||||||
|
const rhs = evaluateExpression(eql.rhs, args, captures, context);
|
||||||
|
const T = @TypeOf(lhs, rhs);
|
||||||
|
if (comptime std.meta.trait.isZigString(T)) {
|
||||||
|
return std.mem.eql(u8, lhs, rhs);
|
||||||
|
} else if (comptime std.meta.trait.isContainer(T) and @hasDecl(T, "eql")) {
|
||||||
|
return T.eql(lhs, rhs);
|
||||||
|
} else return lhs == rhs;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,29 +412,50 @@ fn parseExpression(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIt
|
||||||
comptime {
|
comptime {
|
||||||
var iter = tokens;
|
var iter = tokens;
|
||||||
|
|
||||||
var expr: Expression = while (iter.next()) |token| switch (token) {
|
var last_valid_iter: ?ControlTokenIter = null;
|
||||||
|
var expr: ?Expression = null;
|
||||||
|
while (iter.next()) |token| switch (token) {
|
||||||
.whitespace => {},
|
.whitespace => {},
|
||||||
.period => {
|
.period => {
|
||||||
const names = parseDeref(iter);
|
const names = parseDeref(iter);
|
||||||
iter = names.new_iter;
|
iter = names.new_iter;
|
||||||
break .{ .arg_deref = names.item };
|
expr = .{ .arg_deref = names.item };
|
||||||
|
last_valid_iter = iter;
|
||||||
},
|
},
|
||||||
.dollar => {
|
.dollar => {
|
||||||
const names = parseDeref(iter);
|
const names = parseDeref(iter);
|
||||||
iter = names.new_iter;
|
iter = names.new_iter;
|
||||||
break .{ .capture_deref = names.item };
|
expr = .{ .capture_deref = names.item };
|
||||||
|
last_valid_iter = iter;
|
||||||
},
|
},
|
||||||
.percent => {
|
.percent => {
|
||||||
const names = parseDeref(iter);
|
const names = parseDeref(iter);
|
||||||
iter = names.new_iter;
|
iter = names.new_iter;
|
||||||
break .{ .context_deref = names.item };
|
expr = .{ .context_deref = names.item };
|
||||||
|
last_valid_iter = iter;
|
||||||
},
|
},
|
||||||
else => @compileError("TODO"),
|
.equals => {
|
||||||
|
const next = iter.next() orelse break;
|
||||||
|
if (next == .equals) {
|
||||||
|
const lhs = expr orelse break;
|
||||||
|
const rhs = parseExpression(iter);
|
||||||
|
iter = rhs.new_iter;
|
||||||
|
|
||||||
|
expr = .{
|
||||||
|
.equals = &.{
|
||||||
|
.lhs = lhs,
|
||||||
|
.rhs = rhs.item,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
last_valid_iter = iter;
|
||||||
|
} else break;
|
||||||
|
},
|
||||||
|
else => break,
|
||||||
};
|
};
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.new_iter = iter,
|
.new_iter = last_valid_iter orelse @compileError("Invalid Expression"),
|
||||||
.item = expr,
|
.item = expr orelse @compileError("Invalid Expression"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -518,7 +551,7 @@ fn parseControlBlock(comptime tokens: ControlTokenIter) ParseResult(ControlToken
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
@compileLog(iter.row);
|
@compileLog(iter.row);
|
||||||
@compileError("TODO" ++ @tagName(token));
|
@compileError("TODO " ++ @tagName(token) ++ " " ++ token.text);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -702,10 +735,16 @@ const TemplateItem = union(enum) {
|
||||||
statement: Statement,
|
statement: Statement,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const EqualsExpr = struct {
|
||||||
|
lhs: Expression,
|
||||||
|
rhs: Expression,
|
||||||
|
};
|
||||||
|
|
||||||
const Expression = union(enum) {
|
const Expression = union(enum) {
|
||||||
arg_deref: []const []const u8,
|
arg_deref: []const []const u8,
|
||||||
capture_deref: []const []const u8,
|
capture_deref: []const []const u8,
|
||||||
context_deref: []const []const u8,
|
context_deref: []const []const u8,
|
||||||
|
equals: *const EqualsExpr,
|
||||||
};
|
};
|
||||||
|
|
||||||
const For = struct {
|
const For = struct {
|
||||||
|
@ -830,7 +869,7 @@ const ControlTokenIter = struct {
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
var idx: usize = 0;
|
var idx: usize = 0;
|
||||||
while (idx < remaining.len and std.mem.indexOfScalar(u8, "{}.#|$/=@ \t\n\r", remaining[idx]) == null) : (idx += 1) {}
|
while (idx < remaining.len and std.mem.indexOfScalar(u8, "{}.#|$/=@,% \t\n\r", remaining[idx]) == null) : (idx += 1) {}
|
||||||
|
|
||||||
self.start += idx - 1;
|
self.start += idx - 1;
|
||||||
return .{ .text = remaining[0..idx] };
|
return .{ .text = remaining[0..idx] };
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
{$b}:
|
{$b}:
|
||||||
{= /for =}
|
{= /for =}
|
||||||
{= /for}
|
{= /for}
|
||||||
|
{#if .quxx == .quxx2}eql{#else}neq{/if}
|
||||||
|
{#if .quxx == .qux}eql{#else}neq{/if}
|
||||||
{#if .qux=}
|
{#if .qux=}
|
||||||
qux
|
qux
|
||||||
{=#elif .quxx=}
|
{=#elif .quxx=}
|
||||||
|
|
Loading…
Reference in a new issue