Switch to a newer, actively maintained Zig parser

Fixes #851
pull/856/head
Wilfred Hughes 2025-07-02 22:42:05 +07:00
parent 62752b6ab6
commit b3995cd967
30 changed files with 22 additions and 162610 deletions

@ -2,6 +2,8 @@
### Parsing
Updated Zig parser.
File detection is now stricter with Windows-1252 (Latin 1) encoded
text. Windows-1252 was added in 0.63 and some binary files
(e.g. Brotli compressed files) were incorrectly treated as this

11
Cargo.lock generated

@ -305,6 +305,7 @@ dependencies = [
"tree-sitter-verilog",
"tree-sitter-xml",
"tree-sitter-yaml",
"tree-sitter-zig",
"tree_magic_mini",
"typed-arena",
"unicode-width",
@ -1323,6 +1324,16 @@ dependencies = [
"tree-sitter-language",
]
[[package]]
name = "tree-sitter-zig"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab11fc124851b0db4dd5e55983bbd9631192e93238389dcd44521715e5d53e28"
dependencies = [
"cc",
"tree-sitter-language",
]
[[package]]
name = "tree_magic_mini"
version = "3.1.6"

@ -105,6 +105,7 @@ tree-sitter-typescript = "0.23.2"
tree-sitter-verilog = "1.0.3"
tree-sitter-xml = "0.7.0"
tree-sitter-yaml = "0.7.0"
tree-sitter-zig = "1.1.2"
[target.'cfg(not(target_env = "msvc"))'.dependencies]
tikv-jemallocator = "0.6"

@ -207,11 +207,6 @@ fn main() {
src_dir: "vendored_parsers/tree-sitter-vhdl-src",
extra_files: vec![],
},
TreeSitterParser {
name: "tree-sitter-zig",
src_dir: "vendored_parsers/tree-sitter-zig-src",
extra_files: vec![],
},
];
// Only rerun if relevant files in the vendored_parsers/ directory change.

@ -40,7 +40,7 @@ with `difft --list-languages`.
| Nix | [nix-community/tree-sitter-nix](https://github.com/nix-community/tree-sitter-nix) |
| Objective-C | [amaanq/tree-sitter-objc](https://github.com/amaanq/tree-sitter-objc) |
| OCaml | [tree-sitter/tree-sitter-ocaml](https://github.com/tree-sitter/tree-sitter-ocaml) |
| Pascal | [Isopod/tree-sitter-pascal](https://github.com/Isopod/tree-sitter-pascal) |
| Pascal | [Isopod/tree-sitter-pascal](https://github.com/Isopod/tree-sitter-pascal) |
| Perl | [ganezdragon/tree-sitter-perl](https://github.com/ganezdragon/tree-sitter-perl) |
| PHP | [tree-sitter/tree-sitter-php](https://github.com/tree-sitter/tree-sitter-php) |
| Python | [tree-sitter/tree-sitter-python](https://github.com/tree-sitter/tree-sitter-python) |
@ -58,6 +58,7 @@ with `difft --list-languages`.
| TypeScript, TSX | [tree-sitter/tree-sitter-typescript](https://github.com/tree-sitter/tree-sitter-typescript) |
| Verilog | [tree-sitter/tree-sitter-verilog](https://github.com/tree-sitter/tree-sitter-verilog) |
| VHDL | [JLeemaster/tree-sitter-vhdl](https://github.com/JLeemaster/tree-sitter-vhdl) |
| VHDL | [tree-sitter-grammars/tree-sitter-zig](https://github.com/tree-sitter-grammars/tree-sitter-zig) |
| Zig | [maxxnino/tree-sitter-zig](https://github.com/maxxnino/tree-sitter-zig) |
## Structured Text Formats

@ -97,7 +97,6 @@ extern "C" {
fn tree_sitter_solidity() -> ts::Language;
fn tree_sitter_sql() -> ts::Language;
fn tree_sitter_vhdl() -> ts::Language;
fn tree_sitter_zig() -> ts::Language;
}
// TODO: begin/end and object/end.
@ -1134,7 +1133,9 @@ pub(crate) fn from_language(language: guess::Language) -> TreeSitterConfig {
}
}
Zig => {
let language = unsafe { tree_sitter_zig() };
let language_fn = tree_sitter_zig::LANGUAGE;
let language = tree_sitter::Language::new(language_fn);
TreeSitterConfig {
language: language.clone(),
atom_nodes: ["STRINGLITERALSINGLE", "BUILTINIDENTIFIER"]
@ -1143,11 +1144,8 @@ pub(crate) fn from_language(language: guess::Language) -> TreeSitterConfig {
delimiter_tokens: vec![("{", "}"), ("[", "]"), ("(", ")")]
.into_iter()
.collect(),
highlight_query: ts::Query::new(
&language,
include_str!("../../vendored_parsers/highlights/zig.scm"),
)
.unwrap(),
highlight_query: ts::Query::new(&language, tree_sitter_zig::HIGHLIGHTS_QUERY)
.unwrap(),
sub_languages: vec![],
}
}

@ -4,7 +4,7 @@
## 编程语言
| 语言 | 使用的解析器 |
| 语言 | 使用的解析器 |
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Bash | [tree-sitter/tree-sitter-bash](https://github.com/tree-sitter/tree-sitter-bash) |
| Apex | [aheber/tree-sitter-sfapex](https://github.com/aheber/tree-sitter-sfapex) |

@ -1 +0,0 @@
../tree-sitter-zig/queries/highlights.scm

@ -1 +0,0 @@
tree-sitter-zig/src

@ -1,26 +0,0 @@
[package]
name = "tree-sitter-zig"
description = "zig grammar for the tree-sitter parsing library"
version = "0.0.1"
keywords = ["incremental", "parsing", "zig"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/tree-sitter/tree-sitter-zig"
edition = "2018"
license = "MIT"
build = "bindings/rust/build.rs"
include = [
"bindings/rust/*",
"grammar.js",
"queries/*",
"src/*",
]
[lib]
path = "bindings/rust/lib.rs"
[dependencies]
tree-sitter = "~0.20"
[build-dependencies]
cc = "1.0"

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2022 maxxnino
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -1,20 +0,0 @@
<div align="center">
<h1>Tree Sitter For Zig</h1>
</div>
<div align="center">
<p>
<a href="https://github.com/maxxnino/tree-sitter-zig">Zig's Tree Sitter</a>
based on
<a href="https://github.com/ziglang/zig-spec">Zig Spec</a> Official.
</p>
<p>
<i>
Made by Zig's enthusiasts
</i>
</p>
</div>
>Check [Gallery](https://github.com/maxxnino/tree-sitter-zig/wiki/Gallery) for more images
>
![Highlight](https://github.com/maxxnino/good-stuff/blob/main/img/darkplus.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

@ -1,19 +0,0 @@
{
"targets": [
{
"target_name": "tree_sitter_zig_binding",
"include_dirs": [
"<!(node -e \"require('nan')\")",
"src"
],
"sources": [
"bindings/node/binding.cc",
"src/parser.c",
# If your language uses an external scanner, add it here.
],
"cflags_c": [
"-std=c99",
]
}
]
}

@ -1,28 +0,0 @@
#include "tree_sitter/parser.h"
#include <node.h>
#include "nan.h"
using namespace v8;
extern "C" TSLanguage * tree_sitter_zig();
namespace {
NAN_METHOD(New) {}
void Init(Local<Object> exports, Local<Object> module) {
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Language").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
Nan::SetInternalFieldPointer(instance, 0, tree_sitter_zig());
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("zig").ToLocalChecked());
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
}
NODE_MODULE(tree_sitter_zig_binding, Init)
} // namespace

@ -1,19 +0,0 @@
try {
module.exports = require("../../build/Release/tree_sitter_zig_binding");
} catch (error1) {
if (error1.code !== 'MODULE_NOT_FOUND') {
throw error1;
}
try {
module.exports = require("../../build/Debug/tree_sitter_zig_binding");
} catch (error2) {
if (error2.code !== 'MODULE_NOT_FOUND') {
throw error2;
}
throw error1
}
}
try {
module.exports.nodeTypeInfo = require("../../src/node-types.json");
} catch (_) {}

@ -1,40 +0,0 @@
fn main() {
let src_dir = std::path::Path::new("src");
let mut c_config = cc::Build::new();
c_config.include(&src_dir);
c_config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable")
.flag_if_supported("-Wno-trigraphs");
let parser_path = src_dir.join("parser.c");
c_config.file(&parser_path);
// If your language uses an external scanner written in C,
// then include this block of code:
/*
let scanner_path = src_dir.join("scanner.c");
c_config.file(&scanner_path);
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
*/
c_config.compile("parser");
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
// If your language uses an external scanner written in C++,
// then include this block of code:
/*
let mut cpp_config = cc::Build::new();
cpp_config.cpp(true);
cpp_config.include(&src_dir);
cpp_config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable");
let scanner_path = src_dir.join("scanner.cc");
cpp_config.file(&scanner_path);
cpp_config.compile("scanner");
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
*/
}

@ -1,52 +0,0 @@
//! This crate provides zig language support for the [tree-sitter][] parsing library.
//!
//! Typically, you will use the [language][language func] function to add this language to a
//! tree-sitter [Parser][], and then use the parser to parse some code:
//!
//! ```
//! let code = "";
//! let mut parser = tree_sitter::Parser::new();
//! parser.set_language(tree_sitter_zig::language()).expect("Error loading zig grammar");
//! let tree = parser.parse(code, None).unwrap();
//! ```
//!
//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
//! [language func]: fn.language.html
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
//! [tree-sitter]: https://tree-sitter.github.io/
use tree_sitter::Language;
extern "C" {
fn tree_sitter_zig() -> Language;
}
/// Get the tree-sitter [Language][] for this grammar.
///
/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
pub fn language() -> Language {
unsafe { tree_sitter_zig() }
}
/// The content of the [`node-types.json`][] file for this grammar.
///
/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json");
// Uncomment these to include any queries that this grammar contains
// pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm");
// pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm");
// pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
// pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm");
#[cfg(test)]
mod tests {
#[test]
fn test_can_load_grammar() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(super::language())
.expect("Error loading zig language");
}
}

@ -1,867 +0,0 @@
const AMPERSAND = "&",
AMPERSANDEQUAL = "&=",
ASTERISK = "*",
ASTERISK2 = "**",
ASTERISKEQUAL = "*=",
ASTERISKPERCENT = "*%",
ASTERISKPERCENTEQUAL = "*%=",
ASTERISKPIPE = "*|",
ASTERISKPIPEEQUAL = "*|=",
CARET = "^",
CARETEQUAL = "^=",
COLON = ":",
COMMA = ",",
DOT = ".",
DOT2 = "..",
DOT3 = "...",
DOTASTERISK = ".*",
DOTQUESTIONMARK = ".?",
EQUAL = "=",
EQUALEQUAL = "==",
EQUALRARROW = "=>",
EXCLAMATIONMARK = "!",
EXCLAMATIONMARKEQUAL = "!=",
LARROW = "<",
LARROW2 = "<<",
LARROW2PIPE = "<<|",
LARROW2PIPEEQUAL = "<<|=",
LARROW2EQUAL = "<<=",
LARROWEQUAL = "<=",
LBRACE = "{",
LBRACKET = "[",
LPAREN = "(",
MINUS = "-",
MINUSEQUAL = "-=",
MINUSPERCENT = "-%",
MINUSPERCENTEQUAL = "-%=",
MINUSPIPE = "-|",
MINUSPIPEEQUAL = "-|=",
MINUSRARROW = "->",
PERCENT = "%",
PERCENTEQUAL = "%=",
PIPE = "|",
PIPE2 = "||",
PIPEEQUAL = "|=",
PLUS = "+",
PLUS2 = "++",
PLUSEQUAL = "+=",
PLUSPERCENT = "+%",
PLUSPERCENTEQUAL = "+%=",
PLUSPIPE = "+|",
PLUSPIPEEQUAL = "+|=",
LETTERC = "c",
QUESTIONMARK = "?",
RARROW = ">",
RARROW2 = ">>",
RARROW2EQUAL = ">>=",
RARROWEQUAL = ">=",
RBRACE = "}",
RBRACKET = "]",
RPAREN = ")",
SEMICOLON = ";",
SLASH = "/",
SLASHEQUAL = "/=",
TILDE = "~",
PREC = {
label: -1,
curly: 1,
assign: 2,
primary: 3,
statement: 4,
paramType: 5,
or: 6,
and: 7,
comparative: 8,
bitwise: 9,
bitshift: 10,
addition: 11,
multiply: 12,
prefix: 13,
},
buildin_type = [
"bool",
"f16",
"f32",
"f64",
"f128",
"void",
"type",
"anyerror",
"anyframe",
"anyopaque",
"noreturn",
"isize",
"usize",
"comptime_int",
"comptime_float",
"c_short",
"c_ushort",
"c_int",
"c_uint",
"c_long",
"c_ulong",
"c_longlong",
"c_ulonglong",
"c_longdouble",
/(i|u)[0-9]+/,
],
bin = /[01]/,
bin_ = seq(optional("_"), bin),
oct = /[0-7]/,
oct_ = seq(optional("_"), oct),
hex = /[0-9a-fA-F]/,
hex_ = seq(optional("_"), hex),
dec = /[0-9]/,
dec_ = seq(optional("_"), dec),
bin_int = seq(bin, repeat(bin_)),
oct_int = seq(oct, repeat(oct_)),
dec_int = seq(dec, repeat(dec_)),
hex_int = seq(hex, repeat(hex_)),
unescaped_string_fragment = token.immediate(prec(1, /[^"\\\{\}]+/)),
unescaped_char_fragment = token.immediate(prec(1, /[^'\\]/));
module.exports = grammar({
name: "zig",
externals: (_) => [],
inline: ($) => [$.Variable],
extras: ($) => [/\s/, $.line_comment],
rules: {
source_file: ($) =>
seq(optional($.container_doc_comment), optional($._ContainerMembers)),
// *** Top level ***
_ContainerMembers: ($) =>
repeat1(
choice($._ContainerDeclarations, seq($.ContainerField, optional(COMMA)))
),
_ContainerDeclarations: ($) =>
choice(
$.TestDecl,
$.TopLevelComptime,
seq(
optional($.doc_comment),
optional(keyword("pub", $)),
$.TopLevelDecl
)
),
TestDecl: ($) =>
seq(
optional($.doc_comment),
keyword("test", $),
optional($.STRINGLITERALSINGLE),
$.Block
),
TopLevelComptime: ($) =>
seq(optional($.doc_comment), keyword("comptime", $), $.BlockExpr),
TopLevelDecl: ($) =>
// INFO: left and right doesn't matter?
prec.left(
choice(
keyword("export", $),
seq(keyword("extern", $), optional($.STRINGLITERALSINGLE)),
seq(
optional(keyword(choice("inline", "noinline"), $)),
$.FnProto,
choice(SEMICOLON, $.Block)
),
seq(
optional(
choice(
keyword("export", $),
seq(keyword("extern", $), optional($.STRINGLITERALSINGLE))
)
),
optional(keyword("threadlocal", $)),
$.VarDecl
),
seq(keyword("usingnamespace", $), $._Expr, SEMICOLON)
)
),
FnProto: ($) =>
seq(
keyword("fn", $),
optional(field("function", $.IDENTIFIER)),
$.ParamDeclList,
optional($.ByteAlign),
optional($.LinkSection),
optional($.CallConv),
optional(field("exception", EXCLAMATIONMARK)),
$._TypeExpr
),
VarDecl: ($) =>
seq(
keyword(choice("const", "var"), $),
field("variable_type_function", $.IDENTIFIER),
optional(seq(COLON, $._TypeExpr)),
optional($.ByteAlign),
optional($.LinkSection),
optional(seq(EQUAL, $._Expr)),
SEMICOLON
),
ContainerField: ($) =>
seq(
optional($.doc_comment),
optional(keyword("comptime", $)),
field("field_member", $.IDENTIFIER),
optional(
seq(
COLON,
choice(keyword("anytype", $), $._TypeExpr),
optional($.ByteAlign)
)
),
optional(seq(EQUAL, $._Expr))
),
// *** Block Level ***
Statement: ($) =>
prec(
PREC.statement,
choice(
seq(optional(keyword("comptime", $)), $.VarDecl),
seq(
choice(
keyword(choice("comptime", "nosuspend", "defer", "suspend"), $),
seq(keyword("errdefer", $), optional($.Payload))
),
$.BlockExprStatement
),
$.IfStatement,
$.LabeledStatement,
$.SwitchExpr,
seq($.AssignExpr, SEMICOLON)
)
),
IfStatement: ($) =>
choice(
seq($.IfPrefix, $.BlockExpr, optional($._ElseStatementTail)),
seq($.IfPrefix, $.AssignExpr, choice(SEMICOLON, $._ElseStatementTail))
),
_ElseStatementTail: ($) =>
seq(keyword("else", $), optional($.Payload), $.Statement),
LabeledStatement: ($) =>
prec(
PREC.statement,
seq(optional($.BlockLabel), choice($.Block, $.LoopStatement))
),
LoopStatement: ($) =>
seq(
optional(keyword("inline", $)),
choice($.ForStatement, $.WhileStatement)
),
ForStatement: ($) =>
choice(
seq($.ForPrefix, $.BlockExpr, optional($._ElseStatementTail)),
seq($.ForPrefix, $.AssignExpr, choice(SEMICOLON, $._ElseStatementTail))
),
WhileStatement: ($) =>
choice(
seq($.WhilePrefix, $.BlockExpr, optional($._ElseStatementTail)),
seq(
$.WhilePrefix,
$.AssignExpr,
choice(SEMICOLON, $._ElseStatementTail)
)
),
BlockExprStatement: ($) =>
choice($.BlockExpr, seq($.AssignExpr, SEMICOLON)),
BlockExpr: ($) => prec(PREC.curly, seq(optional($.BlockLabel), $.Block)),
// *** Expression Level ***
AssignExpr: ($) =>
prec(PREC.assign, seq($._Expr, optional(seq($.AssignOp, $._Expr)))),
_Expr: ($) => choice($.BinaryExpr, $.UnaryExpr, $._PrimaryExpr),
BinaryExpr: ($) => {
const table = [
[PREC.or, "or"],
[PREC.and, "and"],
[PREC.comparative, $.CompareOp],
[PREC.bitwise, $.BitwiseOp],
[PREC.bitshift, $.BitShiftOp],
[PREC.addition, $.AdditionOp],
[PREC.multiply, $.MultiplyOp],
];
return choice(
...table.map(([precedence, operator]) =>
prec.left(
precedence,
seq(
field("left", $._Expr),
field("operator", operator),
field("right", $._Expr)
)
)
)
);
},
UnaryExpr: ($) =>
prec.left(
PREC.prefix,
seq(field("operator", $.PrefixOp), field("left", $._Expr))
),
_PrimaryExpr: ($) =>
// INFO: left/right doesn't matter?
prec.left(
PREC.primary,
choice(
$.AsmExpr,
$.IfExpr,
seq(keyword("break", $), optional($.BreakLabel), optional($._Expr)),
seq(keyword("continue", $), optional($.BreakLabel)),
seq(keyword(choice("comptime", "nosuspend", "resume"), $), $._Expr),
seq(keyword("return", $), optional($._Expr)),
seq(optional($.BlockLabel), $.LoopExpr),
$.Block,
$._CurlySuffixExpr
)
),
IfExpr: ($) =>
prec.left(seq($.IfPrefix, $._Expr, optional($._ElseExprTail))),
_ElseExprTail: ($) => seq(keyword("else", $), optional($.Payload), $._Expr),
Block: ($) => seq(LBRACE, repeat($.Statement), RBRACE),
LoopExpr: ($) =>
seq(optional(keyword("inline", $)), choice($.ForExpr, $.WhileExpr)),
ForExpr: ($) =>
prec.left(seq($.ForPrefix, $._Expr, optional($._ElseExprTail))),
WhileExpr: ($) =>
prec.left(seq($.WhilePrefix, $._Expr, optional($._ElseExprTail))),
_CurlySuffixExpr: ($) =>
// INFO: solve #1 issue
prec(PREC.curly, seq($._TypeExpr, optional($.InitList))),
InitList: ($) =>
choice(
seq(LBRACE, sepBy1(COMMA, $.FieldInit), RBRACE),
seq(LBRACE, sepBy1(COMMA, $._Expr), RBRACE),
seq(LBRACE, RBRACE)
),
_TypeExpr: ($) => seq(repeat($.PrefixTypeOp), $.ErrorUnionExpr),
ErrorUnionExpr: ($) =>
// INFO: left and right doesn't matter?
prec.left(
seq(
$.SuffixExpr,
optional(seq(field("exception", EXCLAMATIONMARK), $._TypeExpr))
)
),
SuffixExpr: ($) =>
// INFO: solve #1 issue
prec.right(
seq(
optional(keyword("async", $)),
choice(
$._PrimaryTypeExpr,
seq($._PrimaryTypeExpr, $.FnCallArguments),
field("variable_type_function", $.IDENTIFIER),
seq(field("function_call", $.IDENTIFIER), $.FnCallArguments)
),
repeat(
choice(
$.SuffixOp,
seq($.SuffixOp, $.FnCallArguments),
$.FieldOrFnCall
)
)
)
),
FieldOrFnCall: ($) =>
prec.right(
choice(
seq(DOT, field("field_access", $.IDENTIFIER)),
seq(DOT, field("function_call", $.IDENTIFIER), $.FnCallArguments)
)
),
_PrimaryTypeExpr: ($) =>
choice(
seq($.BUILTINIDENTIFIER, $.FnCallArguments),
$.CHAR_LITERAL,
$.ContainerDecl,
seq(DOT, field("field_constant", $.IDENTIFIER)),
seq(DOT, $.InitList),
$.ErrorSetDecl,
$.FLOAT,
$.FnProto,
$.GroupedExpr,
$.LabeledTypeExpr,
$.IfTypeExpr,
$.INTEGER,
seq(keyword("comptime", $), $._TypeExpr),
seq(keyword("error", $), DOT, field("field_constant", $.IDENTIFIER)),
keyword("false", $),
keyword("null", $),
keyword("anyframe", $),
keyword("true", $),
keyword("undefined", $),
keyword("unreachable", $),
$._STRINGLITERAL,
$.SwitchExpr,
$.BuildinTypeExpr
),
BuildinTypeExpr: (_) => token(choice(...buildin_type)),
ContainerDecl: ($) =>
seq(
optional(keyword(choice("extern", "packed"), $)),
$._ContainerDeclAuto
),
ErrorSetDecl: ($) =>
seq(
keyword("error", $),
LBRACE,
sepBy(
COMMA,
seq(optional($.doc_comment), field("field_constant", $.IDENTIFIER))
),
RBRACE
),
GroupedExpr: ($) => seq(LPAREN, $._Expr, RPAREN),
IfTypeExpr: ($) =>
prec.left(seq($.IfPrefix, $._TypeExpr, optional($._ElseTypeExprTail))),
_ElseTypeExprTail: ($) =>
seq(keyword("else", $), optional($.Payload), $._TypeExpr),
LabeledTypeExpr: ($) =>
choice(
seq($.BlockLabel, $.Block),
seq(optional($.BlockLabel), $.LoopTypeExpr)
),
LoopTypeExpr: ($) =>
seq(
optional(keyword("inline", $)),
choice($.ForTypeExpr, $.WhileTypeExpr)
),
ForTypeExpr: ($) =>
prec.left(seq($.ForPrefix, $._TypeExpr, optional($._ElseTypeExprTail))),
WhileTypeExpr: ($) =>
prec.left(seq($.WhilePrefix, $._TypeExpr, optional($._ElseTypeExprTail))),
SwitchExpr: ($) =>
seq(
keyword("switch", $),
LPAREN,
$._Expr,
RPAREN,
LBRACE,
sepBy(COMMA, $.SwitchProng),
RBRACE
),
// *** Assembly ***
AsmExpr: ($) =>
seq(
keyword("asm", $),
optional(keyword("volatile", $)),
LPAREN,
$._Expr,
optional($.AsmOutput),
RPAREN
),
AsmOutput: ($) =>
seq(COLON, sepBy(COMMA, $.AsmOutputItem), optional($.AsmInput)),
AsmOutputItem: ($) =>
seq(
LBRACKET,
$.Variable,
RBRACKET,
$._STRINGLITERAL,
LPAREN,
choice(seq("->", $._TypeExpr), $.Variable),
RPAREN
),
AsmInput: ($) =>
seq(COLON, sepBy(COMMA, $.AsmInputItem), optional($.AsmClobbers)),
AsmInputItem: ($) =>
seq(
LBRACKET,
$.Variable,
RBRACKET,
$._STRINGLITERAL,
LPAREN,
$._Expr,
RPAREN
),
AsmClobbers: ($) => seq(COLON, sepBy(COMMA, $._STRINGLITERAL)),
// *** Helper grammar ***
BreakLabel: ($) => seq(COLON, $.IDENTIFIER),
BlockLabel: ($) => prec(PREC.label, seq($.IDENTIFIER, COLON)),
FieldInit: ($) =>
seq(DOT, field("field_member", $.IDENTIFIER), EQUAL, $._Expr),
WhileContinueExpr: ($) => seq(COLON, LPAREN, $.AssignExpr, RPAREN),
LinkSection: ($) => seq(keyword("linksection", $), LPAREN, $._Expr, RPAREN),
// Fn specific
CallConv: ($) => seq(keyword("callconv", $), LPAREN, $._Expr, RPAREN),
ParamDecl: ($) =>
choice(
seq(
optional($.doc_comment),
optional(keyword(choice("noalias", "comptime"), $)),
optional(seq(field("parameter", $.IDENTIFIER), COLON)),
$.ParamType
),
DOT3
),
ParamType: ($) =>
prec(PREC.paramType, choice(keyword("anytype", $), $._TypeExpr)),
// Control flow prefixes
IfPrefix: ($) =>
seq(keyword("if", $), LPAREN, $._Expr, RPAREN, optional($.PtrPayload)),
WhilePrefix: ($) =>
seq(
keyword("while", $),
LPAREN,
$._Expr,
RPAREN,
optional($.PtrPayload),
optional($.WhileContinueExpr)
),
ForPrefix: ($) =>
seq(keyword("for", $), LPAREN, $._Expr, RPAREN, $.PtrIndexPayload),
// Payloads
Payload: ($) => seq(PIPE, $.Variable, PIPE),
PtrPayload: ($) => seq(PIPE, optional(ASTERISK), $.Variable, PIPE),
PtrIndexPayload: ($) =>
seq(
PIPE,
optional(ASTERISK),
$.Variable,
optional(seq(COMMA, $.Variable)),
PIPE
),
// Switch specific
SwitchProng: ($) =>
seq($.SwitchCase, EQUALRARROW, optional($.PtrPayload), $.AssignExpr),
SwitchCase: ($) => choice(sepBy1(COMMA, $.SwitchItem), keyword("else", $)),
SwitchItem: ($) => seq($._Expr, optional(seq(DOT3, $._Expr))),
AssignOp: (_) =>
choice(
ASTERISKEQUAL,
ASTERISKPIPEEQUAL,
SLASHEQUAL,
PERCENTEQUAL,
PLUSEQUAL,
PLUSPIPEEQUAL,
MINUSEQUAL,
MINUSPIPEEQUAL,
LARROW2EQUAL,
LARROW2PIPEEQUAL,
RARROW2EQUAL,
AMPERSANDEQUAL,
CARETEQUAL,
PIPEEQUAL,
ASTERISKPERCENTEQUAL,
PLUSPERCENTEQUAL,
MINUSPERCENTEQUAL,
EQUAL
),
CompareOp: (_) =>
choice(
EQUALEQUAL,
EXCLAMATIONMARKEQUAL,
LARROW,
RARROW,
LARROWEQUAL,
RARROWEQUAL
),
BitwiseOp: ($) =>
choice(
AMPERSAND,
CARET,
PIPE,
keyword("orelse", $),
seq(keyword("catch", $), optional($.Payload))
),
BitShiftOp: (_) => choice(LARROW2, RARROW2, LARROW2PIPE),
AdditionOp: (_) =>
choice(
PLUS,
MINUS,
PLUS2,
PLUSPERCENT,
MINUSPERCENT,
PLUSPIPE,
MINUSPIPE
),
MultiplyOp: (_) =>
choice(
PIPE2,
ASTERISK,
SLASH,
PERCENT,
ASTERISK2,
ASTERISKPERCENT,
ASTERISKPIPE
),
PrefixOp: ($) =>
choice(
EXCLAMATIONMARK,
MINUS,
TILDE,
MINUSPERCENT,
AMPERSAND,
keyword("try", $),
keyword("await", $)
),
PrefixTypeOp: ($) =>
choice(
QUESTIONMARK,
seq(keyword("anyframe", $), MINUSRARROW),
seq(
$.SliceTypeStart,
repeat(
choice(
$.ByteAlign,
keyword(choice("const", "volatile", "allowzero"), $)
)
)
),
seq(
$.PtrTypeStart,
repeat(
choice(
seq(
keyword("align", $),
LPAREN,
$._Expr,
optional(seq(COLON, $.INTEGER, COLON, $.INTEGER)),
RPAREN
),
keyword(choice("const", "volatile", "allowzero"), $)
)
)
),
$.ArrayTypeStart
),
SuffixOp: ($) =>
choice(
seq(
LBRACKET,
$._Expr,
optional(seq(DOT2, optional($._Expr), optional(seq(COLON, $._Expr)))),
RBRACKET
),
DOTASTERISK,
DOTQUESTIONMARK
),
FnCallArguments: ($) => seq(LPAREN, sepBy(COMMA, $._Expr), RPAREN),
// Ptr specific
SliceTypeStart: ($) =>
seq(LBRACKET, optional(seq(COLON, $._Expr)), RBRACKET),
PtrTypeStart: ($) =>
choice(
ASTERISK,
ASTERISK2,
seq(
LBRACKET,
ASTERISK,
optional(choice(LETTERC, seq(COLON, $._Expr))),
RBRACKET
)
),
ArrayTypeStart: ($) =>
seq(LBRACKET, $._Expr, optional(seq(COLON, $._Expr)), RBRACKET),
// ContainerDecl specific
_ContainerDeclAuto: ($) =>
seq(
$.ContainerDeclType,
LBRACE,
optional($.container_doc_comment),
optional($._ContainerMembers),
RBRACE
),
ContainerDeclType: ($) =>
choice(
keyword("struct", $),
keyword("opaque", $),
seq(keyword("enum", $), optional(seq(LPAREN, $._Expr, RPAREN))),
seq(
keyword("union", $),
optional(
seq(
LPAREN,
choice(
seq(keyword("enum", $), optional(seq(LPAREN, $._Expr, RPAREN))),
$._Expr
),
RPAREN
)
)
)
),
// Alignment
ByteAlign: ($) => seq(keyword("align", $), LPAREN, $._Expr, RPAREN),
// Lists
ParamDeclList: ($) => seq(LPAREN, sepBy(COMMA, $.ParamDecl), RPAREN),
// *** Tokens ***
container_doc_comment: (_) =>
token(repeat1(seq("//!", /[^\n]*/, /[ \n]*/))),
doc_comment: (_) => token(repeat1(seq("///", /[^\n]*/, /[ \n]*/))),
line_comment: (_) => token(seq("//", /.*/)),
CHAR_LITERAL: ($) =>
seq("'", choice(unescaped_char_fragment, $.EscapeSequence), "'"),
FLOAT: (_) =>
choice(
token(
seq("0x", hex_int, ".", hex_int, optional(seq(/[pP][-+]?/, dec_int)))
),
token(seq(dec_int, ".", dec_int, optional(seq(/[eE][-+]?/, dec_int)))),
token(seq("0x", hex_int, /[pP][-+]?/, dec_int)),
token(seq(dec_int, /[eE][-+]?/, dec_int))
),
INTEGER: (_) =>
choice(
token(seq("0b", bin_int)),
token(seq("0o", oct_int)),
token(seq("0x", hex_int)),
token(dec_int)
),
EscapeSequence: (_) =>
token.immediate(
choice(
seq(
"\\",
choice(/x[0-9a-fA-f]{2}/, /u\{[0-9a-fA-F]+\}/, /[nr\\t'"]/)
),
"{{",
"}}"
)
),
FormatSequence: (_) =>
token.immediate(
seq(
"{",
/[0-9]*/,
optional(choice(/[xXsedbocu*]{1}/, "any")),
optional(
seq(
":",
optional(seq(/[^"\\\{\}]{1}/, /[<^>]{1}/, /[0-9]+/)),
/.{0,1}/,
/[0-9]*/
)
),
"}"
)
),
STRINGLITERALSINGLE: ($) =>
seq(
'"',
repeat(
choice(
unescaped_string_fragment,
$.EscapeSequence,
$.FormatSequence,
token.immediate(choice("{", "}"))
)
),
'"'
),
LINESTRING: (_) => seq("\\\\", /[^\n]*/),
_STRINGLITERAL: ($) => choice($.STRINGLITERALSINGLE, repeat1($.LINESTRING)),
Variable: ($) => field("variable", $.IDENTIFIER),
IDENTIFIER: ($) =>
choice(/[A-Za-z_][A-Za-z0-9_]*/, seq("@", $.STRINGLITERALSINGLE)),
BUILTINIDENTIFIER: (_) => seq("@", /[A-Za-z_][A-Za-z0-9_]*/),
},
});
function sepBy1(sep, rule) {
return seq(rule, repeat(seq(sep, rule)), optional(sep));
}
function keyword(rule, _) {
return rule;
// return alias(rule, $.keyword);
}
function sepBy(sep, rule) {
return optional(sepBy1(sep, rule));
}

@ -1,557 +0,0 @@
Root <- skip container_doc_comment? ContainerMembers eof
# *** Top level ***
ContainerMembers <- ContainerDeclarations (ContainerField COMMA)* (ContainerField / ContainerDeclarations)
ContainerDeclarations
<- TestDecl ContainerDeclarations
/ TopLevelComptime ContainerDeclarations
/ doc_comment? KEYWORD_pub? TopLevelDecl ContainerDeclarations
/
TestDecl <- doc_comment? KEYWORD_test STRINGLITERALSINGLE? Block
TopLevelComptime <- doc_comment? KEYWORD_comptime BlockExpr
TopLevelDecl
<- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block)
/ (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl
/ KEYWORD_usingnamespace Expr SEMICOLON
FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr
VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
ContainerField <- doc_comment? KEYWORD_comptime? IDENTIFIER (COLON (KEYWORD_anytype / TypeExpr) ByteAlign?)? (EQUAL Expr)?
# *** Block Level ***
Statement
<- KEYWORD_comptime? VarDecl
/ KEYWORD_comptime BlockExprStatement
/ KEYWORD_nosuspend BlockExprStatement
/ KEYWORD_suspend BlockExprStatement
/ KEYWORD_defer BlockExprStatement
/ KEYWORD_errdefer Payload? BlockExprStatement
/ IfStatement
/ LabeledStatement
/ SwitchExpr
/ AssignExpr SEMICOLON
IfStatement
<- IfPrefix BlockExpr ( KEYWORD_else Payload? Statement )?
/ IfPrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
LabeledStatement <- BlockLabel? (Block / LoopStatement)
LoopStatement <- KEYWORD_inline? (ForStatement / WhileStatement)
ForStatement
<- ForPrefix BlockExpr ( KEYWORD_else Statement )?
/ ForPrefix AssignExpr ( SEMICOLON / KEYWORD_else Statement )
WhileStatement
<- WhilePrefix BlockExpr ( KEYWORD_else Payload? Statement )?
/ WhilePrefix AssignExpr ( SEMICOLON / KEYWORD_else Payload? Statement )
BlockExprStatement
<- BlockExpr
/ AssignExpr SEMICOLON
BlockExpr <- BlockLabel? Block
# *** Expression Level ***
AssignExpr <- Expr (AssignOp Expr)?
Expr <- BoolOrExpr
BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)*
BoolAndExpr <- CompareExpr (KEYWORD_and CompareExpr)*
CompareExpr <- BitwiseExpr (CompareOp BitwiseExpr)?
BitwiseExpr <- BitShiftExpr (BitwiseOp BitShiftExpr)*
BitShiftExpr <- AdditionExpr (BitShiftOp AdditionExpr)*
AdditionExpr <- MultiplyExpr (AdditionOp MultiplyExpr)*
MultiplyExpr <- PrefixExpr (MultiplyOp PrefixExpr)*
PrefixExpr <- PrefixOp* PrimaryExpr
PrimaryExpr
<- AsmExpr
/ IfExpr
/ KEYWORD_break BreakLabel? Expr?
/ KEYWORD_comptime Expr
/ KEYWORD_nosuspend Expr
/ KEYWORD_continue BreakLabel?
/ KEYWORD_resume Expr
/ KEYWORD_return Expr?
/ BlockLabel? LoopExpr
/ Block
/ CurlySuffixExpr
IfExpr <- IfPrefix Expr (KEYWORD_else Payload? Expr)?
Block <- LBRACE Statement* RBRACE
LoopExpr <- KEYWORD_inline? (ForExpr / WhileExpr)
ForExpr <- ForPrefix Expr (KEYWORD_else Expr)?
WhileExpr <- WhilePrefix Expr (KEYWORD_else Payload? Expr)?
CurlySuffixExpr <- TypeExpr InitList?
InitList
<- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
/ LBRACE Expr (COMMA Expr)* COMMA? RBRACE
/ LBRACE RBRACE
TypeExpr <- PrefixTypeOp* ErrorUnionExpr
ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
SuffixExpr
<- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
/ PrimaryTypeExpr (SuffixOp / FnCallArguments)*
PrimaryTypeExpr
<- BUILTINIDENTIFIER FnCallArguments
/ CHAR_LITERAL
/ ContainerDecl
/ DOT IDENTIFIER
/ DOT InitList
/ ErrorSetDecl
/ FLOAT
/ FnProto
/ GroupedExpr
/ LabeledTypeExpr
/ IDENTIFIER
/ IfTypeExpr
/ INTEGER
/ KEYWORD_comptime TypeExpr
/ KEYWORD_error DOT IDENTIFIER
/ KEYWORD_anyframe
/ KEYWORD_unreachable
/ STRINGLITERAL
/ SwitchExpr
ContainerDecl <- (KEYWORD_extern / KEYWORD_packed)? ContainerDeclAuto
ErrorSetDecl <- KEYWORD_error LBRACE IdentifierList RBRACE
GroupedExpr <- LPAREN Expr RPAREN
IfTypeExpr <- IfPrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
LabeledTypeExpr
<- BlockLabel Block
/ BlockLabel? LoopTypeExpr
LoopTypeExpr <- KEYWORD_inline? (ForTypeExpr / WhileTypeExpr)
ForTypeExpr <- ForPrefix TypeExpr (KEYWORD_else TypeExpr)?
WhileTypeExpr <- WhilePrefix TypeExpr (KEYWORD_else Payload? TypeExpr)?
SwitchExpr <- KEYWORD_switch LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE
# *** Assembly ***
AsmExpr <- KEYWORD_asm KEYWORD_volatile? LPAREN Expr AsmOutput? RPAREN
AsmOutput <- COLON AsmOutputList AsmInput?
AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
AsmInput <- COLON AsmInputList AsmClobbers?
AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
AsmClobbers <- COLON StringList
# *** Helper grammar ***
BreakLabel <- COLON IDENTIFIER
BlockLabel <- IDENTIFIER COLON
FieldInit <- DOT IDENTIFIER EQUAL Expr
WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN
LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
# Fn specific
CallConv <- KEYWORD_callconv LPAREN Expr RPAREN
ParamDecl
<- doc_comment? (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
/ DOT3
ParamType
<- KEYWORD_anytype
/ TypeExpr
# Control flow prefixes
IfPrefix <- KEYWORD_if LPAREN Expr RPAREN PtrPayload?
WhilePrefix <- KEYWORD_while LPAREN Expr RPAREN PtrPayload? WhileContinueExpr?
ForPrefix <- KEYWORD_for LPAREN Expr RPAREN PtrIndexPayload
# Payloads
Payload <- PIPE IDENTIFIER PIPE
PtrPayload <- PIPE ASTERISK? IDENTIFIER PIPE
PtrIndexPayload <- PIPE ASTERISK? IDENTIFIER (COMMA IDENTIFIER)? PIPE
# Switch specific
SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr
SwitchCase
<- SwitchItem (COMMA SwitchItem)* COMMA?
/ KEYWORD_else
SwitchItem <- Expr (DOT3 Expr)?
# Operators
AssignOp
<- ASTERISKEQUAL
/ SLASHEQUAL
/ PERCENTEQUAL
/ PLUSEQUAL
/ MINUSEQUAL
/ LARROW2EQUAL
/ LARROW2PIPEEQUAL
/ RARROW2EQUAL
/ AMPERSANDEQUAL
/ CARETEQUAL
/ PIPEEQUAL
/ ASTERISKPERCENTEQUAL
/ PLUSPERCENTEQUAL
/ MINUSPERCENTEQUAL
/ EQUAL
CompareOp
<- EQUALEQUAL
/ EXCLAMATIONMARKEQUAL
/ LARROW
/ RARROW
/ LARROWEQUAL
/ RARROWEQUAL
BitwiseOp
<- AMPERSAND
/ CARET
/ PIPE
/ KEYWORD_orelse
/ KEYWORD_catch Payload?
BitShiftOp
<- LARROW2
/ RARROW2
AdditionOp
<- PLUS
/ MINUS
/ PLUS2
/ PLUSPERCENT
/ MINUSPERCENT
/ PLUSPIPE
/ MINUSPIPE
MultiplyOp
<- PIPE2
/ ASTERISK
/ SLASH
/ PERCENT
/ ASTERISK2
/ ASTERISKPERCENT
/ ASTERISKPIPE
PrefixOp
<- EXCLAMATIONMARK
/ MINUS
/ TILDE
/ MINUSPERCENT
/ AMPERSAND
/ KEYWORD_try
/ KEYWORD_await
PrefixTypeOp
<- QUESTIONMARK
/ KEYWORD_anyframe MINUSRARROW
/ SliceTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
/ PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
/ ArrayTypeStart
SuffixOp
<- LBRACKET Expr (DOT2 (Expr? (COLON Expr)?)?)? RBRACKET
/ DOT IDENTIFIER
/ DOTASTERISK
/ DOTQUESTIONMARK
FnCallArguments <- LPAREN ExprList RPAREN
# Ptr specific
SliceTypeStart <- LBRACKET (COLON Expr)? RBRACKET
PtrTypeStart
<- ASTERISK
/ ASTERISK2
/ LBRACKET ASTERISK (LETTERC / COLON Expr)? RBRACKET
ArrayTypeStart <- LBRACKET Expr (COLON Expr)? RBRACKET
# ContainerDecl specific
ContainerDeclAuto <- ContainerDeclType LBRACE container_doc_comment? ContainerMembers RBRACE
ContainerDeclType
<- KEYWORD_struct
/ KEYWORD_opaque
/ KEYWORD_enum (LPAREN Expr RPAREN)?
/ KEYWORD_union (LPAREN (KEYWORD_enum (LPAREN Expr RPAREN)? / Expr) RPAREN)?
# Alignment
ByteAlign <- KEYWORD_align LPAREN Expr RPAREN
# Lists
IdentifierList <- (doc_comment? IDENTIFIER COMMA)* (doc_comment? IDENTIFIER)?
SwitchProngList <- (SwitchProng COMMA)* SwitchProng?
AsmOutputList <- (AsmOutputItem COMMA)* AsmOutputItem?
AsmInputList <- (AsmInputItem COMMA)* AsmInputItem?
StringList <- (STRINGLITERAL COMMA)* STRINGLITERAL?
ParamDeclList <- (ParamDecl COMMA)* ParamDecl?
ExprList <- (Expr COMMA)* Expr?
# *** Tokens ***
eof <- !.
bin <- [01]
bin_ <- '_'? bin
oct <- [0-7]
oct_ <- '_'? oct
hex <- [0-9a-fA-F]
hex_ <- '_'? hex
dec <- [0-9]
dec_ <- '_'? dec
bin_int <- bin bin_*
oct_int <- oct oct_*
dec_int <- dec dec_*
hex_int <- hex hex_*
ox80_oxBF <- [\200-\277]
oxF4 <- '\364'
ox80_ox8F <- [\200-\217]
oxF1_oxF3 <- [\361-\363]
oxF0 <- '\360'
ox90_0xBF <- [\220-\277]
oxEE_oxEF <- [\356-\357]
oxED <- '\355'
ox80_ox9F <- [\200-\237]
oxE1_oxEC <- [\341-\354]
oxE0 <- '\340'
oxA0_oxBF <- [\240-\277]
oxC2_oxDF <- [\302-\337]
# From https://lemire.me/blog/2018/05/09/how-quickly-can-you-check-that-a-string-is-valid-unicode-utf-8/
# First Byte Second Byte Third Byte Fourth Byte
# [0x00,0x7F]
# [0xC2,0xDF] [0x80,0xBF]
# 0xE0 [0xA0,0xBF] [0x80,0xBF]
# [0xE1,0xEC] [0x80,0xBF] [0x80,0xBF]
# 0xED [0x80,0x9F] [0x80,0xBF]
# [0xEE,0xEF] [0x80,0xBF] [0x80,0xBF]
# 0xF0 [0x90,0xBF] [0x80,0xBF] [0x80,0xBF]
# [0xF1,0xF3] [0x80,0xBF] [0x80,0xBF] [0x80,0xBF]
# 0xF4 [0x80,0x8F] [0x80,0xBF] [0x80,0xBF]
mb_utf8_literal <-
oxF4 ox80_ox8F ox80_oxBF ox80_oxBF
/ oxF1_oxF3 ox80_oxBF ox80_oxBF ox80_oxBF
/ oxF0 ox90_0xBF ox80_oxBF ox80_oxBF
/ oxEE_oxEF ox80_oxBF ox80_oxBF
/ oxED ox80_ox9F ox80_oxBF
/ oxE1_oxEC ox80_oxBF ox80_oxBF
/ oxE0 oxA0_oxBF ox80_oxBF
/ oxC2_oxDF ox80_oxBF
ascii_char_not_nl_slash_squote <- [\000-\011\013-\046-\050-\133\135-\177]
char_escape
<- "\\x" hex hex
/ "\\u{" hex+ "}"
/ "\\" [nr\\t'"]
char_char
<- mb_utf8_literal
/ char_escape
/ ascii_char_not_nl_slash_squote
string_char
<- char_escape
/ [^\\"\n]
container_doc_comment <- ('//!' [^\n]* [ \n]*)+
doc_comment <- ('///' [^\n]* [ \n]*)+
line_comment <- '//' ![!/][^\n]* / '////' [^\n]*
line_string <- ("\\\\" [^\n]* [ \n]*)+
skip <- ([ \n] / line_comment)*
CHAR_LITERAL <- "'" char_char "'" skip
FLOAT
<- "0x" hex_int "." hex_int ([pP] [-+]? dec_int)? skip
/ dec_int "." dec_int ([eE] [-+]? dec_int)? skip
/ "0x" hex_int "."? [pP] [-+]? dec_int skip
/ dec_int "."? [eE] [-+]? dec_int skip
INTEGER
<- "0b" bin_int skip
/ "0o" oct_int skip
/ "0x" hex_int skip
/ dec_int skip
STRINGLITERALSINGLE <- "\"" string_char* "\"" skip
STRINGLITERAL
<- STRINGLITERALSINGLE
/ (line_string skip)+
IDENTIFIER
<- !keyword [A-Za-z_] [A-Za-z0-9_]* skip
/ "@\"" string_char* "\"" skip
BUILTINIDENTIFIER <- "@"[A-Za-z_][A-Za-z0-9_]* skip
AMPERSAND <- '&' ![=] skip
AMPERSANDEQUAL <- '&=' skip
ASTERISK <- '*' ![*%=] skip
ASTERISK2 <- '**' skip
ASTERISKEQUAL <- '*=' skip
ASTERISKPERCENT <- '*%' ![=] skip
ASTERISKPERCENTEQUAL <- '*%=' skip
ASTERISKPIPE <- '*|' ![=] skip
ASTERISKPIPEEQUAL <- '*|=' skip
CARET <- '^' ![=] skip
CARETEQUAL <- '^=' skip
COLON <- ':' skip
COMMA <- ',' skip
DOT <- '.' ![*.?] skip
DOT2 <- '..' ![.] skip
DOT3 <- '...' skip
DOTASTERISK <- '.*' skip
DOTQUESTIONMARK <- '.?' skip
EQUAL <- '=' ![>=] skip
EQUALEQUAL <- '==' skip
EQUALRARROW <- '=>' skip
EXCLAMATIONMARK <- '!' ![=] skip
EXCLAMATIONMARKEQUAL <- '!=' skip
LARROW <- '<' ![<=] skip
LARROW2 <- '<<' ![=] skip
LARROW2PIPE <- '<<|' ![=] skip
LARROW2PIPEEQUAL <- '<<|=' ![=] skip
LARROW2EQUAL <- '<<=' skip
LARROWEQUAL <- '<=' skip
LBRACE <- '{' skip
LBRACKET <- '[' skip
LPAREN <- '(' skip
MINUS <- '-' ![%=>] skip
MINUSEQUAL <- '-=' skip
MINUSPERCENT <- '-%' ![=] skip
MINUSPERCENTEQUAL <- '-%=' skip
MINUSPIPE <- '-|' ![=] skip
MINUSPIPEEQUAL <- '-|=' skip
MINUSRARROW <- '->' skip
PERCENT <- '%' ![=] skip
PERCENTEQUAL <- '%=' skip
PIPE <- '|' ![|=] skip
PIPE2 <- '||' skip
PIPEEQUAL <- '|=' skip
PLUS <- '+' ![%+=] skip
PLUS2 <- '++' skip
PLUSEQUAL <- '+=' skip
PLUSPERCENT <- '+%' ![=] skip
PLUSPERCENTEQUAL <- '+%=' skip
PLUSPIPE <- '+|' ![=] skip
PLUSPIPEEQUAL <- '+|=' skip
LETTERC <- 'c' skip
QUESTIONMARK <- '?' skip
RARROW <- '>' ![>=] skip
RARROW2 <- '>>' ![=] skip
RARROW2EQUAL <- '>>=' skip
RARROWEQUAL <- '>=' skip
RBRACE <- '}' skip
RBRACKET <- ']' skip
RPAREN <- ')' skip
SEMICOLON <- ';' skip
SLASH <- '/' ![=] skip
SLASHEQUAL <- '/=' skip
TILDE <- '~' skip
end_of_word <- ![a-zA-Z0-9_] skip
KEYWORD_align <- 'align' end_of_word
KEYWORD_allowzero <- 'allowzero' end_of_word
KEYWORD_and <- 'and' end_of_word
KEYWORD_anyframe <- 'anyframe' end_of_word
KEYWORD_anytype <- 'anytype' end_of_word
KEYWORD_asm <- 'asm' end_of_word
KEYWORD_async <- 'async' end_of_word
KEYWORD_await <- 'await' end_of_word
KEYWORD_break <- 'break' end_of_word
KEYWORD_callconv <- 'callconv' end_of_word
KEYWORD_catch <- 'catch' end_of_word
KEYWORD_comptime <- 'comptime' end_of_word
KEYWORD_const <- 'const' end_of_word
KEYWORD_continue <- 'continue' end_of_word
KEYWORD_defer <- 'defer' end_of_word
KEYWORD_else <- 'else' end_of_word
KEYWORD_enum <- 'enum' end_of_word
KEYWORD_errdefer <- 'errdefer' end_of_word
KEYWORD_error <- 'error' end_of_word
KEYWORD_export <- 'export' end_of_word
KEYWORD_extern <- 'extern' end_of_word
KEYWORD_fn <- 'fn' end_of_word
KEYWORD_for <- 'for' end_of_word
KEYWORD_if <- 'if' end_of_word
KEYWORD_inline <- 'inline' end_of_word
KEYWORD_noalias <- 'noalias' end_of_word
KEYWORD_nosuspend <- 'nosuspend' end_of_word
KEYWORD_noinline <- 'noinline' end_of_word
KEYWORD_opaque <- 'opaque' end_of_word
KEYWORD_or <- 'or' end_of_word
KEYWORD_orelse <- 'orelse' end_of_word
KEYWORD_packed <- 'packed' end_of_word
KEYWORD_pub <- 'pub' end_of_word
KEYWORD_resume <- 'resume' end_of_word
KEYWORD_return <- 'return' end_of_word
KEYWORD_linksection <- 'linksection' end_of_word
KEYWORD_struct <- 'struct' end_of_word
KEYWORD_suspend <- 'suspend' end_of_word
KEYWORD_switch <- 'switch' end_of_word
KEYWORD_test <- 'test' end_of_word
KEYWORD_threadlocal <- 'threadlocal' end_of_word
KEYWORD_try <- 'try' end_of_word
KEYWORD_union <- 'union' end_of_word
KEYWORD_unreachable <- 'unreachable' end_of_word
KEYWORD_usingnamespace <- 'usingnamespace' end_of_word
KEYWORD_var <- 'var' end_of_word
KEYWORD_volatile <- 'volatile' end_of_word
KEYWORD_while <- 'while' end_of_word
keyword <- KEYWORD_align / KEYWORD_allowzero / KEYWORD_and / KEYWORD_anyframe
/ KEYWORD_anytype / KEYWORD_asm / KEYWORD_async / KEYWORD_await
/ KEYWORD_break / KEYWORD_callconv / KEYWORD_catch / KEYWORD_comptime
/ KEYWORD_const / KEYWORD_continue / KEYWORD_defer / KEYWORD_else
/ KEYWORD_enum / KEYWORD_errdefer / KEYWORD_error / KEYWORD_export
/ KEYWORD_extern / KEYWORD_fn / KEYWORD_for / KEYWORD_if
/ KEYWORD_inline / KEYWORD_noalias / KEYWORD_nosuspend / KEYWORD_noinline
/ KEYWORD_opaque / KEYWORD_or / KEYWORD_orelse / KEYWORD_packed
/ KEYWORD_pub / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
/ KEYWORD_struct / KEYWORD_suspend / KEYWORD_switch / KEYWORD_test
/ KEYWORD_threadlocal / KEYWORD_try / KEYWORD_union / KEYWORD_unreachable
/ KEYWORD_usingnamespace / KEYWORD_var / KEYWORD_volatile / KEYWORD_while

@ -1,29 +0,0 @@
{
"name": "tree-sitter-zig",
"version": "0.0.1",
"description": "zig grammar for tree-sitter",
"main": "bindings/node",
"keywords": [
"parsing",
"incremental"
],
"dependencies": {
"nan": "^2.12.1"
},
"devDependencies": {
"tree-sitter-cli": "^0.20.1"
},
"scripts": {
"test": "tree-sitter test"
}
,
"tree-sitter": [
{
"scope": "source.zig",
"injection-regex": "zig",
"file-types": [
"zig"
]
}
]
}

@ -1,16 +0,0 @@
[
(Block)
(ContainerDecl)
(SwitchExpr)
(InitList)
(AsmExpr)
(ErrorSetDecl)
(LINESTRING)
(
[
(IfPrefix)
(WhilePrefix)
(ForPrefix)
]
)
] @fold

@ -1,234 +0,0 @@
[
(container_doc_comment)
(doc_comment)
(line_comment)
] @comment
[
variable: (IDENTIFIER)
variable_type_function: (IDENTIFIER)
] @variable
parameter: (IDENTIFIER) @parameter
[
field_member: (IDENTIFIER)
field_access: (IDENTIFIER)
] @field
;; assume TitleCase is a type
(
[
variable_type_function: (IDENTIFIER)
field_access: (IDENTIFIER)
parameter: (IDENTIFIER)
] @type
(#match? @type "^[A-Z]([a-z]+[A-Za-z0-9]*)*$")
)
;; assume camelCase is a function
(
[
variable_type_function: (IDENTIFIER)
field_access: (IDENTIFIER)
parameter: (IDENTIFIER)
] @function
(#match? @function "^[a-z]+([A-Z][a-z0-9]*)+$")
)
;; assume all CAPS_1 is a constant
(
[
variable_type_function: (IDENTIFIER)
field_access: (IDENTIFIER)
] @constant
(#match? @constant "^[A-Z][A-Z_0-9]+$")
)
[
function_call: (IDENTIFIER)
function: (IDENTIFIER)
] @function
exception: "!" @exception
(
(IDENTIFIER) @variable.builtin
(#eq? @variable.builtin "_")
)
(PtrTypeStart "c" @variable.builtin)
(
(ContainerDeclType
[
(ErrorUnionExpr)
"enum"
]
)
(ContainerField (IDENTIFIER) @constant)
)
field_constant: (IDENTIFIER) @constant
(BUILTINIDENTIFIER) @function.builtin
((BUILTINIDENTIFIER) @include
(#any-of? @include "@import" "@cImport"))
(INTEGER) @number
(FLOAT) @float
[
(LINESTRING)
(STRINGLITERALSINGLE)
] @string
(CHAR_LITERAL) @character
(EscapeSequence) @string.escape
(FormatSequence) @string.special
[
"allowzero"
"volatile"
"anytype"
"anyframe"
(BuildinTypeExpr)
] @type.builtin
(BreakLabel (IDENTIFIER) @label)
(BlockLabel (IDENTIFIER) @label)
[
"true"
"false"
] @boolean
[
"undefined"
"unreachable"
"null"
] @constant.builtin
[
"else"
"if"
"switch"
] @conditional
[
"for"
"while"
] @repeat
[
"or"
"and"
"orelse"
] @keyword.operator
[
"struct"
"enum"
"union"
"error"
"packed"
"opaque"
] @keyword
[
"try"
"error"
"catch"
] @exception
; VarDecl
[
"const"
"var"
"comptime"
"threadlocal"
"fn"
] @keyword.function
[
"test"
"pub"
"usingnamespace"
] @keyword
[
"return"
"break"
"continue"
] @keyword.return
; Macro
[
"defer"
"errdefer"
"async"
"nosuspend"
"await"
"suspend"
"resume"
"export"
"extern"
] @function.macro
; PrecProc
[
"inline"
"noinline"
"asm"
"callconv"
"noalias"
] @attribute
[
"linksection"
"align"
] @function.builtin
[
(CompareOp)
(BitwiseOp)
(BitShiftOp)
(AdditionOp)
(AssignOp)
(MultiplyOp)
(PrefixOp)
"*"
"**"
"->"
".?"
".*"
"?"
] @operator
[
";"
"."
","
":"
] @punctuation.delimiter
[
".."
"..."
] @punctuation.special
[
"["
"]"
"("
")"
"{"
"}"
(Payload "|")
(PtrPayload "|")
(PtrIndexPayload "|")
] @punctuation.bracket
; Error
(ERROR) @error

@ -1,22 +0,0 @@
[
(Block)
(ContainerDecl)
(SwitchExpr)
(InitList)
] @indent
[
"("
")"
"["
"]"
"{"
"}"
] @branch
[
(line_comment)
(container_doc_comment)
(doc_comment)
(LINESTRING)
] @ignore

@ -1,5 +0,0 @@
[
(container_doc_comment)
(doc_comment)
(line_comment)
] @comment

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,224 +0,0 @@
#ifndef TREE_SITTER_PARSER_H_
#define TREE_SITTER_PARSER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#define ts_builtin_sym_error ((TSSymbol)-1)
#define ts_builtin_sym_end 0
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
typedef uint16_t TSStateId;
#ifndef TREE_SITTER_API_H_
typedef uint16_t TSSymbol;
typedef uint16_t TSFieldId;
typedef struct TSLanguage TSLanguage;
#endif
typedef struct {
TSFieldId field_id;
uint8_t child_index;
bool inherited;
} TSFieldMapEntry;
typedef struct {
uint16_t index;
uint16_t length;
} TSFieldMapSlice;
typedef struct {
bool visible;
bool named;
bool supertype;
} TSSymbolMetadata;
typedef struct TSLexer TSLexer;
struct TSLexer {
int32_t lookahead;
TSSymbol result_symbol;
void (*advance)(TSLexer *, bool);
void (*mark_end)(TSLexer *);
uint32_t (*get_column)(TSLexer *);
bool (*is_at_included_range_start)(const TSLexer *);
bool (*eof)(const TSLexer *);
};
typedef enum {
TSParseActionTypeShift,
TSParseActionTypeReduce,
TSParseActionTypeAccept,
TSParseActionTypeRecover,
} TSParseActionType;
typedef union {
struct {
uint8_t type;
TSStateId state;
bool extra;
bool repetition;
} shift;
struct {
uint8_t type;
uint8_t child_count;
TSSymbol symbol;
int16_t dynamic_precedence;
uint16_t production_id;
} reduce;
uint8_t type;
} TSParseAction;
typedef struct {
uint16_t lex_state;
uint16_t external_lex_state;
} TSLexMode;
typedef union {
TSParseAction action;
struct {
uint8_t count;
bool reusable;
} entry;
} TSParseActionEntry;
struct TSLanguage {
uint32_t version;
uint32_t symbol_count;
uint32_t alias_count;
uint32_t token_count;
uint32_t external_token_count;
uint32_t state_count;
uint32_t large_state_count;
uint32_t production_id_count;
uint32_t field_count;
uint16_t max_alias_sequence_length;
const uint16_t *parse_table;
const uint16_t *small_parse_table;
const uint32_t *small_parse_table_map;
const TSParseActionEntry *parse_actions;
const char * const *symbol_names;
const char * const *field_names;
const TSFieldMapSlice *field_map_slices;
const TSFieldMapEntry *field_map_entries;
const TSSymbolMetadata *symbol_metadata;
const TSSymbol *public_symbol_map;
const uint16_t *alias_map;
const TSSymbol *alias_sequences;
const TSLexMode *lex_modes;
bool (*lex_fn)(TSLexer *, TSStateId);
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
TSSymbol keyword_capture_token;
struct {
const bool *states;
const TSSymbol *symbol_map;
void *(*create)(void);
void (*destroy)(void *);
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
unsigned (*serialize)(void *, char *);
void (*deserialize)(void *, const char *, unsigned);
} external_scanner;
const TSStateId *primary_state_ids;
};
/*
* Lexer Macros
*/
#define START_LEXER() \
bool result = false; \
bool skip = false; \
bool eof = false; \
int32_t lookahead; \
goto start; \
next_state: \
lexer->advance(lexer, skip); \
start: \
skip = false; \
lookahead = lexer->lookahead;
#define ADVANCE(state_value) \
{ \
state = state_value; \
goto next_state; \
}
#define SKIP(state_value) \
{ \
skip = true; \
state = state_value; \
goto next_state; \
}
#define ACCEPT_TOKEN(symbol_value) \
result = true; \
lexer->result_symbol = symbol_value; \
lexer->mark_end(lexer);
#define END_STATE() return result;
/*
* Parse Table Macros
*/
#define SMALL_STATE(id) id - LARGE_STATE_COUNT
#define STATE(id) id
#define ACTIONS(id) id
#define SHIFT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = state_value \
} \
}}
#define SHIFT_REPEAT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = state_value, \
.repetition = true \
} \
}}
#define SHIFT_EXTRA() \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.extra = true \
} \
}}
#define REDUCE(symbol_val, child_count_val, ...) \
{{ \
.reduce = { \
.type = TSParseActionTypeReduce, \
.symbol = symbol_val, \
.child_count = child_count_val, \
__VA_ARGS__ \
}, \
}}
#define RECOVER() \
{{ \
.type = TSParseActionTypeRecover \
}}
#define ACCEPT_INPUT() \
{{ \
.type = TSParseActionTypeAccept \
}}
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_PARSER_H_