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 ++ "|",
.dollar => 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) {
comptime {
var iter = tokens;
var stmt: ExecutableStatement = while (iter.next()) |token| switch (token) {
.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);
var first_token: bool = true;
var strip_before: bool = false;
var stmt: ExecutableStatement = while (iter.next()) |token| {
defer first_token = false;
switch (token) {
.equals => {
if (as_statement and first_token) {
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) {
.@"for" => {
const result = parseForLoop(iter);
// statemnt already finished so just return
return .{
.new_iter = result.new_iter,
.item = .{
.executable = .{ .for_loop = result.item },
.strip_before = false,
.strip_after = false,
},
};
},
.@"if" => {
const result = parseIfStatement(iter);
return .{
.new_iter = result.new_iter,
.item = .{
.executable = .{ .if_statement = result.item },
.strip_before = false,
.strip_after = false,
},
};
},
switch (keyword) {
.@"for" => {
const result = parseForLoop(iter);
// statemnt already finished so just return
return .{
.new_iter = result.new_iter,
.item = .{
.executable = .{ .for_loop = result.item },
.strip_before = false,
.strip_after = false,
},
};
},
.@"if" => {
const result = parseIfStatement(iter);
return .{
.new_iter = result.new_iter,
.item = .{
.executable = .{ .if_statement = result.item },
.strip_before = false,
.strip_after = false,
},
};
},
//else => @compileError("TODO"),
}
},
.slash => {
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(EndKeyword, text) orelse @compileError("Unknown keyword: " ++ text);
//else => @compileError("TODO"),
}
},
.slash => {
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(EndKeyword, text) orelse @compileError("Unknown keyword: " ++ text);
switch (keyword) {
.@"for" => break .{ .end_for = {} },
.@"if" => break .{ .end_if = {} },
}
},
.period => {
const names = parseDeref(iter);
iter = names.new_iter;
break .{ .expression = .{ .arg_deref = names.item } };
},
.dollar => {
const names = parseDeref(iter);
iter = names.new_iter;
break .{ .expression = .{ .capture_deref = names.item } };
},
else => if (as_statement) @compileError("TODO") else break,
switch (keyword) {
.@"for" => break .{ .end_for = {} },
.@"if" => break .{ .end_if = {} },
}
},
.period => {
const names = parseDeref(iter);
iter = names.new_iter;
break .{ .expression = .{ .arg_deref = names.item } };
},
.dollar => {
const names = parseDeref(iter);
iter = names.new_iter;
break .{ .expression = .{ .capture_deref = names.item } };
},
else => if (as_statement) @compileError("TODO") else break,
}
};
if (as_statement) {
// search for end of statement
var strip_after: bool = false;
while (iter.next()) |token| switch (token) {
.whitespace => {},
.equals => {
if (iter.peek()) |t| {
if (t == .close_bracket) {
strip_after = true;
continue;
}
}
@compileError("Unexpected '='");
},
.close_bracket => return .{
.new_iter = iter,
.item = .{
.executable = stmt,
.strip_before = true,
.strip_after = true,
.strip_before = strip_before,
.strip_after = strip_after,
},
},
else => {
@ -425,6 +446,7 @@ const Token = union(enum) {
pipe: void,
dollar: void,
slash: void,
equals: void,
};
const TokenIter = struct {
@ -453,6 +475,7 @@ const TokenIter = struct {
'|' => return .{ .pipe = {} },
'$' => return .{ .dollar = {} },
'/' => return .{ .slash = {} },
'=' => return .{ .equals = {} },
' ', '\t', '\n', '\r' => {
var idx: usize = 0;
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 => {
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;
return .{ .text = remaining[0..idx] };

View file

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