add assignment support (without mut)
This commit is contained in:
parent
366be14cea
commit
72bc932d23
5 changed files with 57 additions and 8 deletions
|
@ -9,6 +9,6 @@ fn main(a int) int {
|
||||||
1 + 2 + 3 + 4
|
1 + 2 + 3 + 4
|
||||||
1 + 1 * 1
|
1 + 1 * 1
|
||||||
3 / (51 + 2)
|
3 / (51 + 2)
|
||||||
mut a := 1+2
|
a := 1+2
|
||||||
println(2 * 1956 + a)
|
println(2 * 1956 + a)
|
||||||
}
|
}
|
||||||
|
|
23
src/ast.zig
23
src/ast.zig
|
@ -54,7 +54,22 @@ pub const LiteralExpr = union(enum) {
|
||||||
String: []const u8,
|
String: []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Expr = union(enum) {
|
pub const AssignExpr = struct {
|
||||||
|
name: Token,
|
||||||
|
value: *Expr,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ExprType = enum {
|
||||||
|
Assign,
|
||||||
|
Binary,
|
||||||
|
Unary,
|
||||||
|
Literal,
|
||||||
|
Variable,
|
||||||
|
Grouping,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Expr = union(ExprType) {
|
||||||
|
Assign: AssignExpr,
|
||||||
Binary: BinaryExpr,
|
Binary: BinaryExpr,
|
||||||
Unary: UnaryExpr,
|
Unary: UnaryExpr,
|
||||||
Literal: LiteralExpr,
|
Literal: LiteralExpr,
|
||||||
|
@ -208,6 +223,12 @@ pub fn printExpr(expr: *Expr) void {
|
||||||
|
|
||||||
.Variable => |token| std.debug.warn("{}", token.lexeme),
|
.Variable => |token| std.debug.warn("{}", token.lexeme),
|
||||||
|
|
||||||
|
.Assign => |assign| {
|
||||||
|
std.debug.warn("(let ");
|
||||||
|
std.debug.warn("{} ", assign.name.lexeme);
|
||||||
|
printExpr(assign.value);
|
||||||
|
},
|
||||||
|
|
||||||
else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)),
|
else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,8 +182,6 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mkBinary(self: *Parser, left: *Expr, op: Token, right: *Expr) !*Expr {
|
fn mkBinary(self: *Parser, left: *Expr, op: Token, right: *Expr) !*Expr {
|
||||||
std.debug.warn("Binary\n");
|
|
||||||
|
|
||||||
var expr = try self.allocator.create(Expr);
|
var expr = try self.allocator.create(Expr);
|
||||||
expr.* = Expr{
|
expr.* = Expr{
|
||||||
.Binary = ast.BinaryExpr{
|
.Binary = ast.BinaryExpr{
|
||||||
|
@ -196,6 +194,18 @@ pub const Parser = struct {
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mkAssign(self: *Parser, name: Token, value: *Expr) !*Expr {
|
||||||
|
var expr = try self.allocator.create(Expr);
|
||||||
|
expr.* = Expr{
|
||||||
|
.Assign = ast.AssignExpr{
|
||||||
|
.name = name,
|
||||||
|
.value = value,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
fn mkBool(self: *Parser, val: bool) !*ast.Expr {
|
fn mkBool(self: *Parser, val: bool) !*ast.Expr {
|
||||||
var expr = try self.allocator.create(Expr);
|
var expr = try self.allocator.create(Expr);
|
||||||
expr.* = Expr{
|
expr.* = Expr{
|
||||||
|
@ -411,7 +421,7 @@ pub const Parser = struct {
|
||||||
|
|
||||||
var name = try self.consumeSingle(.Identifier);
|
var name = try self.consumeSingle(.Identifier);
|
||||||
|
|
||||||
_ = try self.consumeSingle(.Assign);
|
_ = try self.consumeSingle(.Equal);
|
||||||
var initializer = (try self.parseExpr()).Expr;
|
var initializer = (try self.parseExpr()).Expr;
|
||||||
|
|
||||||
return try Stmt.mkVarDecl(self.allocator, name, initializer, true);
|
return try Stmt.mkVarDecl(self.allocator, name, initializer, true);
|
||||||
|
@ -442,10 +452,28 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseExpr(self: *@This()) anyerror!*Node {
|
fn parseExpr(self: *@This()) anyerror!*Node {
|
||||||
var expr = try self.parseEquality();
|
var expr: *Expr = try self.parseAssignment();
|
||||||
return self.mkExpr(expr);
|
return self.mkExpr(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parseAssignment(self: *@This()) anyerror!*Expr {
|
||||||
|
var expr = try self.parseEquality();
|
||||||
|
|
||||||
|
if (self.check(.ColonEqual)) {
|
||||||
|
var op = try self.consumeSingle(.ColonEqual);
|
||||||
|
var value = try self.parseAssignment();
|
||||||
|
|
||||||
|
if (ast.ExprType(expr.*) == .Variable) {
|
||||||
|
return try self.mkAssign(expr.Variable, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.doError("Invalid assignment target");
|
||||||
|
return Result.CompileError;
|
||||||
|
}
|
||||||
|
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
fn parseEquality(self: *@This()) !*Expr {
|
fn parseEquality(self: *@This()) !*Expr {
|
||||||
var expr = try self.parseComparison();
|
var expr = try self.parseComparison();
|
||||||
|
|
||||||
|
|
|
@ -297,7 +297,7 @@ pub const Scanner = struct {
|
||||||
'*' => self.makeToken(.Star),
|
'*' => self.makeToken(.Star),
|
||||||
'%' => self.makeToken(.Modulo),
|
'%' => self.makeToken(.Modulo),
|
||||||
|
|
||||||
':' => self.makeMatchToken('=', .Assign, .Colon),
|
':' => self.makeMatchToken('=', .ColonEqual, .Colon),
|
||||||
|
|
||||||
'!' => self.makeMatchToken('=', .BangEqual, .Bang),
|
'!' => self.makeMatchToken('=', .BangEqual, .Bang),
|
||||||
'=' => self.makeMatchToken('=', .EqualEqual, .Equal),
|
'=' => self.makeMatchToken('=', .EqualEqual, .Equal),
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub const TokenType = enum {
|
||||||
PlusPlus,
|
PlusPlus,
|
||||||
PlusEqual,
|
PlusEqual,
|
||||||
MinusEqual,
|
MinusEqual,
|
||||||
Assign,
|
ColonEqual,
|
||||||
|
|
||||||
// comparison ones
|
// comparison ones
|
||||||
EqualEqual,
|
EqualEqual,
|
||||||
|
|
Loading…
Reference in a new issue