From 460055e186875066a52902fc0613c0aaa15f07f9 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 25 Aug 2019 16:49:08 -0300 Subject: [PATCH 1/3] add loop keyword --- README.md | 5 +++++ src/scanner.zig | 2 ++ src/tokens.zig | 1 + 3 files changed, 8 insertions(+) diff --git a/README.md b/README.md index eed189f..054b284 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,11 @@ a vlang parser in zig because i can +## variations + + - `for` is split between `for` and `loop` because my fucking god i cant stand + having *four* different variations of `for`. + ## how ``` diff --git a/src/scanner.zig b/src/scanner.zig index 23c442b..2ee42d1 100644 --- a/src/scanner.zig +++ b/src/scanner.zig @@ -50,6 +50,7 @@ const keywords = [_][]const u8{ "false", "None", "println", + "loop", }; const keyword_ttypes = [_]TokenType{ @@ -78,6 +79,7 @@ const keyword_ttypes = [_]TokenType{ .False, .None, .Println, + .Loop, }; fn getKeyword(keyword: []const u8) ?TokenType { diff --git a/src/tokens.zig b/src/tokens.zig index 8b45d54..360c6b6 100644 --- a/src/tokens.zig +++ b/src/tokens.zig @@ -55,6 +55,7 @@ pub const TokenType = enum { Enum, Fn, For, + Loop, Go, Goto, If, From 19b79514b46d3abb9a28cb40b0402bd9a01a30d1 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 25 Aug 2019 16:57:22 -0300 Subject: [PATCH 2/3] ast: rename IfBranch to Block, add LoopStmt --- src/ast.zig | 45 ++++++++++++++++++++++++++++++++++----------- src/parser.zig | 18 +++++++++--------- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/ast.zig b/src/ast.zig index f048ac1..609cf48 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -97,12 +97,17 @@ pub const Expr = union(ExprType) { Grouping: *Expr, }; -pub const IfBranch = std.ArrayList(*Stmt); +pub const Block = std.ArrayList(*Stmt); pub const IfStmt = struct { condition: *Expr, - then_branch: IfBranch, - else_branch: ?IfBranch, + then_branch: Block, + else_branch: ?Block, +}; + +pub const LoopStmt = struct { + condition: ?*Expr, + then_branch: Block, }; pub const Stmt = union(enum) { @@ -110,28 +115,46 @@ pub const Stmt = union(enum) { Println: *Expr, If: IfStmt, + Loop: LoopStmt, pub fn mkPrintln(allocator: *std.mem.Allocator, expr: *Expr) !*Stmt { - var println = try allocator.create(Stmt); - println.* = Stmt{ .Println = expr }; - return println; + var stmt = try allocator.create(Stmt); + stmt.* = Stmt{ .Println = expr }; + return stmt; } pub fn mkIfStmt( allocator: *std.mem.Allocator, condition: *Expr, - then: IfBranch, - else_branch: ?IfBranch, + then: Block, + else_branch: ?Block, ) !*Stmt { - var println = try allocator.create(Stmt); - println.* = Stmt{ + var stmt = try allocator.create(Stmt); + stmt.* = Stmt{ .If = IfStmt{ .condition = condition, .then_branch = then, .else_branch = else_branch, }, }; - return println; + + return stmt; + } + + pub fn mkLoop( + allocator: *std.mem.Allocator, + condition: ?*Expr, + then: Block, + ) !*Stmt { + var stmt = try allocator.create(Stmt); + stmt.* = Stmt{ + .Loop = LoopStmt{ + .condition = condition, + .then_branch = then, + }, + }; + + return stmt; } }; diff --git a/src/parser.zig b/src/parser.zig index 21a3015..73d61f3 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -456,35 +456,35 @@ pub const Parser = struct { }; } - /// Copy of parseBlock for if branches - fn parseIfBranch(self: *@This()) !ast.IfBranch { - var branch = ast.IfBranch.init(self.allocator); - errdefer branch.deinit(); + /// Copy of parseBlock for blocks in statements + fn parseStmtBlock(self: *@This()) !ast.Block { + var block = ast.Block.init(self.allocator); + errdefer block.deinit(); _ = try self.consumeSingle(.LeftBrace); while (self.peek().ttype != .RightBrace) { var stmt = try self.parseDecl(); ast.printNode(try self.mkStmt(stmt), 0); - try branch.append(stmt); + try block.append(stmt); } _ = try self.consumeSingle(.RightBrace); - return branch; + return block; } fn parseIfStmt(self: *@This()) !*Stmt { _ = try self.consumeSingle(.If); var condition = (try self.parseExpr()).Expr; - const then_branch = try self.parseIfBranch(); + const then_branch = try self.parseStmtBlock(); - var else_branch: ?ast.IfBranch = null; + var else_branch: ?ast.Block = null; if (self.check(.Else)) { _ = try self.consumeSingle(.Else); - else_branch = try self.parseIfBranch(); + else_branch = try self.parseStmtBlock(); } return try Stmt.mkIfStmt( From 4f0c43865f427558cd036923048dc43fe202cfa4 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 25 Aug 2019 17:14:25 -0300 Subject: [PATCH 3/3] add loop parsing --- examples/hello.v | 10 ++++++++++ src/ast.zig | 14 ++++++++++++++ src/parser.zig | 17 +++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/examples/hello.v b/examples/hello.v index fa6b3ba..6bd25d9 100644 --- a/examples/hello.v +++ b/examples/hello.v @@ -20,4 +20,14 @@ fn main(a int) int { a && b a || b + + loop {} + loop { + println('Ballse') + } + + loop a > 2 {} + loop a > 2 { + println('skirts') + } } diff --git a/src/ast.zig b/src/ast.zig index 609cf48..05f0b25 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -327,6 +327,20 @@ pub fn printStmt(ident: usize, stmt: *Stmt) void { std.debug.warn(")\n"); }, + + .Loop => |loop| { + std.debug.warn("(loop "); + if (loop.condition) |cond| { + printExpr(cond); + } else { + std.debug.warn("true"); + } + std.debug.warn(" "); + + printBlock(ident + 1, loop.then_branch, false); + std.debug.warn(")\n"); + }, + else => std.debug.warn("UnknownStmt-{}", @tagName(stmt.*)), } } diff --git a/src/parser.zig b/src/parser.zig index 73d61f3..e171ea1 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -449,6 +449,7 @@ pub const Parser = struct { fn parseStmt(self: *@This()) anyerror!*Stmt { return switch (self.peek().ttype) { .If => try self.parseIfStmt(), + .Loop => try self.parseLoop(), .Println => try self.parsePrintln(), // TODO make newlines tokens and consume newline? @@ -495,6 +496,22 @@ pub const Parser = struct { ); } + fn parseLoop(self: *@This()) !*Stmt { + _ = try self.consumeSingle(.Loop); + var expr: ?*Expr = null; + var body: ast.Block = undefined; + + // infinite loop + if (self.check(.LeftBrace)) { + body = try self.parseStmtBlock(); + } else { + expr = (try self.parseExpr()).Expr; + body = try self.parseStmtBlock(); + } + + return try Stmt.mkLoop(self.allocator, expr, body); + } + fn parsePrintln(self: *@This()) !*Stmt { _ = try self.consumeSingle(.Println);