feat: minimal parsing of statements

This commit is contained in:
Fernando Araoz 2024-12-14 06:24:13 -05:00
parent e48e36bea8
commit 1225049f76
4 changed files with 64 additions and 9 deletions

View File

@ -31,8 +31,8 @@ Now in Zig!
- [x] Lex single line comments
- [x] Lex strings
- [x] Lex grouping signs
- [ ]
- [x] Parse minimal expression
- [x] Parse minimal variable binding
- [x] Parse minimal statement

View File

@ -94,6 +94,7 @@ pub fn build(b: *std.Build) void {
"src/02_syntax/root.zig",
"src/02_syntax/variable.zig",
"src/02_syntax/expression.zig",
"src/02_syntax/statement.zig",
};
for (files) |file| {
const file_unit_test = b.addTest(.{

View File

@ -0,0 +1,56 @@
const std = @import("std");
const lexic = @import("lexic");
const expression = @import("expression.zig");
const types = @import("./types.zig");
const utils = @import("./utils.zig");
const variable = @import("./variable.zig");
const TokenStream = types.TokenStream;
const ParseError = types.ParseError;
pub const Statement = union(enum) {
VariableBinding: *variable.VariableBinding,
fn init(target: *Statement, tokens: *const TokenStream, pos: usize, allocator: std.mem.Allocator) ParseError!void {
// try to parse a variable definition
var vardef: variable.VariableBinding = undefined;
var parse_failed = false;
vardef.init(tokens, pos, allocator) catch |err| switch (err) {
error.Unmatched => {
parse_failed = true;
},
else => {
return err;
},
};
if (!parse_failed) {
// return the parsed variable definition
target.* = .{
.VariableBinding = &vardef,
};
return;
}
// fail
return ParseError.Unmatched;
}
fn deinit(self: @This()) void {
switch (self) {
.VariableBinding => |v| v.deinit(),
}
}
};
test "should parse a variable declaration statement" {
const input = "var my_variable = 322";
const tokens = try lexic.tokenize(input, std.testing.allocator);
defer tokens.deinit();
var statement: Statement = undefined;
try statement.init(&tokens, 0, std.testing.allocator);
defer statement.deinit();
// try std.testing.expectEqual(true, statement.is_mutable);
}

View File

@ -7,7 +7,7 @@ const utils = @import("./utils.zig");
const TokenStream = types.TokenStream;
const ParseError = types.ParseError;
const VariableBinding = struct {
pub const VariableBinding = struct {
is_mutable: bool,
datatype: ?*lexic.Token,
identifier: *lexic.Token,
@ -15,7 +15,7 @@ const VariableBinding = struct {
alloc: std.mem.Allocator,
/// Parses a variable binding
fn init(target: *VariableBinding, tokens: *const TokenStream, pos: usize, allocator: std.mem.Allocator) ParseError!void {
pub fn init(target: *VariableBinding, tokens: *const TokenStream, pos: usize, allocator: std.mem.Allocator) ParseError!void {
std.debug.assert(pos < tokens.items.len);
// try to parse a var keyword
@ -42,9 +42,7 @@ const VariableBinding = struct {
// parse expression
if (pos + 3 >= tokens.items.len) return ParseError.Error;
var exp = allocator.create(expression.Expression) catch {
return ParseError.Error;
};
var exp = try allocator.create(expression.Expression);
errdefer allocator.destroy(exp);
exp.init(tokens, pos + 3) catch {
return ParseError.Error;
@ -60,7 +58,7 @@ const VariableBinding = struct {
};
}
fn deinit(self: *VariableBinding) void {
pub fn deinit(self: *VariableBinding) void {
self.alloc.destroy(self.expression);
}
};