2019-07-01 18:01:43 +00:00
|
|
|
const std = @import("std");
|
2019-06-05 23:29:03 +00:00
|
|
|
const tokens = @import("tokens.zig");
|
|
|
|
const Token = tokens.Token;
|
|
|
|
|
2019-07-01 18:01:43 +00:00
|
|
|
pub const NodeList = std.ArrayList(*Node);
|
2019-08-24 19:00:22 +00:00
|
|
|
pub const StmtList = std.ArrayList(*Stmt);
|
2019-08-24 01:13:26 +00:00
|
|
|
pub const ExprList = std.ArrayList(*Expr);
|
2019-08-23 18:52:04 +00:00
|
|
|
pub const ParamList = std.ArrayList(ParamDecl);
|
2019-08-23 19:34:41 +00:00
|
|
|
pub const ConstList = std.ArrayList(SingleConst);
|
2019-06-05 02:44:27 +00:00
|
|
|
|
2019-08-23 14:57:49 +00:00
|
|
|
// TODO convert FnCall to something like PrefixOp / InfixOp / SuffixOp
|
2019-07-01 18:01:43 +00:00
|
|
|
pub const NodeType = enum {
|
|
|
|
Root,
|
|
|
|
FnDecl,
|
2019-08-23 19:34:41 +00:00
|
|
|
ConstDecl,
|
2019-08-24 01:13:26 +00:00
|
|
|
Block,
|
|
|
|
Expr,
|
2019-08-24 19:00:22 +00:00
|
|
|
Stmt,
|
2019-06-05 02:44:27 +00:00
|
|
|
};
|
|
|
|
|
2019-07-01 18:55:19 +00:00
|
|
|
pub const ParamDecl = struct {
|
2019-08-23 18:52:04 +00:00
|
|
|
name: Token,
|
2019-07-01 18:55:19 +00:00
|
|
|
|
|
|
|
// TODO types
|
2019-08-23 18:52:04 +00:00
|
|
|
typ: Token,
|
2019-07-01 18:55:19 +00:00
|
|
|
};
|
|
|
|
|
2019-07-01 18:01:43 +00:00
|
|
|
pub const FnDecl = struct {
|
2019-07-01 18:25:07 +00:00
|
|
|
func_name: Token,
|
2019-07-01 18:55:19 +00:00
|
|
|
params: ParamList,
|
2019-08-24 19:00:22 +00:00
|
|
|
body: StmtList,
|
2019-06-05 02:44:27 +00:00
|
|
|
};
|
|
|
|
|
2019-08-23 19:34:41 +00:00
|
|
|
pub const SingleConst = struct {
|
|
|
|
name: Token,
|
2019-08-24 19:00:22 +00:00
|
|
|
expr: *Expr,
|
2019-08-23 19:34:41 +00:00
|
|
|
};
|
|
|
|
|
2019-08-24 01:13:26 +00:00
|
|
|
pub const BinaryExpr = struct {
|
|
|
|
left: *Expr,
|
|
|
|
op: Token,
|
|
|
|
right: *Expr,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const UnaryExpr = struct {
|
|
|
|
op: Token,
|
|
|
|
right: *Expr,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const LiteralExpr = union(enum) {
|
|
|
|
Bool: bool,
|
|
|
|
Integer: []const u8,
|
|
|
|
Float: []const u8,
|
|
|
|
String: []const u8,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const Expr = union(enum) {
|
|
|
|
Binary: BinaryExpr,
|
|
|
|
Unary: UnaryExpr,
|
|
|
|
Literal: LiteralExpr,
|
2019-08-24 20:22:08 +00:00
|
|
|
Variable: Token,
|
2019-08-24 01:13:26 +00:00
|
|
|
Grouping: *Expr,
|
|
|
|
};
|
|
|
|
|
2019-08-24 20:22:08 +00:00
|
|
|
pub const VarDecl = struct {
|
|
|
|
name: Token,
|
|
|
|
initializer: *Expr,
|
|
|
|
};
|
|
|
|
|
2019-08-24 19:00:22 +00:00
|
|
|
pub const Stmt = union(enum) {
|
|
|
|
Expr: *Expr,
|
|
|
|
Println: *Expr,
|
2019-08-24 20:22:08 +00:00
|
|
|
VarDecl: VarDecl,
|
2019-08-24 19:00:22 +00:00
|
|
|
|
|
|
|
pub fn mkPrintln(allocator: *std.mem.Allocator, expr: *Expr) !*Stmt {
|
|
|
|
var println = try allocator.create(Stmt);
|
|
|
|
println.* = Stmt{ .Println = expr };
|
|
|
|
return println;
|
|
|
|
}
|
2019-08-24 20:22:08 +00:00
|
|
|
|
|
|
|
pub fn mkVarDecl(allocator: *std.mem.Allocator, name: Token, init: *Expr) !*Stmt {
|
|
|
|
var vardecl = try allocator.create(Stmt);
|
|
|
|
vardecl.* = Stmt{ .VarDecl = VarDecl{ .name = name, .initializer = init } };
|
|
|
|
return vardecl;
|
|
|
|
}
|
2019-08-24 19:00:22 +00:00
|
|
|
};
|
|
|
|
|
2019-07-01 18:01:43 +00:00
|
|
|
pub const Node = union(NodeType) {
|
|
|
|
Root: NodeList,
|
|
|
|
FnDecl: FnDecl,
|
2019-08-23 19:34:41 +00:00
|
|
|
ConstDecl: ConstList,
|
2019-08-24 14:07:23 +00:00
|
|
|
|
2019-08-24 19:00:22 +00:00
|
|
|
Block: StmtList,
|
|
|
|
|
2019-08-24 01:13:26 +00:00
|
|
|
Expr: *Expr,
|
2019-08-24 19:00:22 +00:00
|
|
|
Stmt: *Stmt,
|
2019-06-05 23:29:03 +00:00
|
|
|
};
|
|
|
|
|
2019-07-01 18:01:43 +00:00
|
|
|
pub fn mkRoot(allocator: *std.mem.Allocator) !*Node {
|
|
|
|
var node = try allocator.create(Node);
|
|
|
|
node.* = Node{ .Root = NodeList.init(allocator) };
|
|
|
|
return node;
|
2019-06-05 23:29:03 +00:00
|
|
|
}
|
2019-08-23 18:42:50 +00:00
|
|
|
|
2019-08-24 14:07:23 +00:00
|
|
|
fn printIdent(ident: usize) void {
|
2019-08-23 18:42:50 +00:00
|
|
|
var i: usize = 0;
|
|
|
|
while (i < ident) : (i += 1) {
|
|
|
|
std.debug.warn("\t");
|
|
|
|
}
|
2019-08-24 14:07:23 +00:00
|
|
|
}
|
2019-08-23 18:42:50 +00:00
|
|
|
|
2019-08-24 14:07:23 +00:00
|
|
|
fn print(ident: usize, comptime fmt: []const u8, args: ...) void {
|
|
|
|
printIdent(ident);
|
2019-08-23 18:42:50 +00:00
|
|
|
std.debug.warn(fmt, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn printNode(node: *Node, ident: usize) void {
|
|
|
|
switch (node.*) {
|
2019-08-23 18:52:04 +00:00
|
|
|
.FnDecl => |decl| {
|
|
|
|
print(ident, "FnDecl name='{}'\n", decl.func_name.lexeme);
|
|
|
|
|
|
|
|
for (decl.params.toSlice()) |param| {
|
|
|
|
print(
|
|
|
|
ident + 1,
|
|
|
|
"param: '{}' {}\n",
|
|
|
|
param.name.lexeme,
|
|
|
|
param.typ.lexeme,
|
|
|
|
);
|
|
|
|
}
|
2019-08-24 14:07:23 +00:00
|
|
|
|
2019-08-24 19:00:22 +00:00
|
|
|
for (decl.body.toSlice()) |stmt| {
|
2019-08-24 14:15:41 +00:00
|
|
|
printIdent(ident + 1);
|
2019-08-24 19:00:22 +00:00
|
|
|
printStmt(stmt);
|
2019-08-24 14:15:41 +00:00
|
|
|
std.debug.warn("\n");
|
2019-08-24 14:07:23 +00:00
|
|
|
}
|
2019-08-23 18:42:50 +00:00
|
|
|
},
|
2019-08-23 19:34:41 +00:00
|
|
|
|
|
|
|
.ConstDecl => |consts| {
|
|
|
|
print(ident, "ConstDecl ({} consts)\n", consts.len);
|
|
|
|
for (consts.toSlice()) |const_decl| {
|
|
|
|
print(
|
|
|
|
ident + 1,
|
2019-08-24 19:00:22 +00:00
|
|
|
"{} = ",
|
2019-08-23 19:34:41 +00:00
|
|
|
const_decl.name.lexeme,
|
|
|
|
);
|
2019-08-24 19:00:22 +00:00
|
|
|
|
|
|
|
printExpr(const_decl.expr);
|
|
|
|
std.debug.warn("\n");
|
2019-08-23 19:34:41 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-08-23 18:42:50 +00:00
|
|
|
.Root => {
|
|
|
|
for (node.Root.toSlice()) |child| {
|
|
|
|
printNode(child, ident + 1);
|
|
|
|
}
|
|
|
|
},
|
2019-08-23 19:34:41 +00:00
|
|
|
|
2019-08-24 19:20:32 +00:00
|
|
|
.Expr => |expr| {
|
|
|
|
printIdent(ident);
|
|
|
|
printExpr(expr);
|
|
|
|
std.debug.warn("\n");
|
|
|
|
},
|
|
|
|
|
|
|
|
.Stmt => |stmt| blk: {
|
2019-08-24 20:22:08 +00:00
|
|
|
printIdent(ident);
|
|
|
|
printStmt(stmt);
|
|
|
|
std.debug.warn("\n");
|
2019-08-24 19:20:32 +00:00
|
|
|
},
|
2019-08-24 14:07:23 +00:00
|
|
|
|
2019-08-23 18:42:50 +00:00
|
|
|
else => {
|
|
|
|
print(ident, "unknown node: {}\n", node);
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2019-08-24 14:07:23 +00:00
|
|
|
|
2019-08-24 14:15:41 +00:00
|
|
|
fn parenthetize(name: []const u8, exprs: []*Expr) void {
|
2019-08-24 14:07:23 +00:00
|
|
|
std.debug.warn("({}", name);
|
|
|
|
|
|
|
|
for (exprs) |expr| {
|
|
|
|
std.debug.warn(" ");
|
2019-08-24 14:15:41 +00:00
|
|
|
printExpr(expr);
|
2019-08-24 14:07:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std.debug.warn(")");
|
|
|
|
}
|
|
|
|
|
2019-08-24 14:15:41 +00:00
|
|
|
pub fn printExpr(expr: *Expr) void {
|
2019-08-24 14:07:23 +00:00
|
|
|
switch (expr.*) {
|
2019-08-24 14:15:41 +00:00
|
|
|
.Binary => |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}),
|
2019-08-24 14:07:23 +00:00
|
|
|
|
|
|
|
.Literal => |literal| {
|
|
|
|
switch (literal) {
|
|
|
|
.Bool => |val| std.debug.warn("{}", val),
|
|
|
|
.Integer => |val| std.debug.warn("{}", val),
|
|
|
|
.Float => |val| std.debug.warn("{}", val),
|
|
|
|
.String => |val| std.debug.warn("'{}'", val),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-08-24 20:25:08 +00:00
|
|
|
.Variable => |token| std.debug.warn("{}", token.lexeme),
|
|
|
|
|
|
|
|
else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)),
|
2019-08-24 14:07:23 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-24 19:00:22 +00:00
|
|
|
|
|
|
|
pub fn printStmt(stmt: *Stmt) void {
|
|
|
|
switch (stmt.*) {
|
|
|
|
.Println => |expr| parenthetize("println", &[_]*Expr{expr}),
|
|
|
|
.Expr => |expr| printExpr(expr),
|
2019-08-24 20:22:08 +00:00
|
|
|
|
|
|
|
else => std.debug.warn("STMT_UNKNOWN"),
|
2019-08-24 19:00:22 +00:00
|
|
|
}
|
|
|
|
}
|