Hi!
I’m a beginner with Zig, learning the language by creating a bytecode VM.
Thanks for your feedback under this post: A VM bytecode interpreter for EduScript, an educational language
I started the development of the parser, and I wonder if I use pointers correctly, if I structure my nodes in an optimal way… Particularly the construction of binary expressions.
I’d be very happy to have some feedback before continuing ![]()
You can read the code and tests here.
Nodes:
pub const Stmt = union(enum) {
expr: Expr,
empty: Empty,
};
pub const Expr = union(enum) {
binary: Binary,
literal: Literal,
};
pub const Binary = struct {
left: *Expr,
operator: Token.Type,
right: *Expr,
};
pub const Literal = union(enum) {
number: f64,
string: []const u8,
boolean: bool,
nullVal: void,
undefinedVal: void,
};
pub const Empty = struct {};
pub const Program = struct {
statements: std.ArrayList(Stmt),
};
pub fn createBinary(allocator: std.mem.Allocator, op: Token.Type, left: Expr, right: Expr) !Binary {
const binary = Binary{
.left = try allocator.create(Expr),
.right = try allocator.create(Expr),
.operator = op,
};
binary.left.* = left;
binary.right.* = right;
return binary;
}
Use-case:
fn parseExpr(self: *@This(), allocator: std.mem.Allocator, min_precedence: usize) !?Node.Expr {
var left = try self.parsePrimaryExpr(allocator);
// Try to create binary expression node (e.g. 1 + 2, true == false)
while (self.current < self.tokens.len) {
var op = self.peek();
// if precedence == 0, not a binary expression operator
const precedence = self.getPrecedence(op.token_type);
if (precedence < min_precedence or precedence == 0) break;
op = try self.consume(op.token_type);
const right = try self.parseExpr(allocator, precedence + 1) orelse unreachable;
left = Node.Expr{ .binary = try Node.createBinary(allocator, op.token_type, left.?, right) };
}
return left;
}