Metadata-Version: 2.4
Name: tree-sitter-swi-prolog
Version: 0.1.0
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

Changes are listed in [CHANGELOG.md](CHANGELOG.md). To release:

1. In a pull request, bump the version (`npx tree-sitter version X.Y.Z`, then `npm install --package-lock-only`) and add a `## X.Y.Z` section to `CHANGELOG.md`. CI checks that the manifests and the changelog agree.
2. Merge it, then run the **Release** workflow on `main` from the Actions tab.

The workflow refuses a version that is already tagged. It creates the `vX.Y.Z` tag and GitHub release, with the changelog section as notes and the Wasm parser attached, and publishes to npm, crates.io and PyPI. Don't create tags or releases by hand.

## License

MIT
