From 71cef32fb07e9659a6714385b700f27d52614636 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 4 Jun 2019 22:11:11 -0300 Subject: [PATCH] add basic ast, parser files --- src/ast.zig | 19 +++++++++++++ src/parser.zig | 73 +++++++++++++++++++++++++++++++++++++++++++++++++- src/runner.zig | 18 ++++++++++--- 3 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 src/ast.zig diff --git a/src/ast.zig b/src/ast.zig new file mode 100644 index 0000000..1ed62f4 --- /dev/null +++ b/src/ast.zig @@ -0,0 +1,19 @@ +pub const AstNodeType = enum { + Program, +}; + +pub const AstNode = union(AstNodeType) { + Program: []AstNode, +}; + +pub fn printNode(stdout: var, node: AstNode) anyerror!void { + switch (node) { + .Program => |children| try printNodes(stdout, children), + } +} + +fn printNodes(stdout: var, nodes: []AstNode) anyerror!void { + for (nodes) |node| { + try printNode(stdout, node); + } +} diff --git a/src/parser.zig b/src/parser.zig index c4deda6..e57d0ec 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -1 +1,72 @@ -pub const Parser = struct {}; +const std = @import("std"); +const scanners = @import("scanner.zig"); +const main = @import("main.zig"); +const ast = @import("ast.zig"); +const tokens = @import("tokens.zig"); + +const Allocator = std.mem.Allocator; +const Scanner = scanners.Scanner; +const AstNode = ast.AstNode; +const Token = tokens.Token; +const TokenType = tokens.TokenType; +const Result = main.Result; + +pub const Parser = struct { + allocator: *Allocator, + scanner: *Scanner, + current: Token = undefined, + root: AstNode = undefined, + + pub fn init(allocator: *Allocator, scanner: *Scanner) Parser { + return Parser{ .allocator = allocator, .scanner = scanner }; + } + + fn doError(self: *Parser, comptime fmt: []const u8, args: ...) !void { + std.debug.warn("parser error at line {}\n\t", self.scanner.line); + std.debug.warn(fmt, args); + std.debug.warn("\n"); + + return Result.CompileError; + } + + fn advance(self: *Parser) !void { + var tok_opt = try self.scanner.nextToken(); + if (tok_opt) |tok| { + self.current = tok; + } + } + + fn accept(self: *Parser, ttype: TokenType) !bool { + if (self.current.ttype == ttype) { + try self.advance(); + return true; + } else { + return false; + } + } + + fn expect(self: *Parser, ttype: TokenType) !void { + if (!try self.accept(ttype)) { + try self.doError("expected {x}, got {}", ttype, self.current.ttype); + } + } + + fn program(self: *Parser) !void { + try self.advance(); + try self.advance(); + try self.advance(); + try self.advance(); + + try self.expect(.EOF); + } + + pub fn parse(self: *Parser) !AstNode { + self.root = AstNode{ + .Program = try self.allocator.alloc(AstNode, 0), + }; + + try self.program(); + + return self.root; + } +}; diff --git a/src/runner.zig b/src/runner.zig index 0846552..61c0af1 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -1,21 +1,22 @@ const std = @import("std"); const scanners = @import("scanner.zig"); +const parsers = @import("parser.zig"); const main = @import("main.zig"); +const ast = @import("ast.zig"); const Allocator = std.mem.Allocator; const Result = main.Result; +const Parser = parsers.Parser; pub const Runner = struct { allocator: *Allocator, stdout: main.StdOut, - pub fn init(allocator: *Allocator, stdout: var) Runner { + pub fn init(allocator: *Allocator, stdout: main.StdOut) Runner { return Runner{ .allocator = allocator, .stdout = stdout }; } - pub fn execute(self: *Runner, code: []u8) !void { - var scanner = scanners.Scanner.init(self.allocator, code); - + fn testScanner(self: *Runner, scanner: *scanners.Scanner) !void { while (true) { var tok_opt = scanner.nextToken() catch |err| { try self.stdout.print( @@ -32,7 +33,16 @@ pub const Runner = struct { try self.stdout.print("{x}\n", tok); } } + } + pub fn execute(self: *Runner, code: []u8) !void { + var scanner = scanners.Scanner.init(self.allocator, code); + try self.testScanner(&scanner); + + scanner = scanners.Scanner.init(self.allocator, code); + var parser = Parser.init(self.allocator, &scanner); + var tree = try parser.parse(); + try ast.printNode(self.stdout, tree); return Result.Ok; } };