authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2021-08-08 21:35:35 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2021-08-08 21:35:35 -07:00
log10eb03e0c2a8597754a05f56c6b511f97c714a6a
treece40f581d6dc4b2c2743397753d7d421a9d40240
parent97dee90956930f7c9e8dbe652c36e543c416e3a3

add support for `<else>` statements in `#if` and `#ifnot`


2 files changed, 25 insertions(+), 10 deletions(-)

src/astgen.zig+14-1
...@@ -31,6 +31,7 @@ pub const Block = struct {...@@ -31,6 +31,7 @@ pub const Block = struct {
31 name: Type,31 name: Type,
32 args: []const []const string,32 args: []const []const string,
33 body: []const Value,33 body: []const Value,
34 bttm: []const Value,
3435
35 pub const Type = enum {36 pub const Type = enum {
36 each,37 each,
...@@ -134,8 +135,19 @@ const Parser = struct {...@@ -134,8 +135,19 @@ const Parser = struct {
134 if (std.meta.stringToEnum(Block.Type, w)) |name| {135 if (std.meta.stringToEnum(Block.Type, w)) |name| {
135 const args = self.doArgs();136 const args = self.doArgs();
136 var children: []const Value = &.{};137 var children: []const Value = &.{};
138 var bottom: []const Value = &.{};
139 var top = true;
137 while (!self.tryEatSymbol("/")) {140 while (!self.tryEatSymbol("/")) {
138 children = children ++ &[_]Value{self.doValue()};141 if (self.tryEatSymbol("<")) {
142 std.debug.assert(std.mem.eql(u8, "else", self.eat(.word)));
143 self.eatSymbol(">");
144 top = false;
145 }
146 if (top) {
147 children = children ++ &[_]Value{self.doValue()};
148 } else {
149 bottom = bottom ++ &[_]Value{self.doValue()};
150 }
139 }151 }
140 std.debug.assert(std.mem.eql(u8, @tagName(name), self.eat(.word)));152 std.debug.assert(std.mem.eql(u8, @tagName(name), self.eat(.word)));
141 self.eatSymbol("/");153 self.eatSymbol("/");
...@@ -143,6 +155,7 @@ const Parser = struct {...@@ -143,6 +155,7 @@ const Parser = struct {
143 .name = name,155 .name = name,
144 .args = args,156 .args = args,
145 .body = children,157 .body = children,
158 .bttm = bottom,
146 } };159 } };
147 }160 }
148 return Value{ .function = .{161 return Value{ .function = .{
src/lib.zig+11-9
...@@ -14,7 +14,7 @@ const tokenize = @import("./tokenize.zig");...@@ -14,7 +14,7 @@ const tokenize = @import("./tokenize.zig");
14const astgen = @import("./astgen.zig");14const astgen = @import("./astgen.zig");
1515
16pub fn parse(comptime input: []const u8) astgen.Value {16pub fn parse(comptime input: []const u8) astgen.Value {
17 return astgen.Value{ .element = astgen.do(tokenize.do(input, &.{ '[', '=', ']', '(', ')', '{', '}', '#', '/', '.' })) };17 return astgen.Value{ .element = astgen.do(tokenize.do(input, &.{ '[', '=', ']', '(', ')', '{', '}', '#', '/', '.', '<', '>' })) };
18}18}
1919
20pub fn compile(writer: anytype, comptime value: astgen.Value, data: anytype) !void {20pub fn compile(writer: anytype, comptime value: astgen.Value, data: anytype) !void {
...@@ -83,20 +83,22 @@ fn do(writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype...@@ -83,20 +83,22 @@ fn do(writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype
83 .@"if" => {83 .@"if" => {
84 comptime assertEqual(v.args.len, 1);84 comptime assertEqual(v.args.len, 1);
85 const x = search(v.args[0], data);85 const x = search(v.args[0], data);
86 switch (@typeInfo(@TypeOf(x))) {86 const content = switch (@typeInfo(@TypeOf(x))) {
87 .Bool => if (x) try do(writer, body, data, ctx, indent, flag1),87 .Bool => if (x) v.body else v.bttm,
88 .Optional => if (x) |_| try do(writer, body, data, ctx, indent, flag1),88 .Optional => if (x) |_| v.body else v.bttm,
89 else => unreachable,89 else => unreachable,
90 }90 };
91 try do(writer, body, content, ctx, indent, flag1);
91 },92 },
92 .ifnot => {93 .ifnot => {
93 comptime assertEqual(v.args.len, 1);94 comptime assertEqual(v.args.len, 1);
94 const x = search(v.args[0], data);95 const x = search(v.args[0], data);
95 switch (@typeInfo(@TypeOf(x))) {96 const content = switch (@typeInfo(@TypeOf(x))) {
96 .Bool => if (x) {} else try do(writer, body, data, ctx, indent, flag1),97 .Bool => if (x) v.bttm else v.body,
97 .Optional => if (x) |_| {} else try do(writer, body, data, ctx, indent, flag1),98 .Optional => if (x) |_| v.bttm else v.body,
98 else => unreachable,99 else => unreachable,
99 }100 };
101 try do(writer, body, content, ctx, indent, flag1);
100 },102 },
101 .ifequal => {103 .ifequal => {
102 comptime assertEqual(v.args.len, 2);104 comptime assertEqual(v.args.len, 2);