tokenizer: add finish function to check if there is trailing data

Since the tokenizer is decoupled from the parser, there's no good way
to do this. Also without attempting to parse the last line, it's
impossible to say if it is junk data or simply a missing trailing new
line.
This commit is contained in:
torque 2023-09-27 23:35:24 -07:00
parent 0e60719c85
commit 3258e7fdb5
Signed by: torque
SSH Key Fingerprint: SHA256:nCrXefBNo6EbjNSQhv0nXmEg/VuNq3sMF5b8zETw3Tk
3 changed files with 21 additions and 0 deletions

View File

@ -60,6 +60,10 @@ pub fn LineBuffer(comptime options: Strictness) type {
}; };
} }
pub fn empty(self: @This()) bool {
return self.internal.empty();
}
pub fn deinit(self: @This()) void { pub fn deinit(self: @This()) void {
self.allocator.free(self.internal.buffer); self.allocator.free(self.internal.buffer);
} }
@ -112,6 +116,12 @@ pub fn FixedLineBuffer(comptime options: Strictness) type {
return .{ .buffer = data, .window = .{ .start = 0, .len = data.len } }; return .{ .buffer = data, .window = .{ .start = 0, .len = data.len } };
} }
pub fn empty(self: @This()) bool {
// we can't check the overall buffer size because the dynamic buffer may be
// overallocated
return self.window.len == 0;
}
pub fn nextLine(self: *@This()) !?[]const u8 { pub fn nextLine(self: *@This()) !?[]const u8 {
if (self.window.start >= self.buffer.len or self.window.len == 0) if (self.window.start >= self.buffer.len or self.window.len == 0)
return null; return null;

View File

@ -54,6 +54,10 @@ pub fn parseBuffer(allocator: std.mem.Allocator, buffer: []const u8, options: Op
}; };
while (try tok.next()) |line| try state.parseLine(line, options.duplicate_key_behavior); while (try tok.next()) |line| try state.parseLine(line, options.duplicate_key_behavior);
// state doesn't have access to the tokenizer, which is the only thing that can
// error if unparsed lines remain in the buffer by the time that "finish" is
// called.
try tok.finish();
return try state.finish(options); return try state.finish(options);
} }
@ -90,6 +94,7 @@ pub const StreamParser = struct {
} }
pub fn finish(self: *StreamParser) !Document { pub fn finish(self: *StreamParser) !Document {
try self.linetok.finish();
return try self.parse_state.finish(self.parse_options); return try self.parse_state.finish(self.parse_options);
} }
}; };

View File

@ -70,6 +70,12 @@ pub fn LineTokenizer(comptime Buffer: type) type {
diagnostics: *Diagnostics, diagnostics: *Diagnostics,
row: usize = 0, row: usize = 0,
pub fn finish(self: @This()) !void {
if (!self.buffer.empty()) {
return error.ExtraContent;
}
}
pub fn next(self: *@This()) !?Line { pub fn next(self: *@This()) !?Line {
lineloop: while (try self.buffer.nextLine()) |raw_line| { lineloop: while (try self.buffer.nextLine()) |raw_line| {
var indent: usize = 0; var indent: usize = 0;