tree-sitter-glsl-spec 1.0.0

GLSL grammar for the tree-sitter parsing library
Documentation

tree-sitter-glsl

A specification-compliant GLSL and ESSL parser for tree-sitter covering the full GLSL 4.60 core grammar, all current Khronos extensions, and common real-world macro patterns.

Features

  • Full GLSL 4.60 and ESSL 3.20 grammar
  • All Khronos extension keywords, types, built-in functions, and variables
  • Structured preprocessor parsing (#define, #if/#ifdef/#elif/#else)
  • Macro expansion support for real-world shaders (COMPAT_PRECISION, MYTYPE(args))
  • Multilingual header support (#ifdef __cplusplus language injection)
  • Extension-defined grammar rules (demote, terminateInvocation)

Queries

File Purpose
highlights.scm Syntax highlighting with built-in function/variable/constant recognition
injections.scm Language injection for #ifdef __cplusplus / __STDC__ guards
locals.scm Scope-aware local variable tracking
tags.scm Symbol indexing for code navigation
- -
version-tags.scm #version-dependent construct validation
constructor-heuristics.scm Opt-in heuristic for capitalized constructor calls

version-tags.scm and constructor-heuristics.scm are custom selectors, that might be useful in some cases, but you likely don't need them.

Usage

Node.js

const Parser = require('tree-sitter');
const GLSL = require('tree-sitter-glsl-spec');

const parser = new Parser();
parser.setLanguage(GLSL);
const tree = parser.parse('void main() { gl_FragColor = vec4(1.0); }');

Rust

let mut parser = tree_sitter::Parser::new();
parser.set_language(&tree_sitter_glsl_spec::LANGUAGE.into()).unwrap();
let tree = parser.parse("void main() { gl_FragColor = vec4(1.0); }", None).unwrap();

Python

import tree_sitter_glsl_spec as glsl
from tree_sitter import Parser

parser = Parser(glsl.language())
tree = parser.parse(b"void main() { gl_FragColor = vec4(1.0); }")

Development

npm install                                   # Install dependencies
npx tree-sitter generate                      # Regenerate parser from grammar.js
npx tree-sitter test                          # Run corpus tests
npx eslint                                    # Lint
npx tsc --noEmit                              # Type check
node scripts/audit_node_types.js --coverage   # Grammar coverage analysis

The specification is included as a git submodule. Run git submodule update --init to fetch it for spec-scraping scripts.

References

Background

This project began as a fork of tree-sitter-glsl by Stephan Seitz, which inherited its grammar from tree-sitter-c. After running into too many quirks from the C grammar inheritance, I rewrote the grammar from scratch against the GLSL 4.60 specification.

Why not inherit from tree-sitter-c?

GLSL's syntax is C-like but substantially simpler. A dedicated grammar provides:

  • Fewer ambiguities — 1 GLR conflict (without macros) vs C's 16. No pointers, no K&R functions, no multi-word types, no sizeof/typeof, no casts.
  • Flat expression trees — identifiers and literals appear directly in the tree without the unary_expression > postfix_expression > primary_expression wrapper chain that a C-inherited grammar produces.
  • GLSL-native nodes — layout qualifiers with name:/value: fields, precision qualifiers, interface blocks, demote/terminateInvocation extension statements.
  • Specification fidelity — every BNF production from the spec exists as a (hidden or visible) rule, documented with the original grammar notation.

License

This project is licensed under the MIT license.