Skip to main content

AL for Business Central

Project description

tree-sitter-al

A tree-sitter parser for the AL programming language used in Microsoft Dynamics 365 Business Central.

PyPI crates.io npm

Parser Status

Validated against 15,358 production AL files from the Business Central codebase:

Metric Value
Success rate 100% (15,358 / 15,358 files)
Tests 1,451
parser.c size ~28 MB
grammar.js ~3,930 lines
Named keywords 82 (queryable via highlights/tags)
Scanner tokens 8 (stateful, depth-tracking)
Query files 6 (highlights, locals, tags, indents, folds, textobjects)

What's new in 3.0.0

Breaking parse-tree change for editor textobjects and code navigation. Every scoped construct now exposes its content as a single node via a body field (e.g. (page_declaration body: (declaration_body …)), (code_block (begin_keyword) body: (statement_block …) (end_keyword))), instead of a flat list of direct children. This powers Helix / nvim-treesitter textobjects (@class.inside, @function.inside, @parameter) via the new queries/textobjects.scm, plus a parameters field on procedures/triggers/events.

Tree-walkers and structural queries must descend through the body field — see CHANGELOG.md for the full migration guide.

Installation

Rust

cargo add tree-sitter-al
use tree_sitter::Parser;

let mut parser = Parser::new();
let language = tree_sitter_al::LANGUAGE;
parser.set_language(&language.into()).expect("Error loading AL grammar");
let tree = parser.parse("codeunit 50100 MyCodeunit { }", None).unwrap();
println!("{}", tree.root_node().to_sexp());

Query constants are also available:

use tree_sitter_al::{HIGHLIGHTS_QUERY, TAGS_QUERY, LOCALS_QUERY, FOLDS_QUERY, INDENTS_QUERY, TEXTOBJECTS_QUERY};

Python (tree-sitter 0.24+)

pip install tree-sitter-al
import tree_sitter
import tree_sitter_al

lang = tree_sitter.Language(tree_sitter_al.language())
parser = tree_sitter.Parser(lang)
tree = parser.parse(b'codeunit 50100 MyCodeunit { }')
print(tree.root_node.sexp())

Node.js

npm install tree-sitter-al

Pre-built binaries

Download from GitHub Releases:

File Platform Use case
tree-sitter-al.wasm All web-tree-sitter
tree-sitter-al.so Linux x86_64 ast-grep, native bindings
tree-sitter-al.dll Windows x86_64 ast-grep, native bindings
tree-sitter-al.dylib macOS ARM64 ast-grep, native bindings

V2 Architecture

The grammar was rewritten from scratch in March 2026, achieving a major reduction in parser size while improving correctness.

Before / After

Metric V1 V2 (current)
parser.c 106 MB (can't push to GitHub) ~25 MB
Errors 14 0
Success rate 99.91% 100%
Symbols 2,249 ~814
States 29,126 ~12,600
grammar.js 8,500 lines ~3,930 lines
Tests 1,225 1,451
Keywords invisible in queries 82 named nodes
Query files 3 (partial) 6 (comprehensive)

Key design decisions

  • Stateful external scanner — 8 scanner tokens handle property disambiguation, depth tracking (#if/#endif nesting), named begin/end keywords at depth 0, and split-construct detection via lookahead.
  • Parse structure, don't validate — Accept any Name = Value ; as a property. Semantic validation belongs in linters/LSP servers, not the parser.
  • Generic preprocessor — One preproc_conditional rule + ~15 dedicated rules for genuinely complex split constructs (begin/end, var/begin, brace-close across #if/#else branches).
  • 82 named keyword nodes — All keywords including begin/end are named nodes, enabling proper syntax highlighting and code navigation queries.

See docs/v2-blog-post-notes.md for the full rewrite narrative.

Development

Prerequisites

  • Node.js (v16+)
  • tree-sitter CLI: npm install -g tree-sitter-cli

Building

tree-sitter generate    # Generate parser from grammar.js
tree-sitter test        # Run test suite

Validation

./validate-grammar.sh        # Quick: generation, tests, orphan/duplicate detection
./validate-grammar.sh --full # Full: includes production AL file parsing

For grammar refactors, the parse-tree diff harness proves a change is zero-behavior-change by re-parsing every production file and asserting byte-identical trees:

./tools/tree-harness.sh snapshot ./BC.History .snapshots/bc   # baseline
./tools/tree-harness.sh verify   ./BC.History .snapshots/bc   # verify after a change

Parsing AL files

tree-sitter parse path/to/file.al
tree-sitter parse path/to/file.al -d    # Debug output
tree-sitter parse path/to/file.al -q    # Quiet (errors only)

Key files

File Purpose
grammar.js Main grammar definition
src/scanner.c External scanner (8 tokens: property, depth tracking, named begin/end, split detection)
test/corpus/ Test suite (1,451 tests)
queries/ Syntax highlighting, code navigation, folding, indentation, textobjects

Contributing

See CLAUDE.md for detailed development guidelines including architecture, debugging, and conventions.


Author: Torben Leth (sshadows@sshadows.dk) License: MIT (see LICENSE)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tree_sitter_al-3.0.1.tar.gz (1.4 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

tree_sitter_al-3.0.1-cp312-abi3-win_amd64.whl (464.4 kB view details)

Uploaded CPython 3.12+Windows x86-64

tree_sitter_al-3.0.1-cp312-abi3-win32.whl (464.6 kB view details)

Uploaded CPython 3.12+Windows x86

tree_sitter_al-3.0.1-cp312-abi3-musllinux_1_2_x86_64.whl (547.5 kB view details)

Uploaded CPython 3.12+musllinux: musl 1.2+ x86-64

tree_sitter_al-3.0.1-cp312-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (550.8 kB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

tree_sitter_al-3.0.1-cp312-abi3-macosx_11_0_arm64.whl (536.9 kB view details)

Uploaded CPython 3.12+macOS 11.0+ ARM64

File details

Details for the file tree_sitter_al-3.0.1.tar.gz.

File metadata

  • Download URL: tree_sitter_al-3.0.1.tar.gz
  • Upload date:
  • Size: 1.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tree_sitter_al-3.0.1.tar.gz
Algorithm Hash digest
SHA256 a2f606763a1decce9f9fa63848413e0d2f81e2571015ae264aca8222ba6e8ca6
MD5 75ac7ff3665e347a80d88a2f9bec5eba
BLAKE2b-256 dcd7514d0bb888bdfcda0fb4c6c740674fdd81b6673501a0b7fd9a3e539475e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for tree_sitter_al-3.0.1.tar.gz:

Publisher: publish-pypi.yml on SShadowS/tree-sitter-al

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tree_sitter_al-3.0.1-cp312-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for tree_sitter_al-3.0.1-cp312-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 f0baf67043267f67b433a98fbd15125a6c8f4949bc45f4e65fb38277b72cab4f
MD5 fdb0fda57c3315bf9499da397a30f0c2
BLAKE2b-256 02ba32a07be4f7bd57fd11859fa67089cbff814eaf7266a87f72d7c476ccdf07

See more details on using hashes here.

Provenance

The following attestation bundles were made for tree_sitter_al-3.0.1-cp312-abi3-win_amd64.whl:

Publisher: publish-pypi.yml on SShadowS/tree-sitter-al

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tree_sitter_al-3.0.1-cp312-abi3-win32.whl.

File metadata

  • Download URL: tree_sitter_al-3.0.1-cp312-abi3-win32.whl
  • Upload date:
  • Size: 464.6 kB
  • Tags: CPython 3.12+, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tree_sitter_al-3.0.1-cp312-abi3-win32.whl
Algorithm Hash digest
SHA256 fc009179c91bd0231b7070d5ec636100b9a49490d3b6f65682d3d113bbe5cb28
MD5 e0ec2347906a6f97ae50c0cd43e29f31
BLAKE2b-256 4dc983562c8ff561995dd47abdbb5b05abbf3a7419e61f3a817609531fbde5b7

See more details on using hashes here.

Provenance

The following attestation bundles were made for tree_sitter_al-3.0.1-cp312-abi3-win32.whl:

Publisher: publish-pypi.yml on SShadowS/tree-sitter-al

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tree_sitter_al-3.0.1-cp312-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for tree_sitter_al-3.0.1-cp312-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e8c698382406d5cdee6fef75334efdac4e5af6eaff45678709b58f24462adb5e
MD5 5e81ee32681fffb42234714fb68d44c2
BLAKE2b-256 e4be4267f59a4aa4ccf7729804b63be11fa2b99369a992de7fc61b86b4cb3334

See more details on using hashes here.

Provenance

The following attestation bundles were made for tree_sitter_al-3.0.1-cp312-abi3-musllinux_1_2_x86_64.whl:

Publisher: publish-pypi.yml on SShadowS/tree-sitter-al

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tree_sitter_al-3.0.1-cp312-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for tree_sitter_al-3.0.1-cp312-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 f23c075e9261edb29c12537b8b23cf74797c680aa880019eb7d472bf4a85fd15
MD5 e09a154988e5e0404353c1f744b0612e
BLAKE2b-256 182d30ee314767ca6321257202119d5b9f41e116f78d42a9c2eb3237350aadc3

See more details on using hashes here.

Provenance

The following attestation bundles were made for tree_sitter_al-3.0.1-cp312-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl:

Publisher: publish-pypi.yml on SShadowS/tree-sitter-al

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tree_sitter_al-3.0.1-cp312-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for tree_sitter_al-3.0.1-cp312-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ef176ec67d89f3531e1c1667ee9ea84df25383dbfd96b429fc6eab61412c5441
MD5 c0d33de90e7d983d8a571a38ff0b9476
BLAKE2b-256 55ed6e538c7bfc803040e317064ee44638bd7d238190c97661496365b7fa300d

See more details on using hashes here.

Provenance

The following attestation bundles were made for tree_sitter_al-3.0.1-cp312-abi3-macosx_11_0_arm64.whl:

Publisher: publish-pypi.yml on SShadowS/tree-sitter-al

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page