Skip to content

Acture/tree-sitter-paradox

Repository files navigation

tree-sitter-paradox

Tree-sitter grammar for the Paradox family of games (e.g., Europa Universalis IV, Crusader Kings, Hearts of Iron) configuration and scripting files. This repository defines the grammar and ships bindings for multiple ecosystems so editors and tools can parse and highlight Paradox scripts.

Features

  • Incremental parsing via Tree-sitter
  • Query files for syntax highlighting (queries/*.scm)
  • Multi-language bindings: Node.js, Python, Rust, Swift, and C
  • Corpus tests to validate grammar behavior (test/corpus)

Repository layout

  • grammar.js — Tree-sitter grammar specification (source of truth)
  • src/ — C sources for the generated parser
  • queries/ — Highlighting and other Tree-sitter queries
  • test/corpus — Tree-sitter CLI corpus tests
  • bindings/ — Bindings and packaging for Node, Python, Rust, Swift, C
  • tree-sitter.json — Grammar metadata

Prerequisites

  • A C/C++ toolchain (for native builds)
  • Node.js (for Node binding/tests)
  • Python 3.10+ (for Python binding/tests)
  • Rust (optional; for crate build)
  • Tree-sitter CLI (optional; for developing and running corpus tests)
    • Install: npm i -g tree-sitter-cli or use the devDependency via npx tree-sitter

Quick start

Node.js

Install dependencies (builds the native addon):

npm install

Parse some Paradox code:

const Parser = require('tree-sitter');
const Paradox = require('tree-sitter-paradox');

const parser = new Parser();
parser.setLanguage(Paradox);

const source = 'country_event = { id = 42 }';
const tree = parser.parse(source);
console.log(tree.rootNode.toString());

Run the Node tests:

npm test

Python

Install the package in editable mode and run the binding test:

pip install -e .[core]
python -m unittest bindings/python/tests/test_binding.py

Use it from Python:

from tree_sitter import Parser
import tree_sitter_paradox as tsp

parser = Parser()
parser.set_language(tsp.language())
source = b"country_event = { id = 42 }"
tree = parser.parse(source)
print(tree.root_node)

Rust

Add the crate in your Cargo.toml (if using this as a dependency from crates.io; otherwise use a path dependency):

[dependencies]
tree-sitter = "0.25"
tree-sitter-paradox = "0.2"

Example usage:

use tree_sitter::{Parser, Language};
use tree_sitter_paradox as paradox;

fn main() {
    let mut parser = Parser::new();
    parser.set_language(&Language::from(paradox::language())).unwrap();
    let source = "country_event = { id = 42 }";
    let tree = parser.parse(source, None).unwrap();
    println!("{}", tree.root_node().to_sexp());
}

Build the crate in this repo:

cargo build

Developing the grammar

Common tasks:

  • Run corpus tests (via Tree-sitter CLI):

    npx tree-sitter test
    # or
    make test
  • Rebuild the native addon for Node:

    npm install
  • Build WASM for playground (optional):

    npm run prestart
  • Build the C library (optional):

    make

When changing grammar.js:

  • Keep changes minimal and add/adjust fixtures in test/corpus to cover new syntax or bug fixes.
  • Update queries/*.scm if node types or structure affecting highlighting change.

Release automation

This repository uses the official tree-sitter/workflows reusable workflows for release assets plus npm publication. Crates and PyPI are published separately with trusted publishing so no long-lived registry tokens need to live in GitHub secrets.

Release flow:

  1. Update the version consistently in tree-sitter.json, package.json, Cargo.toml, and pyproject.toml.
  2. Merge that change to master.
  3. The Version tag workflow verifies the four versions match, creates the annotated tag vX.Y.Z, and pushes it.
  4. The tag triggers:
    • Create release via tree-sitter/workflows
    • npm publication via tree-sitter/workflows
    • PyPI wheel and sdist builds in .github/workflows/package.yml
    • PyPI publication via trusted publishing in .github/workflows/package.yml
    • crates.io publication via trusted publishing in .github/workflows/package.yml

If you need a manual recovery path, rerun Version tag after fixing the version files, or rerun the existing tag-triggered publish job in GitHub Actions. Publishing itself is intentionally restricted to v* tag pushes.

Repository configuration required:

  • GitHub secret NPM_TOKEN for npm publication
  • A crates.io trusted publisher configured for this repository with workflow file package.yml and environment release
  • A PyPI trusted publisher configured for this repository with workflow file package.yml and environment pypi

The first crates.io release still has to be published manually before trusted publishing can be enabled on crates.io.

Supported editors

Any editor integrating Tree-sitter can load this grammar. For Neovim or Helix, use a plugin that sources the parser and the queries/highlights.scm file, or configure them to find the generated library.

License

AGPL-3.0-only. See LICENSE for details.

Acknowledgments

  • Built on Tree-sitter.
  • Inspired by community grammars and Paradox modding documentation.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors