diff options
author | Baitinq <manuelpalenzuelamerino@gmail.com> | 2025-01-07 01:08:32 +0100 |
---|---|---|
committer | Baitinq <manuelpalenzuelamerino@gmail.com> | 2025-01-07 01:08:38 +0100 |
commit | 85c33e02224a02d2c98c927c85aeabec0fca32d3 (patch) | |
tree | fe7cefab8268df318198080ba24947139b8c1f77 /src/parser.zig | |
parent | Parser: Improvements? (diff) | |
download | interpreter-85c33e02224a02d2c98c927c85aeabec0fca32d3.tar.gz interpreter-85c33e02224a02d2c98c927c85aeabec0fca32d3.tar.bz2 interpreter-85c33e02224a02d2c98c927c85aeabec0fca32d3.zip |
Parser: Memory improvements
Diffstat (limited to 'src/parser.zig')
-rw-r--r-- | src/parser.zig | 84 |
1 files changed, 49 insertions, 35 deletions
diff --git a/src/parser.zig b/src/parser.zig index 480757a..00921e8 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -2,7 +2,8 @@ const std = @import("std"); const tokenizer = @import("tokenizer.zig"); const ParserError = error{ - Error, + ParsingError, + OutOfMemory, }; const NodeType = enum { @@ -39,89 +40,102 @@ pub const Parser = struct { allocator: std.mem.Allocator, - pub fn init(tokens: []tokenizer.Token, allocator: std.mem.Allocator) *Parser { - return @constCast(&Parser{ + pub fn init(tokens: []tokenizer.Token, allocator: std.mem.Allocator) ParserError!*Parser { + const parser = try allocator.create(Parser); + parser.* = .{ .tokens = tokens, .offset = 0, .allocator = allocator, - }); + }; + return parser; } - pub fn deinit(_: *Parser) void { - //TODO: We should somehow free the arraylist we created + pub fn deinit(self: *Parser, ast: *Node) void { + std.debug.assert(ast.* == .PROGRAM); + std.debug.print("STATEMENTS FREE: {any}\n", .{ast.PROGRAM.statements.len}); + for (ast.PROGRAM.statements) |statement| { + self.allocator.destroy(statement); //TODO: We're missing frees of children. we also dont want to double free! + } } - pub fn parse(self: *Parser) !Node { + pub fn parse(self: *Parser) !*Node { return self.parse_program(); } - fn parse_program(self: *Parser) !Node { + fn parse_program(self: *Parser) !*Node { var nodes = std.ArrayList(*Node).init(self.allocator); while (self.offset < self.tokens.len) { - std.debug.print("OFFSET: {any} - len: {any}\n", .{ self.offset, self.tokens.len }); - try nodes.append(@constCast(&try self.parse_statement())); //TODO: This is not good, should we be allocating mem for every node? + try nodes.append(@constCast(try self.parse_statement())); //TODO: This is not good, should we be allocating mem for every node? } - return Node{ .PROGRAM = .{ - .statements = nodes.items, + const node = try self.allocator.create(Node); + node.* = .{ .PROGRAM = .{ + .statements = try nodes.toOwnedSlice(), } }; + return node; } - fn parse_identifier(self: *Parser) ParserError!Node { - const token = self.peek_token() orelse return ParserError.Error; + fn parse_identifier(self: *Parser) ParserError!*Node { + const token = self.peek_token() orelse return ParserError.ParsingError; - if (token != .IDENTIFIER) return ParserError.Error; + if (token != .IDENTIFIER) return ParserError.ParsingError; _ = self.consume_token(); - return Node{ .IDENTIFIER = .{ + const node = try self.allocator.create(Node); + node.* = .{ .IDENTIFIER = .{ .name = token.IDENTIFIER, } }; + return node; } - fn parse_number(self: *Parser) ParserError!Node { - const token = self.peek_token() orelse return ParserError.Error; + fn parse_number(self: *Parser) ParserError!*Node { + const token = self.peek_token() orelse return ParserError.ParsingError; - if (token != .NUMBER) return ParserError.Error; + if (token != .NUMBER) return ParserError.ParsingError; _ = self.consume_token(); - return Node{ .NUMBER = .{ + const node = try self.allocator.create(Node); + node.* = .{ .NUMBER = .{ .value = token.NUMBER, } }; + return node; } - fn parse_print_statement(self: *Parser) ParserError!Node { + fn parse_print_statement(self: *Parser) ParserError!*Node { // print + ( + statement + ) + ; - var token = self.consume_token() orelse return ParserError.Error; + var token = self.consume_token() orelse return ParserError.ParsingError; - if (token != .PRINT) return ParserError.Error; + if (token != .PRINT) return ParserError.ParsingError; - token = self.consume_token() orelse return ParserError.Error; + token = self.consume_token() orelse return ParserError.ParsingError; - if (token != .LPAREN) return ParserError.Error; + if (token != .LPAREN) return ParserError.ParsingError; const expression = try self.parse_statement(); std.debug.print("PARSED expression: {any}\n", .{expression}); - token = self.consume_token() orelse return ParserError.Error; + token = self.consume_token() orelse return ParserError.ParsingError; - if (token != .RPAREN) return ParserError.Error; + if (token != .RPAREN) return ParserError.ParsingError; - token = self.consume_token() orelse return ParserError.Error; + token = self.consume_token() orelse return ParserError.ParsingError; - if (token != .SEMICOLON) return ParserError.Error; //TODO: This should not be handled at this level + if (token != .SEMICOLON) return ParserError.ParsingError; //TODO: This should not be handled at this level - return Node{ + const node = try self.allocator.create(Node); + node.* = .{ .PRINT_STATEMENT = .{ - .expression = @constCast(&expression), //TODO: Warning ptr + .expression = @constCast(expression), //TODO: Warning ptr }, }; + return node; } - fn parse_statement(self: *Parser) ParserError!Node { - const token = self.peek_token() orelse return ParserError.Error; + fn parse_statement(self: *Parser) ParserError!*Node { + const token = self.peek_token() orelse return ParserError.ParsingError; std.debug.print("TOKEN: {any}\n", .{token}); @@ -133,7 +147,7 @@ pub const Parser = struct { } else if (token == .PRINT) { return self.parse_print_statement(); } else { - return ParserError.Error; + return ParserError.ParsingError; } } @@ -145,7 +159,7 @@ pub const Parser = struct { return self.tokens[self.offset]; } - fn peek_token(self: Parser) ?tokenizer.Token { + fn peek_token(self: *Parser) ?tokenizer.Token { if (self.offset >= self.tokens.len) return null; return self.tokens[self.offset]; |