add boolean AND and boolean OR
This commit is contained in:
parent
9b3e9e8139
commit
1ab966b853
5 changed files with 64 additions and 5 deletions
|
@ -17,4 +17,7 @@ fn main(a int) int {
|
|||
} else {
|
||||
println(50)
|
||||
}
|
||||
|
||||
a && b
|
||||
a || b
|
||||
}
|
||||
|
|
10
src/ast.zig
10
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}),
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue