tree-sitter-vba
v0.8.1
Published
Tree-sitter grammar for Visual Basic for Applications (VBA).
Maintainers
Readme
tree-sitter-vba
A Tree-sitter grammar for Visual Basic for Applications (VBA), targeting
exported Excel/VBA source files such as .bas, .cls, and .frm.
This grammar is designed as a parsing foundation for editor and tooling use cases, including syntax highlighting, folding, tags, outline extraction, symbol inspection, linting, formatting, and future LSP integrations.
Why another VBA grammar?
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.
This project focuses on practical Excel/VBA source compatibility:
.bas,.cls, and.frmfiles exported from the VBE- real-world VBA fixtures
- UserForm metadata
- conditional compilation
- error handling
- Excel-style member access and procedure calls
- editor queries for highlights, folds, and tags
- permissive MIT licensing
Status
This is a v0.x public release.
The grammar is already usable for syntax-aware tooling such as highlighting,
folding, tags, outline extraction, and initial symbol analysis. The current test
suite covers 189 focused corpus cases and 343 checked-in VBA example files
without ERROR or MISSING recovery nodes.
It is not yet a complete VBA grammar. Node names and tree shapes may still change before v1.0.0.
Installation
npm install tree-sitter tree-sitter-vbaUsage
const Parser = require("tree-sitter");
const VBA = require("tree-sitter-vba");
const parser = new Parser();
parser.setLanguage(VBA);
const tree = parser.parse(`
Sub Hello()
Debug.Print "Hello"
End Sub
`);
console.log(tree.rootNode.toString());Go Usage
The Go binding is self-contained when installed through Go modules; its package directory includes the generated C parser needed by cgo.
package main
import (
"fmt"
tree_sitter "github.com/tree-sitter/go-tree-sitter"
tree_sitter_vba "github.com/harumiWeb/tree-sitter-vba/bindings/go"
)
func main() {
parser := tree_sitter.NewParser()
defer parser.Close()
parser.SetLanguage(tree_sitter.NewLanguage(tree_sitter_vba.Language()))
tree := parser.Parse([]byte("Sub Hello()\nEnd Sub\n"), nil)
defer tree.Close()
fmt.Println(tree.RootNode().ToSexp())
}Example output:
(source_file
(sub_declaration
name: (identifier)
(parameter_list)
body: (block
(call_statement
callee: (qualified_member_expression
receiver: (identifier)
operator: "."
member: (identifier))
arguments: (unparenthesized_argument_list
(string_literal))))))Node.js native build requirements
The npm package currently builds its native addon from source during installation. Prebuilt native binaries may be added in a future release.
A supported Python installation, a C/C++ toolchain, and the platform
requirements documented by node-gyp are required.
On Windows, Visual Studio 2022 Build Tools with the Desktop development with C++ workload is recommended.
At minimum, Windows users typically need:
- Python 3.11 or later
- Visual Studio 2022 Build Tools
- MSVC C++ x64/x86 build tools
- Windows 10 SDK or Windows 11 SDK
If multiple Python installations are present, configure npm to use the intended Python executable:
npm config set python "C:\Users\<you>\AppData\Local\Programs\Python\Python312\python.exe"For reliable native builds on Windows, run installation from:
x64 Native Tools Command Prompt for VS 2022Supported syntax
The grammar currently supports:
- apostrophe comments and
Remcomments - string, integer, floating-point, boolean, date,
Nothing,Null, andEmptyliterals - decimal and hexadecimal literals with common VBA type characters, including
Currency (
@) and LongLong (^), exponent notation such as1E-3, and abbreviated decimal forms such as.5and1. - identifiers with common VBA type-declaration characters, including
@and^ - identifiers, simple type clauses, dotted type names, and array type suffixes
AttributestatementsOption Explicit,Option Private Module,Option Compare, andOption BaseImplementsstatementsSub,Function, andProperty Get/Let/SetproceduresEventdeclarationsRaiseEventstatementsDim,Static,WithEvents, visibility-based variable declarations, arrays,ReDim,Erase, andConst- default type declaration statements such as
DefIntandDefStr TypeandEnumdeclarations- external
Declare FunctionandDeclare Subdeclarations, includingPtrSafe,Lib, andAlias - simple assignments and
Setassignments Name oldPath As newPathfile rename statements- calls, named arguments, omitted arguments, call-site
ByVal, member access, bang member access, and leading-dot member access ? exprDebug.Print shorthand statements, including comma- and semicolon-separated output argumentsNewexpressions andAs Newdeclarations- fixed-length string declarations
AddressOfexpressions- common VBA operator precedence for arithmetic, concatenation, comparison, and
logical operators;
=,<>,<,<=,>,>=,Is, andLikecomparisons are represented ascomparison_expression - block
If, single-lineIf,Select Case,For,For Each,Do,While/Wend, andWith On Error, computedOn ... GoTo/GoSub,Resume,GoTo, labels, standaloneEnd, andExitstatements- common file I/O statements:
Open,Input #,Line Input #,Print #,Close,Get #,Put #,Lock,Unlock,Seek, andReset, including commonAccess ... Sharedlocking clauses - simple runtime statements:
Stop,Beep,Load, andUnload - Access report
Linedrawing calls that use coordinate ranges such asMe.Line (x, y)-(x2, y2) TypeOf ... Is ...checks, including dotted type names such asAccess.Line- numeric line labels, numbered statements, and numbered control-flow delimiters
- conditional compilation with
#Const,#If,#ElseIf,#Else, and#End If, including statement branches inside procedures, members insideTypeandEnumdeclarations, and alternative procedure headers - line continuations, including trailing whitespace, and colon-separated
statements and
Enummembers - minimal
.frmand.clsexport metadata, includingVERSION,Begin ... End,BeginProperty ... EndProperty, GUID form blocks, and.frxblob references - initial
highlights.scm,folds.scm, andtags.scmqueries
Declaration node API
This release line is still pre-1.0.0, and declaration node shapes may change
when doing so makes syntactic metadata more directly available to downstream
tools.
Declaration consumers should prefer these structural nodes and fields over source-text scanning:
property_get_declaration,property_let_declaration, andproperty_set_declarationdistinguish property accessors directly.declare_sub_statementanddeclare_function_statementdistinguish external declaration kind directly.- declaration headers expose stable fields such as
visibility,name,parameters,type,library,alias,ptrsafe_modifier,body, andendwhere applicable. Procedure terminators are exposed throughend_sub_statement,end_function_statement, andend_property_statementnodes. - procedure declarations expose additional procedure modifiers through a
modifiersfield, separate fromvisibility. - variable, constant, type-member, and parameter declarations expose stable
name,bounds,type,initializer,passing_mode,optional_modifier,paramarray_modifier, anddefault_valuefields where syntactically valid. with_events_modifier,static_modifier,byval_modifier,byref_modifier,optional_modifier,paramarray_modifier, andptrsafe_modifierare explicit modifier nodes.implements_statementexposes its target asname, andattribute_statementexposesnameandvalue.
Expression node API
Member access and calls expose stable fields for analysis tools:
qualified_member_expressionusesreceiver,operator, andmember.implicit_member_expressionusesoperatorandmember; it has noreceiver, matching leading-dot and leading-bang VBA syntax.call_expressionusesfunctionandarguments, whereargumentsis anargument_list.call_statementusescalleeand, when arguments are present,arguments. Parenthesized arguments useargument_list; statement-style arguments useunparenthesized_argument_list.
Known limitations
This grammar parses VBA syntax only.
It does not currently provide:
- type checking
- semantic analysis
- Excel Object Model or COM reference knowledge
- validation of identifier, member, type, procedure, workbook, or reference existence
- validation of context-sensitive statement placement
- a formatter
- an LSP server
- complete coverage of every VBA expression edge case
- semantic interpretation of
.frmdesigner metadata
For example, invalid placement of Exit For, unresolved procedure calls, invalid
Excel object members, or missing workbook references are intentionally left to
downstream tools.
General expression-level = comparison is still context-limited to avoid
ambiguity with assignment.
Queries
This package includes initial Tree-sitter queries for:
queries/highlights.scm
queries/folds.scm
queries/tags.scmThese queries are intended as a starting point for editor integrations and tooling. They may evolve as the grammar stabilizes.
Development
Install dependencies:
pnpm installGenerate the parser:
pnpm generateAfter grammar changes, keep the Go module artifact in sync:
cp src/parser.c bindings/go/parser.c
pnpm check:go-parserRun corpus tests:
pnpm testParse example files:
pnpm parse:examplesThis recursively parses the checked-in VBA examples and fails if any parse tree
contains an ERROR or MISSING node.
Run queries against the example files:
pnpm query:examplesThis validates that highlights.scm, folds.scm, and tags.scm can run
against the checked-in examples.
Run the coarse parser benchmark:
pnpm benchThis reports file counts, total bytes, parse time, node counts, and
ERROR/MISSING counts for the checked-in examples. It is intended to catch
large regressions, not to provide a strict microbenchmark.
Run the full local check:
pnpm checkTesting
Tree-sitter grammar behavior is tested with corpus files under:
test/corpus/When changing grammar.js, always add or update focused corpus tests. Do not
weaken existing expectations just to make a grammar change pass.
The repository also includes real-world exported VBA examples. These examples are parsed in CI to catch regressions against practical Excel/VBA code.
Broken or incomplete examples can be kept under:
examples/broken/These fixtures are intentionally excluded from pnpm parse:examples. Add
focused recovery expectations under test/corpus/recovery.txt when the
surrounding tree shape should remain stable.
Design principles
This repository parses VBA syntax only.
It does not validate whether identifiers, types, members, procedures, workbook
objects, or references are semantically valid. Those concerns belong in
downstream tools such as xlflow, xlflow-lsp, editor extensions, or other
analysis tools.
Node names should remain stable once introduced because downstream query files
and integrations may depend on them. However, because this is a v0.x release,
node names and tree shapes may still change before v1.0.0.
Versioning
Recommended interpretation of the current release line:
0.1.x: parser coverage fixes, query fixes, and non-breaking improvements0.2.x: expanded real-world VBA coverage; tree shapes may still evolve0.x.0: notable grammar expansion or tree-shape changes1.0.0: node names and tree shapes are considered stable for downstream use
Related projects
This grammar is intended to support practical VBA tooling, including the
xlflow ecosystem for AI-assisted Excel/VBA development.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Third-party examples
The examples/third_party directory may contain third-party fixture files under
their original licenses. These files are provided for parser coverage only and
are not licensed under this repository's MIT license unless explicitly stated.
