From 366be14cea557d1ea19a5d3a7c357eeff654d7d2 Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 24 Aug 2019 17:46:42 -0300 Subject: [PATCH] add assignment of mutable variables --- examples/hello.v | 1 + src/ast.zig | 20 +++++++++++++++++--- src/parser.zig | 32 ++++++++++++++++++++++++-------- src/scanner.zig | 3 ++- src/tokens.zig | 1 + 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/examples/hello.v b/examples/hello.v index c0aba91..98b1de0 100644 --- a/examples/hello.v +++ b/examples/hello.v @@ -9,5 +9,6 @@ fn main(a int) int { 1 + 2 + 3 + 4 1 + 1 * 1 3 / (51 + 2) + mut a := 1+2 println(2 * 1956 + a) } diff --git a/src/ast.zig b/src/ast.zig index d206807..ef10787 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -65,6 +65,7 @@ pub const Expr = union(enum) { pub const VarDecl = struct { name: Token, initializer: *Expr, + mutable: bool = false, }; pub const Stmt = union(enum) { @@ -78,9 +79,15 @@ pub const Stmt = union(enum) { return println; } - pub fn mkVarDecl(allocator: *std.mem.Allocator, name: Token, init: *Expr) !*Stmt { + pub fn mkVarDecl(allocator: *std.mem.Allocator, name: Token, init: *Expr, mutable: bool) !*Stmt { var vardecl = try allocator.create(Stmt); - vardecl.* = Stmt{ .VarDecl = VarDecl{ .name = name, .initializer = init } }; + vardecl.* = Stmt{ + .VarDecl = VarDecl{ + .name = name, + .initializer = init, + .mutable = mutable, + }, + }; return vardecl; } }; @@ -210,6 +217,13 @@ pub fn printStmt(stmt: *Stmt) void { .Println => |expr| parenthetize("println", &[_]*Expr{expr}), .Expr => |expr| printExpr(expr), - else => std.debug.warn("STMT_UNKNOWN"), + .VarDecl => |decl| { + if (decl.mutable) + std.debug.warn("mut "); + std.debug.warn("assign {} := ", decl.name.lexeme); + printExpr(decl.initializer); + }, + + else => std.debug.warn("UnknownStmt-{}", @tagName(stmt.*)), } } diff --git a/src/parser.zig b/src/parser.zig index e74eb19..89cfa32 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -389,9 +389,9 @@ pub const Parser = struct { while (self.peek().ttype != .RightBrace) { std.debug.warn("get smt with cur {}\n", self.peek().ttype); - var node = try self.parseStmt(); - ast.printNode(node, 0); - try stmts.append(node.Stmt); + var stmt = try self.parseDecl(); + ast.printNode(try self.mkStmt(stmt), 0); + try stmts.append(stmt); } _ = try self.consumeSingle(.RightBrace); @@ -399,15 +399,31 @@ pub const Parser = struct { return try self.mkBlock(stmts); } - fn parseStmt(self: *@This()) anyerror!*Node { - var stmt = switch (self.peek().ttype) { + fn parseDecl(self: *@This()) !*Stmt { + return switch (self.peek().ttype) { + .Mut => try self.parseMutVarDecl(), + else => try self.parseStmt(), + }; + } + + fn parseMutVarDecl(self: *@This()) !*Stmt { + _ = try self.consumeSingle(.Mut); + + var name = try self.consumeSingle(.Identifier); + + _ = try self.consumeSingle(.Assign); + var initializer = (try self.parseExpr()).Expr; + + return try Stmt.mkVarDecl(self.allocator, name, initializer, true); + } + + fn parseStmt(self: *@This()) anyerror!*Stmt { + return switch (self.peek().ttype) { .Println => try self.parsePrintln(), // TODO make newlines tokens and consume newline? else => try self.parseStmtExpr(), }; - - return try self.mkStmt(stmt); } fn parsePrintln(self: *@This()) !*Stmt { @@ -531,7 +547,7 @@ pub const Parser = struct { }, else => blk: { - self.doError("expected false/true/int/float/string/leftparen, got {}", curtype); + self.doError("expected literal, got {}", curtype); return Result.CompileError; }, }; diff --git a/src/scanner.zig b/src/scanner.zig index 811c1c9..09b9fc3 100644 --- a/src/scanner.zig +++ b/src/scanner.zig @@ -288,7 +288,6 @@ pub const Scanner = struct { '.' => self.makeToken(.Dot), ';' => self.makeToken(.Semicolon), ',' => self.makeToken(.Comma), - ':' => self.makeToken(.Colon), '&' => self.makeToken(.Ampersand), '|' => self.makeToken(.Pipe), '?' => self.makeToken(.QuestionMark), @@ -298,6 +297,8 @@ pub const Scanner = struct { '*' => self.makeToken(.Star), '%' => self.makeToken(.Modulo), + ':' => self.makeMatchToken('=', .Assign, .Colon), + '!' => self.makeMatchToken('=', .BangEqual, .Bang), '=' => self.makeMatchToken('=', .EqualEqual, .Equal), '>' => self.makeMatchToken('=', .GreaterEqual, .Greater), diff --git a/src/tokens.zig b/src/tokens.zig index 7579028..841d2ef 100644 --- a/src/tokens.zig +++ b/src/tokens.zig @@ -29,6 +29,7 @@ pub const TokenType = enum { PlusPlus, PlusEqual, MinusEqual, + Assign, // comparison ones EqualEqual,