Skip to main content

tree-sitter-haskell

CI discord matrix crates npm pypi

Haskell grammar for tree-sitter.

References

Supported Language Extensions

These extensions are supported ✅, unsupported ❌ or not applicable because they don't involve parsing ➖️:

  • AllowAmbiguousTypes ➖️
  • ApplicativeDo ➖️
  • Arrows ❌
  • BangPatterns ✅
  • BinaryLiterals ✅
  • BlockArguments ✅
  • CApiFFI ✅
  • ConstrainedClassMethods ✅
  • ConstraintKinds ✅
  • CPP ✅
  • CUSKs ✅
  • DataKinds ✅
  • DatatypeContexts ✅
  • DefaultSignatures ✅
  • DeriveAnyClass ➖️
  • DeriveDataTypeable ➖️
  • DeriveFoldable ➖️
  • DeriveFunctor ➖️
  • DeriveGeneric ➖️
  • DeriveLift ➖️
  • DeriveTraversable ➖️
  • DerivingStrategies ✅
  • DerivingVia ✅
  • DisambiguateRecordFields ➖️
  • DuplicateRecordFields ➖️
  • EmptyCase ✅
  • EmptyDataDecls ✅
  • EmptyDataDeriving ✅
  • ExistentialQuantification ✅
  • ExplicitForAll ✅
  • ExplicitNamespaces ✅
  • ExtendedDefaultRules ➖️
  • FlexibleContexts ✅
  • FlexibleInstances ✅
  • ForeignFunctionInterface ✅
  • FunctionalDependencies ✅
  • GADTs ✅
  • GADTSyntax ✅
  • GeneralisedNewtypeDeriving ➖️
  • GHCForeignImportPrim ✅
  • Haskell2010 ➖️
  • Haskell98 ➖️
  • HexFloatLiterals ✅
  • ImplicitParams ✅
  • ImplicitPrelude ➖️
  • ImportQualifiedPost ✅
  • ImpredicativeTypes ➖️
  • IncoherentInstances ➖️
  • InstanceSigs ✅
  • InterruptibleFFI ✅
  • KindSignatures ✅
  • LambdaCase ✅
  • LexicalNegation ❌
  • LiberalTypeSynonyms ✅
  • LinearTypes ✅
  • ListTuplePuns ✅
  • MagicHash ✅
  • Modifiers ❌
  • MonadComprehensions ➖️
  • MonadFailDesugaring ➖️
  • MonoLocalBinds ➖️
  • MonomorphismRestriction ➖️
  • MultiParamTypeClasses ✅
  • MultiWayIf ✅
  • NamedFieldPuns ✅
  • NamedWildCards ✅
  • NegativeLiterals ➖️
  • NondecreasingIndentation ✅
  • NPlusKPatterns ➖️
  • NullaryTypeClasses ✅
  • NumDecimals ➖️
  • NumericUnderscores ✅
  • OverlappingInstances ➖️
  • OverloadedLabels ✅
  • OverloadedLists ➖️
  • OverloadedRecordDot ✅
  • OverloadedRecordUpdate ✅
  • OverloadedStrings ➖️
  • PackageImports ✅
  • ParallelListComp ✅
  • PartialTypeSignatures ✅
  • PatternGuards ✅
  • PatternSynonyms ✅
  • PolyKinds ➖️
  • PostfixOperators ➖️
  • QualifiedDo ✅
  • QuantifiedConstraints ✅
  • QuasiQuotes ✅
  • Rank2Types ✅
  • RankNTypes ✅
  • RebindableSyntax ➖️
  • RecordWildCards ➖️
  • RecursiveDo ✅
  • RequiredTypeArguments ✅
  • RoleAnnotations ✅
  • Safe ➖️
  • ScopedTypeVariables ✅
  • StandaloneDeriving ✅
  • StandaloneKindSignatures ✅
  • StarIsType ✅
  • StaticPointers ❌
  • Strict ➖️
  • StrictData ✅
  • TemplateHaskell ✅
  • TemplateHaskellQuotes ✅
  • TraditionalRecordSyntax ➖️
  • TransformListComp ✅
  • Trustworthy ➖️
  • TupleSections ✅
  • TypeAbstractions ✅
  • TypeApplications ✅
  • TypeData ✅
  • TypeFamilies ✅
  • TypeFamilyDependencies ✅
  • TypeInType ✅
  • TypeOperators ✅
  • TypeSynonymInstances ➖️
  • UnboxedSums ✅
  • UnboxedTuples ✅
  • UndecidableInstances ➖️
  • UndecidableSuperClasses ➖️
  • UnicodeSyntax ✅
  • UnliftedFFITypes ➖️
  • UnliftedNewtypes ✅
  • Unsafe ➖️
  • ViewPatterns ✅

Bugs

CPP

Preprocessor #elif and #else directives cannot be handled correctly, since the parser state would have to be manually reset to what it was at the #if. As a workaround, the code blocks in the alternative branches are parsed as part of the directives.

Querying

The grammar contains several supertypes, which group multiple other node types under a single name.

Supertype names do not occur as extra nodes in parse trees, but they can be used in queries in special ways:

  • As an alias, matching any of their subtypes
  • As prefix for one of their subtypes, matching its symbol only when it occurs as a production of the supertype

For example, the query (expression) matches the nodes infix, record, projection, constructor, and the second and third variable in this tree for cats <> Cat {mood = moods.sleepy}:

(infix
  (variable)
  (operator)
  (record
    (constructor)
    (field_update
      (field_name (variable))
      (projection (variable) (field_name (variable)))))))))

The two occurrences of variable in field_name (mood and sleepy) are not expressions, but record field names part of a composite record expression.

Matching variable nodes specifically that are expressions is possible with the second special form. A query for (expression/variable) will match only the other two, cats and moods.

The grammar's supertypes consist of the following sets:

  • expression

    Rules that are valid in any expression position, excluding type applications, explicit types and expression signatures.

  • pattern

    Rules that are valid in any pattern position, excluding type binders, explicit types and pattern signatures.

  • type

    Types that are either atomic (have no ambiguous associativity, like bracketed constructs, variables and type constructors), applied types or infix types.

  • quantified_type

    Types prefixed with a forall, context or function parameter.

  • constraint

    Almost the same rules as type, but mirrored for use in contexts.

  • constraints

    Analog of quantified_type, for constraints with forall or context.

  • type_param

    Atomic nodes in type and class heads, like the three nodes following A in data A @k a (b :: k).

  • declaration

    All top-level declarations, like functions and data types.

  • decl

    Shorthand for declarations that are also valid in local bindings (let and where) and in class and instance bodies, except for fixity declarations. Consists of signature, function and bind.

  • class_decl and instance_decl

    All declarations that are valid in classes and instances, which includes associated type and data families.

  • statement

    Different forms of do-notation statements.

  • qualifier

    Different forms of list comprehension qualifiers.

  • guard

    Different forms of guards in function equations and case alternatives.

Development

The main driver for generating and testing the parser for this grammar is the tree-sitter CLI. Other components of the project require additional tools, described below.

Some are made available through npm – for example, npx tree-sitter runs the CLI. If you don't have tree-sitter available otherwise, prefix all the commands in the following sections with npx.

Output path

The CLI writes the shared library containing the parser to the directory denoted by $TREE_SITTER_LIBDIR. If that variable is unset, it defaults to $HOME/.cache/tree-sitter/lib.

In order to avoid clobbering this global directory with development versions, you can set the env var to a local path:

export TREE_SITTER_LIBDIR=$PWD/.lib

The grammar

The javascript file grammar.js contains the entry point into the grammar's production rules. Please consult the tree-sitter documentation for a comprehensive introduction to the syntax and semantics.

Parsing starts with the first item in the rules field:

{
  rules: {
    haskell: $ => seq(
      optional($.header),
      optional($._body),
    ),
  }
}

Generating the parser

The first step in the development workflow converts the javascript rule definitions to C code in src/parser.c:

$ tree-sitter generate

Two byproducts of this process are written to src/grammar.json and src/node-types.json.

Compiling the parser

The C code is automatically compiled by most of the test tools mentioned below, but you can instruct tree-sitter to do it in one go:

$ tree-sitter generate --build

If you've set $TREE_SITTER_LIBDIR as mentioned above, the shared object will be written to $PWD/.lib/haskell.so.

Aside from the generated src/parser.c, tree-sitter will also compile and link src/scanner.c into this object. This file contains the external scanner, which is a custom extension of the built-in lexer whose purpose is to handle language constructs that cannot be expressed (efficiently) in the javascript grammar, like Haskell layouts.

WebAssembly

The parser can be compiled to WebAssembly as well, which requires emscripten:

$ tree-sitter build --wasm

The resulting binary is written to $PWD/tree-sitter-haskell.wasm.

Testing the parser

The most fundamental test infrastructure for tree-sitter grammars consists of a set of code snippets with associated reference ASTs stored in ./test/corpus/*.txt.

$ tree-sitter test

Individual tests can be run by specifying (a substring of) their description with -f:

$ tree-sitter test -f 'module: exports empty'

The project contains several other types of tests:

  • test/parse/run.bash [update] [test names ...] parses the files in test/parse/*.hs and compares the output with test/parse/*.target. If update is specified as the first argument, it will update the .target file for the first failing test.

  • test/query/run.bash [update] [test names ...] parses the files in test/query/*.hs, applies the queries in test/query/*.query and compares the output with test/query/*.target, similar to test/parse.

  • test/rust/parse-test.rs contains a few tests that use tree-sitter's Rust API to extract the test ranges for terminals in a slightly more convenient way. This requires cargo to be installed, and can be executed with cargo test (which also runs the tests in bindings/rust).

  • test/parse-libs [wasm] clones a set of Haskell libraries to test/libs and parses the entire codebase. When invoked as test/parse-libs wasm, it will use the WebAssembly parser. This requires bc to be installed.

  • test/parse-lib name [wasm] parses only the library name in that directory (without cloning the repository).

Debugging

The shared library built by tree-sitter test includes debug symbols, so if the scanner segfaults you can just run coredumpctl debug to inspect the backtrace and memory:

newline_lookahead () at src/scanner.c:2583
2583                ((Newline *) 0)->indent = 5;
(gdb) bt
#0  newline_lookahead () at src/scanner.c:2583
#1  0x00007ffff7a0740e in newline_start () at src/scanner.c:2604
#2  scan () at src/scanner.c:2646
#3  eval () at src/scanner.c:2684
#4  tree_sitter_haskell_external_scanner_scan (payload=<optimized out>, lexer=<optimized out>,
    valid_symbols=<optimized out>) at src/scanner.c:2724
#5  0x0000555555772488 in ts_parser.lex ()

For more control, launch gdb tree-sitter and start the process with run test -f 'some test', and set a breakpoint with break tree_sitter_haskell_external_scanner_scan.

To disable optimizations, run tree-sitter test --debug-build.

Tracing

The test and parse commands offer two modes for obtaining detailed information about the parsing process.

With tree-sitter test --debug, every lexer step and shift/reduce action is printed to stderr.

With tree-sitter test --debug-graph, the CLI will generate an HTML file showing a graph representation of every step. This requires graphviz to be installed.

Metadata

Release files for tree-sitter-haskell 0.24.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tree-sitter-haskell 0.24.1
File Size Uploaded
tree_sitter_haskell-0.24.1.tar.gz 813.5 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for tree-sitter-haskell 0.24.1
File
tree_sitter_haskell-0.24.1-cp39-abi3-win_arm64.whl CPython 3.9 abi3 Windows ARM64 Details
tree_sitter_haskell-0.24.1-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details
tree_sitter_haskell-0.24.1-cp39-abi3-musllinux_1_2_x86_64.whl CPython 3.9 abi3 Linux musl 1.2+ x86-64 Details
tree_sitter_haskell-0.24.1-cp39-abi3-musllinux_1_2_aarch64.whl CPython 3.9 abi3 Linux musl 1.2+ ARM64 Details
tree_sitter_haskell-0.24.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.9 abi3 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
tree_sitter_haskell-0.24.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.9 abi3 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
tree_sitter_haskell-0.24.1-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details
tree_sitter_haskell-0.24.1-cp39-abi3-macosx_10_9_x86_64.whl CPython 3.9 abi3 macOS 10.9+ x86-64 Details

Total release size: 3.8 MB

Release files / tree_sitter_haskell-0.24.1.tar.gz

Download URL tree_sitter_haskell-0.24.1.tar.gz
Size 813.5 kB
Tags Source
SHA-256 checksum
How to use checksums
8e321622266cf06f1d3ec6caa64d642b87a68e7b0257b2a20a55b5a6b1112837
BLAKE2b-256 checksum
How to use checksums
d703d91460cc260ff965e0098edcf4cceafe4dcdd498a4736eea5a13897ee1af
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / tree_sitter_haskell-0.24.1-cp39-abi3-win_arm64.whl

Download URL tree_sitter_haskell-0.24.1-cp39-abi3-win_arm64.whl
Size 319.5 kB
Tags CPython 3.9 Windows ARM64 abi3
SHA-256 checksum
How to use checksums
b950945fa9e113701fd86cea5547ee8245da9373816182ec8828513d4fa899c1
BLAKE2b-256 checksum
How to use checksums
dc9a5653eb5b9ae411c70e88c68a3f0b844927e15eb3c1e6794855ac29a3f978
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / tree_sitter_haskell-0.24.1-cp39-abi3-win_amd64.whl

Download URL tree_sitter_haskell-0.24.1-cp39-abi3-win_amd64.whl
Size 318.7 kB
Tags CPython 3.9 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
e8e3292d4dc2782913cebb589b59e094ab3f656c7ef078d327843c04a0f30e3c
BLAKE2b-256 checksum
How to use checksums
1d8ca4c7b693a445aacd4e27fa3d946f3926afe9fabcb34e3788df7bc9bc0de6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / tree_sitter_haskell-0.24.1-cp39-abi3-musllinux_1_2_x86_64.whl

Download URL tree_sitter_haskell-0.24.1-cp39-abi3-musllinux_1_2_x86_64.whl
Size 424.9 kB
Tags CPython 3.9 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
8b1b3be7c690da88b4369351fbe4ad4da97e635a003f0e4883c54e34cc0c8adf
BLAKE2b-256 checksum
How to use checksums
ad1a857838c75ad523c3ab0b3b040fec7d0318fd81676c9d31926b3c4d506b1b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / tree_sitter_haskell-0.24.1-cp39-abi3-musllinux_1_2_aarch64.whl

Download URL tree_sitter_haskell-0.24.1-cp39-abi3-musllinux_1_2_aarch64.whl
Size 430.4 kB
Tags CPython 3.9 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
3feee87670cd4f1cde16b4db7fc53c2b9e7e148fe8cf10b86eaa23f011a8a805
BLAKE2b-256 checksum
How to use checksums
7a787e6b1c7eec39b3820b60d26a1328144128a7e8594d8b13da7df3e05a7ff3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / tree_sitter_haskell-0.24.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL tree_sitter_haskell-0.24.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 428.0 kB
Tags CPython 3.9 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
497da57552e76b0b764536daacc12fac84bf93da81202883c94753340831f80c
BLAKE2b-256 checksum
How to use checksums
8fc645cbd20bd1df8a83dbbc530ee47a35c586a3f002f42256e037d5eea53f47
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / tree_sitter_haskell-0.24.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL tree_sitter_haskell-0.24.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 434.2 kB
Tags CPython 3.9 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
2a62b0c5c39d6c7c2adf1b446ee0314b1e0d73449f83b1e99711d739807d467a
BLAKE2b-256 checksum
How to use checksums
6dbdd218877004d175e77f1ac805c3205b1571912d8516e799eac85bf15e8645
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / tree_sitter_haskell-0.24.1-cp39-abi3-macosx_11_0_arm64.whl

Download URL tree_sitter_haskell-0.24.1-cp39-abi3-macosx_11_0_arm64.whl
Size 352.1 kB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
84b88dadc74837b8d056c985758d98edc513df3da40bac7471064103fb38639e
BLAKE2b-256 checksum
How to use checksums
82a7445bf62068b0ef10bd436d0b36974626635b1d32e7639ef01f0e603d79e0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / tree_sitter_haskell-0.24.1-cp39-abi3-macosx_10_9_x86_64.whl

Download URL tree_sitter_haskell-0.24.1-cp39-abi3-macosx_10_9_x86_64.whl
Size 322.2 kB
Tags CPython 3.9 abi3 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
a7575968f665c5527b105996a73701baed4181268ed02191e20f0d52f15ebaef
BLAKE2b-256 checksum
How to use checksums
eb9105f822699ab96d6af385d6c72985b6747b92419e9d91c020b194a8a4f8ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.24.1 This release

9 release files

0.24.0

9 release files

0.23.1

8 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page