Home

Awesome

jinx-rust · GitHub license npm version GitHub Repo stars Twitter Follow

jinx-rust is a Rust parser written in Typescript; it enables the development of Rust Tooling in Typescript.

Example project using jinx-rust: Prettier Rust formatter

Get Started

npm install jinx-rust
import { rs } from "jinx-rust";

const file = rs.parseFile("let leet: u32 = 1337;");

console.log(JSON.stringify(file));

{
  "type": "SourceFile",
  "program": {
    "type": "Program",
    "ast": [
      {
        "type": "LetVariableDeclaration",
        "pattern": { "type": "Identifier", "name": "leet" },
        "typeAnnotation": { "type": "Identifier", "name": "u32" },
        "expression": { "type": "Literal", "kind": 11, "value": "1337" }
      }
    ],
    "danglingAttributes": [],
    "comments": []
  }
}

A tolerant parser for better Rust Tooling

jinx-rust is unstrict by default and tolerates bad syntax

import { rs } from "jinx-rust";

const arg_0 = rs.parseFile("fn foo(arg_0) {}").program.ast[0].parameters[0];

assert(arg_0.typeAnnotation.type === "MissingNode");

In the future, jinx-rust should eventually get a strict option.

Conversion between nodes and tokens

Attributes and Macro invocation arguments are returned as tokens in rs.parseFile.
rs exposes other methods to re-read tokens in arbitrary contexts, or to re-read nodes as tokens.

import { rs, MacroInvocation } from "jinx-rust";

const node = rs.parseFile("foo!(123);").program.ast[0].expression as MacroInvocation;

const args = rs.toCallExpressionArguments(node.segments).ast; // ExpressionNode[]
const block = rs.toBlockBody(node.segments).ast; // StatementNode[]

const tokens = rs.toTokens(node).ast; // TokenNode[]

Nightly features

jinx-rust supports 23 nightly features. The full list can be found in src/parser/nodes.ts under enum Feature. (link)

jinx-rust/utils

jinx-rust/utils is automatically included on install. It is a library of (mostly) auto-generated helpers from the parser's type declarations. E.g. tree traversing helpers, is_{Type}(node) functions for every type declared exported by the parser.

import { each_node, is_StatementNode } from "jinx-rust/utils";

declare const target: Node;

each_node(target, (child, parent) => {
  if (is_StatementNode(child)) {
    // gets called for every statement in target
  }
});

Gotchas


Why jinx-rust? And why in Typescript?