@backbencher/brain 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +298 -0
- package/EMBEDDINGS.md +355 -0
- package/LICENSE +21 -0
- package/README.md +415 -2
- package/bin/bb +13 -0
- package/dist/analysis-exclusions-7ZJDXOVZ.js +35 -0
- package/dist/brain-index-health-KY7K552E.js +17 -0
- package/dist/brain-relationship-enrichment-QH7OOHUF.js +558 -0
- package/dist/brain.sql-EIM4WS4D.js +29 -0
- package/dist/chunk-2BSKD7O3.js +40 -0
- package/dist/chunk-2DE27DVC.js +1314 -0
- package/dist/chunk-2RRBMNBQ.js +322 -0
- package/dist/chunk-2RTN2DFU.js +711 -0
- package/dist/chunk-2WXYNLBA.js +29 -0
- package/dist/chunk-3CTFIJJB.js +17 -0
- package/dist/chunk-3LFTSMIV.js +174 -0
- package/dist/chunk-47HKX4AJ.js +930 -0
- package/dist/chunk-4H22TLOT.js +543 -0
- package/dist/chunk-5SD45FLC.js +818 -0
- package/dist/chunk-66A5ZFYA.js +1758 -0
- package/dist/chunk-6AIRWAO2.js +247 -0
- package/dist/chunk-6WNGD3NN.js +196 -0
- package/dist/chunk-7AN7U5IZ.js +371 -0
- package/dist/chunk-BHB7BYYI.js +626 -0
- package/dist/chunk-BQ3OVQ3P.js +125 -0
- package/dist/chunk-CW4XXSNN.js +1479 -0
- package/dist/chunk-D2Q4Y47A.js +53 -0
- package/dist/chunk-DIYAGQJL.js +34 -0
- package/dist/chunk-DYM4FQEE.js +90 -0
- package/dist/chunk-EWMWK7WN.js +75 -0
- package/dist/chunk-FVVQTSIM.js +3427 -0
- package/dist/chunk-FWSL4VG6.js +1290 -0
- package/dist/chunk-GBI7V7KY.js +69 -0
- package/dist/chunk-GEFFO6O2.js +152 -0
- package/dist/chunk-HOWAQXJO.js +236 -0
- package/dist/chunk-HQSPJDHI.js +613 -0
- package/dist/chunk-IFZNR5UJ.js +2863 -0
- package/dist/chunk-J4PMBXQQ.js +336 -0
- package/dist/chunk-KAET47ZL.js +125 -0
- package/dist/chunk-KCDECRJY.js +440 -0
- package/dist/chunk-KLK3PBTO.js +1119 -0
- package/dist/chunk-L5TDYKYK.js +76 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-OWISBAOF.js +61 -0
- package/dist/chunk-PJTNGD3Z.js +6924 -0
- package/dist/chunk-QLK6ED4Q.js +235 -0
- package/dist/chunk-R2GW4F6R.js +19 -0
- package/dist/chunk-RCMTFSEF.js +87 -0
- package/dist/chunk-RH7KC5HU.js +12050 -0
- package/dist/chunk-RM3PY6TG.js +376 -0
- package/dist/chunk-ROMM6KMC.js +433 -0
- package/dist/chunk-SK6YVHFZ.js +211 -0
- package/dist/chunk-SM7RFQRO.js +214 -0
- package/dist/chunk-UFE77L67.js +782 -0
- package/dist/chunk-UGR4QIGS.js +67 -0
- package/dist/chunk-UUNHHX4M.js +13 -0
- package/dist/chunk-V44PGPA6.js +2104 -0
- package/dist/chunk-VL52PL2T.js +71 -0
- package/dist/chunk-VURYFIHW.js +201 -0
- package/dist/chunk-XJKJYIPP.js +7436 -0
- package/dist/chunk-YI6FF2ZR.js +340 -0
- package/dist/cli/index.js +37 -0
- package/dist/config-HZAAYDP3.js +10 -0
- package/dist/content-search-642F7E5V.js +593 -0
- package/dist/database-TCTZDLE5.js +9 -0
- package/dist/doctor-GXCKSJOX.js +395 -0
- package/dist/edit-engine-KM7MPFEC.js +51 -0
- package/dist/engine-42TZFNIZ.js +11 -0
- package/dist/engine-LO6L4JLQ.js +18 -0
- package/dist/fingerprint-XDXFRWO6.js +33 -0
- package/dist/framework-intelligence-DWFCKV44.js +860 -0
- package/dist/freshness-3K6VU5OT.js +174 -0
- package/dist/graph-engine-PL5YA7BA.js +21 -0
- package/dist/graph_request-MM4REP6H.js +350 -0
- package/dist/impact_request-WDE47IZ5.js +68 -0
- package/dist/index-space-IUUN5WYV.js +15 -0
- package/dist/index-status-6BD7UBHR.js +34 -0
- package/dist/index.js +159 -0
- package/dist/instance-FO6QZRLH.js +19 -0
- package/dist/language-detection-DFCAU5DZ.js +11 -0
- package/dist/lsp/server.js +4301 -0
- package/dist/mcp/server.js +132 -0
- package/dist/onboard-DIQZV2NW.js +161 -0
- package/dist/override-companion-pass-XR7MHTP7.js +117 -0
- package/dist/parallel-indexer-4PW3AFXP.js +88 -0
- package/dist/pool-worker.js +1153 -0
- package/dist/project-health-ZS5TS2Z6.js +94 -0
- package/dist/project-index-5SDPHITE.js +57 -0
- package/dist/project-registry-DGZBIZS7.js +355 -0
- package/dist/real-bash-analyzer-SXSV67E2.js +2201 -0
- package/dist/real-c-analyzer-SY7FTZ6W.js +5942 -0
- package/dist/real-clean-analyzer-IGDHHLZK.js +3470 -0
- package/dist/real-clojure-analyzer-4OH7IWLB.js +2818 -0
- package/dist/real-cpp-analyzer-7LTDRJRJ.js +4101 -0
- package/dist/real-csharp-analyzer-KICU3TLH.js +3298 -0
- package/dist/real-css-analyzer-HPU277Q6.js +15 -0
- package/dist/real-dart-analyzer-7LZ5LCMW.js +3944 -0
- package/dist/real-elixir-analyzer-BE3MEVZO.js +2192 -0
- package/dist/real-erlang-analyzer-BZMAKYBK.js +1731 -0
- package/dist/real-fsharp-analyzer-5QLTOV3E.js +2390 -0
- package/dist/real-go-analyzer-POD7MZQR.js +4126 -0
- package/dist/real-graphql-analyzer-MAQRZ6QW.js +1442 -0
- package/dist/real-groovy-analyzer-MEWSUPMJ.js +2285 -0
- package/dist/real-haskell-analyzer-I5L2GR3Y.js +2533 -0
- package/dist/real-hcl-analyzer-DBOPXSWJ.js +725 -0
- package/dist/real-html-analyzer-O63XZLZD.js +1759 -0
- package/dist/real-java-analyzer-CHCW3EKA.js +4677 -0
- package/dist/real-javascript-analyzer-QAAJQYZE.js +14 -0
- package/dist/real-json-analyzer-UGBR7YQN.js +1640 -0
- package/dist/real-julia-analyzer-35Q4GHOZ.js +2085 -0
- package/dist/real-kotlin-analyzer-GRAYCWW2.js +3956 -0
- package/dist/real-lua-analyzer-5BAPDZDF.js +1957 -0
- package/dist/real-makefile-analyzer-YJKAHNAS.js +920 -0
- package/dist/real-markdown-analyzer-UKUQZO4F.js +1215 -0
- package/dist/real-matlab-analyzer-FVIKQZKG.js +480 -0
- package/dist/real-nim-analyzer-M7FAIABG.js +3603 -0
- package/dist/real-objective-c-analyzer-XMYQIGQI.js +1518 -0
- package/dist/real-perl-analyzer-ZLY6M2DZ.js +1865 -0
- package/dist/real-php-analyzer-KI2ZAM7X.js +9368 -0
- package/dist/real-powershell-analyzer-B3T5ZP6U.js +2915 -0
- package/dist/real-protobuf-analyzer-23OZ75XV.js +867 -0
- package/dist/real-python-analyzer-I4TIUB6D.js +4880 -0
- package/dist/real-r-analyzer-FJZJXXS6.js +2596 -0
- package/dist/real-ruby-analyzer-M3UFIVTQ.js +2429 -0
- package/dist/real-rust-analyzer-LVSONPAN.js +3359 -0
- package/dist/real-scala-analyzer-CWPI33Q2.js +3293 -0
- package/dist/real-scss-analyzer-TGRJQ7TH.js +1515 -0
- package/dist/real-solidity-analyzer-4P2VBVWA.js +2608 -0
- package/dist/real-sql-analyzer-J7DYZOZR.js +3840 -0
- package/dist/real-svelte-analyzer-NHEN2SX5.js +2532 -0
- package/dist/real-swift-analyzer-2NSYULWI.js +2311 -0
- package/dist/real-toml-analyzer-L3C66L7Q.js +929 -0
- package/dist/real-typescript-analyzer-FTC6ETRQ.js +14 -0
- package/dist/real-vb-analyzer-ORY7LAQS.js +3145 -0
- package/dist/real-vba-analyzer-JH2TTUFI.js +466 -0
- package/dist/real-vue-analyzer-OO4FUGBV.js +2680 -0
- package/dist/real-xml-analyzer-6CQVR477.js +2405 -0
- package/dist/real-yaml-analyzer-J6MQG3YX.js +3528 -0
- package/dist/real-zig-analyzer-EFKCPJNU.js +2430 -0
- package/dist/regex-search-OPTLKUN5.js +239 -0
- package/dist/rules-I453JTRC.js +152 -0
- package/dist/scoped-path-MJYWJZQX.js +11 -0
- package/dist/setup-show-Y5GB5KXA.js +15 -0
- package/dist/setup-wizard-G5YYR5T6.js +24 -0
- package/dist/symbol-search-KB4MU4SI.js +16 -0
- package/dist/taint-YOTN5X55.js +202 -0
- package/dist/taint-analyzer-N7YLZU3N.js +163 -0
- package/dist/tool-handlers-G4NAGJIH.js +72 -0
- package/dist/tool-registry-BPEJNSZG.js +17 -0
- package/dist/tool-validation-RF675A3C.js +32 -0
- package/dist/type-inference-4Y7WTMFE.js +13 -0
- package/dist/vector-binary-LMY4QGAN.js +19 -0
- package/dist/version-LXGNFO37.js +9 -0
- package/dist/wasm-NMWO3WXY.js +16 -0
- package/docs/EMBEDDINGS.md +132 -0
- package/docs/README.md +178 -0
- package/docs/data/m10-baseline.json +602 -0
- package/docs/data/m10-benchmark-baseline.json +57 -0
- package/docs/data/m10-benchmark-last-run.json +127 -0
- package/docs/data/m10-final-audit.json +215 -0
- package/docs/data/m12-final-audit.json +138 -0
- package/docs/data/m12-surface-matrix.json +50 -0
- package/docs/data/public-tools.json +1902 -0
- package/docs/indexing/DEAD-ASSETS.md +88 -0
- package/docs/indexing/INDEXER-REVIEW.md +634 -0
- package/docs/indexing/PERFORMANCE-FINDINGS.md +106 -0
- package/docs/indexing/README.md +427 -0
- package/docs/indexing/discovery-matrix.md +41 -0
- package/docs/indexing/embeddings.md +325 -0
- package/docs/indexing/environment-variables.md +77 -0
- package/docs/indexing/performance.md +323 -0
- package/docs/indexing/resume.md +345 -0
- package/docs/indexing/troubleshooting.md +391 -0
- package/docs/man/bb.1 +190 -0
- package/docs/tools/bb_analyze.md +147 -0
- package/docs/tools/bb_annotate.md +110 -0
- package/docs/tools/bb_annotations.md +106 -0
- package/docs/tools/bb_ask.md +101 -0
- package/docs/tools/bb_cross_language.md +103 -0
- package/docs/tools/bb_doc.md +169 -0
- package/docs/tools/bb_edit.md +185 -0
- package/docs/tools/bb_graph.md +169 -0
- package/docs/tools/bb_health.md +156 -0
- package/docs/tools/bb_impact.md +117 -0
- package/docs/tools/bb_index.md +108 -0
- package/docs/tools/bb_migrate.md +135 -0
- package/docs/tools/bb_patterns.md +140 -0
- package/docs/tools/bb_search.md +150 -0
- package/docs/tools/bb_security.md +100 -0
- package/docs/tools/bb_visualize.md +184 -0
- package/grammars/README.md +57 -0
- package/grammars/THIRD-PARTY-NOTICES.md +50 -0
- package/grammars/tree-sitter-c/LICENSE +21 -0
- package/grammars/tree-sitter-clojure/LICENSE.md +21 -0
- package/grammars/tree-sitter-cpp/LICENSE +21 -0
- package/grammars/tree-sitter-csharp/LICENSE +21 -0
- package/grammars/tree-sitter-css/LICENSE +21 -0
- package/grammars/tree-sitter-css/README.md +21 -0
- package/grammars/tree-sitter-dart/LICENSE +20 -0
- package/grammars/tree-sitter-dart-upstream/LICENSE +20 -0
- package/grammars/tree-sitter-dart-upstream/README.md +18 -0
- package/grammars/tree-sitter-elixir/LICENSE +176 -0
- package/grammars/tree-sitter-elixir/README.md +11 -0
- package/grammars/tree-sitter-fsharp/LICENSE +21 -0
- package/grammars/tree-sitter-fsharp/README.md +45 -0
- package/grammars/tree-sitter-graphql/LICENSE +21 -0
- package/grammars/tree-sitter-graphql/README.md +106 -0
- package/grammars/tree-sitter-groovy/LICENSE +21 -0
- package/grammars/tree-sitter-groovy/README.md +4 -0
- package/grammars/tree-sitter-haskell/LICENSE +21 -0
- package/grammars/tree-sitter-haskell/README.md +394 -0
- package/grammars/tree-sitter-hcl/CHANGELOG.md +102 -0
- package/grammars/tree-sitter-hcl/LICENSE +201 -0
- package/grammars/tree-sitter-hcl/README.md +39 -0
- package/grammars/tree-sitter-html/LICENSE +21 -0
- package/grammars/tree-sitter-html/README.md +21 -0
- package/grammars/tree-sitter-julia/LICENSE +21 -0
- package/grammars/tree-sitter-julia/README.md +24 -0
- package/grammars/tree-sitter-kotlin/LICENSE +9 -0
- package/grammars/tree-sitter-lua/LICENSE.md +21 -0
- package/grammars/tree-sitter-lua/README.md +29 -0
- package/grammars/tree-sitter-make/LICENSE +21 -0
- package/grammars/tree-sitter-matlab/LICENSE +19 -0
- package/grammars/tree-sitter-matlab/README.md +99 -0
- package/grammars/tree-sitter-nim/LICENSE +373 -0
- package/grammars/tree-sitter-nim/README.md +46 -0
- package/grammars/tree-sitter-objc/LICENSE +21 -0
- package/grammars/tree-sitter-objc/README.md +20 -0
- package/grammars/tree-sitter-perl/LICENSE +7 -0
- package/grammars/tree-sitter-perl/README.md +100 -0
- package/grammars/tree-sitter-powershell/LICENSE +21 -0
- package/grammars/tree-sitter-powershell/README.md +7 -0
- package/grammars/tree-sitter-proto/LICENSE +21 -0
- package/grammars/tree-sitter-proto/README.md +105 -0
- package/grammars/tree-sitter-r/LICENSE +9 -0
- package/grammars/tree-sitter-r/README.md +66 -0
- package/grammars/tree-sitter-ruby/LICENSE +22 -0
- package/grammars/tree-sitter-scss/LICENSE +21 -0
- package/grammars/tree-sitter-scss/README.md +17 -0
- package/grammars/tree-sitter-solidity/LICENSE +7 -0
- package/grammars/tree-sitter-sql/LICENSE +21 -0
- package/grammars/tree-sitter-typescript/LICENSE +21 -0
- package/grammars/tree-sitter-vba/LICENSE +21 -0
- package/grammars/tree-sitter-vba/README.md +738 -0
- package/grammars/tree-sitter-vbnet/LICENSE +21 -0
- package/grammars/tree-sitter-vbnet/README.md +322 -0
- package/grammars/tree-sitter-xml/LICENSE +19 -0
- package/grammars/tree-sitter-yaml/LICENSE +20 -0
- package/grammars/tree-sitter-yaml/README.md +21 -0
- package/package.json +184 -4
- package/wasm/dart.wasm +0 -0
- package/wasm/tree-sitter-bash.wasm +0 -0
- package/wasm/tree-sitter-c.wasm +0 -0
- package/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/wasm/tree-sitter-clean.wasm +0 -0
- package/wasm/tree-sitter-clojure.wasm +0 -0
- package/wasm/tree-sitter-core_schema.wasm +0 -0
- package/wasm/tree-sitter-cpp.wasm +0 -0
- package/wasm/tree-sitter-css.wasm +0 -0
- package/wasm/tree-sitter-dart.wasm +0 -0
- package/wasm/tree-sitter-elisp.wasm +0 -0
- package/wasm/tree-sitter-elixir.wasm +0 -0
- package/wasm/tree-sitter-elm.wasm +0 -0
- package/wasm/tree-sitter-embedded_template.wasm +0 -0
- package/wasm/tree-sitter-erlang.wasm +0 -0
- package/wasm/tree-sitter-fsharp.wasm +0 -0
- package/wasm/tree-sitter-fsharp_signature.wasm +0 -0
- package/wasm/tree-sitter-go.wasm +0 -0
- package/wasm/tree-sitter-graphql.wasm +0 -0
- package/wasm/tree-sitter-groovy.wasm +0 -0
- package/wasm/tree-sitter-haskell.wasm +0 -0
- package/wasm/tree-sitter-hcl.wasm +0 -0
- package/wasm/tree-sitter-html.wasm +0 -0
- package/wasm/tree-sitter-java.wasm +0 -0
- package/wasm/tree-sitter-javascript.wasm +0 -0
- package/wasm/tree-sitter-json.wasm +0 -0
- package/wasm/tree-sitter-json_schema.wasm +0 -0
- package/wasm/tree-sitter-julia.wasm +0 -0
- package/wasm/tree-sitter-kotlin.wasm +0 -0
- package/wasm/tree-sitter-lua.wasm +0 -0
- package/wasm/tree-sitter-make.wasm +0 -0
- package/wasm/tree-sitter-markdown.wasm +0 -0
- package/wasm/tree-sitter-markdown_inline.wasm +0 -0
- package/wasm/tree-sitter-matlab.wasm +0 -0
- package/wasm/tree-sitter-nim.wasm +0 -0
- package/wasm/tree-sitter-objc.wasm +0 -0
- package/wasm/tree-sitter-ocaml.wasm +0 -0
- package/wasm/tree-sitter-perl.wasm +0 -0
- package/wasm/tree-sitter-php.wasm +0 -0
- package/wasm/tree-sitter-php_only.wasm +0 -0
- package/wasm/tree-sitter-powershell.wasm +0 -0
- package/wasm/tree-sitter-protobuf.wasm +0 -0
- package/wasm/tree-sitter-python.wasm +0 -0
- package/wasm/tree-sitter-ql.wasm +0 -0
- package/wasm/tree-sitter-r.wasm +0 -0
- package/wasm/tree-sitter-rescript.wasm +0 -0
- package/wasm/tree-sitter-ruby.wasm +0 -0
- package/wasm/tree-sitter-rust.wasm +0 -0
- package/wasm/tree-sitter-scala.wasm +0 -0
- package/wasm/tree-sitter-scss.wasm +0 -0
- package/wasm/tree-sitter-solidity.wasm +0 -0
- package/wasm/tree-sitter-sql.wasm +0 -0
- package/wasm/tree-sitter-svelte.wasm +0 -0
- package/wasm/tree-sitter-swift.wasm +0 -0
- package/wasm/tree-sitter-systemrdl.wasm +0 -0
- package/wasm/tree-sitter-terraform.wasm +0 -0
- package/wasm/tree-sitter-tlaplus.wasm +0 -0
- package/wasm/tree-sitter-toml.wasm +0 -0
- package/wasm/tree-sitter-tsx.wasm +0 -0
- package/wasm/tree-sitter-typescript.wasm +0 -0
- package/wasm/tree-sitter-vba.wasm +0 -0
- package/wasm/tree-sitter-vbnet.wasm +0 -0
- package/wasm/tree-sitter-vue.wasm +0 -0
- package/wasm/tree-sitter-xml.wasm +0 -0
- package/wasm/tree-sitter-yaml.wasm +0 -0
- package/wasm/tree-sitter-zig.wasm +0 -0
- package/wasm/tree-sitter.wasm +0 -0
- package/wasm/tsx.wasm +0 -0
- package/wasm/typescript.wasm +0 -0
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
# tree-sitter-vba
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/tree-sitter-vba)
|
|
4
|
+
[](https://www.npmjs.com/package/tree-sitter-vba)
|
|
5
|
+
[](https://github.com/harumiWeb/tree-sitter-vba/actions/workflows/ci.yml)
|
|
6
|
+
|
|
7
|
+
Tree-sitter grammars for Visual Basic for Applications (VBA) and Visual Basic 6
|
|
8
|
+
(VB6), targeting exported Excel/VBA source files such as `.bas`, `.cls`, and
|
|
9
|
+
`.frm`, and VB6 project sources including `.frm` forms and `.ctl` user
|
|
10
|
+
controls. Two parsers, `vba` and `vb6`, are generated from one shared grammar
|
|
11
|
+
core.
|
|
12
|
+
|
|
13
|
+
[Try tree-sitter-vba online](https://harumiweb.github.io/tree-sitter-vba/)
|
|
14
|
+
|
|
15
|
+
The playground runs the `vba` parser through WebAssembly entirely in your
|
|
16
|
+
browser. Use it to test parser compatibility, inspect synchronized concrete
|
|
17
|
+
syntax trees, and see the official `highlights.scm` query in action; source
|
|
18
|
+
code is not uploaded or sent to a parsing service.
|
|
19
|
+
|
|
20
|
+
This grammar is designed as a parsing foundation for editor and tooling use
|
|
21
|
+
cases, including syntax highlighting, folding, tags, outline extraction, symbol
|
|
22
|
+
inspection, linting, formatting, and future LSP integrations.
|
|
23
|
+
|
|
24
|
+
## Why another VBA grammar?
|
|
25
|
+
|
|
26
|
+
Several tree-sitter grammars exist for Visual Basic-family languages, but VBA has its own syntax and practical edge cases, especially in code exported from the VBE.
|
|
27
|
+
|
|
28
|
+
This project focuses on practical Excel/VBA source compatibility:
|
|
29
|
+
|
|
30
|
+
- `.bas`, `.cls`, and `.frm` files exported from the VBE
|
|
31
|
+
- real-world VBA fixtures
|
|
32
|
+
- UserForm metadata
|
|
33
|
+
- conditional compilation
|
|
34
|
+
- error handling
|
|
35
|
+
- Excel-style member access and procedure calls
|
|
36
|
+
- editor queries for highlights, folds, and tags
|
|
37
|
+
- permissive MIT licensing
|
|
38
|
+
|
|
39
|
+
VB6 shares its statement grammar with VBA, so the `vb6` parser reuses all of
|
|
40
|
+
the above and adds what is VB6's own: the `.frm`/`.ctl` form header and `.cls`
|
|
41
|
+
class header as the VB6 IDE writes them, and the constructs that predate VBA.
|
|
42
|
+
|
|
43
|
+
## Status
|
|
44
|
+
|
|
45
|
+
This is a `v0.x` public release.
|
|
46
|
+
|
|
47
|
+
The grammar is already usable for syntax-aware tooling such as highlighting,
|
|
48
|
+
folding, tags, outline extraction, and initial symbol analysis. The current test
|
|
49
|
+
suite covers 261 focused VBA corpus cases, 45 VB6 corpus cases, generated
|
|
50
|
+
`Select Case` stress coverage through 500 clauses, and 481 checked-in VBA
|
|
51
|
+
example files without `ERROR` or `MISSING` recovery nodes. The `vb6` parser is
|
|
52
|
+
additionally measured against 1,436 real VB6 source files from 71 public
|
|
53
|
+
projects; see [Testing](#testing) for the numbers.
|
|
54
|
+
|
|
55
|
+
It is not yet a complete VBA grammar. Node names and tree shapes may still change before `v1.0.0`.
|
|
56
|
+
|
|
57
|
+
## Two parsers from one grammar
|
|
58
|
+
|
|
59
|
+
The statement grammar is written once, in `common/define-grammar.js`, as a
|
|
60
|
+
function of the dialect. Each dialect directory holds a one-line entry point,
|
|
61
|
+
its generated parser, and its corpus tests:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
common/define-grammar.js the whole grammar: defineGrammar("vba" | "vb6")
|
|
65
|
+
vba/grammar.js module.exports = require("../common/define-grammar")("vba")
|
|
66
|
+
vba/src/ generated vba parser; node-types.json is tracked, parser.c is generated
|
|
67
|
+
vba/test/corpus/ 261 VBA corpus cases
|
|
68
|
+
vb6/grammar.js module.exports = require("../common/define-grammar")("vb6")
|
|
69
|
+
vb6/src/scanner.c a four-token external scanner (see Design principles)
|
|
70
|
+
vb6/src/ generated vb6 parser
|
|
71
|
+
vb6/test/corpus/ 45 VB6 corpus cases
|
|
72
|
+
corpus/ provenance of the VB6 acceptance corpus; the source files are fetched, not vendored
|
|
73
|
+
examples/ 481 VBA example files
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Everything dialect-specific is an `isVB6` / `isVBA` branch inside the core;
|
|
77
|
+
`grep -n "isVB6\|isVBA" common/define-grammar.js` lists the complete delta.
|
|
78
|
+
This is the layout `tree-sitter-typescript` uses for TypeScript and TSX, and
|
|
79
|
+
the reason both grammars live in subdirectories: with more than one grammar in
|
|
80
|
+
`tree-sitter.json`, the CLI picks the grammar from the working directory.
|
|
81
|
+
|
|
82
|
+
Generated artifacts follow [ADR 0002](docs/adr/0002-generated-parser-artifacts.md):
|
|
83
|
+
`src/parser.c` and `src/grammar.json` are not tracked in either dialect
|
|
84
|
+
directory, `src/node-types.json` is, and `bindings/go/parser.c` is a tracked copy
|
|
85
|
+
of the `vba` parser.
|
|
86
|
+
|
|
87
|
+
## Installation
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm install tree-sitter tree-sitter-vba
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The npm package's native addon is the `vba` parser. The `vb6` parser ships as
|
|
94
|
+
generated C source (`vb6/src/parser.c` and `vb6/src/scanner.c`) for the
|
|
95
|
+
tree-sitter CLI and for direct embedding; Node.js and Go bindings for it are
|
|
96
|
+
not provided yet.
|
|
97
|
+
|
|
98
|
+
## Usage
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
const Parser = require("tree-sitter");
|
|
102
|
+
const VBA = require("tree-sitter-vba");
|
|
103
|
+
|
|
104
|
+
const parser = new Parser();
|
|
105
|
+
parser.setLanguage(VBA);
|
|
106
|
+
|
|
107
|
+
const tree = parser.parse(`
|
|
108
|
+
Sub Hello()
|
|
109
|
+
Debug.Print "Hello"
|
|
110
|
+
End Sub
|
|
111
|
+
`);
|
|
112
|
+
|
|
113
|
+
console.log(tree.rootNode.toString());
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
To parse VB6 from the command line, run the CLI inside the `vb6` directory,
|
|
117
|
+
which is how it selects the grammar:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
cd vb6 && tree-sitter parse /path/to/Form1.frm
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`scripts/run-tree-sitter.mjs --cwd vb6 parse <file>` does the same from the
|
|
124
|
+
repository root.
|
|
125
|
+
|
|
126
|
+
## Go Usage
|
|
127
|
+
|
|
128
|
+
The Go binding is self-contained when installed through Go modules; its package
|
|
129
|
+
directory includes the generated C parser needed by cgo. It exposes the `vba`
|
|
130
|
+
parser.
|
|
131
|
+
|
|
132
|
+
```go
|
|
133
|
+
package main
|
|
134
|
+
|
|
135
|
+
import (
|
|
136
|
+
"fmt"
|
|
137
|
+
|
|
138
|
+
tree_sitter "github.com/tree-sitter/go-tree-sitter"
|
|
139
|
+
tree_sitter_vba "github.com/harumiWeb/tree-sitter-vba/bindings/go"
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
func main() {
|
|
143
|
+
parser := tree_sitter.NewParser()
|
|
144
|
+
defer parser.Close()
|
|
145
|
+
|
|
146
|
+
parser.SetLanguage(tree_sitter.NewLanguage(tree_sitter_vba.Language()))
|
|
147
|
+
|
|
148
|
+
tree := parser.Parse([]byte("Sub Hello()\nEnd Sub\n"), nil)
|
|
149
|
+
defer tree.Close()
|
|
150
|
+
|
|
151
|
+
fmt.Println(tree.RootNode().ToSexp())
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Example output:
|
|
156
|
+
|
|
157
|
+
```text
|
|
158
|
+
(source_file
|
|
159
|
+
(sub_declaration
|
|
160
|
+
name: (identifier)
|
|
161
|
+
(parameter_list)
|
|
162
|
+
body: (block
|
|
163
|
+
(call_statement
|
|
164
|
+
callee: (qualified_member_expression
|
|
165
|
+
receiver: (identifier)
|
|
166
|
+
operator: "."
|
|
167
|
+
member: (identifier))
|
|
168
|
+
arguments: (unparenthesized_argument_list
|
|
169
|
+
(string_literal))))))
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Node.js native build requirements
|
|
173
|
+
|
|
174
|
+
The npm package currently builds its native addon from source during
|
|
175
|
+
installation. Prebuilt native binaries may be added in a future release.
|
|
176
|
+
|
|
177
|
+
A supported Python installation, a C/C++ toolchain, and the platform
|
|
178
|
+
requirements documented by `node-gyp` are required.
|
|
179
|
+
|
|
180
|
+
On Windows, Visual Studio 2022 Build Tools with the **Desktop development with
|
|
181
|
+
C++** workload is recommended.
|
|
182
|
+
|
|
183
|
+
At minimum, Windows users typically need:
|
|
184
|
+
|
|
185
|
+
- Python 3.11 or later
|
|
186
|
+
- Visual Studio 2022 Build Tools
|
|
187
|
+
- MSVC C++ x64/x86 build tools
|
|
188
|
+
- Windows 10 SDK or Windows 11 SDK
|
|
189
|
+
|
|
190
|
+
If multiple Python installations are present, configure npm to use the intended
|
|
191
|
+
Python executable:
|
|
192
|
+
|
|
193
|
+
```powershell
|
|
194
|
+
npm config set python "C:\Users\<you>\AppData\Local\Programs\Python\Python312\python.exe"
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
For reliable native builds on Windows, run installation from:
|
|
198
|
+
|
|
199
|
+
```text
|
|
200
|
+
x64 Native Tools Command Prompt for VS 2022
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Supported syntax
|
|
204
|
+
|
|
205
|
+
The grammar currently supports:
|
|
206
|
+
|
|
207
|
+
- apostrophe comments and `Rem` comments
|
|
208
|
+
- string, integer, floating-point, boolean, date, `Nothing`, `Null`, and `Empty`
|
|
209
|
+
literals
|
|
210
|
+
- decimal and hexadecimal literals with common VBA type characters, including
|
|
211
|
+
Currency (`@`) and LongLong (`^`), exponent notation such as `1E-3`, and
|
|
212
|
+
abbreviated decimal forms such as `.5` and `1.`
|
|
213
|
+
- identifiers with common VBA type-declaration characters, including `@` and
|
|
214
|
+
`^`; in declarations the Single character `!` (`Dim X!`, `Const Y! = 1`) is
|
|
215
|
+
a `bang_identifier` because it shares its token with the bang member operator
|
|
216
|
+
- identifiers, simple type clauses, dotted type names, and array type suffixes
|
|
217
|
+
- `Attribute` statements
|
|
218
|
+
- `Option Explicit`, `Option Private Module`, `Option Compare`, and `Option Base`
|
|
219
|
+
- `Implements` statements
|
|
220
|
+
- `Sub`, `Function`, and `Property Get/Let/Set` procedures
|
|
221
|
+
- `Event` declarations
|
|
222
|
+
- `RaiseEvent` statements
|
|
223
|
+
- `Dim`, `Static`, `WithEvents`, visibility-based variable declarations,
|
|
224
|
+
arrays, `ReDim`, `Erase`, and `Const`
|
|
225
|
+
- default type declaration statements such as `DefInt` and `DefStr`
|
|
226
|
+
- `Type` and `Enum` declarations
|
|
227
|
+
- external `Declare Function` and `Declare Sub` declarations, including
|
|
228
|
+
`PtrSafe`, `Lib`, and `Alias`
|
|
229
|
+
- simple assignments and `Set` assignments
|
|
230
|
+
- `Name oldPath As newPath` file rename statements
|
|
231
|
+
- calls, named arguments, omitted arguments anywhere in an unparenthesized
|
|
232
|
+
list, call-site `ByVal`, member access, bang member access, and leading-dot
|
|
233
|
+
member access
|
|
234
|
+
- `Debug.Print`, unparenthesized `Print` methods, and `? expr` Debug.Print
|
|
235
|
+
shorthand statements, including comma- and semicolon-separated output lists
|
|
236
|
+
with trailing output-position controls
|
|
237
|
+
- `New` expressions and `As New` declarations
|
|
238
|
+
- fixed-length string declarations
|
|
239
|
+
- `AddressOf` expressions
|
|
240
|
+
- common VBA operator precedence for arithmetic, concatenation, comparison, and
|
|
241
|
+
logical operators; `=`, `<>`, `<`, `<=`, `>`, `>=`, `Is`, and `Like`
|
|
242
|
+
comparisons are represented as `comparison_expression`
|
|
243
|
+
- comparison expressions in `Case` clauses, including object identity forms
|
|
244
|
+
such as `Case obj Is Nothing` and condition lists such as `Case x = 1, y = 2`
|
|
245
|
+
- block `If`, including colon-separated multi-statement single-line branches;
|
|
246
|
+
`Select Case`; and nested single-line `For`, `For Each`, `Do`, `While/Wend`,
|
|
247
|
+
and `With`
|
|
248
|
+
- `Next` counter lists such as `Next i` and `Next j, i`
|
|
249
|
+
- `On Error`, computed `On ... GoTo`/`GoSub`, `Resume`, `GoTo`, labels,
|
|
250
|
+
standalone `End`, and `Exit` statements
|
|
251
|
+
- common file I/O statements: `Open`, `Input #`, `Line Input #`, `Print #`,
|
|
252
|
+
`Write #`, `Close`, `Get #`, `Put #`, `Lock`, `Unlock`, `Seek`, and `Reset`,
|
|
253
|
+
including Print/Write output lists with trailing `;` or `,` and common
|
|
254
|
+
`Access ... Shared` locking clauses
|
|
255
|
+
- simple runtime statements: `Stop`, `Beep`, `Load`, and `Unload`
|
|
256
|
+
- Access report `Line` drawing calls that use coordinate ranges such as
|
|
257
|
+
`Me.Line (x, y)-(x2, y2)`
|
|
258
|
+
- `TypeOf ... Is ...` checks, including dotted type names such as `Access.Line`
|
|
259
|
+
- numeric line labels, numbered statements, and numbered control-flow delimiters
|
|
260
|
+
- conditional compilation with `#Const`, `#If`, `#ElseIf`, `#Else`, and
|
|
261
|
+
`#End If`, including statement branches inside procedures, members inside
|
|
262
|
+
`Type` and `Enum` declarations, and alternative procedure headers
|
|
263
|
+
- line continuations, including trailing whitespace, and colon-separated
|
|
264
|
+
statements and `Enum` members
|
|
265
|
+
- minimal `.frm` and `.cls` export metadata, including `VERSION`,
|
|
266
|
+
`Begin ... End`, `BeginProperty ... EndProperty`, GUID form blocks, and
|
|
267
|
+
`.frx` blob references
|
|
268
|
+
- initial `highlights.scm`, `folds.scm`, and `tags.scm` queries
|
|
269
|
+
|
|
270
|
+
### VB6 additions
|
|
271
|
+
|
|
272
|
+
The `vb6` parser accepts everything above except the VBA7-only constructs
|
|
273
|
+
(`PtrSafe`, `LongPtr`, `LongLong`, `DefLngPtr`, `DefLngLng`: `PtrSafe` on a
|
|
274
|
+
`Declare` is an error, `LongPtr` and `LongLong` are ordinary user type names),
|
|
275
|
+
and adds:
|
|
276
|
+
|
|
277
|
+
- the `.frm`/`.ctl` header as the VB6 IDE writes it: `Object = "{GUID}#2.0#0"; "X.OCX"`
|
|
278
|
+
component references, nested `Begin Lib.Class Name ... End` blocks to any
|
|
279
|
+
depth, `BeginProperty` blocks with the OCX GUID and indexed names
|
|
280
|
+
(`BeginProperty ColumnHeader(1) {...}`), property values as strings, numbers,
|
|
281
|
+
negative numbers, hex literals, annotated booleans (`-1 'True`), `.frx`/`.ctx`
|
|
282
|
+
resource references with hexadecimal offsets and the `$` string prefix, menu
|
|
283
|
+
shortcuts (`^O`, `{F5}`, `+{DEL}`), indexed property-bag names
|
|
284
|
+
(`Tab(0).Control(1) = "txt(1)"`), and Single values written with a decimal
|
|
285
|
+
comma by IDEs on European locales (`FontSize = 8,25`); VB3-era
|
|
286
|
+
`Begin Form Form1` headers parse too
|
|
287
|
+
- the `.cls` header, `VERSION 1.0 CLASS` / `BEGIN ... END`, and two-valued
|
|
288
|
+
`Attribute VB_Ext_KEY = "A" ,"B"` lines written by Class Builder
|
|
289
|
+
- form and PictureBox graphics statements with coordinate pairs, bare or
|
|
290
|
+
`obj.`-qualified: `Line (x1, y1)-(x2, y2), color, BF`, `PSet (x, y), c`,
|
|
291
|
+
`Circle (x, y), r, , , , aspect`, and `Scale (0, 0)-(w, h)`, with any
|
|
292
|
+
trailing argument omitted
|
|
293
|
+
- a comment whose line ends in ` _` continuing onto the next line, which
|
|
294
|
+
compiled VB6 projects rely on
|
|
295
|
+
- multi-statement single-line loops, `For i = 1 To n: a = 1: b = 2: Next`
|
|
296
|
+
- calls whose first argument is an implicit member, `Foo .Bar, x`, read as a
|
|
297
|
+
call with two arguments rather than a chain `Foo.Bar` with an omitted
|
|
298
|
+
argument, through the external scanner described under Design principles
|
|
299
|
+
- constructs VBA also has but the base VBA grammar never accepted; most remain
|
|
300
|
+
`vb6` only so that the `vba` parser's trees and parse table stay within
|
|
301
|
+
the measured size and CST contract (see
|
|
302
|
+
[ADR 0005](docs/adr/0005-vba-parser-stays-the-base-grammar.md)).
|
|
303
|
+
Since v0.14.5, VBA also accepts `Let`, `On Local Error`, and `Global`;
|
|
304
|
+
the remaining `vb6`-only forms include `LSet`/`RSet`, `GoSub`/`Return`,
|
|
305
|
+
`Dim WithEvents`, `ReDim x(n) As T`, octal `&O` literals,
|
|
306
|
+
`AddressOf Module.Procedure`, `Name.Member` receivers, a comparison as the
|
|
307
|
+
left operand of another (`a = b <> 0`, `x Is Nothing = False`), a comparison
|
|
308
|
+
as the `Select Case` selector, `#If` around whole `Case` clauses, an empty
|
|
309
|
+
`Else` in a single-line `If`, `::` between inline
|
|
310
|
+
statements, a colon before a `For` body's line break, a `Type` member named
|
|
311
|
+
`End`, and the Single `!` suffix in expression positions (`total! = 0#`,
|
|
312
|
+
`rec.Percent! = 0#`)
|
|
313
|
+
- an indexed or property target on the left of `=` is an assignment; the base
|
|
314
|
+
lets `arr(i) = x` fall to a call of `arr` with the comparison `(i) = x` as
|
|
315
|
+
its argument when tree shape happens to prefer it
|
|
316
|
+
|
|
317
|
+
The VB6-only rules are gated by `isVB6` in the core and add these node types:
|
|
318
|
+
`frm_object_reference`, `frm_shortcut_value`, `frm_locale_number`,
|
|
319
|
+
`frm_property_index`, `frm_property_name`, `frm_blob_offset`, `line_statement`,
|
|
320
|
+
`pset_statement`, `circle_statement`, and `scale_statement`. The rest of the
|
|
321
|
+
additions in the list above are shared by both dialects; the `vba` tree shapes
|
|
322
|
+
pinned by the VBA corpus are unchanged.
|
|
323
|
+
|
|
324
|
+
## Declaration node API
|
|
325
|
+
|
|
326
|
+
This release line is still pre-`1.0.0`, and declaration node shapes may change
|
|
327
|
+
when doing so makes syntactic metadata more directly available to downstream
|
|
328
|
+
tools.
|
|
329
|
+
|
|
330
|
+
Declaration consumers should prefer these structural nodes and fields over
|
|
331
|
+
source-text scanning:
|
|
332
|
+
|
|
333
|
+
- `property_get_declaration`, `property_let_declaration`, and
|
|
334
|
+
`property_set_declaration` distinguish property accessors directly.
|
|
335
|
+
- `declare_sub_statement` and `declare_function_statement` distinguish external
|
|
336
|
+
declaration kind directly.
|
|
337
|
+
- declaration headers expose stable fields such as `visibility`, `name`,
|
|
338
|
+
`parameters`, `type`, `library`, `alias`, `ptrsafe_modifier`, `body`, and
|
|
339
|
+
`end` where applicable. Procedure terminators are exposed through
|
|
340
|
+
`end_sub_statement`, `end_function_statement`, and `end_property_statement`
|
|
341
|
+
nodes.
|
|
342
|
+
- procedure declarations expose additional procedure modifiers through a
|
|
343
|
+
`modifiers` field, separate from `visibility`.
|
|
344
|
+
- variable, constant, type-member, and parameter declarations expose stable
|
|
345
|
+
`name`, `bounds`, `type`, `initializer`, `passing_mode`, `optional_modifier`,
|
|
346
|
+
`paramarray_modifier`, and `default_value` fields where syntactically valid.
|
|
347
|
+
- `with_events_modifier`, `static_modifier`, `byval_modifier`, `byref_modifier`,
|
|
348
|
+
`optional_modifier`, `paramarray_modifier`, and `ptrsafe_modifier` are
|
|
349
|
+
explicit modifier nodes.
|
|
350
|
+
- `implements_statement` exposes its target as `name`, and
|
|
351
|
+
`attribute_statement` exposes `name` and `value`.
|
|
352
|
+
- a name written with the Single type character is a `bang_identifier` whose
|
|
353
|
+
children are the `identifier` and the `!`; the other type characters stay
|
|
354
|
+
inside the `identifier` token. In `vba` the node occurs where a declaration
|
|
355
|
+
names something (`Dim`, `Const`, `ReDim`, `Type` members, parameters,
|
|
356
|
+
`Function` names); `vb6` also produces it in expression positions.
|
|
357
|
+
|
|
358
|
+
## Expression node API
|
|
359
|
+
|
|
360
|
+
Member access and calls expose stable fields for analysis tools:
|
|
361
|
+
|
|
362
|
+
- `qualified_member_expression` uses `receiver`, `operator`, and `member`.
|
|
363
|
+
- `implicit_member_expression` uses `operator` and `member`; it has no
|
|
364
|
+
`receiver`, matching leading-dot and leading-bang VBA syntax.
|
|
365
|
+
- `call_expression` uses `function` and `arguments`, where `arguments` is an
|
|
366
|
+
`argument_list`.
|
|
367
|
+
- `call_statement` uses `callee` and, when arguments are present, `arguments`.
|
|
368
|
+
Parenthesized arguments use `argument_list`; statement-style arguments use
|
|
369
|
+
`unparenthesized_argument_list`. Unparenthesized `Print` methods are the
|
|
370
|
+
Print-family exception: their `arguments` field contains an `output_list`.
|
|
371
|
+
- `output_list` is shared by `Debug.Print`, `?`, `Print #`, `Write #`, and
|
|
372
|
+
unparenthesized `Print` methods. Output expressions use the `value` field;
|
|
373
|
+
`;` and `,` output-position controls use the `position` field containing a
|
|
374
|
+
`char_position` node. A position may follow the final output expression.
|
|
375
|
+
- in the `vb6` parser, `line_statement` and `scale_statement` use `start` and
|
|
376
|
+
`end` (each a `coordinate_pair` with `x` and `y`), `pset_statement` uses
|
|
377
|
+
`point`, `circle_statement` uses `center` and `radius`, the qualified forms
|
|
378
|
+
expose the receiver through `method`, and trailing graphics arguments use
|
|
379
|
+
`argument`.
|
|
380
|
+
- in the `vb6` parser, form header nodes expose `frm_property_statement` as
|
|
381
|
+
`name` and `value`, `frm_begin_block` as `type` and `name`,
|
|
382
|
+
`frm_begin_property_block` as `name`, `index`, and `guid`,
|
|
383
|
+
`frm_blob_reference` as `offset`, and `frm_object_reference` as `class` and
|
|
384
|
+
`file`.
|
|
385
|
+
|
|
386
|
+
## Control-flow node API
|
|
387
|
+
|
|
388
|
+
- `for_statement` and `for_each_statement` expose optional terminator counters
|
|
389
|
+
through `next_variables: next_variable_list`; `next_variable` is no longer
|
|
390
|
+
emitted.
|
|
391
|
+
- `next_variable_list` always contains the ordered identifiers from `Next`,
|
|
392
|
+
whether there is one counter or several.
|
|
393
|
+
- A colon-separated single-line `If` branch with multiple statements is an
|
|
394
|
+
`inline_statement_sequence`; one-statement branches keep their direct child.
|
|
395
|
+
- `shared_next_for_body` represents an enclosing loop whose nested loop is
|
|
396
|
+
closed by the same `Next ...` counter list.
|
|
397
|
+
- In the `vb6` parser, `single_line_block` owns the colon after each of its
|
|
398
|
+
statements, so an inline loop may hold several statements before its `Next`,
|
|
399
|
+
`Loop`, or `End With`. The `vba` parser keeps its current shape.
|
|
400
|
+
|
|
401
|
+
## Known limitations
|
|
402
|
+
|
|
403
|
+
This grammar parses VBA and VB6 syntax only.
|
|
404
|
+
|
|
405
|
+
It does not currently provide:
|
|
406
|
+
|
|
407
|
+
- type checking
|
|
408
|
+
- semantic analysis
|
|
409
|
+
- Excel Object Model or COM reference knowledge
|
|
410
|
+
- validation of identifier, member, type, procedure, workbook, or reference
|
|
411
|
+
existence
|
|
412
|
+
- validation of context-sensitive statement placement
|
|
413
|
+
- a formatter
|
|
414
|
+
- an LSP server
|
|
415
|
+
- complete coverage of every VBA expression edge case
|
|
416
|
+
- semantic interpretation of `.frm` designer metadata
|
|
417
|
+
|
|
418
|
+
For example, invalid placement of `Exit For`, unresolved procedure calls, invalid
|
|
419
|
+
Excel object members, or missing workbook references are intentionally left to
|
|
420
|
+
downstream tools.
|
|
421
|
+
|
|
422
|
+
General expression-level `=` comparison is still context-limited to avoid
|
|
423
|
+
ambiguity with assignment.
|
|
424
|
+
|
|
425
|
+
For the `vb6` parser:
|
|
426
|
+
|
|
427
|
+
- Input must be UTF-8 (or UTF-16 through the C API). VB6 source is stored in the
|
|
428
|
+
machine's code page, and bytes above 0x7F fed in raw never match the
|
|
429
|
+
identifier class, so identifiers such as `BtnAñadir` or a Big5 library name
|
|
430
|
+
in a `Begin` line are errors until the file is transcoded. Comments and
|
|
431
|
+
strings survive raw bytes; identifiers do not. Nine of the 1,436 corpus files
|
|
432
|
+
fail this way without transcoding.
|
|
433
|
+
- `Debug.Assert (a >= b And c <= d) Or e = 0`, a call statement whose single
|
|
434
|
+
unparenthesized argument is a parenthesized condition followed by `Or` and a
|
|
435
|
+
comparison, parses as `Debug.Assert(...) Or e` with an orphaned `= 0` and two
|
|
436
|
+
`MISSING` nodes. The same shape with plain identifiers inside the parentheses
|
|
437
|
+
parses correctly; the comparisons inside the parentheses tip a GLR fork. One
|
|
438
|
+
corpus file, one line.
|
|
439
|
+
- `.vbp` project files, `.dsr` designers, and `.pag` property pages are not
|
|
440
|
+
parsed; `.frx`/`.ctx` binaries are referenced, not read. VBA7 constructs are
|
|
441
|
+
rejected, and `#If VBA7` blocks are left to the conditional-compilation rules.
|
|
442
|
+
- There are no Node.js or Go bindings for the `vb6` parser yet; the npm addon,
|
|
443
|
+
the Go module, and the Wasm artifact are the `vba` parser.
|
|
444
|
+
|
|
445
|
+
## Queries
|
|
446
|
+
|
|
447
|
+
This package includes initial Tree-sitter queries for:
|
|
448
|
+
|
|
449
|
+
```text
|
|
450
|
+
queries/highlights.scm
|
|
451
|
+
queries/folds.scm
|
|
452
|
+
queries/tags.scm
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
These queries are intended as a starting point for editor integrations and
|
|
456
|
+
tooling. They may evolve as the grammar stabilizes. Both grammars in
|
|
457
|
+
`tree-sitter.json` point at the same query files; the VB6-only node types are
|
|
458
|
+
not yet highlighted.
|
|
459
|
+
|
|
460
|
+
## Development
|
|
461
|
+
|
|
462
|
+
Install dependencies:
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
pnpm install
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Generate both parsers, or one of them:
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
pnpm generate
|
|
472
|
+
pnpm generate:vba
|
|
473
|
+
pnpm generate:vb6
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
After grammar changes, keep the Go module artifact in sync:
|
|
477
|
+
|
|
478
|
+
```bash
|
|
479
|
+
cp vba/src/parser.c bindings/go/parser.c
|
|
480
|
+
pnpm check:go-parser
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
Run corpus tests:
|
|
484
|
+
|
|
485
|
+
```bash
|
|
486
|
+
pnpm test
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
`pnpm test:corpus` runs the VBA corpus under the `vba` parser, the VB6 corpus
|
|
490
|
+
under the `vb6` parser, and then the VBA corpus under the `vb6` parser through
|
|
491
|
+
`scripts/test-shared-corpus.mjs`, which skips the cases whose expectations differ
|
|
492
|
+
between the dialects by design and prints the reason for each. `pnpm
|
|
493
|
+
test:corpus:vba` and `pnpm test:corpus:vb6` run one side.
|
|
494
|
+
|
|
495
|
+
The tree-sitter CLI selects the grammar from the working directory, so run it
|
|
496
|
+
inside `vba/` or `vb6/`; `scripts/run-tree-sitter.mjs --cwd vb6 <args>` does
|
|
497
|
+
that from the repository root.
|
|
498
|
+
|
|
499
|
+
Parse example files:
|
|
500
|
+
|
|
501
|
+
```bash
|
|
502
|
+
pnpm parse:examples
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
This recursively parses the checked-in VBA examples with the `vba` parser and
|
|
506
|
+
fails if any parse tree contains an `ERROR` or `MISSING` node.
|
|
507
|
+
|
|
508
|
+
Parse the VB6 acceptance corpus:
|
|
509
|
+
|
|
510
|
+
```bash
|
|
511
|
+
node scripts/fetch-corpus.mjs
|
|
512
|
+
pnpm parse:corpus -- --transcode
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
See [Testing](#testing) for what the corpus is and how it is measured.
|
|
516
|
+
|
|
517
|
+
Run queries against the example files:
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
pnpm query:examples
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
This validates that `highlights.scm`, `folds.scm`, and `tags.scm` can run
|
|
524
|
+
against the checked-in examples.
|
|
525
|
+
|
|
526
|
+
Run the coarse parser benchmark:
|
|
527
|
+
|
|
528
|
+
```bash
|
|
529
|
+
pnpm bench
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
This reports file counts, total bytes, parse time, node counts, and
|
|
533
|
+
`ERROR`/`MISSING` counts for the checked-in examples. It is intended to catch
|
|
534
|
+
large regressions, not to provide a strict microbenchmark.
|
|
535
|
+
|
|
536
|
+
Run the full local check:
|
|
537
|
+
|
|
538
|
+
```bash
|
|
539
|
+
pnpm check
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
Build and test the standalone browser parser (the `vba` parser):
|
|
543
|
+
|
|
544
|
+
```bash
|
|
545
|
+
pnpm build:wasm
|
|
546
|
+
pnpm test:wasm
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
Compare the native and browser parser targets on representative corpus and
|
|
550
|
+
exported-module fixtures:
|
|
551
|
+
|
|
552
|
+
```bash
|
|
553
|
+
pnpm test:parity
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
The parity suite checks root node types, `ERROR` / `MISSING` recovery, and
|
|
557
|
+
normalized syntax-tree structure. It uses the standalone Wasm parser through
|
|
558
|
+
`web-tree-sitter`; the browser consumer smoke test separately covers loading
|
|
559
|
+
and parsing in Chromium.
|
|
560
|
+
|
|
561
|
+
The complete browser artifact, release, versioning, and loading contract is
|
|
562
|
+
documented in [docs/specs/wasm-artifact.md](docs/specs/wasm-artifact.md).
|
|
563
|
+
In brief, versioned releases attach `tree-sitter-vba.wasm` and its SHA-256
|
|
564
|
+
checksum to the matching GitHub Release. The artifact is not committed or
|
|
565
|
+
included in the npm package. A browser consumer uses the matching
|
|
566
|
+
`web-tree-sitter@0.26.9` runtime:
|
|
567
|
+
|
|
568
|
+
```js
|
|
569
|
+
import { Language, Parser } from "web-tree-sitter";
|
|
570
|
+
|
|
571
|
+
await Parser.init({ locateFile: () => "/assets/web-tree-sitter.wasm" });
|
|
572
|
+
const language = await Language.load("/assets/tree-sitter-vba.wasm");
|
|
573
|
+
const parser = new Parser();
|
|
574
|
+
parser.setLanguage(language);
|
|
575
|
+
const tree = parser.parse("Sub Hello()\nEnd Sub\n");
|
|
576
|
+
try {
|
|
577
|
+
if (!tree) throw new Error("Parser did not return a syntax tree");
|
|
578
|
+
console.log(tree.rootNode.toString());
|
|
579
|
+
} finally {
|
|
580
|
+
tree?.delete();
|
|
581
|
+
parser.delete();
|
|
582
|
+
}
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
For a complete minimal static example, including local WebAssembly runtime
|
|
586
|
+
assets and `ERROR` / `MISSING` reporting, see
|
|
587
|
+
[examples/browser-consumer](examples/browser-consumer/README.md).
|
|
588
|
+
|
|
589
|
+
## Testing
|
|
590
|
+
|
|
591
|
+
Tree-sitter grammar behavior is tested with corpus files under:
|
|
592
|
+
|
|
593
|
+
```text
|
|
594
|
+
vba/test/corpus/
|
|
595
|
+
vb6/test/corpus/
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
Community-reported production syntax regressions are kept permanently under
|
|
599
|
+
`vba/test/corpus/regressions/`; each fixture records whether it was already
|
|
600
|
+
supported or required a grammar change.
|
|
601
|
+
|
|
602
|
+
When changing `common/define-grammar.js`, always add or update focused corpus
|
|
603
|
+
tests in the dialect the change affects. Do not weaken existing expectations
|
|
604
|
+
just to make a grammar change pass. A shared change must leave the `vba` trees
|
|
605
|
+
unchanged; `scripts/test-shared-corpus.mjs` then runs the VBA corpus under the
|
|
606
|
+
`vb6` parser as well, so a `vb6` divergence shows up as a failure there and is
|
|
607
|
+
either fixed or recorded in the script's skip list with its reason. The 23
|
|
608
|
+
skips today are the VBA7 constructs, the `.frx` offset node
|
|
609
|
+
(`frm_blob_offset` in `vb6`, `number_literal` in `vba`), the pinned one-statement
|
|
610
|
+
inline-loop shape, four cases where the `vba` parser emits an opaque
|
|
611
|
+
`_ambiguous_call_statement` token that `vb6` parses with structure, and five
|
|
612
|
+
error-recovery shapes on deliberately invalid input.
|
|
613
|
+
|
|
614
|
+
A clean parse is not a stable tree. A bare call whose callee has been split
|
|
615
|
+
into its own `expression_statement` still has zero `ERROR` nodes, so neither
|
|
616
|
+
`pnpm parse:examples` nor the corpus can see that class of regression unless a
|
|
617
|
+
case pins the exact shape. `scripts/compare-cst.mjs` closes that gap for the
|
|
618
|
+
`vba` parser: it parses all 481 example files with a reference checkout and with
|
|
619
|
+
this checkout, strips positions, and lists every differing file by the node
|
|
620
|
+
types each hunk adds and removes. Point `--base` at a `main` worktree and name
|
|
621
|
+
the intended differences with `--allow`:
|
|
622
|
+
|
|
623
|
+
```text
|
|
624
|
+
git worktree add /tmp/tree-sitter-vba-main main
|
|
625
|
+
node scripts/compare-cst.mjs --base /tmp/tree-sitter-vba-main --allow bang_identifier
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
Run it before proposing any change to `common/define-grammar.js` that touches
|
|
629
|
+
calls, arguments, or precedence, and explain every remaining hunk in the pull
|
|
630
|
+
request.
|
|
631
|
+
|
|
632
|
+
The repository also includes real-world exported VBA examples. These examples
|
|
633
|
+
are parsed in CI to catch regressions against practical Excel/VBA code.
|
|
634
|
+
|
|
635
|
+
Broken or incomplete examples can be kept under:
|
|
636
|
+
|
|
637
|
+
```text
|
|
638
|
+
examples/broken/
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
These fixtures are intentionally excluded from `pnpm parse:examples`. Add
|
|
642
|
+
focused recovery expectations under `vba/test/corpus/recovery.txt` when the
|
|
643
|
+
surrounding tree shape should remain stable.
|
|
644
|
+
|
|
645
|
+
### VB6 acceptance corpus
|
|
646
|
+
|
|
647
|
+
The `vb6` parser is measured against 1,436 real VB6 source files (647 `.frm`,
|
|
648
|
+
382 `.bas`, 283 `.cls`, 124 `.ctl`) from 71 public GitHub projects, including
|
|
649
|
+
code from the late 1990s. The files are not vendored: `corpus/MANIFEST.md` pins
|
|
650
|
+
every project to a full commit SHA with its licence and file counts,
|
|
651
|
+
`corpus/FILES.tsv` lists every file, and `scripts/fetch-corpus.mjs` clones each
|
|
652
|
+
project at its pinned SHA and copies exactly those paths, so the set is
|
|
653
|
+
byte-identical to the one measured:
|
|
654
|
+
|
|
655
|
+
```bash
|
|
656
|
+
node scripts/fetch-corpus.mjs # all 71 projects
|
|
657
|
+
node scripts/fetch-corpus.mjs --only <owner__repo>
|
|
658
|
+
pnpm parse:corpus -- --transcode
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
Files are copied as raw bytes; most are Windows-1252 with CRLF and must not be
|
|
662
|
+
re-encoded, so the runner transcodes at read time per `corpus/ENCODINGS.json`
|
|
663
|
+
(180 files via Windows-1252, 56 via GBK, 22 via Big5). Keeping the source out of
|
|
664
|
+
the tree also means this repository redistributes nobody else's code; five of
|
|
665
|
+
the 71 projects are copyleft and are marked as such in the manifest.
|
|
666
|
+
|
|
667
|
+
Measured on 2026-09-25 with tree-sitter CLI 0.26.9:
|
|
668
|
+
|
|
669
|
+
| Check | Result |
|
|
670
|
+
| --- | --- |
|
|
671
|
+
| VB6 corpus, transcoded | 1,432 of 1,436 files parse with zero `ERROR` and zero `MISSING`. Three files carry syntax errors VB6 itself rejects and are listed with the defect in `corpus/EXCLUDED.json`; the runner reports them separately. One file keeps two `MISSING` nodes on the `Debug.Assert` shape described under Known limitations |
|
|
672
|
+
| VB6 corpus, raw bytes | nine further files fail on non-ASCII identifiers in legacy code pages |
|
|
673
|
+
| VBA corpus under `vba` | 261 of 261 cases; 481 of 481 example files without `ERROR` or `MISSING` |
|
|
674
|
+
| VB6 corpus cases under `vb6` | 45 of 45 |
|
|
675
|
+
| VBA corpus under `vb6` | 238 of 238 cases run, 23 skipped by design as listed above |
|
|
676
|
+
| Parse time | the largest corpus file, a 2.2 MB module, parses in about 410 ms (5.4 MB/s); a 500 KB `.frm` in 97 ms |
|
|
677
|
+
|
|
678
|
+
## Design principles
|
|
679
|
+
|
|
680
|
+
This repository parses VBA and VB6 syntax only.
|
|
681
|
+
|
|
682
|
+
It does not validate whether identifiers, types, members, procedures, workbook
|
|
683
|
+
objects, or references are semantically valid. Those concerns belong in
|
|
684
|
+
downstream tools such as `xlflow`, `xlflow-lsp`, editor extensions, or other
|
|
685
|
+
analysis tools.
|
|
686
|
+
|
|
687
|
+
Node names should remain stable once introduced because downstream query files
|
|
688
|
+
and integrations may depend on them. However, because this is a `v0.x` release,
|
|
689
|
+
node names and tree shapes may still change before `v1.0.0`.
|
|
690
|
+
|
|
691
|
+
Over-acceptance is preferred to ambiguity: where a choice exists between
|
|
692
|
+
rejecting invalid code and keeping the tree unambiguous, the grammar keeps the
|
|
693
|
+
tree and leaves validation to downstream tools.
|
|
694
|
+
|
|
695
|
+
### Why the `vb6` parser has an external scanner
|
|
696
|
+
|
|
697
|
+
VB6 reads whitespace before a member operator at statement level: `Foo .Bar, x`
|
|
698
|
+
is a call to `Foo` with two arguments, `Foo.Bar , x` a call to `Foo.Bar` with an
|
|
699
|
+
omitted first argument. A context-free grammar never sees the space. The `vba`
|
|
700
|
+
parser works around one shape with whole-line regex tokens
|
|
701
|
+
(`_ambiguous_call_statement`), which keep the tree free of errors but hide the
|
|
702
|
+
statement's structure, and `token.immediate(".")` cannot share a lexer state
|
|
703
|
+
with a regular `"."`. The scanner in [vb6/src/scanner.c](vb6/src/scanner.c)
|
|
704
|
+
emits `_dot_immediate` / `_dot_spaced` / `_bang_immediate` / `_bang_spaced`:
|
|
705
|
+
member chains use the immediate kind only, an implicit member may start with
|
|
706
|
+
either, a dot after a line continuation counts as immediate (`x("y") _`
|
|
707
|
+
followed by `.Add(...)` is a chain), and a dot followed by a digit is left to
|
|
708
|
+
the internal lexer (`.5`). It carries no state. The `vba` parser has no scanner.
|
|
709
|
+
|
|
710
|
+
## Versioning
|
|
711
|
+
|
|
712
|
+
Recommended interpretation of the current release line:
|
|
713
|
+
|
|
714
|
+
- `0.1.x`: parser coverage fixes, query fixes, and non-breaking improvements
|
|
715
|
+
- `0.2.x`: expanded real-world VBA coverage; tree shapes may still evolve
|
|
716
|
+
- `0.x.0`: notable grammar expansion or tree-shape changes
|
|
717
|
+
- `1.0.0`: node names and tree shapes are considered stable for downstream use
|
|
718
|
+
|
|
719
|
+
## Related projects
|
|
720
|
+
|
|
721
|
+
This grammar is intended to support practical VBA tooling, including the
|
|
722
|
+
[harumiWeb/xlflow](https://github.com/harumiWeb/xlflow) ecosystem for AI-assisted Excel/VBA development.
|
|
723
|
+
|
|
724
|
+
## License
|
|
725
|
+
|
|
726
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
|
727
|
+
|
|
728
|
+
### Third-party examples
|
|
729
|
+
|
|
730
|
+
The `examples/third_party` directory may contain third-party fixture files under
|
|
731
|
+
their original licenses. These files are provided for parser coverage only and
|
|
732
|
+
are not licensed under this repository's MIT license unless explicitly stated.
|
|
733
|
+
See [THIRD_PARTY_LICENSE.md](THIRD_PARTY_LICENSE.md) for the project inventory,
|
|
734
|
+
upstream sources, acknowledgements, and local license records.
|
|
735
|
+
|
|
736
|
+
The VB6 acceptance corpus is not part of this repository; `corpus/MANIFEST.md`
|
|
737
|
+
records the repository, commit, and licence of every project it is fetched
|
|
738
|
+
from.
|