summaryrefslogtreecommitdiff
path: root/src/parser.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.zig')
-rw-r--r--src/parser.zig231
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;";