@@ -12,43 +12,6 @@ Tree-sitter grammars for Haskell-ecosystem file formats.
1212
1313The ` .cabal ` grammar was initially forked from [ magus/tree-sitter-cabal] ( https://gitlab.com/magus/tree-sitter-cabal/ ) .
1414
15- ## Design: why the cabal pair is two grammars
16-
17- Tree-sitter binds one language id, one ` parser.c ` , and one query set per grammar,
18- so the two file formats cannot share a single grammar even where their syntax
19- agrees. They also differ where it matters to an editor: ` .cabal ` has a fixed
20- section vocabulary (` library ` , ` executable ` , ...) and a ` cabal-version ` preamble,
21- ` cabal.project ` has stanzas and paths.
22-
23- What they do share is the layout law, so both link the same external scanner:
24- ` common/scanners/cabal.c ` , checked in as each grammar's ` src/scanner.c ` symlink.
25- Upstream Cabal draws the line in the same place. One ` Lexer.x ` and one
26- ` Distribution.Fields.Parser.readFields ` serve both formats, and the paths only
27- diverge once fields are interpreted into typed config.
28-
29- Consequences the code relies on:
30-
31- - The ` externals ` array comes from ` makeCabalExternals ` in ` common/utils.mjs ` .
32- Its order is the scanner's ` enum Token ` order, and a grammar declares even the
33- tokens it never uses so the indices line up.
34- - Value tokens and predicate expressions come from ` common/utils.mjs ` factories.
35- The lexical precedence map stays per-grammar because ` .cabal ` inserts
36- ` module_name ` into the ladder and shifts everything above it.
37- - Node names for concepts present in both grammars are kept identical, so one
38- query pattern works against either tree. Each ` queries/helix/*.scm ` pair is
39- split into a byte-identical shared block and a grammar-specific tail; diff the
40- two files before editing the shared half.
41- - Value tokens, predicate expressions, ` path ` , and ` qualified_name ` all come from
42- factories in ` common/utils.mjs ` , so the two grammars cannot disagree about what
43- a path or a package-qualified name is. Only the lexical precedence * numbers*
44- stay per-grammar, because ` .cabal ` inserts ` module_name ` into the ladder.
45- - ` qualified_name ` is one atomic token rather than a rule with ` package: ` and
46- ` sublibrary: ` fields. The friendlier structured form is not available: it
47- commits at the colon, and ` .cabal ` prose (` Libraries: a framework ... ` ) then
48- parses as a package with a missing sublibrary. The reasoning and the evidence
49- are recorded at the rule; split the node text on the first ` : ` if you need the
50- halves.
51-
5215## Setup
5316
5417``` sh
0 commit comments