feat: minimal parse of variable binding
This commit is contained in:
parent
44bd9fc5ad
commit
55231e986e
@ -8,15 +8,17 @@ pub const Expression = union(enum) {
|
|||||||
number: *const Token,
|
number: *const Token,
|
||||||
|
|
||||||
/// Attempts to parse an expression from a token stream.
|
/// Attempts to parse an expression from a token stream.
|
||||||
fn parse(tokens: *const std.ArrayList(Token), pos: usize) ParseError!@This() {
|
///
|
||||||
|
/// Receives a pointer to the memory for initialization
|
||||||
|
pub fn init(target: *Expression, tokens: *const std.ArrayList(Token), pos: usize) error{Unmatched}!void {
|
||||||
std.debug.assert(pos < tokens.items.len);
|
std.debug.assert(pos < tokens.items.len);
|
||||||
|
|
||||||
const t = tokens.items[pos];
|
const t = tokens.items[pos];
|
||||||
if (t.token_type != TokenType.Int) {
|
if (t.token_type != TokenType.Int) {
|
||||||
return ParseError.Unmatched;
|
return error.Unmatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
return .{
|
target.* = .{
|
||||||
.number = &t,
|
.number = &t,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -27,7 +29,8 @@ test "should parse expression" {
|
|||||||
const tokens = try lexic.tokenize(input, std.testing.allocator);
|
const tokens = try lexic.tokenize(input, std.testing.allocator);
|
||||||
defer tokens.deinit();
|
defer tokens.deinit();
|
||||||
|
|
||||||
const expr = try Expression.parse(&tokens, 0);
|
var expr: Expression = undefined;
|
||||||
|
try expr.init(&tokens, 0);
|
||||||
try std.testing.expectEqualDeep("322", expr.number.value);
|
try std.testing.expectEqualDeep("322", expr.number.value);
|
||||||
try std.testing.expectEqualDeep(TokenType.Int, expr.number.token_type);
|
try std.testing.expectEqualDeep(TokenType.Int, expr.number.token_type);
|
||||||
}
|
}
|
||||||
@ -37,7 +40,8 @@ test "should fail on non expression" {
|
|||||||
const tokens = try lexic.tokenize(input, std.testing.allocator);
|
const tokens = try lexic.tokenize(input, std.testing.allocator);
|
||||||
defer tokens.deinit();
|
defer tokens.deinit();
|
||||||
|
|
||||||
const expr = Expression.parse(&tokens, 0) catch |err| {
|
var expr: Expression = undefined;
|
||||||
|
expr.init(&tokens, 0) catch |err| {
|
||||||
try std.testing.expectEqual(ParseError.Unmatched, err);
|
try std.testing.expectEqual(ParseError.Unmatched, err);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -10,6 +10,8 @@ pub const ParseError = error{
|
|||||||
/// For example, a `var` keyword was found, but then no identifier
|
/// For example, a `var` keyword was found, but then no identifier
|
||||||
/// The parsing should stop
|
/// The parsing should stop
|
||||||
Error,
|
Error,
|
||||||
|
/// OOM. Fatal error, blows up everything
|
||||||
|
OutOfMemory,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const TokenStream = std.ArrayList(lexic.Token);
|
pub const TokenStream = std.ArrayList(lexic.Token);
|
||||||
|
@ -11,14 +11,12 @@ const VariableBinding = struct {
|
|||||||
is_mutable: bool,
|
is_mutable: bool,
|
||||||
datatype: ?*lexic.Token,
|
datatype: ?*lexic.Token,
|
||||||
identifier: *lexic.Token,
|
identifier: *lexic.Token,
|
||||||
expression: expression.Expression,
|
expression: *expression.Expression,
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
|
|
||||||
fn init(tokens: *const TokenStream, pos: usize, allocator: std.mem.Allocator) ParseError!@This() {
|
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);
|
||||||
|
|
||||||
_ = allocator;
|
|
||||||
|
|
||||||
// try to parse a var keyword
|
// try to parse a var keyword
|
||||||
const var_keyword = try utils.expect_token_type(lexic.TokenType.K_Var, &tokens.items[pos]);
|
const var_keyword = try utils.expect_token_type(lexic.TokenType.K_Var, &tokens.items[pos]);
|
||||||
_ = var_keyword;
|
_ = var_keyword;
|
||||||
@ -33,7 +31,6 @@ const VariableBinding = struct {
|
|||||||
const identifier = utils.expect_token_type(lexic.TokenType.Identifier, &tokens.items[pos + 1]) catch {
|
const identifier = utils.expect_token_type(lexic.TokenType.Identifier, &tokens.items[pos + 1]) catch {
|
||||||
return ParseError.Error;
|
return ParseError.Error;
|
||||||
};
|
};
|
||||||
_ = identifier;
|
|
||||||
|
|
||||||
// parse equal sign
|
// parse equal sign
|
||||||
if (pos + 2 >= tokens.items.len) return ParseError.Error;
|
if (pos + 2 >= tokens.items.len) return ParseError.Error;
|
||||||
@ -43,25 +40,36 @@ const VariableBinding = struct {
|
|||||||
_ = equal_sign;
|
_ = equal_sign;
|
||||||
|
|
||||||
// parse expression
|
// parse expression
|
||||||
|
if (pos + 3 >= tokens.items.len) return ParseError.Error;
|
||||||
|
var exp = allocator.create(expression.Expression) catch {
|
||||||
|
return ParseError.Error;
|
||||||
|
};
|
||||||
|
errdefer allocator.destroy(exp);
|
||||||
|
try exp.init(tokens, pos + 3);
|
||||||
|
|
||||||
// provisional good return value
|
// return
|
||||||
return ParseError.Unmatched;
|
target.* = .{
|
||||||
|
.is_mutable = true,
|
||||||
|
.datatype = null,
|
||||||
|
.identifier = identifier,
|
||||||
|
.expression = exp,
|
||||||
|
.alloc = allocator,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(self: *@This()) void {
|
fn deinit(self: *@This()) void {
|
||||||
_ = self;
|
self.alloc.destroy(self.expression);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
test "should parse a minimal var" {
|
test "should parse a minimal var" {
|
||||||
const input = "var my_variable =";
|
const input = "var my_variable = 322";
|
||||||
const tokens = try lexic.tokenize(input, std.testing.allocator);
|
const tokens = try lexic.tokenize(input, std.testing.allocator);
|
||||||
defer tokens.deinit();
|
defer tokens.deinit();
|
||||||
|
|
||||||
const binding = VariableBinding.init(&tokens, 0, std.testing.allocator) catch |err| {
|
var binding: VariableBinding = undefined;
|
||||||
try std.testing.expectEqual(ParseError.Unmatched, err);
|
try binding.init(&tokens, 0, std.testing.allocator);
|
||||||
return;
|
defer binding.deinit();
|
||||||
};
|
|
||||||
|
|
||||||
try std.testing.expectEqual(false, binding.is_mutable);
|
try std.testing.expectEqual(true, binding.is_mutable);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user