const std = @import("std"); const tokens = @import("tokens.zig"); const Token = tokens.Token; pub const NodeList = std.ArrayList(*Node); pub const ParamList = std.ArrayList(ParamDecl); // TODO convert FnCall to something like PrefixOp / InfixOp / SuffixOp pub const NodeType = enum { Root, FnDecl, FnCall, String, }; pub const ParamDecl = struct { name: Token, // TODO types typ: Token, }; pub const FnDecl = struct { func_name: Token, params: ParamList, body: NodeList, }; pub const FnCall = struct { func_name: Token, arguments: NodeList, }; pub const Node = union(NodeType) { Root: NodeList, FnDecl: FnDecl, FnCall: FnCall, String: Token, }; pub fn mkRoot(allocator: *std.mem.Allocator) !*Node { var node = try allocator.create(Node); node.* = Node{ .Root = NodeList.init(allocator) }; return node; } fn print(ident: usize, comptime fmt: []const u8, args: ...) void { var i: usize = 0; while (i < ident) : (i += 1) { std.debug.warn("\t"); } std.debug.warn(fmt, args); } pub fn printNode(node: *Node, ident: usize) void { switch (node.*) { .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, ); } }, .Root => { for (node.Root.toSlice()) |child| { printNode(child, ident + 1); } }, else => { print(ident, "unknown node: {}\n", node); }, } }