diff --git a/examples/hello.v b/examples/hello.v index 28df0e2..561bd45 100644 --- a/examples/hello.v +++ b/examples/hello.v @@ -49,4 +49,6 @@ fn main(a int) int { p.x = 69 println(a.b(3).c(d)) + + v()()() } diff --git a/src/parser.zig b/src/parser.zig index d00465f..0a3007e 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -88,6 +88,8 @@ pub const Parser = struct { return token; } + /// Consume the current token type, then walk to the next token. + /// Returns the consumed token. fn consume(self: *Parser, ttype: TokenType, comptime msg: []const u8) !Token { if (self.check(ttype)) { var tok = self.peek(); @@ -99,16 +101,15 @@ pub const Parser = struct { return Result.CompileError; } + /// Consume the current token. Gives default error messages fn consumeSingle(self: *Parser, ttype: TokenType) !Token { - std.debug.warn("consume {}..?", ttype); - if (self.check(ttype)) { var cur = self.peek(); _ = try self.nextToken(); - std.debug.warn(" now has {}\n", self.peek()); return cur; } + // TODO maybe this could be entirely comptime? var buf_main: [1000]u8 = undefined; var buf = try std.fmt.bufPrint( buf_main[0..], @@ -116,11 +117,12 @@ pub const Parser = struct { ttype, self.peek().ttype, ); - try self.tokenError(self.peek(), buf); + try self.tokenError(self.peek(), buf); return Result.CompileError; } + /// check() against multiple tokens fn compareAnyOf(self: *@This(), ttypes: []TokenType) bool { for (ttypes) |ttype| { if (self.check(ttype)) return true; @@ -727,18 +729,14 @@ pub const Parser = struct { return expr; } + /// Parse either: + /// - A function call + /// - A struct initialization (Point.{...}) + /// - A struct Get expression (p.x) fn parseCall(self: *@This()) !*Expr { - // we parse a primary expression instead of consuming a .Identifier - // since parseCall is connected to the rest of the parser. doing - // identifiers would break the rest of the rules that want primaries. - - // nothing stops us from ensuring expr is a Variable though ;) var expr = try self.parsePrimary(); while (true) { - std.debug.warn("maybe fncall / struct: {}\n", self.peek().ttype); - printer.printExpr(expr); - if (self.check(.LeftParen)) { _ = try self.consumeSingle(.LeftParen); expr = try self.finishCall(expr); @@ -749,7 +747,11 @@ pub const Parser = struct { _ = try self.consumeSingle(.LeftBrace); expr = try self.finishStructVal(expr); } else { - var name = try self.consume(.Identifier, "Expect property name after '.'"); + var name = try self.consume( + .Identifier, + "Expect property name after '.'", + ); + expr = try self.mkGet(expr, name); } } else { @@ -778,7 +780,6 @@ pub const Parser = struct { } } - // TODO shouldnt consume() return the current token, not nextToken? var paren = try self.consume(.RightParen, "Expected ')' after arguments"); return self.mkCall(callee, paren, args); @@ -843,7 +844,6 @@ pub const Parser = struct { }; _ = try self.nextToken(); - return expr; } };