Parse whitespace stripping chars

This commit is contained in:
jaina heartles 2022-11-18 00:09:10 -08:00
parent 22277beffc
commit 58adc38945
2 changed files with 85 additions and 62 deletions

View file

@ -162,6 +162,7 @@ fn parseTemplate(comptime tokens: TokenIter, comptime template_type: TemplateTyp
.pipe => current_text = current_text ++ "|", .pipe => current_text = current_text ++ "|",
.dollar => current_text = current_text ++ "$", .dollar => current_text = current_text ++ "$",
.slash => current_text = current_text ++ "/", .slash => current_text = current_text ++ "/",
.equals => current_text = current_text ++ "=",
} }
} }
@ -182,78 +183,98 @@ fn parseExpressionOrStatement(
) ParseResult(if (as_statement) Statement else Expression) { ) ParseResult(if (as_statement) Statement else Expression) {
comptime { comptime {
var iter = tokens; var iter = tokens;
var stmt: ExecutableStatement = while (iter.next()) |token| switch (token) { var first_token: bool = true;
.whitespace => {}, var strip_before: bool = false;
.pound => { var stmt: ExecutableStatement = while (iter.next()) |token| {
if (!as_statement) @compileError("Unexpected Token"); defer first_token = false;
const next = iter.next() orelse @compileError("Unexpected end of template"); switch (token) {
if (next != .text) @compileError("Expected keyword following '#' character"); .equals => {
const text = next.text; if (as_statement and first_token) {
const keyword = std.meta.stringToEnum(Keyword, text) orelse @compileError("Unknown keyword: " ++ text); strip_before = true;
} else @compileError("Unexpected '='");
},
.whitespace => {},
.pound => {
if (!as_statement) @compileError("Unexpected Token");
const next = iter.next() orelse @compileError("Unexpected end of template");
if (next != .text) @compileError("Expected keyword following '#' character");
const text = next.text;
const keyword = std.meta.stringToEnum(Keyword, text) orelse @compileError("Unknown keyword: " ++ text);
switch (keyword) { switch (keyword) {
.@"for" => { .@"for" => {
const result = parseForLoop(iter); const result = parseForLoop(iter);
// statemnt already finished so just return // statemnt already finished so just return
return .{ return .{
.new_iter = result.new_iter, .new_iter = result.new_iter,
.item = .{ .item = .{
.executable = .{ .for_loop = result.item }, .executable = .{ .for_loop = result.item },
.strip_before = false, .strip_before = false,
.strip_after = false, .strip_after = false,
}, },
}; };
}, },
.@"if" => { .@"if" => {
const result = parseIfStatement(iter); const result = parseIfStatement(iter);
return .{ return .{
.new_iter = result.new_iter, .new_iter = result.new_iter,
.item = .{ .item = .{
.executable = .{ .if_statement = result.item }, .executable = .{ .if_statement = result.item },
.strip_before = false, .strip_before = false,
.strip_after = false, .strip_after = false,
}, },
}; };
}, },
//else => @compileError("TODO"), //else => @compileError("TODO"),
} }
}, },
.slash => { .slash => {
if (!as_statement) !@compileError("Unexpected Token"); if (!as_statement) !@compileError("Unexpected Token");
const next = iter.next() orelse @compileError("Unexpected end of template"); const next = iter.next() orelse @compileError("Unexpected end of template");
if (next != .text) @compileError("Expected keyword following '/' character"); if (next != .text) @compileError("Expected keyword following '/' character");
const text = next.text; const text = next.text;
const keyword = std.meta.stringToEnum(EndKeyword, text) orelse @compileError("Unknown keyword: " ++ text); const keyword = std.meta.stringToEnum(EndKeyword, text) orelse @compileError("Unknown keyword: " ++ text);
switch (keyword) { switch (keyword) {
.@"for" => break .{ .end_for = {} }, .@"for" => break .{ .end_for = {} },
.@"if" => break .{ .end_if = {} }, .@"if" => break .{ .end_if = {} },
} }
}, },
.period => { .period => {
const names = parseDeref(iter); const names = parseDeref(iter);
iter = names.new_iter; iter = names.new_iter;
break .{ .expression = .{ .arg_deref = names.item } }; break .{ .expression = .{ .arg_deref = names.item } };
}, },
.dollar => { .dollar => {
const names = parseDeref(iter); const names = parseDeref(iter);
iter = names.new_iter; iter = names.new_iter;
break .{ .expression = .{ .capture_deref = names.item } }; break .{ .expression = .{ .capture_deref = names.item } };
}, },
else => if (as_statement) @compileError("TODO") else break, else => if (as_statement) @compileError("TODO") else break,
}
}; };
if (as_statement) { if (as_statement) {
// search for end of statement // search for end of statement
var strip_after: bool = false;
while (iter.next()) |token| switch (token) { while (iter.next()) |token| switch (token) {
.whitespace => {}, .whitespace => {},
.equals => {
if (iter.peek()) |t| {
if (t == .close_bracket) {
strip_after = true;
continue;
}
}
@compileError("Unexpected '='");
},
.close_bracket => return .{ .close_bracket => return .{
.new_iter = iter, .new_iter = iter,
.item = .{ .item = .{
.executable = stmt, .executable = stmt,
.strip_before = true, .strip_before = strip_before,
.strip_after = true, .strip_after = strip_after,
}, },
}, },
else => { else => {
@ -425,6 +446,7 @@ const Token = union(enum) {
pipe: void, pipe: void,
dollar: void, dollar: void,
slash: void, slash: void,
equals: void,
}; };
const TokenIter = struct { const TokenIter = struct {
@ -453,6 +475,7 @@ const TokenIter = struct {
'|' => return .{ .pipe = {} }, '|' => return .{ .pipe = {} },
'$' => return .{ .dollar = {} }, '$' => return .{ .dollar = {} },
'/' => return .{ .slash = {} }, '/' => return .{ .slash = {} },
'=' => return .{ .equals = {} },
' ', '\t', '\n', '\r' => { ' ', '\t', '\n', '\r' => {
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) {}
@ -464,7 +487,7 @@ const TokenIter = 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] };

View file

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>{.community.name}</title> <title> {= .community.name =} </title>
</head> </head>
<body> <body>
@ -9,7 +9,7 @@
<h2> {{ REAL BRACKETS }} </h2> <h2> {{ REAL BRACKETS }} </h2>
<section> <section>
{#for .baz |$f|}{#for $f |$b|}{$b}:{/for} {= #for .baz |$f|}{#for $f |$b|}{$b}:{/for}
{/for} {/for}
{#if .qux}qux!{/if} {#if .qux}qux!{/if}
{#if .quxx}quxx!{/if} {#if .quxx}quxx!{/if}