C# grammar for tree-sitter, forked from tree-sitter/tree-sitter-c-sharp. We are grateful to its authors and contributors. This is not an official release of that project.
This fork fixes parsing bugs and raises conformance with the C# language specification.
The grammar is based upon the Roslyn grammar with changes in order to:
- Deal with differences between the parsing technologies
- Work around some bugs in that grammar
- Handle
#if,#else,#elif,#endifblocks - Support syntax highlighting/parsing of fragments
- Simplify the output tree
- Reduce parser state count and complexity
- Be in-line with tree-sitter's convention where applicable
Known gaps:
varandawaitcannot be used as identifiers everywhere they are valid
Type tests use is_pattern_expression. Queries can use expression and its concrete expression nodes.
Constant patterns can contain a direct conditional_access_expression child.
Conditional access includes its complete dependent chain and, for conditional assignment, the assignment in its consequence field.
Tuple-shaped patterns such as x is (1, 2) use recursive_pattern with a positional_pattern_clause.
The contextual type names nint and nuint use identifier nodes.
The npm package ships tree-sitter-c_sharp.wasm for
@willbooster/web-tree-sitter, which runs in Node.js, Bun,
browsers, and Cloudflare Workers. The parser uses WillBooster ABI 9 and loads only with that runtime. Use version 13.0.0 or later within major version 13; upstream's runtime rejects it. Install the runtime alongside the grammar when using
the Wasm parser; it remains an optional peer for consumers that only use the grammar source or queries.
In Node.js and Bun, load it from the package:
import { fileURLToPath } from 'node:url';
import { Language, Parser } from '@willbooster/web-tree-sitter';
await Parser.init();
const parser = new Parser();
const wasmPath = fileURLToPath(import.meta.resolve('@willbooster/tree-sitter-c-sharp/tree-sitter-c_sharp.wasm'));
parser.setLanguage(await Language.load(wasmPath));
const tree = parser.parse('class Program {}\n');In browsers, serve both .wasm files and load them by URL. With Vite:
import { Language, Parser } from '@willbooster/web-tree-sitter';
import runtimeUrl from '@willbooster/web-tree-sitter/web-tree-sitter.wasm?url';
import cSharpUrl from '@willbooster/tree-sitter-c-sharp/tree-sitter-c_sharp.wasm?url';
await Parser.init({ locateFile: () => runtimeUrl });
const parser = new Parser();
parser.setLanguage(await Language.load(cSharpUrl));In Cloudflare Workers, which do not allow compiling Wasm at run time, import both .wasm files as modules (Wrangler
compiles them at build time) and pass them to Parser.init and Language.load. This works with and without the
nodejs_compat flag:
import { Language, Parser } from '@willbooster/web-tree-sitter';
import runtime from '@willbooster/web-tree-sitter/web-tree-sitter.wasm';
import cSharp from '@willbooster/tree-sitter-c-sharp/tree-sitter-c_sharp.wasm';
await Parser.init({ wasmModule: runtime });
const parser = new Parser();
parser.setLanguage(await Language.load(cSharp));The package also ships the queries in queries/ and the node types in src/node-types.json.
When extending the source grammar, use grammar.js and the files under src/ from the same repository release tag.
Their external tokens and serialized scanner state must match.
In Rust, depend on the crate and on willbooster-tree-sitter, the runtime this package is tested and fuzzed with. Use runtime 13.0.0 or later within major version 13:
[dependencies]
tree-sitter = { package = "willbooster-tree-sitter", version = "13.0.0" }
tree-sitter-c-sharp = { package = "willbooster-tree-sitter-c-sharp", version = "15" }let mut parser = tree_sitter::Parser::new();
parser.set_language(&tree_sitter_c_sharp::LANGUAGE.into())?;mise install
bun install --frozen-lockfile
bun playwright install chromium
bun run build/ci
bun run verify
bun run test
cargo test- Parser generation and validation: read before changing grammar inputs, runtime versions, examples, or reproducing an incremental parsing failure.
- C# language specification
- Official C# 8 Draft Language Spec provides chapters that formally define the language grammar.
- Roslyn C# language grammar export
- SharpLab (web-based syntax tree playground based on Roslyn)