From 72bc932d23842875f170a1f51ae464991c9d4c9a Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 25 Aug 2019 10:27:50 -0300 Subject: [PATCH] add assignment support (without mut) --- examples/hello.v | 2 +- src/ast.zig | 23 ++++++++++++++++++++++- src/parser.zig | 36 ++++++++++++++++++++++++++++++++---- src/scanner.zig | 2 +- src/tokens.zig | 2 +- 5 files changed, 57 insertions(+), 8 deletions(-) diff --git a/examples/hello.v b/examples/hello.v index 98b1de0..972d9f5 100644 --- a/examples/hello.v +++ b/examples/hello.v @@ -9,6 +9,6 @@ fn main(a int) int { 1 + 2 + 3 + 4 1 + 1 * 1 3 / (51 + 2) - mut a := 1+2 + a := 1+2 println(2 * 1956 + a) } diff --git a/src/ast.zig b/src/ast.zig index ef10787..7599921 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -54,7 +54,22 @@ pub const LiteralExpr = union(enum) { String: []const u8, }; -pub const Expr = union(enum) { +pub const AssignExpr = struct { + name: Token, + value: *Expr, +}; + +pub const ExprType = enum { + Assign, + Binary, + Unary, + Literal, + Variable, + Grouping, +}; + +pub const Expr = union(ExprType) { + Assign: AssignExpr, Binary: BinaryExpr, Unary: UnaryExpr, Literal: LiteralExpr, @@ -208,6 +223,12 @@ pub fn printExpr(expr: *Expr) void { .Variable => |token| std.debug.warn("{}", token.lexeme), + .Assign => |assign| { + std.debug.warn("(let "); + std.debug.warn("{} ", assign.name.lexeme); + printExpr(assign.value); + }, + else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)), } } diff --git a/src/parser.zig b/src/parser.zig index 89cfa32..8dadcb1 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -182,8 +182,6 @@ pub const Parser = struct { } fn mkBinary(self: *Parser, left: *Expr, op: Token, right: *Expr) !*Expr { - std.debug.warn("Binary\n"); - var expr = try self.allocator.create(Expr); expr.* = Expr{ .Binary = ast.BinaryExpr{ @@ -196,6 +194,18 @@ pub const Parser = struct { return expr; } + fn mkAssign(self: *Parser, name: Token, value: *Expr) !*Expr { + var expr = try self.allocator.create(Expr); + expr.* = Expr{ + .Assign = ast.AssignExpr{ + .name = name, + .value = value, + }, + }; + + return expr; + } + fn mkBool(self: *Parser, val: bool) !*ast.Expr { var expr = try self.allocator.create(Expr); expr.* = Expr{ @@ -411,7 +421,7 @@ pub const Parser = struct { var name = try self.consumeSingle(.Identifier); - _ = try self.consumeSingle(.Assign); + _ = try self.consumeSingle(.Equal); var initializer = (try self.parseExpr()).Expr; return try Stmt.mkVarDecl(self.allocator, name, initializer, true); @@ -442,10 +452,28 @@ pub const Parser = struct { } fn parseExpr(self: *@This()) anyerror!*Node { - var expr = try self.parseEquality(); + var expr: *Expr = try self.parseAssignment(); return self.mkExpr(expr); } + fn parseAssignment(self: *@This()) anyerror!*Expr { + var expr = try self.parseEquality(); + + if (self.check(.ColonEqual)) { + var op = try self.consumeSingle(.ColonEqual); + var value = try self.parseAssignment(); + + if (ast.ExprType(expr.*) == .Variable) { + return try self.mkAssign(expr.Variable, value); + } + + self.doError("Invalid assignment target"); + return Result.CompileError; + } + + return expr; + } + fn parseEquality(self: *@This()) !*Expr { var expr = try self.parseComparison(); diff --git a/src/scanner.zig b/src/scanner.zig index 09b9fc3..922374a 100644 --- a/src/scanner.zig +++ b/src/scanner.zig @@ -297,7 +297,7 @@ pub const Scanner = struct { '*' => self.makeToken(.Star), '%' => self.makeToken(.Modulo), - ':' => self.makeMatchToken('=', .Assign, .Colon), + ':' => self.makeMatchToken('=', .ColonEqual, .Colon), '!' => self.makeMatchToken('=', .BangEqual, .Bang), '=' => self.makeMatchToken('=', .EqualEqual, .Equal), diff --git a/src/tokens.zig b/src/tokens.zig index 841d2ef..2484082 100644 --- a/src/tokens.zig +++ b/src/tokens.zig @@ -29,7 +29,7 @@ pub const TokenType = enum { PlusPlus, PlusEqual, MinusEqual, - Assign, + ColonEqual, // comparison ones EqualEqual,