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