summaryrefslogtreecommitdiff
path: root/src/parser.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.zig')
-rw-r--r--src/parser.zig128
1 files changed, 103 insertions, 25 deletions
diff --git a/src/parser.zig b/src/parser.zig
index 422c9cb..18b2348 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -3,46 +3,112 @@ const tok = @import("tokenize.zig");
const Iterator = tok.Iterator;
const Token = tok.Token;
-const ParsingError = error{ InvalidExpression, ExpectedExit, ExpectedSemicolon };
+const ParsingError = error{
+ InvalidExpression,
+ ExpectedExit,
+ ExpectedSemicolon,
+ ExpectedEqual,
+ ExpectedIdentifier,
+ InvalidStatement,
+};
+
+pub const NodeExpr = union(enum) {
+ intLit: NodeIntlit,
+ ident: NodeIdent,
+};
-pub const NodeExpr = struct {
- intLit: Token,
+pub const NodeStmt = union(enum) {
+ exit: NodeExit,
+ value: NodeValue,
+};
+
+pub const NodeValue = struct {
+ ident: Token,
+ value: NodeExpr,
+ isConst: bool,
};
pub const NodeExit = struct {
expr: NodeExpr,
};
+pub const NodeIntlit = struct {
+ intlit: Token,
+};
+
+pub const NodeIdent = struct {
+ ident: Token,
+};
+
pub const Parser = struct {
tokens: Iterator(Token),
+ allocator: std.mem.Allocator,
+ nodes: std.ArrayList(NodeStmt),
- pub fn init(tokens: []Token) Parser {
+ pub fn init(allocator: std.mem.Allocator, tokens: []Token) Parser {
return .{
+ .allocator = allocator,
.tokens = Iterator(Token).init(tokens),
+ .nodes = std.ArrayList(NodeStmt).init(allocator),
};
}
- fn parseExpr(self: *Parser) !NodeExpr {
- if (tok.checkType(self.tokens.peek().?, tok.TokenType.intLit))
- return NodeExpr{ .intLit = self.tokens.consume().? };
- return ParsingError.InvalidExpression;
+ pub fn deinit(self: *Parser) void {
+ self.nodes.deinit();
}
- pub fn parse(self: *Parser) !NodeExit {
- var root: NodeExit = undefined;
- while (self.tokens.peek()) |token| {
- switch (token) {
- .exit => {
- self.tokens.skip();
- root.expr = try self.parseExpr();
- if (!tok.checkType(self.tokens.peek().?, tok.TokenType.semiCol))
- return ParsingError.ExpectedSemicolon;
- self.tokens.skip();
+ fn parseExpr(self: *Parser) !NodeExpr {
+ return switch (self.tokens.peek().?) {
+ .intLit => NodeExpr{
+ .intLit = NodeIntlit{
+ .intlit = (try self.tokens.consume(.intLit)).?,
+ },
+ },
+ .ident => NodeExpr{
+ .ident = NodeIdent{
+ .ident = (try self.tokens.consume(.ident)).?,
},
- else => return ParsingError.ExpectedExit,
- }
- }
- return root;
+ },
+ else => ParsingError.InvalidExpression,
+ };
+ }
+
+ 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) },
+ else => ParsingError.InvalidStatement,
+ };
+ }
+
+ fn parseExit(self: *Parser) !NodeExit {
+ _ = try self.tokens.consume(.exit);
+ const expr = try self.parseExpr();
+ _ = try self.tokens.consume(.semiCol);
+ return NodeExit{
+ .expr = expr,
+ };
+ }
+
+ fn parseValue(self: *Parser, isConst: bool) !NodeValue {
+ self.tokens.skip();
+ 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,
+ };
+ }
+
+ pub fn parse(self: *Parser) ![]const NodeStmt {
+ while (self.tokens.peek()) |_|
+ try self.nodes.append(try self.parseStmt());
+
+ return self.nodes.items;
}
};
@@ -52,8 +118,20 @@ test "Parser" {
var tokenizer = tok.Tokenizer.init(std.testing.allocator, src);
defer tokenizer.deinit();
const toks = try tokenizer.tokenize();
- var parser = Parser.init(toks);
+ var parser = Parser.init(std.testing.allocator, toks);
+ defer parser.deinit();
const parseTree = try parser.parse();
- const exp = NodeExit{ .expr = NodeExpr{ .intLit = Token{ .intLit = 120 } } };
- try expect(std.meta.eql(parseTree, exp));
+ const exp: []const NodeStmt = &[_]NodeStmt{NodeStmt{
+ .exit = NodeExit{
+ .expr = NodeExpr{
+ .intLit = NodeIntlit{
+ .intlit = Token{
+ .intLit = 120,
+ },
+ },
+ },
+ },
+ }};
+ for (parseTree, exp) |stmt, expStmt|
+ try expect(std.meta.eql(stmt, expStmt));
}