feat: minimal parsing of statements
This commit is contained in:
parent
e48e36bea8
commit
1225049f76
@ -31,8 +31,8 @@ Now in Zig!
|
|||||||
- [x] Lex single line comments
|
- [x] Lex single line comments
|
||||||
- [x] Lex strings
|
- [x] Lex strings
|
||||||
- [x] Lex grouping signs
|
- [x] Lex grouping signs
|
||||||
- [ ]
|
- [x] Parse minimal expression
|
||||||
|
- [x] Parse minimal variable binding
|
||||||
|
- [x] Parse minimal statement
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
"src/02_syntax/root.zig",
|
"src/02_syntax/root.zig",
|
||||||
"src/02_syntax/variable.zig",
|
"src/02_syntax/variable.zig",
|
||||||
"src/02_syntax/expression.zig",
|
"src/02_syntax/expression.zig",
|
||||||
|
"src/02_syntax/statement.zig",
|
||||||
};
|
};
|
||||||
for (files) |file| {
|
for (files) |file| {
|
||||||
const file_unit_test = b.addTest(.{
|
const file_unit_test = b.addTest(.{
|
||||||
|
56
src/02_syntax/statement.zig
Normal file
56
src/02_syntax/statement.zig
Normal 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);
|
||||||
|
}
|
@ -7,7 +7,7 @@ const utils = @import("./utils.zig");
|
|||||||
const TokenStream = types.TokenStream;
|
const TokenStream = types.TokenStream;
|
||||||
const ParseError = types.ParseError;
|
const ParseError = types.ParseError;
|
||||||
|
|
||||||
const VariableBinding = struct {
|
pub const VariableBinding = struct {
|
||||||
is_mutable: bool,
|
is_mutable: bool,
|
||||||
datatype: ?*lexic.Token,
|
datatype: ?*lexic.Token,
|
||||||
identifier: *lexic.Token,
|
identifier: *lexic.Token,
|
||||||
@ -15,7 +15,7 @@ const VariableBinding = struct {
|
|||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
|
|
||||||
/// Parses a variable binding
|
/// 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);
|
std.debug.assert(pos < tokens.items.len);
|
||||||
|
|
||||||
// try to parse a var keyword
|
// try to parse a var keyword
|
||||||
@ -42,9 +42,7 @@ const VariableBinding = struct {
|
|||||||
|
|
||||||
// parse expression
|
// parse expression
|
||||||
if (pos + 3 >= tokens.items.len) return ParseError.Error;
|
if (pos + 3 >= tokens.items.len) return ParseError.Error;
|
||||||
var exp = allocator.create(expression.Expression) catch {
|
var exp = try allocator.create(expression.Expression);
|
||||||
return ParseError.Error;
|
|
||||||
};
|
|
||||||
errdefer allocator.destroy(exp);
|
errdefer allocator.destroy(exp);
|
||||||
exp.init(tokens, pos + 3) catch {
|
exp.init(tokens, pos + 3) catch {
|
||||||
return ParseError.Error;
|
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);
|
self.alloc.destroy(self.expression);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user