diff --git a/src/compiler.zig b/src/compiler.zig index 6695de9..a04fd1f 100644 --- a/src/compiler.zig +++ b/src/compiler.zig @@ -3,18 +3,14 @@ const scanner = @import("new_scanner.zig"); const vm = @import("vm.zig"); const chunks = @import("chunk.zig"); const tokens = @import("token.zig"); -const values = @import("value.zig"); const Allocator = std.mem.Allocator; const Scanner = scanner.Scanner; const Chunk = chunks.Chunk; const Token = tokens.Token; const TokenType = tokens.TokenType; -const Value = values.Value; -const OpCode = chunks.OpCode; -/// Holds parser state for the compiler. -const Parser = struct { +pub const Parser = struct { previous: Token = undefined, current: Token = undefined, @@ -23,93 +19,6 @@ const Parser = struct { panicMode: bool = false, }; -/// Represents the order of operations in the parser. -const Precedence = enum(u5) { - None, - Assignment, // = - Or, // or - And, // and - Equality, // == != - Comparison, // < > <= >= - Term, // + - - Factor, // * / - Unary, // ! - - Call, // . () [] - Primary, -}; - -const ParseFn = fn (*Compiler) anyerror!void; - -const ParseRule = struct { - prefix: ?ParseFn = null, - infix: ?ParseFn = null, - precedence: Precedence = Precedence.None, -}; - -/// For each token, this defines a parse rule for it. -var rules = []ParseRule{ - // for LEFT_PAREN, we determine it as a call precedence - // plus a prefix parse function of grouping - ParseRule{ .prefix = Compiler.grouping, .precedence = .Call }, - ParseRule{}, - ParseRule{}, - ParseRule{}, - ParseRule{}, - - // dot token, means a call too, for things like a.b - ParseRule{ .precedence = .Call }, - - // specific to -, as it can be an unary operator when its a prefix - // of something, or a binary one, when its a infix or another thing. - ParseRule{ - .prefix = Compiler.unary, - .infix = Compiler.binary, - .precedence = .Term, - }, - - ParseRule{ .infix = Compiler.binary, .precedence = .Term }, - ParseRule{}, - - // slash is a binary operator, as well as star. - ParseRule{ .infix = Compiler.binary, .precedence = .Factor }, - ParseRule{ .infix = Compiler.binary, .precedence = .Factor }, - - // as the token enum says, those are 1/2 char tokens. - ParseRule{}, - // this is specifically for the != operator - ParseRule{ .precedence = .Equality }, - ParseRule{}, - // this is specifically for the == operator - ParseRule{ .precedence = .Equality }, - - // all the comparison ones - ParseRule{ .precedence = .Comparison }, - ParseRule{ .precedence = .Comparison }, - ParseRule{ .precedence = .Comparison }, - ParseRule{ .precedence = .Comparison }, - - ParseRule{}, - ParseRule{}, - ParseRule{ .prefix = Compiler.number }, - ParseRule{ .precedence = .And }, - ParseRule{}, - ParseRule{}, - ParseRule{}, - ParseRule{}, - ParseRule{}, - ParseRule{}, - ParseRule{}, - ParseRule{ .precedence = .Or }, - ParseRule{}, - ParseRule{}, - ParseRule{}, - ParseRule{}, - ParseRule{}, - ParseRule{}, - ParseRule{}, - ParseRule{}, -}; - pub const Compiler = struct { src: []const u8, stdout: vm.StdOut, @@ -117,14 +26,12 @@ pub const Compiler = struct { parser: Parser, scanr: Scanner = undefined, chunk: *chunks.Chunk, - debug_flag: bool = false, pub fn init( allocator: *Allocator, chunk: *chunks.Chunk, stdout: vm.StdOut, source: []const u8, - debug_flag: bool, ) Compiler { return Compiler{ .src = source, @@ -132,7 +39,6 @@ pub const Compiler = struct { .allocator = allocator, .stdout = stdout, .parser = Parser{}, - .debug_flag = debug_flag, }; } @@ -195,91 +101,12 @@ pub const Compiler = struct { try self.emitByte(byte2); } - fn emitReturn(self: *Compiler) !void { - try self.emitByte(OpCode.Return); - } - - fn emitConstant(self: *Compiler, value: Value) !void { - try self.currentChunk().writeConstant( - value, - self.parser.previous.line, - ); + fn writeReturn(self: *Compiler) !void { + try self.emitByte(chunks.OpCode.Return); } fn end(self: *Compiler) !void { - try self.emitReturn(); - - if (self.debug_flag and !self.parser.hadError) { - try self.currentChunk().disassemble(self.stdout, "code"); - } - } - - fn grouping(self: *Compiler) !void { - try self.expression(); - try self.consume(.RIGHT_PAREN, "Expect ')' after expression."); - } - - /// Emits bytecode for a number being loaded into the code. - fn number(self: *Compiler) !void { - var value: f64 = try std.fmt.parseFloat( - f64, - self.parser.previous.lexeme, - ); - try self.emitConstant(value); - } - - /// Emits bytecode for a given unary. - fn unary(self: *Compiler) !void { - var ttype = self.parser.previous.ttype; - try self.parsePrecedence(.Unary); - - switch (ttype) { - .MINUS => try self.emitByte(OpCode.Negate), - else => unreachable, - } - } - - fn binary(self: *Compiler) !void { - var op_type = self.parser.previous.ttype; - var rule: *ParseRule = self.getRule(op_type); - try self.parsePrecedence(@intToEnum(Precedence, @enumToInt(rule.precedence) + 1)); - - switch (op_type) { - .PLUS => try self.emitByte(OpCode.Add), - .MINUS => try self.emitByte(OpCode.Subtract), - .STAR => try self.emitByte(OpCode.Multiply), - .SLASH => try self.emitByte(OpCode.Divide), - else => unreachable, - } - } - - fn parsePrecedence(self: *Compiler, precedence: Precedence) !void { - try self.advance(); - var as_int = @enumToInt(precedence); - var prefix_rule_opt = self.getRule(self.parser.previous.ttype).prefix; - - if (prefix_rule_opt) |prefix_rule| { - try prefix_rule(self); - - while (as_int <= @enumToInt(self.getRule(self.parser.current.ttype).precedence)) { - try self.advance(); - var infix_rule_opt = self.getRule(self.parser.previous.ttype).infix; - if (infix_rule_opt) |infix_rule| { - try infix_rule(self); - } - } - } else { - self.errorPrevious("Expect expression."); - return; - } - } - - fn getRule(self: *Compiler, ttype: TokenType) *ParseRule { - return &rules[@enumToInt(ttype)]; - } - - fn expression(self: *Compiler) !void { - try self.parsePrecedence(.Assignment); + try self.writeReturn(); } /// Compile the source given when initializing the compiler @@ -288,7 +115,7 @@ pub const Compiler = struct { self.scanr = try scanner.Scanner.init(self.allocator, self.src); try self.advance(); - try self.expression(); + //try self.expression(); try self.consume(.EOF, "Expect end of expression."); try self.end(); diff --git a/src/vm.zig b/src/vm.zig index e58bc66..3375684 100644 --- a/src/vm.zig +++ b/src/vm.zig @@ -167,13 +167,7 @@ pub const VM = struct { //return res; var chk = try Chunk.init(self.allocator); - var cmpr = Compiler.init( - self.allocator, - &chk, - self.stdout, - self.src, - self.debug_flag, - ); + var cmpr = Compiler.init(self.allocator, &chk, self.stdout, self.src); if (!try cmpr.compile(&chk)) { return InterpretResult.CompileError; }