diff --git a/examples/hello.v b/examples/hello.v index 81b5f60..fa6b3ba 100644 --- a/examples/hello.v +++ b/examples/hello.v @@ -17,4 +17,7 @@ fn main(a int) int { } else { println(50) } + + a && b + a || b } diff --git a/src/ast.zig b/src/ast.zig index 27c0b8c..f048ac1 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -46,6 +46,13 @@ pub const UnaryExpr = struct { right: *Expr, }; +// looks like a BinaryExpr, but is not a BinaryExpr +pub const LogicalExpr = struct { + left: *Expr, + op: Token, + right: *Expr, +}; + pub const LiteralExpr = union(enum) { Bool: bool, Integer: []const u8, @@ -66,6 +73,7 @@ pub const ExprType = enum { Binary, Unary, + Logical, Literal, Variable, Grouping, @@ -82,6 +90,7 @@ pub const Expr = union(ExprType) { Binary: BinaryExpr, Unary: UnaryExpr, + Logical: LogicalExpr, Literal: LiteralExpr, Variable: Token, @@ -239,6 +248,7 @@ fn parenthetize(name: []const u8, exprs: []*Expr) void { pub fn printExpr(expr: *Expr) void { switch (expr.*) { .Binary => |binary| parenthetize(binary.op.lexeme, &[_]*Expr{ binary.left, binary.right }), + .Logical => |binary| parenthetize(binary.op.lexeme, &[_]*Expr{ binary.left, binary.right }), .Unary => |unary| parenthetize(unary.op.lexeme, &[_]*Expr{unary.right}), .Grouping => |expr_ptr| parenthetize("group", &[_]*Expr{expr_ptr}), diff --git a/src/parser.zig b/src/parser.zig index 768bd0b..21a3015 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -201,6 +201,19 @@ pub const Parser = struct { return expr; } + fn mkLogical(self: *Parser, left: *Expr, op: Token, right: *Expr) !*Expr { + var expr = try self.allocator.create(Expr); + expr.* = Expr{ + .Logical = ast.LogicalExpr{ + .left = left, + .op = op, + .right = right, + }, + }; + + return expr; + } + fn mkAssign(self: *Parser, name: Token, value: *Expr) !*Expr { var expr = try self.allocator.create(Expr); expr.* = Expr{ @@ -518,7 +531,7 @@ pub const Parser = struct { mutable = true; } - var expr = try self.parseEquality(); + var expr = try self.parseOr(); std.debug.warn("lvalue: {}, cur: {}\n", expr, self.peek()); var value: *Expr = undefined; @@ -545,10 +558,38 @@ pub const Parser = struct { return expr; } + fn parseOr(self: *@This()) !*Expr { + var expr = try self.parseAnd(); + + while (self.check(.Or)) { + var op = self.peek(); + _ = try self.nextToken(); + + var right = try self.parseAnd(); + expr = try self.mkLogical(expr, op, right); + } + + return expr; + } + + fn parseAnd(self: *@This()) !*Expr { + var expr = try self.parseEquality(); + + while (self.check(.And)) { + var op = self.peek(); + _ = try self.nextToken(); + + var right = try self.parseEquality(); + expr = try self.mkLogical(expr, op, right); + } + + return expr; + } + fn parseEquality(self: *@This()) !*Expr { var expr = try self.parseComparison(); - while (self.peek().ttype == .EqualEqual) { + while (self.check(.EqualEqual)) { var op = self.peek(); _ = try self.nextToken(); diff --git a/src/scanner.zig b/src/scanner.zig index 922374a..23c442b 100644 --- a/src/scanner.zig +++ b/src/scanner.zig @@ -288,8 +288,6 @@ pub const Scanner = struct { '.' => self.makeToken(.Dot), ';' => self.makeToken(.Semicolon), ',' => self.makeToken(.Comma), - '&' => self.makeToken(.Ampersand), - '|' => self.makeToken(.Pipe), '?' => self.makeToken(.QuestionMark), '$' => self.makeToken(.DollarSign), @@ -299,6 +297,12 @@ pub const Scanner = struct { ':' => self.makeMatchToken('=', .ColonEqual, .Colon), + // we use the existing .And and .Or tokens + // representing the and and or keywords to + // also have || and && + '&' => self.makeMatchToken('&', .And, .Address), + '|' => self.makeMatchToken('|', .Or, .Pipe), + '!' => self.makeMatchToken('=', .BangEqual, .Bang), '=' => self.makeMatchToken('=', .EqualEqual, .Equal), '>' => self.makeMatchToken('=', .GreaterEqual, .Greater), diff --git a/src/tokens.zig b/src/tokens.zig index 2484082..8b45d54 100644 --- a/src/tokens.zig +++ b/src/tokens.zig @@ -11,7 +11,7 @@ pub const TokenType = enum { Semicolon, Comma, Colon, - Ampersand, + Address, Pipe, QuestionMark, DollarSign, @@ -65,6 +65,7 @@ pub const TokenType = enum { Module, Mut, Or, + And, Return, Struct, Type,