repo: hackvr-turbo action: commit revision: path_from: revision_from: eea55bcd0406f877918f5907da94e034c15c2455: path_to: revision_to:
commit eea55bcd0406f877918f5907da94e034c15c2455 Author: Felix (xq) QueißnerDate: Thu Jun 25 21:32:27 2020 +0200 Completes parser. diff --git a/lib/hackvr/parser.zig b/lib/hackvr/parser.zig
--- a/lib/hackvr/parser.zig
+++ b/lib/hackvr/parser.zig
@@ -21,10 +21,11 @@ pub const Parser = struct {
return Parser{
.line_buffer = undefined,
.line_offset = 0,
+ .point_buffer = undefined,
};
}
- fn parseLine(line: []const u8) !?Event {
+ fn parseLine(self: *Parser, line: []const u8) !?Event {
// max number of slices separated by a
var items = FixedList([]const u8, 512).init();
@@ -133,8 +134,109 @@ pub const Parser = struct {
.groups = args[0],
},
};
- }
+ } else if (std.mem.eql(u8, cmd, "addshape")) {
+ if (args.len < 2)
+ return error.ArgumentMismatch;
+ const color = try std.fmt.parseInt(u8, args[0], 10);
+ const argc = try std.fmt.parseInt(usize, args[1], 10);
+
+ if (args.len != (2 + 3 * argc))
+ return error.ArgumentMismatch;
+
+ const slice = self.point_buffer[0..argc];
+
+ for (slice) |*item, i| {
+ const off = 2 + 3 * i;
+ item.x = try std.fmt.parseFloat(hvr.real, args[off + 0]);
+ item.y = try std.fmt.parseFloat(hvr.real, args[off + 1]);
+ item.z = try std.fmt.parseFloat(hvr.real, args[off + 2]);
+ }
+ return Event{
+ .add_shape = AddShapeData{
+ .selector = selector,
+ .color = color,
+ .polygon = slice,
+ },
+ };
+ } else if (std.mem.eql(u8, cmd, "ping")) {
+ if (args.len != 1)
+ return error.ArgumentMismatch;
+ return Event{
+ .ping = PingData{
+ .selector = selector,
+ .ping_target = args[0],
+ },
+ };
+ } else if (std.mem.eql(u8, cmd, "scale")) {
+ if (args.len != 3)
+ return error.ArgumentMismatch;
+ return Event{
+ .scale = ScaleData{
+ .selector = selector,
+ .scale = hvr.Vec3D{
+ .x = try std.fmt.parseFloat(hvr.real, args[0]),
+ .y = try std.fmt.parseFloat(hvr.real, args[1]),
+ .z = try std.fmt.parseFloat(hvr.real, args[2]),
+ },
+ },
+ };
+ } else if (std.mem.eql(u8, cmd, "rotate")) {
+ if (args.len != 3)
+ return error.ArgumentMismatch;
+ return Event{
+ .rotate = AbsRelVectorData{
+ .selector = selector,
+ .vector = AbsRelVector{
+ .x = try AbsRel.parse(args[0]),
+ .y = try AbsRel.parse(args[1]),
+ .z = try AbsRel.parse(args[2]),
+ },
+ },
+ };
+ } else if (std.mem.eql(u8, cmd, "move")) {
+ switch (args.len) {
+ 1 => {
+ var dir = if (std.mem.eql(u8, args[0], "forward"))
+ MoveData.Direction{ .forward = {} }
+ else if (std.mem.eql(u8, args[0], "backward"))
+ MoveData.Direction{ .backward = {} }
+ else if (std.mem.eql(u8, args[0], "up"))
+ MoveData.Direction{ .up = {} }
+ else if (std.mem.eql(u8, args[0], "down"))
+ MoveData.Direction{ .down = {} }
+ else if (std.mem.eql(u8, args[0], "left"))
+ MoveData.Direction{ .left = {} }
+ else if (std.mem.eql(u8, args[0], "right"))
+ MoveData.Direction{ .right = {} }
+ else
+ return error.InvalidArgument;
+
+ return Event{
+ .move = MoveData{
+ .selector = selector,
+ .direction = dir,
+ },
+ };
+ },
+ 3 => {
+ return Event{
+ .move = MoveData{
+ .selector = selector,
+ .direction = .{
+ .offset = AbsRelVector{
+ .x = try AbsRel.parse(args[0]),
+ .y = try AbsRel.parse(args[1]),
+ .z = try AbsRel.parse(args[2]),
+ },
+ },
+ },
+ };
+ },
+
+ else => return error.ArgumentMismatch,
+ }
+ }
return error.UnknownCommand;
},
}
@@ -161,7 +263,7 @@ pub const Parser = struct {
const rest = source[offset..];
if (line.len > 0) {
- const event = parseLine(line) catch |err| switch (err) {
+ const event = self.parseLine(line) catch |err| switch (err) {
error.UnknownCommand => return PushResult{
.parse_error = .{
.rest = rest,
@@ -228,30 +330,9 @@ pub const PushResult = union(enum) {
},
};
-pub const EventType = enum {
- help,
- version,
- status,
- dump,
- quit,
- set,
- physics,
- control,
- addshape,
- @"export",
- ping,
- scale,
- rotate,
- periodic,
- flatten,
- move,
- delete_group,
- assimilate,
- rename_group,
- delete_all_except,
-};
-
pub const AbsRel = union(enum) {
+ const Self = @This();
+
absolute: hvr.real,
relative: hvr.real,
@@ -263,16 +344,34 @@ pub const AbsRel = union(enum) {
};
} else {
return AbsRel{
- .absolute = try std.fmt.parseFloat(hvr.real, str[1..]),
+ .absolute = try std.fmt.parseFloat(hvr.real, str),
};
}
}
+
+ /// Applies the value to a previous value
+ pub fn apply(self: Self, in: hvr.real) hvr.real {
+ return switch (self) {
+ .relative => |v| in + v,
+ .absolute => |v| v,
+ };
+ }
};
pub const AbsRelVector = struct {
+ const Self = @This();
+
x: AbsRel,
y: AbsRel,
z: AbsRel,
+
+ pub fn apply(self: Self, v3d: hvr.Vec3D) hvr.Vec3D {
+ return .{
+ .x = self.x.apply(v3d.x),
+ .y = self.x.apply(v3d.y),
+ .z = self.x.apply(v3d.z),
+ };
+ }
};
pub const Selector = struct {
@@ -301,8 +400,8 @@ pub const AbsRelVectorData = struct {
};
pub const MoveData = struct {
- selector: Selector,
- direction: union(enum) {
+ const Type = @TagType(Direction);
+ const Direction = union(enum) {
forward,
backward,
left,
@@ -310,7 +409,10 @@ pub const MoveData = struct {
up,
down,
offset: AbsRelVector,
- },
+ };
+
+ selector: Selector,
+ direction: Direction,
};
pub const PingData = struct {
@@ -318,7 +420,8 @@ pub const PingData = struct {
ping_target: []const u8,
};
-pub const Event = union(EventType) {
+pub const EventType = @TagType(Event);
+pub const Event = union(enum) {
delete_group: GroupArgSelector,
assimilate: GroupArgSelector,
rename_group: GroupArgSelector,
@@ -331,7 +434,7 @@ pub const Event = union(EventType) {
set: Selector,
physics: Selector,
control: GroupArgSelector,
- addshape: AddShapeData,
+ add_shape: AddShapeData,
@"export": GroupArgSelector,
ping: PingData,
scale: ScaleData,
@@ -383,7 +486,7 @@ test "parser: ParseResult.rest/event" {
}
test "parser: parse line" {
- _ = Parser.parseLine(" a bb cccc ") catch |err| {
+ _ = Parser.init().parseLine(" a bb cccc ") catch |err| {
std.testing.expect(err == error.UnknownCommand);
return;
};
@@ -391,59 +494,59 @@ test "parser: parse line" {
}
test "parser: cmd help" {
- const result = (try Parser.parseLine("help")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("help")) orelse return error.ExpectedEvent;
std.testing.expect(result == .help);
}
test "parser: cmd version" {
- const result = (try Parser.parseLine("version")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("version")) orelse return error.ExpectedEvent;
std.testing.expect(result == .version);
}
test "parser: cmd status" {
- const result = (try Parser.parseLine("foobar status")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar status")) orelse return error.ExpectedEvent;
std.testing.expect(result == .status);
std.testing.expectEqualStrings("foobar", result.status.groups);
}
test "parser: cmd dump" {
- const result = (try Parser.parseLine("foobar dump")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar dump")) orelse return error.ExpectedEvent;
std.testing.expect(result == .dump);
std.testing.expectEqualStrings("foobar", result.dump.groups);
}
test "parser: cmd quit" {
- const result = (try Parser.parseLine("foobar quit")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar quit")) orelse return error.ExpectedEvent;
std.testing.expect(result == .quit);
std.testing.expectEqualStrings("foobar", result.quit.groups);
}
test "parser: cmd set" {
- const result = (try Parser.parseLine("foobar set")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar set")) orelse return error.ExpectedEvent;
std.testing.expect(result == .set);
std.testing.expectEqualStrings("foobar", result.set.groups);
}
test "parser: cmd physics" {
- const result = (try Parser.parseLine("foobar physics")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar physics")) orelse return error.ExpectedEvent;
std.testing.expect(result == .physics);
std.testing.expectEqualStrings("foobar", result.physics.groups);
}
test "parser: cmd periodic" {
- const result = (try Parser.parseLine("foobar periodic")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar periodic")) orelse return error.ExpectedEvent;
std.testing.expect(result == .periodic);
std.testing.expectEqualStrings("foobar", result.periodic.groups);
}
test "parser: cmd flatten" {
- const result = (try Parser.parseLine("foobar flatten")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar flatten")) orelse return error.ExpectedEvent;
std.testing.expect(result == .flatten);
std.testing.expectEqualStrings("foobar", result.flatten.groups);
}
test "parser: cmd deleteallexcept" {
- const result = (try Parser.parseLine("foobar deleteallexcept groupsel")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar deleteallexcept groupsel")) orelse return error.ExpectedEvent;
std.testing.expect(result == .delete_all_except);
std.testing.expectEqualStrings("foobar", result.delete_all_except.selector.groups);
@@ -451,7 +554,7 @@ test "parser: cmd deleteallexcept" {
}
test "parser: cmd delete_group" {
- const result = (try Parser.parseLine("foobar deletegroup groupsel")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar deletegroup groupsel")) orelse return error.ExpectedEvent;
std.testing.expect(result == .delete_group);
std.testing.expectEqualStrings("foobar", result.delete_group.selector.groups);
@@ -459,7 +562,7 @@ test "parser: cmd delete_group" {
}
test "parser: cmd delete_group" {
- const result = (try Parser.parseLine("foobar renamegroup groupsel")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar renamegroup groupsel")) orelse return error.ExpectedEvent;
std.testing.expect(result == .rename_group);
std.testing.expectEqualStrings("foobar", result.rename_group.selector.groups);
@@ -467,7 +570,7 @@ test "parser: cmd delete_group" {
}
test "parser: cmd delete_group" {
- const result = (try Parser.parseLine("foobar assimilate groupsel")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar assimilate groupsel")) orelse return error.ExpectedEvent;
std.testing.expect(result == .assimilate);
std.testing.expectEqualStrings("foobar", result.assimilate.selector.groups);
@@ -475,7 +578,7 @@ test "parser: cmd delete_group" {
}
test "parser: cmd control" {
- const result = (try Parser.parseLine("foobar control groupsel")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar control groupsel")) orelse return error.ExpectedEvent;
std.testing.expect(result == .control);
std.testing.expectEqualStrings("foobar", result.control.selector.groups);
@@ -483,9 +586,150 @@ test "parser: cmd control" {
}
test "parser: cmd export" {
- const result = (try Parser.parseLine("foobar export groupsel")) orelse return error.ExpectedEvent;
+ const result = (try Parser.init().parseLine("foobar export groupsel")) orelse return error.ExpectedEvent;
std.testing.expect(result == .@"export");
std.testing.expectEqualStrings("foobar", result.@"export".selector.groups);
std.testing.expectEqualStrings("groupsel", result.@"export".groups);
}
+
+test "parser: cmd addshape" {
+ var parser = Parser.init();
+
+ {
+ const result = (try parser.parseLine("foobar addshape 3 0")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .add_shape);
+ std.testing.expectEqualStrings("foobar", result.add_shape.selector.groups);
+ std.testing.expectEqual(@as(u8, 3), result.add_shape.color);
+ std.testing.expectEqualSlices(
+ hvr.Vec3D,
+ &[_]hvr.Vec3D{},
+ result.add_shape.polygon,
+ );
+ }
+
+ {
+ const result = (try parser.parseLine("foobar addshape 3 1 1.5 2.5 3.5")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .add_shape);
+ std.testing.expectEqualStrings("foobar", result.add_shape.selector.groups);
+ std.testing.expectEqual(@as(u8, 3), result.add_shape.color);
+ std.testing.expectEqualSlices(
+ hvr.Vec3D,
+ &[_]hvr.Vec3D{
+ .{ .x = 1.5, .y = 2.5, .z = 3.5 },
+ },
+ result.add_shape.polygon,
+ );
+ }
+
+ {
+ const result = (try parser.parseLine("foobar addshape 3 2 1.5 2.5 3.5 7 8 132213.3")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .add_shape);
+ std.testing.expectEqualStrings("foobar", result.add_shape.selector.groups);
+ std.testing.expectEqual(@as(u8, 3), result.add_shape.color);
+ std.testing.expectEqualSlices(
+ hvr.Vec3D,
+ &[_]hvr.Vec3D{
+ .{ .x = 1.5, .y = 2.5, .z = 3.5 },
+ .{ .x = 7.0, .y = 8.0, .z = 132213.3 },
+ },
+ result.add_shape.polygon,
+ );
+ }
+}
+
+test "parser: cmd ping" {
+ const result = (try Parser.init().parseLine("foobar ping long.text.without.spaces")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .ping);
+ std.testing.expectEqualStrings("foobar", result.ping.selector.groups);
+ std.testing.expectEqualStrings("long.text.without.spaces", result.ping.ping_target);
+}
+
+test "parser: cmd scale" {
+ const result = (try Parser.init().parseLine("foobar scale 1.4 -2.3 1.8")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .scale);
+ std.testing.expectEqualStrings("foobar", result.scale.selector.groups);
+ std.testing.expectEqual(hvr.Vec3D{ .x = 1.4, .y = -2.3, .z = 1.8 }, result.scale.scale);
+}
+
+test "parser: cmd rotate" {
+ const result = (try Parser.init().parseLine("foobar rotate +1.4 -2.25 +-1.8")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .rotate);
+ std.testing.expectEqualStrings("foobar", result.rotate.selector.groups);
+ std.testing.expectEqual(AbsRelVector{
+ .x = AbsRel{ .relative = 1.4 },
+ .y = AbsRel{ .absolute = -2.25 },
+ .z = AbsRel{ .relative = -1.8 },
+ }, result.rotate.vector);
+}
+
+test "parser: cmd move" {
+ var parser = Parser.init();
+
+ {
+ const result = (try parser.parseLine("foobar move +1.4 -2.3 +-1.8")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .move);
+ std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+ std.testing.expectEqual(MoveData.Type.offset, result.move.direction);
+ std.testing.expectEqual(AbsRelVector{
+ .x = AbsRel{ .relative = 1.4 },
+ .y = AbsRel{ .absolute = -2.3 },
+ .z = AbsRel{ .relative = -1.8 },
+ }, result.move.direction.offset);
+ }
+
+ {
+ const result = (try parser.parseLine("foobar move forward")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .move);
+ std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+ std.testing.expectEqual(MoveData.Type.forward, result.move.direction);
+ }
+
+ {
+ const result = (try parser.parseLine("foobar move backward")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .move);
+ std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+ std.testing.expectEqual(MoveData.Type.backward, result.move.direction);
+ }
+
+ {
+ const result = (try parser.parseLine("foobar move right")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .move);
+ std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+ std.testing.expectEqual(MoveData.Type.right, result.move.direction);
+ }
+
+ {
+ const result = (try parser.parseLine("foobar move left")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .move);
+ std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+ std.testing.expectEqual(MoveData.Type.left, result.move.direction);
+ }
+
+ {
+ const result = (try parser.parseLine("foobar move up")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .move);
+ std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+ std.testing.expectEqual(MoveData.Type.up, result.move.direction);
+ }
+
+ {
+ const result = (try parser.parseLine("foobar move down")) orelse return error.ExpectedEvent;
+
+ std.testing.expect(result == .move);
+ std.testing.expectEqualStrings("foobar", result.move.selector.groups);
+ std.testing.expectEqual(MoveData.Type.down, result.move.direction);
+ }
+}
-----END OF PAGE-----