Skip to content

Commit

Permalink
Merge pull request #15 from optimism-java/yaml-parser
Browse files Browse the repository at this point in the history
feat: yaml parse error and add ssz test cases
  • Loading branch information
GrapeBaBa authored Nov 2, 2024
2 parents fb9c95f + 5a577df commit 8a62f1d
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 17 deletions.
14 changes: 7 additions & 7 deletions src/spec_tests/ssz_static/root.zig
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ const CommonUnion = union {
// AttestationData: types.AttestationData,
// AttesterSlashing: types.AttesterSlashing,
// BeaconBlock: types.BeaconBlock,
// BeaconBlockHeader: types.BeaconBlockHeader,
BeaconBlockHeader: types.BeaconBlockHeader,
Checkpoint: types.Checkpoint,
// Deposit: types.Deposit,
// DepositData: types.DepositData,
// DepositMessage: types.DepositMessage,
// Eth1Block: types.Eth1Block,
// Eth1Data: types.Eth1Data,
DepositData: types.DepositData,
DepositMessage: types.DepositMessage,
Eth1Block: types.Eth1Block,
Eth1Data: types.Eth1Data,
Fork: types.Fork,
ForkData: types.ForkData,
// HistoricalBatch: types.HistoricalBatch,
Expand All @@ -77,9 +77,9 @@ const CommonUnion = union {
// ProposerSlashing: types.ProposerSlashing,
// SignedBeaconBlock: types.SignedBeaconBlock,
// SignedBeaconBlockHeader: types.SignedBeaconBlockHeader,
// SigningData: types.SigningData,
SigningData: types.SigningData,
SyncAggregatorSelectionData: types.SyncAggregatorSelectionData, // only exist in altair or later
// Validator: types.Validator,
Validator: types.Validator,
VoluntaryExit: types.VoluntaryExit,
};

Expand Down
97 changes: 87 additions & 10 deletions src/yaml/parse.zig
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
//! The code bellow is essentially a port of https://github.com/kubkon/zig-yaml
//! to the most recent version of zig with a couple of stylistic changes and support for
//! json yaml.

const std = @import("std");
const assert = std.debug.assert;
const log = std.log.scoped(.parse);
Expand Down Expand Up @@ -386,16 +382,17 @@ const Parser = struct {

log.debug("(doc) begin {s}@{d}", .{ @tagName(self.tree.tokens[node.base.start].id), node.base.start });
// json format yaml
const is_one_line: bool = if (self.eatToken(.flow_map_start, &.{})) |doc_pos| is_one_line: {

const is_json_format: bool = if (self.eatToken(.flow_map_start, &.{})) |doc_pos| is_one_line: {
if (self.getCol(doc_pos) > 0) return error.MalformedYaml;
if (self.eatToken(.tag, &.{ .new_line, .comment })) |_| {
node.directive = try self.expectToken(.literal, &.{ .new_line, .comment });
}
break :is_one_line true;
} else false;

if (is_one_line) {
return self.one_line_doc(node);
if (is_json_format) {
return self.handle_json_format(node);
}

// Parse header
Expand Down Expand Up @@ -443,9 +440,9 @@ const Parser = struct {
return &node.base;
}

fn one_line_doc(self: *Parser, node: *Node.Doc) ParseError!*Node {
fn handle_json_format(self: *Parser, node: *Node.Doc) ParseError!*Node {
// Parse value
node.value = try self.value();
node.value = try self.json_format_map();
if (node.value == null) {
self.token_it.seekBy(-1);
}
Expand Down Expand Up @@ -499,7 +496,6 @@ const Parser = struct {
if (self.getCol(key_pos) < col) {
break;
}

const key = self.token_it.next() orelse return error.UnexpectedEof;
switch (key.id) {
.literal => {},
Expand All @@ -513,7 +509,88 @@ const Parser = struct {
continue;
},
}
log.debug("(map) key {s}@{d}", .{ self.tree.getRaw(key_pos, key_pos), key_pos });

// Separator
_ = try self.expectToken(.map_value_ind, &.{ .new_line, .comment });

// Parse value
const val = try self.value();
errdefer if (val) |v| {
v.deinit(self.allocator);
};

if (val) |v| {
if (self.getCol(v.start) < self.getCol(key_pos)) {
return error.MalformedYaml;
}
if (v.cast(Node.Value)) |_| {
if (self.getCol(v.start) == self.getCol(key_pos)) {
return error.MalformedYaml;
}
}
}

try node.values.append(self.allocator, .{
.key = key_pos,
.value = val,
});
}

node.base.end = self.token_it.pos - 1;

log.debug("(map) end {s}@{d}", .{ @tagName(self.tree.tokens[node.base.end].id), node.base.end });

return &node.base;
}

fn json_format_map(self: *Parser) ParseError!*Node {
const node = try self.allocator.create(Node.Map);
errdefer self.allocator.destroy(node);
node.* = .{};
node.base.tree = self.tree;
node.base.start = self.token_it.pos;
errdefer {
for (node.values.items) |entry| {
if (entry.value) |val| {
val.deinit(self.allocator);
}
}
node.values.deinit(self.allocator);
}

log.debug("(map) begin {s}@{d}", .{ @tagName(self.tree.tokens[node.base.start].id), node.base.start });

const col = self.getCol(node.base.start);
var currentNewLine = self.getLine(node.base.start);

while (true) {
self.eatCommentsAndSpace(&.{});

// Parse key
const key_pos = self.token_it.pos;
if (self.getCol(key_pos) < col) {
// multiline cases, see validator.txt in test
const newLine = self.getLine(key_pos);
if (newLine > currentNewLine) {
currentNewLine = newLine;
} else {
break;
}
}
const key = self.token_it.next() orelse return error.UnexpectedEof;
switch (key.id) {
.literal => {},
.doc_start, .doc_end, .eof => {
self.token_it.seekBy(-1);
break;
},
else => {
// TODO key not being a literal
// return error.Unhandled;
continue;
},
}
log.debug("(map) key {s}@{d}", .{ self.tree.getRaw(key_pos, key_pos), key_pos });

// Separator
Expand Down
11 changes: 11 additions & 0 deletions src/yaml/yaml.zig
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub const Value = union(enum) {
string: []const u8,
list: List,
map: Map,
bool: bool,

pub fn asInt(self: Value) !i64 {
if (self != .int) return error.TypeMismatch;
Expand All @@ -53,6 +54,14 @@ pub const Value = union(enum) {
return self.string;
}

pub fn asBool(self: Value) !bool {
if (self != .string) return error.TypeMismatch;
const str = self.string;
if (std.mem.eql(u8, str, "true")) return true;
if (std.mem.eql(u8, str, "false")) return false;
return error.TypeMismatch;
}

pub fn asList(self: Value) !List {
if (self == .list) {
return self.list;
Expand Down Expand Up @@ -97,6 +106,7 @@ pub const Value = union(enum) {
.uint => |uint| return writer.print("{}", .{uint}),
.float => |float| return writer.print("{d}", .{float}),
.string => |string| return writer.print("{s}", .{string}),
.bool => |data| return writer.print("{any}", .{data}),
.list => |list| {
const len = list.len;
if (len == 0) return;
Expand Down Expand Up @@ -427,6 +437,7 @@ pub const Yaml = struct {
},
.void => error.TypeMismatch,
.optional => unreachable,
.bool => try value.asBool(),
else => error.Unimplemented,
};
}
Expand Down

0 comments on commit 8a62f1d

Please sign in to comment.