diff options
| author | Nic Gaffney <gaffney_nic@protonmail.com> | 2024-07-29 06:30:47 -0500 |
|---|---|---|
| committer | Nic Gaffney <gaffney_nic@protonmail.com> | 2024-07-29 06:30:47 -0500 |
| commit | 9334af0c76c9410b3d0028febd4b1972ab7d4d7e (patch) | |
| tree | 40665df61158ace0951b1cdf887035b42e9e4fca /src/parser.zig | |
| parent | e5d311f91ecda870c8e50d3f9c860b99e244a908 (diff) | |
| download | calico-9334af0c76c9410b3d0028febd4b1972ab7d4d7e.tar.gz | |
Started symbol table and restructured AST
Diffstat (limited to 'src/parser.zig')
| -rw-r--r-- | src/parser.zig | 231 |
1 files changed, 170 insertions, 61 deletions
diff --git a/src/parser.zig b/src/parser.zig index df0f068..feaa226 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -1,5 +1,6 @@ const std = @import("std"); const tok = @import("tokenize.zig"); +const symb = @import("symtable.zig"); const Iterator = tok.Iterator; const Token = tok.Token; @@ -12,50 +13,85 @@ const ParsingError = error{ InvalidStatement, }; -pub const NodeExpr = union(enum) { - intLit: NodeIntlit, - ident: NodeIdent, -}; - -pub const NodeStmt = union(enum) { - exit: NodeExit, - value: NodeValue, - assign: NodeAssign, -}; +pub const Node = union(enum) { + Expr: NodeExpr, + Stmt: NodeStmt, -pub const NodeAssign = struct { - ident: Token, - value: NodeExpr, + pub fn children(self: Node, allocator: std.mem.Allocator) ![]Node { + var childrenArray = std.ArrayList(Node).init(allocator); + defer childrenArray.deinit(); + switch (self) { + .Expr => |expr| try childrenArray.appendSlice(try expr.children()), + .Stmt => |stmt| try childrenArray.appendSlice(try stmt.children()), + } + return try childrenArray.toOwnedSlice(); + } }; -pub const NodeValue = struct { - ident: Token, - value: NodeExpr, +pub const NodeExpr = struct { + id: u32, + kind: ExprKind, + symtable: *symb.SymbolTable, + typ: ?symb.SymbType, isConst: bool, -}; -pub const NodeExit = struct { - expr: NodeExpr, -}; + pub fn asNode(self: NodeExpr) Node { + return Node{ .Expr = self }; + } -pub const NodeIntlit = struct { - intlit: Token, + pub fn children(self: NodeExpr, allocator: std.mem.Allocator) ![]Node { + var childrenArray = std.ArrayList(Node).init(allocator); + defer childrenArray.deinit(); + switch (self.kind) { + else => {}, + } + return try childrenArray.toOwnedSlice(); + } }; -pub const NodeIdent = struct { - ident: Token, +pub const NodeStmt = struct { + id: u32, + kind: StmtKind, + symtable: *symb.SymbolTable, + + pub fn asNode(self: NodeStmt) Node { + return Node{ .Stmt = self }; + } + + pub fn children(self: NodeStmt, allocator: std.mem.Allocator) ![]Node { + var childrenArray = std.ArrayList(Node).init(allocator); + defer childrenArray.deinit(); + switch (self.kind) { + .exit => |exit| try childrenArray.append(exit.expr.asNode()), + .defValue => |value| try childrenArray.append(value.expr.asNode()), + .defVar => |variable| try childrenArray.append(variable.expr.asNode()), + .assignVar => |assign| try childrenArray.append(assign.expr.asNode()), + else => {}, + } + return try childrenArray.toOwnedSlice(); + } }; pub const Parser = struct { + top: *symb.SymbolTable, + id: u32, tokens: Iterator(Token), allocator: std.mem.Allocator, nodes: std.ArrayList(NodeStmt), + nextId: u32 = 1, + + fn reserveId(self: *Parser) u32 { + defer self.nextId += 1; + return self.nextId; + } - pub fn init(allocator: std.mem.Allocator, tokens: []Token) Parser { + pub fn init(allocator: std.mem.Allocator, tokens: []Token, symbolTable: *symb.SymbolTable) Parser { return .{ + .top = symbolTable, .allocator = allocator, .tokens = Iterator(Token).init(tokens), .nodes = std.ArrayList(NodeStmt).init(allocator), + .id = 0, }; } @@ -64,76 +100,103 @@ pub const Parser = struct { } fn parseExpr(self: *Parser) !NodeExpr { - return switch (self.tokens.peek().?) { - .intLit => NodeExpr{ + const kind = try switch (self.tokens.peek().?) { + .intLit => ExprKind{ .intLit = NodeIntlit{ .intlit = (try self.tokens.consume(.intLit)).?, }, }, - .ident => NodeExpr{ + .ident => ExprKind{ .ident = NodeIdent{ .ident = (try self.tokens.consume(.ident)).?, }, }, else => ParsingError.InvalidExpression, }; + return NodeExpr{ + .id = self.reserveId(), + .kind = kind, + .isConst = kind.isConstant(), + .typ = null, + .symtable = self.top, + }; } fn parseStmt(self: *Parser) !NodeStmt { return switch (self.tokens.peek().?) { - .exit => NodeStmt{ .exit = try self.parseExit() }, - .constant => NodeStmt{ .value = try self.parseValue(true) }, - .variable => NodeStmt{ .value = try self.parseValue(false) }, - .ident => NodeStmt{ .assign = try self.parseAssign() }, + .exit => try self.parseExit(), + .constant => try self.parseConstant(), + .variable => try self.parseVariable(), + .ident => try self.parseAssign(), else => ParsingError.InvalidStatement, }; } - fn parseAssign(self: *Parser) !NodeAssign { - const ident = try self.tokens.consume(.ident); - var isMutable = false; - var exists = false; - for (self.nodes.items) |item| { - switch (item) { - .value => |v| { - if (std.mem.eql(u8, v.ident.ident, ident.?.ident)) { - isMutable = !v.isConst; - exists = true; - } - }, - else => {}, - } - } - if (!exists) return error.UnknownIdentifier; - if (!isMutable) return error.ImmutableValue; + fn parseAssign(self: *Parser) !NodeStmt { + const ident = (try self.tokens.consume(.ident)).?; _ = try self.tokens.consume(.equal); const expr = try self.parseExpr(); _ = try self.tokens.consume(.semiCol); - return NodeAssign{ - .ident = ident.?, - .value = expr, + const kind = StmtKind{ + .assignVar = NodeAssign{ + .ident = ident, + .expr = expr, + }, + }; + return NodeStmt{ + .id = self.reserveId(), + .kind = kind, + .symtable = self.top, }; } - fn parseExit(self: *Parser) !NodeExit { + fn parseExit(self: *Parser) !NodeStmt { _ = try self.tokens.consume(.exit); const expr = try self.parseExpr(); _ = try self.tokens.consume(.semiCol); - return NodeExit{ - .expr = expr, + const kind = StmtKind{ .exit = NodeExit{ .expr = expr } }; + return NodeStmt{ + .symtable = self.top, + .kind = kind, + .id = self.reserveId(), + }; + } + + fn parseVariable(self: *Parser) !NodeStmt { + _ = try self.tokens.consume(.variable); + const ident = (try self.tokens.consume(.ident)).?; + _ = try self.tokens.consume(.equal); + const expr = try self.parseExpr(); + _ = try self.tokens.consume(.semiCol); + const kind = StmtKind{ + .defVar = NodeVar{ + .ident = ident, + .expr = expr, + }, + }; + return NodeStmt{ + .id = self.reserveId(), + .kind = kind, + .symtable = self.top, }; } - fn parseValue(self: *Parser, isConst: bool) !NodeValue { - self.tokens.skip(); + fn parseConstant(self: *Parser) !NodeStmt { + _ = try self.tokens.consume(.constant); const ident = (try self.tokens.consume(.ident)).?; _ = try self.tokens.consume(.equal); const expr = try self.parseExpr(); _ = try self.tokens.consume(.semiCol); - return NodeValue{ - .ident = ident, - .value = expr, - .isConst = isConst, + const kind = StmtKind{ + .defValue = NodeValue{ + .ident = ident, + .expr = expr, + }, + }; + return NodeStmt{ + .id = self.reserveId(), + .kind = kind, + .symtable = self.top, }; } @@ -145,6 +208,52 @@ pub const Parser = struct { } }; +pub const NodeAssign = struct { + ident: Token, + expr: NodeExpr, +}; + +pub const NodeValue = struct { + ident: Token, + expr: NodeExpr, +}; + +pub const NodeVar = struct { + ident: Token, + expr: NodeExpr, +}; + +pub const NodeExit = struct { + expr: NodeExpr, +}; + +pub const NodeIntlit = struct { + intlit: Token, +}; + +pub const NodeIdent = struct { + ident: Token, +}; + +pub const StmtKind = union(enum) { + exit: NodeExit, + defValue: NodeValue, + defVar: NodeVar, + assignVar: NodeAssign, +}; + +pub const ExprKind = union(enum) { + intLit: NodeIntlit, + ident: NodeIdent, + + pub fn isConstant(self: ExprKind) bool { + return switch (self) { + .intLit => true, + .ident => false, + }; + } +}; + test "Parser" { const expect = std.testing.expect; const src = "exit 120;"; |
