add boolean AND and boolean OR

This commit is contained in:
Luna 2019-08-25 13:21:22 -03:00
parent 9b3e9e8139
commit 1ab966b853
5 changed files with 64 additions and 5 deletions

View file

@ -17,4 +17,7 @@ fn main(a int) int {
} else {
println(50)
}
a && b
a || b
}

View file

@ -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}),

View file

@ -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();

View file

@ -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),

View file

@ -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,