Compare commits
No commits in common. "71cef32fb07e9659a6714385b700f27d52614636" and "a44f04c7c8f0ae92f2f9388b9c4e2ae59278a9dc" have entirely different histories.
71cef32fb0
...
a44f04c7c8
4 changed files with 21 additions and 144 deletions
19
src/ast.zig
19
src/ast.zig
|
@ -1,19 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
26
src/main.zig
26
src/main.zig
|
@ -1,6 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const runners = @import("runner.zig");
|
const scanners = @import("scanner.zig");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
@ -9,14 +9,30 @@ pub const Result = error{
|
||||||
CompileError,
|
CompileError,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const StdOut = *std.io.OutStream(std.fs.File.WriteError);
|
|
||||||
|
|
||||||
fn run(allocator: *Allocator, data: []u8) !void {
|
fn run(allocator: *Allocator, data: []u8) !void {
|
||||||
var stdout_file = try std.io.getStdOut();
|
var stdout_file = try std.io.getStdOut();
|
||||||
const stdout = &stdout_file.outStream().stream;
|
const stdout = &stdout_file.outStream().stream;
|
||||||
|
|
||||||
var runner = runners.Runner.init(allocator, stdout);
|
var scanner = scanners.Scanner.init(allocator, data);
|
||||||
return runner.execute(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runFile(allocator: *Allocator, path: []const u8) !void {
|
fn runFile(allocator: *Allocator, path: []const u8) !void {
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,48 +0,0 @@
|
||||||
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: main.StdOut) Runner {
|
|
||||||
return Runner{ .allocator = allocator, .stdout = stdout };
|
|
||||||
}
|
|
||||||
|
|
||||||
fn testScanner(self: *Runner, scanner: *scanners.Scanner) !void {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
|
Loading…
Add table
Add a link
Reference in a new issue