From c19f6df834f712642bec3958be94db21bcf204b5 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 4 Jun 2019 21:27:05 -0300 Subject: [PATCH 1/2] split main code into a runner struct --- src/main.zig | 26 +++++--------------------- src/parser.zig | 1 + src/runner.zig | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 src/parser.zig create mode 100644 src/runner.zig diff --git a/src/main.zig b/src/main.zig index e538343..b9ca981 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const scanners = @import("scanner.zig"); +const runners = @import("runner.zig"); const Allocator = std.mem.Allocator; @@ -9,30 +9,14 @@ pub const Result = error{ CompileError, }; +pub const StdOut = *std.io.OutStream(std.fs.File.WriteError); + fn run(allocator: *Allocator, data: []u8) !void { var stdout_file = try std.io.getStdOut(); const stdout = &stdout_file.outStream().stream; - var scanner = scanners.Scanner.init(allocator, data); - - while (true) { - var tok_opt = scanner.nextToken() catch |err| { - try stdout.print( - "error at '{}': {}\n", - scanner.currentLexeme(), - err, - ); - - return Result.CompileError; - }; - - if (tok_opt) |tok| { - if (tok.ttype == .EOF) break; - try stdout.print("{x}\n", tok); - } - } - - return Result.Ok; + var runner = runners.Runner.init(allocator, stdout); + return runner.execute(data); } fn runFile(allocator: *Allocator, path: []const u8) !void { diff --git a/src/parser.zig b/src/parser.zig new file mode 100644 index 0000000..c4deda6 --- /dev/null +++ b/src/parser.zig @@ -0,0 +1 @@ +pub const Parser = struct {}; diff --git a/src/runner.zig b/src/runner.zig new file mode 100644 index 0000000..0846552 --- /dev/null +++ b/src/runner.zig @@ -0,0 +1,38 @@ +const std = @import("std"); +const scanners = @import("scanner.zig"); +const main = @import("main.zig"); + +const Allocator = std.mem.Allocator; +const Result = main.Result; + +pub const Runner = struct { + allocator: *Allocator, + stdout: main.StdOut, + + pub fn init(allocator: *Allocator, stdout: var) Runner { + return Runner{ .allocator = allocator, .stdout = stdout }; + } + + pub fn execute(self: *Runner, code: []u8) !void { + var scanner = scanners.Scanner.init(self.allocator, code); + + while (true) { + var tok_opt = scanner.nextToken() catch |err| { + try self.stdout.print( + "error at '{}': {}\n", + scanner.currentLexeme(), + err, + ); + + return Result.CompileError; + }; + + if (tok_opt) |tok| { + if (tok.ttype == .EOF) break; + try self.stdout.print("{x}\n", tok); + } + } + + return Result.Ok; + } +}; From 71cef32fb07e9659a6714385b700f27d52614636 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 4 Jun 2019 22:11:11 -0300 Subject: [PATCH 2/2] 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; } };