Split expression/statements in parser

This commit is contained in:
jaina heartles 2022-11-18 01:58:13 -08:00
parent 58adc38945
commit 1a7db9a834
1 changed files with 67 additions and 47 deletions

View File

@ -142,7 +142,7 @@ fn parseTemplate(comptime tokens: TokenIter, comptime template_type: TemplateTyp
items = items ++ [_]TemplateItem{.{ .text = current_text }};
current_text = "";
}
const result = parseExpressionOrStatement(iter, true);
const result = parseStatement(iter);
iter = result.new_iter;
const stmt = result.item.executable;
if (stmt == .end_for) {
@ -177,10 +177,33 @@ fn parseTemplate(comptime tokens: TokenIter, comptime template_type: TemplateTyp
}
}
fn parseExpressionOrStatement(
comptime tokens: TokenIter,
comptime as_statement: bool,
) ParseResult(if (as_statement) Statement else Expression) {
fn parseExpression(comptime tokens: TokenIter) ParseResult(Expression) {
comptime {
var iter = tokens;
var expr: Expression = while (iter.next()) |token| switch (token) {
.whitespace => {},
.period => {
const names = parseDeref(iter);
iter = names.new_iter;
break .{ .arg_deref = names.item };
},
.dollar => {
const names = parseDeref(iter);
iter = names.new_iter;
break .{ .capture_deref = names.item };
},
else => @compileError("TODO"),
};
return .{
.new_iter = iter,
.item = expr,
};
}
}
fn parseStatement(comptime tokens: TokenIter) ParseResult(Statement) {
comptime {
var iter = tokens;
var first_token: bool = true;
@ -189,13 +212,12 @@ fn parseExpressionOrStatement(
defer first_token = false;
switch (token) {
.equals => {
if (as_statement and first_token) {
if (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;
@ -230,7 +252,6 @@ fn parseExpressionOrStatement(
}
},
.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;
@ -241,50 +262,44 @@ fn parseExpressionOrStatement(
.@"if" => break .{ .end_if = {} },
}
},
.period => {
const names = parseDeref(iter);
iter = names.new_iter;
break .{ .expression = .{ .arg_deref = names.item } };
.period, .dollar => {
iter.putBack(token);
const expr = parseExpression(iter);
iter = expr.new_iter;
break .{ .expression = expr.item };
},
.dollar => {
const names = parseDeref(iter);
iter = names.new_iter;
break .{ .expression = .{ .capture_deref = names.item } };
},
else => if (as_statement) @compileError("TODO") else break,
else => @compileError("TODO"),
}
};
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;
}
// 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 '='");
}
@compileError("Unexpected '='");
},
.close_bracket => return .{
.new_iter = iter,
.item = .{
.executable = stmt,
.strip_before = strip_before,
.strip_after = strip_after,
},
.close_bracket => return .{
.new_iter = iter,
.item = .{
.executable = stmt,
.strip_before = strip_before,
.strip_after = strip_after,
},
},
else => {
@compileLog(iter.row);
@compileError("TODO" ++ @tagName(token));
},
};
},
else => {
@compileLog(iter.row);
@compileError("TODO" ++ @tagName(token));
},
};
@compileError("Unexpected end of template");
} else return .{ .new_iter = iter, .item = stmt.expression };
@compileError("Unexpected end of template");
}
}
@ -312,7 +327,7 @@ fn endStatement(comptime tokens: TokenIter) TokenIter {
fn parseForLoop(comptime tokens: TokenIter) ParseResult(ForLoop) {
comptime {
const iterable = parseExpressionOrStatement(tokens, false);
const iterable = parseExpression(tokens);
var iter = iterable.new_iter;
iter = skipWhitespace(iter);
@ -347,7 +362,7 @@ fn parseForLoop(comptime tokens: TokenIter) ParseResult(ForLoop) {
fn parseIfStatement(comptime tokens: TokenIter) ParseResult(IfStatement) {
comptime {
const condition = parseExpressionOrStatement(tokens, false);
const condition = parseExpression(tokens);
var iter = endStatement(condition.new_iter);
const subtemplate = parseTemplate(iter, .if_block);
@ -500,4 +515,9 @@ const TokenIter = struct {
self.peeked_token = token;
return token;
}
fn putBack(self: *TokenIter, token: Token) void {
std.debug.assert(self.peeked_token == null);
self.peeked_token = token;
}
};