Metadata-Version: 2.4
Name: tree-sitter-swi-prolog
Version: 0.1.1
Summary: SWI-Prolog grammar for tree-sitter
Author: Piotr Franczyk
License: MIT
Project-URL: Homepage, https://github.com/Looted/tree-sitter-swi-prolog
Keywords: incremental,parsing,tree-sitter,swi-prolog
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Compilers
Classifier: Topic :: Text Processing :: Linguistic
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: core
Requires-Dist: tree-sitter~=0.24; extra == "core"
Dynamic: license-file

# tree-sitter-swi-prolog

[![Kibi requirement health](https://looted.github.io/tree-sitter-swi-prolog/kibi-report/badge.svg)](https://looted.github.io/tree-sitter-swi-prolog/kibi-report/)

[SWI-Prolog](https://www.swi-prolog.org) grammar for [tree-sitter](https://tree-sitter.github.io/tree-sitter/).

It parses the Prolog that real SWI-Prolog projects are written in, not only ISO core:

- the default SWI-Prolog operator table, including `:` module qualification, `=>` single-sided unification, `=@=`, `>:<`, `:<`, `as`, `$`, and declaration prefixes such as `dynamic`, `discontiguous`, `meta_predicate`, `multifile` and `table`
- operators from common libraries: `library(clpfd)` (`#=`, `in`, `..`, ...), `library(chr)` (`<=>`, `==>`, `\`), `library(semweb/rdf_db)` (`^^`), `library(wasm)` (`#Value`, `Expr[Index]`) and the `rdf_meta`, `persistent`, `record` and `html_meta` declarations
- dicts (`_{name: "x"}`, `Tag{...}`) and functional notation on dicts (`D.key`, `D.put(k, V)`)
- strings, back-quoted strings, `0'c` character codes, radix integers (`16'FF`), digit groups (`1 000 000`), rationals (`1r3`) and special floats (`1.0Inf`)
- Unicode atoms and variables, multi-line quoted text, `%` and `/* */` comments, and a leading `#!` line

Clauses are structured for tools: every top-level term is a `clause` (with `head`, `neck` and `body` fields), a `directive` or a `query`.

```
max(X, Y, X) :- X >= Y, !.

(clause
  head: (compound_term functor: (atom) arguments: (arguments (variable) (variable) (variable)))
  neck: (operator)
  body: (binary_operation left: (binary_operation ...) operator: (operator) right: (atom))
  (end))
```

## Coverage

CI parses SWI-Prolog's own `boot/` and `library/` sources and fails if fewer than 99.5% of top-level terms parse without errors. On SWI-Prolog's current `boot/` and `library/` 99.88% of terms parse cleanly, and on the full SWI-Prolog 10.0.2 library with packages (413 files, about 240,000 lines) 99.91%; the rest use prefix operators their files declare themselves.

## Limits

A tree-sitter grammar has a fixed operator table, so operators declared at load time with `op/3` are not known while parsing:

- an unknown infix operator between two operands, symbolic or alphanumeric (for example `X ===> Y` or `X cis Y`), is read as an infix operator at priority 700, so the clause still parses, with the grouping that priority gives
- unknown prefix and postfix operators produce an `ERROR` node for that term only; the parser recovers at the next clause
- the parser does not lower operator priorities the way SWI-Prolog does in some argument positions, so `foo(:- a)` or `foo(a|b)` are errors

A negative number literal is parsed as the prefix operator `-` applied to the number.

## Queries

- `queries/highlights.scm`: syntax highlighting
- `queries/tags.scm`: predicate definitions (clause heads, including module-qualified heads and single-sided-unification heads with guards), module declarations, and calls. `@name` is the predicate name without arity; count the head's arguments for the arity, and add two for DCG rules (neck `-->`)
- `queries/locals.scm`: variables are local to their clause, directive or query

## Usage

Node, Rust, Python, Go, Swift and C bindings are generated by `tree-sitter init`. For the browser or other WebAssembly hosts, build the parser with:

```sh
npx tree-sitter build --wasm
```

and load `tree-sitter-swi_prolog.wasm` with [`web-tree-sitter`](https://www.npmjs.com/package/web-tree-sitter).

## Development

```sh
npm install
npx tree-sitter generate
npx tree-sitter test
npx tree-sitter build --wasm
node scripts/check-corpus.mjs path/to/prolog/sources
```

`grammar.js` lists the operator tables at the top. To support another library's operators, add them to the matching table with their SWI-Prolog priority and type.

## Releasing

Releases are made from [changesets](https://github.com/changesets/changesets).

1. A pull request with a user-visible change adds a changeset: run `npx changeset`, pick the bump and describe the change for users.
2. When it is merged, the **Release** workflow opens (or updates) a **Version packages** pull request that applies all pending changesets: it bumps the version in every manifest and writes their text into `CHANGELOG.md`.
3. Merging that pull request releases the new version: the `vX.Y.Z` tag and GitHub release (with the changelog section as notes and the Wasm parser attached), npm, crates.io and PyPI.

The release step publishes only what is missing for the current version, so if a registry fails, run the **Release** workflow again from the Actions tab. Don't create tags or releases by hand.

## License

MIT
