Yuku

Parser

Yuku’s parser turns JavaScript and TypeScript source code into an Abstract Syntax Tree.

Node.js

npm install yuku-parser
import { parse } from "yuku-parser";

const { program, comments, diagnostics } = parse("const x = 1 + 2;");

Outputs an ESTree / TS-ESTree-compatible AST matching Oxc. Runs 3-10x faster than alternatives on npm. See yuku-parser on npm for the full API.

Zig

zig fetch --save git+https://github.com/yuku-toolchain/yuku.git

In your build.zig.

const yuku_dep = b.dependency("yuku", .{
    .target = target,
    .optimize = optimize,
});
my_module.addImport("parser", yuku_dep.module("parser"));

Yuku requires Zig 0.16.0 or later.

Quick Start

const std = @import("std");
const parser = @import("parser");

pub fn main() !void {
    // the smp allocator is used as the backing allocator for the tree's internal arena
    var tree = try parser.parse(std.heap.smp_allocator, "const x = 5;", .{});
    defer tree.deinit();

    for (tree.diagnostics.items) |d| {
        std.debug.print("{s}\n", .{d.message});
    }
}

Options

parse takes an Options struct to configure the parsing mode.

const tree = try parser.parse(allocator, source, .{
    .source_type = .module,
    .lang = .jsx,
});
FieldValuesDefaultDescription
source_type.script, .module.moduleScript mode or ES module mode (strict mode)
lang.js, .ts, .jsx, .tsx, .dts.jsLanguage variant and syntax features to enable
preserve_parenstrue, falsetrueKeep ParenthesizedExpression nodes in the AST
allow_return_outside_functiontrue, falsefalseAllow return statements at the top level
comments.none, .flat, .attached, .both.flatCollect comments as a flat list (tree.comments), attached to host nodes (tree.commentsOf), or both. See Comments

Both fields can be inferred from a file path.

const tree = try parser.parse(allocator, source, .{
    .source_type = .fromPath("app.cjs"), // .script
    .lang = .fromPath("app.tsx"),               // .tsx
});

The Tree

parse returns a Tree containing the full AST, diagnostics, and source metadata. The allocator passed to parse is used as the backing allocator for the tree’s internal arena, so tree.deinit() frees everything at once.

The AST is a flat array of nodes referenced by integer index. tree.root is always a program node, so unpack it directly. Everything below it is a tagged union you switch on.

var tree = try parser.parse(allocator, source, .{});
defer tree.deinit();

const program = tree.data(tree.root).program;

for (tree.extra(program.body)) |child_idx| {
    switch (tree.data(child_idx)) {
        .variable_declaration => |decl| {
            for (tree.extra(decl.declarators)) |d| {
                _ = d;
            }
        },
        .function => |func| {
            _ = func;
        },
        else => {},
    }
}

The four read primitives are tree.data(idx) for a node’s typed payload, tree.span(idx) for its source range, tree.extra(range) for a variadic child list, and tree.string(handle) for string content. See the AST reference for the full node catalog, the field conventions, and the eight categorical predicates on NodeData.

Diagnostics

The parser recovers from errors and continues, so a single parse produces the full AST alongside all diagnostics.

for (tree.diagnostics.items) |d| {
    std.debug.print("[{s}] {s} at {d}..{d}\n", .{
        d.severity.toString(), d.message, d.span.start, d.span.end,
    });

    for (d.labels) |label| {
        std.debug.print("  {d}..{d}: {s}\n", .{ label.span.start, label.span.end, label.message });
    }

    if (d.help) |help| {
        std.debug.print("  help: {s}\n", .{help});
    }
}

Each diagnostic has a severity (.error, .warning, .hint, .info), a message, a source span, optional labels pointing to related code regions, and optional help text.

Going Further

  • Semantic Analysis documents the semantic model of a tree, with scopes, symbols, resolved references, early errors, and module records.
  • Traverse walks the AST with typed visitor hooks in four modes (basic, scoped, semantic, transform).
  • Codegen prints a tree back to JavaScript/TypeScript source.