Add 'vendor/tree-sitter-rust/' from commit 'a360da0a29a19c281d08295a35ecd0544d2da211'

git-subtree-dir: vendor/tree-sitter-rust
git-subtree-mainline: e7a6c3b11e
git-subtree-split: a360da0a29
ida_star
Wilfred Hughes 2021-08-15 16:33:53 +07:00
commit 59f80c20dd
36 changed files with 145594 additions and 0 deletions

@ -0,0 +1,2 @@
/src/** linguist-vendored
/examples/* linguist-vendored

@ -0,0 +1,28 @@
name: Build/test
on:
push:
branches:
- "**"
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [macos-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 14
- run: npm install
- run: npm test
test_windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 14
- run: npm install
- run: npm run-script test-windows

@ -0,0 +1,8 @@
Cargo.lock
node_modules
build
*.log
package-lock.json
examples
!examples/ast.rs
/target/

@ -0,0 +1,5 @@
corpus
build
script
examples
target

@ -0,0 +1,29 @@
[package]
name = "tree-sitter-rust"
description = "Rust grammar for the tree-sitter parsing library"
version = "0.19.1"
authors = ["Max Brunsfeld <maxbrunsfeld@gmail.com>"]
license = "MIT"
readme = "bindings/rust/README.md"
keywords = ["incremental", "parsing", "rust"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/tree-sitter/tree-sitter-rust"
edition = "2018"
build = "bindings/rust/build.rs"
include = [
"bindings/rust/*",
"grammar.js",
"queries/*",
"src/*",
]
autoexamples = false
[lib]
path = "bindings/rust/lib.rs"
[dependencies]
tree-sitter = "0.19"
[build-dependencies]
cc = "1.0"

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Maxim Sokolov
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.

@ -0,0 +1,28 @@
# tree-sitter-rust
[![Build/test](https://github.com/tree-sitter/tree-sitter-rust/actions/workflows/ci.yml/badge.svg)](https://github.com/tree-sitter/tree-sitter-rust/actions/workflows/ci.yml)
Rust grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter)
## Features
* **Speed** - When initially parsing a file, `tree-sitter-rust` takes around twice as long as Rustc's hand-coded parser.
```sh
$ wc -l examples/ast.rs
2157 examples/ast.rs
$ rustc -Z ast-json-noexpand -Z time-passes examples/ast.rs | head -n1
time: 0.007 parsing # (7 ms)
$ tree-sitter parse examples/ast.rs --quiet --time
examples/ast.rs 16 ms
```
But if you *edit* the file after parsing it, this parser can generally *update* the previous existing syntax tree to reflect your edit in less than a millisecond, thanks to Tree-sitter's incremental parsing system.
## References
* [The Rust Grammar Reference](https://doc.rust-lang.org/grammar.html) - The grammar reference provides chapters that formally define the language grammar.
* [The Rust Reference](https://doc.rust-lang.org/reference/) - While Rust does not have a specification, the reference tries to describe its working in detail. It tends to be out of date.
* [Syntax Index](https://doc.rust-lang.org/book/first-edition/syntax-index.html) - This appendix from The Book contains examples of all syntax in Rust cross-referenced with the section of The Book that describes it.

@ -0,0 +1,19 @@
{
"targets": [
{
"target_name": "tree_sitter_rust_binding",
"include_dirs": [
"<!(node -e \"require('nan')\")",
"src"
],
"sources": [
"src/parser.c",
"src/scanner.c",
"bindings/node/binding.cc"
],
"cflags_c": [
"-std=c99",
]
}
]
}

@ -0,0 +1,28 @@
#include "tree_sitter/parser.h"
#include <node.h>
#include "nan.h"
using namespace v8;
extern "C" TSLanguage * tree_sitter_rust();
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_rust());
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("rust").ToLocalChecked());
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
}
NODE_MODULE(tree_sitter_rust_binding, Init)
} // namespace

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

@ -0,0 +1,37 @@
# tree-sitter-rust
This crate provides a Rust grammar for the [tree-sitter][] parsing library. To
use this crate, add it to the `[dependencies]` section of your `Cargo.toml`
file. (Note that you will probably also need to depend on the
[`tree-sitter`][tree-sitter crate] crate to use the parsed result in any useful
way.)
``` toml
[dependencies]
tree-sitter = "0.17"
tree-sitter-rust = "0.16"
```
Typically, you will use the [language][language func] function to add this
grammar to a tree-sitter [Parser][], and then use the parser to parse some code:
``` rust
let code = r#"
fn double(x: i32) -> i32 {
x * 2
}
"#;
let mut parser = Parser::new();
parser.set_language(tree_sitter_rust::language()).expect("Error loading Rust grammar");
let parsed = parser.parse(code, None);
```
If you have any questions, please reach out to us in the [tree-sitter
discussions] page.
[Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
[language func]: https://docs.rs/tree-sitter-rust/*/tree_sitter_rust/fn.language.html
[Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
[tree-sitter]: https://tree-sitter.github.io/
[tree-sitter crate]: https://crates.io/crates/tree-sitter
[tree-sitter discussions]: https://github.com/tree-sitter/tree-sitter/discussions

@ -0,0 +1,16 @@
fn main() {
let src_dir = std::path::Path::new("src");
let mut config = cc::Build::new();
config.include(&src_dir);
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");
let scanner_path = src_dir.join("scanner.c");
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
config.file(&parser_path);
config.file(&scanner_path);
config.compile("parser-scanner");
}

@ -0,0 +1,66 @@
// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2021, tree-sitter-rust authors.
// See the LICENSE file in this repo for license details.
// ------------------------------------------------------------------------------------------------
//! This crate provides a Rust grammar for the [tree-sitter][] parsing library.
//!
//! Typically, you will use the [language][language func] function to add this grammar to a
//! tree-sitter [Parser][], and then use the parser to parse some code:
//!
//! ```
//! use tree_sitter::Parser;
//!
//! let code = r#"
//! fn double(x: i32) -> i32 {
//! x * 2
//! }
//! "#;
//! let mut parser = Parser::new();
//! parser.set_language(tree_sitter_rust::language()).expect("Error loading Rust grammar");
//! let parsed = parser.parse(code, None);
//! # let parsed = parsed.unwrap();
//! # let root = parsed.root_node();
//! # assert!(!root.has_error());
//! ```
//!
//! [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_rust() -> Language;
}
/// Returns 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_rust() }
}
/// The source of the Rust tree-sitter grammar description.
pub const GRAMMAR: &str = include_str!("../../grammar.js");
/// The syntax highlighting query for this language.
pub const HIGHLIGHT_QUERY: &str = include_str!("../../queries/highlights.scm");
/// 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: &str = include_str!("../../src/node-types.json");
#[cfg(test)]
mod tests {
#[test]
fn can_load_grammar() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(super::language())
.expect("Error loading Rust grammar");
}
}

@ -0,0 +1,71 @@
============================================
Async function
============================================
async fn abc() {}
async fn main() {
let x = futures.await?;
}
---
(source_file
(function_item
(function_modifiers)
(identifier)
(parameters)
(block))
(function_item (function_modifiers) (identifier) (parameters)
(block
(let_declaration (identifier) (try_expression
(await_expression (identifier)))))))
============================================
Await expression
============================================
futures.await;
futures.await?;
futures.await?.await?;
futures.await?.function().await?;
---
(source_file
(await_expression (identifier))
(try_expression
(await_expression (identifier)))
(try_expression
(await_expression
(try_expression
(await_expression (identifier)))))
(try_expression
(await_expression
(call_expression
(field_expression
(try_expression
(await_expression (identifier)))
(field_identifier))
(arguments)))))
============================================
Async Block
============================================
async {}
async { let x = 10; }
async move {}
---
(source_file
(async_block
(block))
(async_block
(block
(let_declaration
(identifier)
(integer_literal))))
(async_block
(block)))

File diff suppressed because it is too large Load Diff

@ -0,0 +1,817 @@
============================================
Identifiers
============================================
fn main() {
abc;
}
---
(source_file
(function_item (identifier) (parameters) (block
(identifier))))
============================================
Raw identifiers
============================================
fn main() {
(r#abc as r#Def).r#ghi;
}
---
(source_file
(function_item
(identifier)
(parameters)
(block
(field_expression
(parenthesized_expression
(type_cast_expression (identifier) (type_identifier)))
(field_identifier)))))
============================================
Unary operator expressions
============================================
-num;
!bits;
*boxed_thing;
---
(source_file
(unary_expression (identifier))
(unary_expression (identifier))
(unary_expression (identifier)))
============================================
Reference expressions
============================================
&a;
&mut self.name;
---
(source_file
(reference_expression (identifier))
(reference_expression (mutable_specifier) (field_expression (self) (field_identifier))))
============================================
Try expressions
============================================
a.unwrap()?;
---
(source_file
(try_expression (call_expression (field_expression (identifier) (field_identifier)) (arguments))))
============================================
Binary operator expressions
============================================
a * b;
a / b;
a % b;
a + b;
a - b;
a >> b;
a << b;
a == b;
a && b;
a || b;
---
(source_file
(binary_expression (identifier) (identifier))
(binary_expression (identifier) (identifier))
(binary_expression (identifier) (identifier))
(binary_expression (identifier) (identifier))
(binary_expression (identifier) (identifier))
(binary_expression (identifier) (identifier))
(binary_expression (identifier) (identifier))
(binary_expression (identifier) (identifier))
(binary_expression (identifier) (identifier))
(binary_expression (identifier) (identifier)))
============================================
Grouped expressions
============================================
(0);
(2 * (3 + 4));
---
(source_file
(parenthesized_expression (integer_literal))
(parenthesized_expression (binary_expression
(integer_literal)
(parenthesized_expression (binary_expression (integer_literal) (integer_literal))))))
============================================
Range expressions
============================================
1..2;
3..;
..4;
..;
1..b;
a..b;
1..(1);
(1)..1;
(1)..(1);
---
(source_file
(range_expression (integer_literal) (integer_literal))
(range_expression (integer_literal))
(range_expression (integer_literal))
(range_expression)
(range_expression (integer_literal) (identifier))
(range_expression (identifier) (identifier))
(range_expression
(integer_literal)
(parenthesized_expression (integer_literal)))
(range_expression
(parenthesized_expression (integer_literal))
(integer_literal))
(range_expression
(parenthesized_expression (integer_literal))
(parenthesized_expression (integer_literal))))
============================================
Assignment expressions
============================================
x = y;
---
(source_file
(assignment_expression
left: (identifier)
right: (identifier)))
============================================
Compound assignment expressions
============================================
x += 1;
x += y;
---
(source_file
(compound_assignment_expr
left: (identifier)
right: (integer_literal))
(compound_assignment_expr
left: (identifier)
right: (identifier)))
============================================
Type cast expressions
============================================
1000 as u8;
let character = integer as char;
let size: f64 = len(values) as f64;
---
(source_file
(type_cast_expression
value: (integer_literal)
type: (primitive_type))
(let_declaration
pattern: (identifier)
value: (type_cast_expression
value: (identifier)
type: (primitive_type)))
(let_declaration
pattern: (identifier)
type: (primitive_type)
value: (type_cast_expression
value: (call_expression
function: (identifier)
arguments: (arguments (identifier)))
type: (primitive_type))))
============================================
Call expressions
============================================
foo();
add(1i32, 2i32);
add(
1i32,
2i32,
);
---
(source_file
(call_expression
function: (identifier)
arguments: (arguments))
(call_expression
function: (identifier)
arguments: (arguments (integer_literal) (integer_literal)))
(call_expression
function: (identifier)
arguments: (arguments (integer_literal) (integer_literal))))
============================================
Array expressions
============================================
[];
[1, 2, 3];
["a", "b", "c"];
[0; 128];
---
(source_file
(array_expression)
(array_expression
(integer_literal)
(integer_literal)
(integer_literal))
(array_expression
(string_literal)
(string_literal)
(string_literal))
(array_expression
(integer_literal)
length: (integer_literal)))
============================================
Tuple expressions
============================================
();
(0,);
let (x, y, z) = (1, 2, 3);
---
(source_file
(unit_expression)
(tuple_expression (integer_literal))
(let_declaration
(tuple_pattern (identifier) (identifier) (identifier))
(tuple_expression (integer_literal) (integer_literal) (integer_literal))))
============================================
Struct expressions
============================================
NothingInMe {};
Point {x: 10.0, y: 20.0};
let a = SomeStruct { field1, field2: expression, field3, };
let u = game::User {name: "Joe", age: 35, score: 100_000};
---
(source_file
(struct_expression (type_identifier)
(field_initializer_list))
(struct_expression (type_identifier)
(field_initializer_list
(field_initializer (field_identifier) (float_literal))
(field_initializer (field_identifier) (float_literal))))
(let_declaration
(identifier)
(struct_expression
(type_identifier)
(field_initializer_list
(shorthand_field_initializer
(identifier))
(field_initializer (field_identifier) (identifier))
(shorthand_field_initializer
(identifier)))))
(let_declaration
(identifier)
(struct_expression
(scoped_type_identifier (identifier) (type_identifier))
(field_initializer_list
(field_initializer (field_identifier) (string_literal))
(field_initializer (field_identifier) (integer_literal))
(field_initializer (field_identifier) (integer_literal))))))
============================================
Struct expressions with update initializers
============================================
let u = User{name, ..current_user()};
---
(source_file
(let_declaration
(identifier)
(struct_expression
(type_identifier)
(field_initializer_list
(shorthand_field_initializer
(identifier))
(base_field_initializer (call_expression (identifier) (arguments)))))))
============================================
If expressions
============================================
fn main() {
if n == 1 {
} else if n == 2 {
} else {
}
}
let y = if x == 5 { 10 } else { 15 };
---
(source_file
(function_item
name: (identifier)
parameters: (parameters)
body: (block
(if_expression
condition: (binary_expression
left: (identifier)
right: (integer_literal))
consequence: (block)
alternative: (else_clause
(if_expression
condition: (binary_expression
left: (identifier)
right: (integer_literal))
consequence: (block)
alternative: (else_clause (block)))))))
(let_declaration
pattern: (identifier)
value: (if_expression
condition: (binary_expression
left: (identifier)
right: (integer_literal))
consequence: (block (integer_literal))
alternative: (else_clause (block (integer_literal))))))
============================================
If let expressions
============================================
if let ("Bacon", b) = dish {
}
---
(source_file
(if_let_expression
(tuple_pattern (string_literal) (identifier))
(identifier)
(block)))
============================================
While let expressions
============================================
while let ("Bacon", b) = dish {
}
---
(source_file
(while_let_expression
(tuple_pattern (string_literal) (identifier))
(identifier)
(block)))
============================================
Match expressions
============================================
match x {
1 => { "one" }
2 => "two",
-1 => 1,
-3.14 => 3,
#[attr1]
3 => "three",
macro!(4) => "four",
_ => "something else",
}
let msg = match x {
0 | 1 | 10 => "one of zero, one, or ten",
y if y < 20 => "less than 20, but not zero, one, or ten",
y if y == 200 =>
if a {
"200 (but this is not very stylish)"
}
_ => "something else",
};
---
(source_file
(match_expression
value: (identifier)
body: (match_block
(match_arm
pattern: (match_pattern
(integer_literal))
value: (block
(string_literal)))
(match_arm
pattern: (match_pattern
(integer_literal))
value: (string_literal))
(match_arm
pattern: (match_pattern
(negative_literal
(integer_literal)))
value: (integer_literal))
(match_arm
pattern: (match_pattern
(negative_literal
(float_literal)))
value: (integer_literal))
(match_arm
(attribute_item
(meta_item
(identifier)))
pattern: (match_pattern
(integer_literal))
value: (string_literal))
(match_arm
pattern: (macro_invocation
macro: (identifier)
(token_tree
(integer_literal)))
value: (string_literal))
(match_arm
pattern: (match_pattern)
value: (string_literal))))
(let_declaration
pattern: (identifier)
value: (match_expression
value: (identifier)
body: (match_block
(match_arm
pattern: (match_pattern
(or_pattern
(or_pattern
(integer_literal)
(integer_literal))
(integer_literal)))
value: (string_literal))
(match_arm
pattern: (match_pattern
(identifier)
condition: (binary_expression
left: (identifier)
right: (integer_literal)))
value: (string_literal))
(match_arm
pattern: (match_pattern
(identifier)
condition: (binary_expression
left: (identifier)
right: (integer_literal)))
value: (if_expression
condition: (identifier)
consequence: (block
(string_literal))))
(match_arm
pattern: (match_pattern)
value: (string_literal))))))
============================================
While expressions
============================================
while !done {
done = true;
}
---
(source_file
(while_expression
condition: (unary_expression (identifier))
body: (block
(assignment_expression
left: (identifier)
right: (boolean_literal)))))
============================================
Loop expressions
============================================
'outer: loop {
'inner: loop {
break 'outer;
break true;
}
}
---
(source_file
(loop_expression (loop_label (identifier)) (block
(loop_expression (loop_label (identifier)) (block
(break_expression (loop_label (identifier)))
(break_expression (boolean_literal)))))))
============================================
For expressions
============================================
for e in v {
bar(e);
}
for i in 0..256 {
bar(i);
}
'outer: for x in 0..10 {
'inner: for y in 0..10 {
if x % 2 == 0 { continue 'outer; }
if y % 2 == 0 { continue 'inner; }
}
}
---
(source_file
(for_expression (identifier) (identifier) (block
(call_expression (identifier) (arguments (identifier)))))
(for_expression (identifier) (range_expression (integer_literal) (integer_literal)) (block
(call_expression (identifier) (arguments (identifier)))))
(for_expression (loop_label (identifier)) (identifier) (range_expression (integer_literal) (integer_literal)) (block
(for_expression (loop_label (identifier)) (identifier) (range_expression (integer_literal) (integer_literal)) (block
(if_expression (binary_expression (binary_expression (identifier) (integer_literal)) (integer_literal)) (block
(continue_expression (loop_label (identifier)))))
(if_expression (binary_expression (binary_expression (identifier) (integer_literal)) (integer_literal)) (block
(continue_expression (loop_label (identifier))))))))))
============================================
Field expressions
============================================
mystruct.myfield;
foo().x;
value.0.1.iter();
1.max(2);
---
(source_file
(field_expression (identifier) (field_identifier))
(field_expression (call_expression (identifier) (arguments)) (field_identifier))
(call_expression
(field_expression
(field_expression (field_expression (identifier) (integer_literal)) (integer_literal))
(field_identifier))
(arguments))
(call_expression
(field_expression (integer_literal) (field_identifier)) (arguments (integer_literal))))
============================================
Method call expressions
============================================
mystruct.foo();
---
(source_file (call_expression (field_expression (identifier) (field_identifier)) (arguments)))
============================================
Index expressions
============================================
([1, 2, 3, 4])[0];
arr[10];
arr[n];
---
(source_file
(index_expression
(parenthesized_expression
(array_expression (integer_literal) (integer_literal) (integer_literal) (integer_literal)))
(integer_literal))
(index_expression (identifier) (integer_literal))
(index_expression (identifier) (identifier)))
============================================
Scoped functions
============================================
a::b();
C::<D>::e();
::f();
::g::h();
---
(source_file
(call_expression
(scoped_identifier (identifier) (identifier))
(arguments))
(call_expression
(scoped_identifier
(generic_type (type_identifier) (type_arguments (type_identifier)))
(identifier))
(arguments))
(call_expression (scoped_identifier (identifier)) (arguments))
(call_expression (scoped_identifier (scoped_identifier (identifier)) (identifier)) (arguments)))
============================================
Scoped functions with fully qualified syntax
============================================
<Dog as Animal>::eat(d);
---
(source_file
(call_expression
(scoped_identifier
(bracketed_type (qualified_type (type_identifier) (type_identifier)))
(identifier))
(arguments (identifier))))
============================================
Scoped functions with macros as types
============================================
<Token![]>::foo();
---
(source_file
(call_expression
(scoped_identifier
(bracketed_type (macro_invocation
(identifier)
(token_tree)))
(identifier))
(arguments)))
============================================
Generic functions
============================================
std::sizeof::<u32>();
foo::<8>();
---
(source_file
(call_expression
function: (generic_function
function: (scoped_identifier
path: (identifier)
name: (identifier))
type_arguments: (type_arguments
(primitive_type)))
arguments: (arguments))
(call_expression
function: (generic_function
function: (identifier)
type_arguments: (type_arguments
(integer_literal)))
arguments: (arguments)))
===========================================
Closures
===========================================
a.map(|(b, c)| b.push(c));
d.map(move |mut e| {
f(e);
g(e)
});
h(|| -> i { j });
---
(source_file
(call_expression
(field_expression (identifier) (field_identifier))
(arguments
(closure_expression
(closure_parameters (tuple_pattern (identifier) (identifier)))
(call_expression
(field_expression (identifier) (field_identifier))
(arguments (identifier))))))
(call_expression
(field_expression (identifier) (field_identifier))
(arguments
(closure_expression
(closure_parameters (mut_pattern (mutable_specifier) (identifier)))
(block
(call_expression (identifier) (arguments (identifier)))
(call_expression (identifier) (arguments (identifier)))))))
(call_expression
(identifier)
(arguments
(closure_expression
(closure_parameters)
(type_identifier)
(block (identifier))))))
===========================================
Closures with typed parameteres
===========================================
a.map(|b: usize| b.push(c));
---
(source_file
(call_expression
(field_expression (identifier) (field_identifier))
(arguments (closure_expression
(closure_parameters (parameter (identifier) (primitive_type)))
(call_expression (field_expression (identifier) (field_identifier)) (arguments (identifier)))))))
===========================================
Unsafe blocks
===========================================
const a : A = unsafe { foo() };
---
(source_file
(const_item
(identifier)
(type_identifier)
(unsafe_block (block (call_expression (identifier) (arguments))))))
===========================================
Inline const or Const blocks as expression
===========================================
const { 1 + 3 };
if *x < 0 { const { &4i32.pow(4) } } else { x }
let three_ranges = [const { (0..=5).into_inner() }; 3];
---
(source_file
(const_block
body: (block
(binary_expression
left: (integer_literal)
right: (integer_literal))))
(empty_statement)
(if_expression
condition: (binary_expression
left: (unary_expression
(identifier))
right: (integer_literal))
consequence: (block
(const_block
body: (block
(reference_expression
value: (call_expression
function: (field_expression
value: (integer_literal)
field: (field_identifier))
arguments: (arguments
(integer_literal)))))))
alternative: (else_clause
(block
(identifier))))
(let_declaration
pattern: (identifier)
value: (array_expression
(const_block
body: (block
(call_expression
function: (field_expression
value: (parenthesized_expression
(range_expression
(integer_literal)
(integer_literal)))
field: (field_identifier))
arguments: (arguments))))
length: (integer_literal))))

@ -0,0 +1,142 @@
============================================
Integer literals
============================================
0;
0___0;
123;
0usize;
123i32;
123u32;
123_u32;
0xff_u8;
0o70_i16;
0b1111_1111_1001_0000_i32;
1u128;
---
(source_file
(integer_literal)
(integer_literal)
(integer_literal)
(integer_literal)
(integer_literal)
(integer_literal)
(integer_literal)
(integer_literal)
(integer_literal)
(integer_literal)
(integer_literal))
============================================
Floating-point literals
============================================
123.123;
2.;
123.0f64;
0.1f64;
0.1f32;
12E+99_f64;
---
(source_file
(float_literal)
(float_literal)
(float_literal)
(float_literal)
(float_literal)
(float_literal))
============================================
String literals
============================================
"";
"abc";
b"foo\nbar";
"foo\
bar";
"\"foo\"";
"/* foo bar */ foo bar";
"foo\x42\x43bar";
"foo \x42 \x43 bar";
---
(source_file
(string_literal)
(string_literal)
(string_literal (escape_sequence))
(string_literal (escape_sequence))
(string_literal (escape_sequence) (escape_sequence))
(string_literal)
(string_literal (escape_sequence) (escape_sequence))
(string_literal (escape_sequence) (escape_sequence)))
============================================
Raw string literals
============================================
r#"abc"#; r##"ok"##;
r##"foo #"# bar"##;
r###"foo ##"## bar"###;
r######"foo ##### bar"######;
---
(source_file
(raw_string_literal)
(raw_string_literal)
(raw_string_literal)
(raw_string_literal)
(raw_string_literal))
============================================
Raw byte string literals
============================================
br#"abc"#;
br##"abc"##;
---
(source_file
(raw_string_literal)
(raw_string_literal))
============================================
Character literals
============================================
'a';
'\'';
'\0';
b'x';
'\t';
'\xff';
'\\';
---
(source_file
(char_literal)
(char_literal)
(char_literal)
(char_literal)
(char_literal)
(char_literal)
(char_literal))
============================================
Boolean literals
============================================
true;
false;
---
(source_file (boolean_literal) (boolean_literal))

@ -0,0 +1,184 @@
============================================
Macro invocation - no arguments
============================================
a!();
b![];
c!{};
d::e!();
f::g::h!{};
---
(source_file
(macro_invocation (identifier) (token_tree))
(macro_invocation (identifier) (token_tree))
(macro_invocation (identifier) (token_tree))
(macro_invocation (scoped_identifier (identifier) (identifier)) (token_tree))
(macro_invocation (scoped_identifier (scoped_identifier (identifier) (identifier)) (identifier)) (token_tree)))
============================================
Macro invocation - arbitrary tokens
============================================
a!(* a *);
a!(& a &);
a!(- a -);
a!(b + c + +);
a!('a'..='z');
a!('\u{0}'..='\u{2}');
a!('lifetime)
default!(a);
union!(a);
----
(source_file
(macro_invocation
(identifier)
(token_tree (identifier)))
(macro_invocation
(identifier)
(token_tree (identifier)))
(macro_invocation
(identifier)
(token_tree (identifier)))
(macro_invocation
(identifier)
(token_tree (identifier) (identifier)))
(macro_invocation
(identifier)
(token_tree (char_literal) (char_literal)))
(macro_invocation
(identifier)
(token_tree (char_literal) (char_literal)))
(macro_invocation
(identifier)
(token_tree (identifier)))
(macro_invocation
(identifier)
(token_tree (identifier)))
(macro_invocation
(identifier)
(token_tree (identifier))))
=====================================
Macro invocation with comments
=====================================
ok! {
// one
/* two */
}
---
(source_file
(macro_invocation
(identifier)
(token_tree (line_comment) (block_comment))))
============================================
Macro definition
============================================
macro_rules! say_hello {
() => (
println!("Hello!");
)
}
macro_rules! four {
() => {1 + 3};
}
macro_rules! foo {
(x => $e:expr) => (println!("mode X: {}", $e));
(y => $e:expr) => (println!("mode Y: {}", $e))
}
macro_rules! o_O {
(
$($x:expr; [ $( $y:expr ),* ]);*
) => {
$($($x + $e),*),*
}
}
macro_rules! zero_or_one {
($($e:expr),?) => {
$($e),?
};
}
----
(source_file
(macro_definition
name: (identifier)
(macro_rule
left: (token_tree_pattern)
right: (token_tree
(identifier)
(token_tree
(string_literal)))))
(macro_definition
name: (identifier)
(macro_rule
left: (token_tree_pattern)
right: (token_tree
(integer_literal)
(integer_literal))))
(macro_definition
name: (identifier)
(macro_rule
left: (token_tree_pattern
(identifier)
(token_binding_pattern
name: (metavariable)
type: (fragment_specifier)))
right: (token_tree
(identifier)
(token_tree
(string_literal)
(metavariable))))
(macro_rule
left: (token_tree_pattern
(identifier)
(token_binding_pattern
name: (metavariable)
type: (fragment_specifier)))
right: (token_tree
(identifier)
(token_tree
(string_literal)
(metavariable)))))
(macro_definition
name: (identifier)
(macro_rule
left: (token_tree_pattern
(token_repetition_pattern
(token_binding_pattern
name: (metavariable)
type: (fragment_specifier))
(token_tree_pattern
(token_repetition_pattern
(token_binding_pattern
name: (metavariable)
type: (fragment_specifier))))))
right: (token_tree
(token_repetition
(token_repetition
(metavariable)
(metavariable))))))
(macro_definition
name: (identifier)
(macro_rule
left: (token_tree_pattern
(token_repetition_pattern
(token_binding_pattern
name: (metavariable)
type: (fragment_specifier))))
right: (token_tree
(token_repetition
(metavariable))))))

@ -0,0 +1,391 @@
=================================
Tuple struct patterns
=================================
match x {
Some(x) => "some",
std::None() => "none"
}
---
(source_file
(match_expression (identifier) (match_block
(match_arm
(match_pattern (tuple_struct_pattern (identifier) (identifier)))
(string_literal))
(match_arm
(match_pattern (tuple_struct_pattern (scoped_identifier (identifier) (identifier))))
(string_literal)))))
=================================
Reference patterns
=================================
match x {
A(ref x) => x.0,
ref mut y => y,
& mut z => z,
}
---
(source_file
(match_expression (identifier) (match_block
(match_arm
(match_pattern (tuple_struct_pattern (identifier) (ref_pattern (identifier))))
(field_expression (identifier) (integer_literal)))
(match_arm
(match_pattern (ref_pattern (mut_pattern (mutable_specifier) (identifier))))
(identifier))
(match_arm
(match_pattern (reference_pattern (mutable_specifier) (identifier)))
(identifier)))))
=================================
Struct patterns
=================================
match x {
Person{name, age} if age < 5 => ("toddler", name),
Person{name: adult_name, age: _} => ("adult", adult_name),
}
---
(source_file
(match_expression (identifier) (match_block
(match_arm
(match_pattern (struct_pattern
(type_identifier)
(field_pattern (shorthand_field_identifier))
(field_pattern (shorthand_field_identifier)))
(binary_expression (identifier) (integer_literal)))
(tuple_expression (string_literal) (identifier)))
(match_arm
(match_pattern
(struct_pattern
(type_identifier)
(field_pattern (field_identifier) (identifier))
(field_pattern (field_identifier))))
(tuple_expression (string_literal) (identifier))))))
=================================
Ignored patterns
=================================
match x {
(a, ..) => a,
B(..) => c,
D::E{f: g, ..} => g
}
---
(source_file
(match_expression (identifier) (match_block
(match_arm
(match_pattern
(tuple_pattern (identifier) (remaining_field_pattern)))
(identifier))
(match_arm
(match_pattern
(tuple_struct_pattern (identifier) (remaining_field_pattern)))
(identifier))
(match_arm
(match_pattern
(struct_pattern
(scoped_type_identifier (identifier) (type_identifier))
(field_pattern (field_identifier) (identifier))
(remaining_field_pattern)))
(identifier)))))
=================================
Captured patterns
=================================
match x {
a @ A(_) | b @ B(..) => a,
a @ 1 ... 5 => a,
Some(1 ... 5) => a,
a @ b...c => a,
a @ b..=c => a,
}
---
(source_file
(match_expression
value: (identifier)
body: (match_block
(match_arm
pattern: (match_pattern
(or_pattern
(captured_pattern
(identifier)
(tuple_struct_pattern
type: (identifier)))
(captured_pattern
(identifier)
(tuple_struct_pattern
type: (identifier)
(remaining_field_pattern)))))
value: (identifier))
(match_arm
pattern: (match_pattern
(captured_pattern
(identifier)
(range_pattern
(integer_literal)
(integer_literal))))
value: (identifier))
(match_arm
pattern: (match_pattern
(tuple_struct_pattern
type: (identifier)
(range_pattern
(integer_literal)
(integer_literal))))
value: (identifier))
(match_arm
pattern: (match_pattern
(captured_pattern
(identifier)
(range_pattern
(identifier)
(identifier))))
value: (identifier))
(match_arm
pattern: (match_pattern
(captured_pattern
(identifier)
(range_pattern
(identifier)
(identifier))))
value: (identifier)))))
=================================
Or patterns
=================================
if let A(x) | B(x) = expr {
do_stuff_with(x);
}
while let A(x) | B(x) = expr {
do_stuff_with(x);
}
let Ok(index) | Err(index) = slice.binary_search(&x);
for ref a | b in c {}
let Ok(x) | Err(x) = binary_search(x);
for A | B | C in c {}
|(Ok(x) | Err(x))| expr();
let ref mut x @ (A | B | C);
fn foo((1 | 2 | 3): u8) {}
// Discomment after box pattern land on master
// let box (A | B | C);
// Not handled cause devs didn't got into agreement if should be acceptd or not
// |Ok(x) | Err(x)| expr();
---
(source_file
(if_let_expression
pattern: (or_pattern
(tuple_struct_pattern
type: (identifier)
(identifier))
(tuple_struct_pattern
type: (identifier)
(identifier)))
value: (identifier)
consequence: (block
(call_expression
function: (identifier)
arguments: (arguments
(identifier)))))
(while_let_expression
pattern: (or_pattern
(tuple_struct_pattern
type: (identifier)
(identifier))
(tuple_struct_pattern
type: (identifier)
(identifier)))
value: (identifier)
body: (block
(call_expression
function: (identifier)
arguments: (arguments
(identifier)))))
(let_declaration
pattern: (or_pattern
(tuple_struct_pattern
type: (identifier)
(identifier))
(tuple_struct_pattern
type: (identifier)
(identifier)))
value: (call_expression
function: (field_expression
value: (identifier)
field: (field_identifier))
arguments: (arguments
(reference_expression
value: (identifier)))))
(for_expression
pattern: (or_pattern
(ref_pattern
(identifier))
(identifier))
value: (identifier)
body: (block))
(let_declaration
pattern: (or_pattern
(tuple_struct_pattern
type: (identifier)
(identifier))
(tuple_struct_pattern
type: (identifier)
(identifier)))
value: (call_expression
function: (identifier)
arguments: (arguments
(identifier))))
(for_expression
pattern: (or_pattern
(or_pattern
(identifier)
(identifier))
(identifier))
value: (identifier)
body: (block))
(closure_expression
parameters: (closure_parameters
(tuple_pattern
(or_pattern
(tuple_struct_pattern
type: (identifier)
(identifier))
(tuple_struct_pattern
type: (identifier)
(identifier)))))
body: (call_expression
function: (identifier)
arguments: (arguments)))
(let_declaration
pattern: (ref_pattern
(mut_pattern
(mutable_specifier)
(captured_pattern
(identifier)
(tuple_pattern
(or_pattern
(or_pattern
(identifier)
(identifier))
(identifier)))))))
(function_item
name: (identifier)
parameters: (parameters
(parameter
pattern: (tuple_pattern
(or_pattern
(or_pattern
(integer_literal)
(integer_literal))
(integer_literal)))
type: (primitive_type)))
body: (block))
(line_comment)
(line_comment)
(line_comment)
(line_comment))
===========================================
Inline const or Const blocks as pattern
===========================================
fn foo(x: i32) {
const CUBE: i32 = 3.pow(3);
match x {
CUBE => println!("three cubed"),
_ => {}
}
}
fn foo(x: i32) {
match x {
const { 3.pow(3) } => println!("three cubed"),
_ => {}
}
}
---
(source_file
(function_item
name: (identifier)
parameters: (parameters
(parameter
pattern: (identifier)
type: (primitive_type)))
body: (block
(const_item
name: (identifier)
type: (primitive_type)
value: (call_expression
function: (field_expression
value: (integer_literal)
field: (field_identifier))
arguments: (arguments
(integer_literal))))
(match_expression
value: (identifier)
body: (match_block
(match_arm
pattern: (match_pattern
(identifier))
value: (macro_invocation
macro: (identifier)
(token_tree
(string_literal))))
(match_arm
pattern: (match_pattern)
value: (block))))))
(function_item
name: (identifier)
parameters: (parameters
(parameter
pattern: (identifier)
type: (primitive_type)))
body: (block
(match_expression
value: (identifier)
body: (match_block
(match_arm
pattern: (match_pattern
(const_block
body: (block
(call_expression
function: (field_expression
value: (integer_literal)
field: (field_identifier))
arguments: (arguments
(integer_literal))))))
value: (macro_invocation
macro: (identifier)
(token_tree
(string_literal))))
(match_arm
pattern: (match_pattern)
value: (block)))))))

@ -0,0 +1,69 @@
============================================
Block comments
============================================
/*
* Block comments
*/
/* Comment with asterisks **/
----
(source_file
(block_comment)
(block_comment))
============================================
Nested block comments
============================================
/* /* double nested */ */
// ---
/*/*/* triple nested */*/*/
// ---
/****
/****
nested with extra stars
****/
****/
// ---
----
(source_file
(block_comment)
(line_comment)
(block_comment)
(line_comment)
(block_comment)
(line_comment))
============================================
Line comments
============================================
// Comment
----
(source_file
(line_comment))
=====================================
Greek letters in identifiers
=====================================
const σ1 : Σ = 0;
const ψ_2 : Ψ = 1;
---
(source_file
(const_item (identifier) (type_identifier) (integer_literal))
(const_item (identifier) (type_identifier) (integer_literal)))

@ -0,0 +1,237 @@
=====================
The unit type
=====================
type A = ();
---
(source_file
(type_item (type_identifier) (unit_type)))
=====================
Tuple types
=====================
type A = (i32, String);
---
(source_file
(type_item (type_identifier) (tuple_type (primitive_type) (type_identifier))))
=====================
Reference types
=====================
type A = &B;
type C = &'a str;
type D = &'a mut str;
---
(source_file
(type_item (type_identifier) (reference_type (type_identifier)))
(type_item (type_identifier) (reference_type (lifetime (identifier)) (primitive_type)))
(type_item (type_identifier) (reference_type (lifetime (identifier)) (mutable_specifier) (primitive_type))))
=====================
Raw pointer types
=====================
type A = *mut B;
type C = *const str;
---
(source_file
(type_item (type_identifier) (pointer_type (mutable_specifier) (type_identifier)))
(type_item (type_identifier) (pointer_type (primitive_type))))
=====================
Generic types
=====================
type A = B<C>;
type D = E<F, str>;
type G = H<'a, I>;
type J = H<K=L>;
---
(source_file
(type_item
(type_identifier)
(generic_type (type_identifier) (type_arguments (type_identifier))))
(type_item
(type_identifier)
(generic_type (type_identifier) (type_arguments (type_identifier) (primitive_type))))
(type_item
(type_identifier)
(generic_type (type_identifier) (type_arguments (lifetime (identifier)) (type_identifier))))
(type_item
(type_identifier)
(generic_type (type_identifier) (type_arguments (type_binding (type_identifier) (type_identifier))))))
=====================
Scoped types
=====================
type A = B::C;
type D = E::F::G;
type H = I::J<K>;
type L = M<N>::O;
---
(source_file
(type_item
(type_identifier)
(scoped_type_identifier (identifier) (type_identifier)))
(type_item
(type_identifier)
(scoped_type_identifier (scoped_identifier (identifier) (identifier)) (type_identifier)))
(type_item
(type_identifier)
(generic_type
(scoped_type_identifier (identifier) (type_identifier))
(type_arguments (type_identifier))))
(type_item
(type_identifier)
(scoped_type_identifier
(generic_type (type_identifier) (type_arguments (type_identifier)))
(type_identifier))))
=====================
Array types
=====================
type A = [B; 4];
type C = &[D];
---
(source_file
(type_item (type_identifier) (array_type (type_identifier) (integer_literal)))
(type_item (type_identifier) (reference_type (array_type (type_identifier)))))
============================
Function types
============================
fn high_order1(value: i32, f: fn(i32)) -> i32 {}
fn high_order2(value: i32, f: fn(i32) -> i32) -> i32 {
f(value)
}
fn high_order3(value: i32, f: &FnOnce(i32) -> i32) -> i32 {
f(value)
}
type F = for<'a, 'b> fn(x: &'a A, y: &'a mut B<'i, 't>,) -> C;
---
(source_file
(function_item
(identifier)
(parameters
(parameter (identifier) (primitive_type))
(parameter (identifier) (function_type (parameters (primitive_type)))))
(primitive_type)
(block))
(function_item
(identifier)
(parameters
(parameter (identifier) (primitive_type))
(parameter (identifier) (function_type (parameters (primitive_type)) (primitive_type))))
(primitive_type)
(block (call_expression (identifier) (arguments (identifier)))))
(function_item
(identifier)
(parameters
(parameter (identifier) (primitive_type))
(parameter (identifier) (reference_type (function_type (type_identifier) (parameters (primitive_type)) (primitive_type)))))
(primitive_type) (block (call_expression (identifier) (arguments (identifier)))))
(type_item
(type_identifier)
(function_type
(for_lifetimes (lifetime (identifier)) (lifetime (identifier)))
(parameters (parameter (identifier) (reference_type (lifetime (identifier)) (type_identifier))) (parameter (identifier) (reference_type (lifetime (identifier)) (mutable_specifier) (generic_type (type_identifier) (type_arguments (lifetime (identifier)) (lifetime (identifier)))))))
(type_identifier))))
=================================
Unsafe and extern function types
=================================
type a = extern "C" fn(*mut c_void);
type b = unsafe extern "C" fn() -> *mut c_void;
---
(source_file
(type_item
(type_identifier)
(function_type
(function_modifiers (extern_modifier (string_literal)))
(parameters (pointer_type (mutable_specifier) (type_identifier)))))
(type_item
(type_identifier)
(function_type
(function_modifiers (extern_modifier (string_literal)))
(parameters)
(pointer_type (mutable_specifier) (type_identifier)))))
===================================
Trait objects
===================================
type a = Box<Something + 'a>;
type b = Rc<dyn Something>;
type c = A<&dyn Fn(&B) -> C>;
---
(source_file
(type_item
(type_identifier)
(generic_type
(type_identifier)
(type_arguments (bounded_type (type_identifier) (lifetime (identifier))))))
(type_item
(type_identifier)
(generic_type
(type_identifier)
(type_arguments (dynamic_type (type_identifier)))))
(type_item
(type_identifier)
(generic_type
(type_identifier)
(type_arguments
(reference_type
(dynamic_type (function_type (type_identifier) (parameters (reference_type (type_identifier))) (type_identifier))))))))
====================================
Type cast expressions with generics
====================================
a as B<C>;
d as *mut E<<F as E>::G>;
---
(source_file
(type_cast_expression
(identifier)
(generic_type (type_identifier) (type_arguments (type_identifier))))
(type_cast_expression
(identifier)
(pointer_type
(mutable_specifier)
(generic_type
(type_identifier)
(type_arguments
(scoped_type_identifier
(bracketed_type (qualified_type (type_identifier) (type_identifier)))
(type_identifier)))))))

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,31 @@
{
"name": "tree-sitter-rust",
"version": "0.19.1",
"description": "Rust grammar for tree-sitter",
"main": "bindings/node",
"keywords": [
"parser",
"rust"
],
"author": "Maxim Sokolov <maxim0xff@gmail.com> (https://github.com/MaximSokolov)",
"license": "MIT",
"dependencies": {
"nan": "^2.14.0"
},
"devDependencies": {
"tree-sitter-cli": "^0.19.1"
},
"scripts": {
"test": "tree-sitter test && script/parse-examples",
"test-windows": "tree-sitter test"
},
"tree-sitter": [
{
"scope": "source.rust",
"injection-regex": "rust",
"file-types": [
"rs"
]
}
]
}

@ -0,0 +1,135 @@
; Identifier conventions
; Assume all-caps names are constants
((identifier) @constant
(#match? @constant "^[A-Z][A-Z\\d_]+$'"))
; Assume that uppercase names in paths are types
((scoped_identifier
path: (identifier) @type)
(#match? @type "^[A-Z]"))
((scoped_identifier
path: (scoped_identifier
name: (identifier) @type))
(#match? @type "^[A-Z]"))
; Assume other uppercase names are enum constructors
((identifier) @constructor
(#match? @constructor "^[A-Z]"))
; Function calls
(call_expression
function: (identifier) @function)
(call_expression
function: (field_expression
field: (field_identifier) @function.method))
(call_expression
function: (scoped_identifier
"::"
name: (identifier) @function))
(generic_function
function: (identifier) @function)
(generic_function
function: (scoped_identifier
name: (identifier) @function))
(generic_function
function: (field_expression
field: (field_identifier) @function.method))
(macro_invocation
macro: (identifier) @function.macro
"!" @function.macro)
; Function definitions
(function_item (identifier) @function)
(function_signature_item (identifier) @function)
; Other identifiers
(type_identifier) @type
(primitive_type) @type.builtin
(field_identifier) @property
(line_comment) @comment
(block_comment) @comment
"(" @punctuation.bracket
")" @punctuation.bracket
"[" @punctuation.bracket
"]" @punctuation.bracket
(type_arguments
"<" @punctuation.bracket
">" @punctuation.bracket)
(type_parameters
"<" @punctuation.bracket
">" @punctuation.bracket)
"::" @punctuation.delimiter
"." @punctuation.delimiter
";" @punctuation.delimiter
(parameter (identifier) @variable.parameter)
(lifetime (identifier) @label)
"break" @keyword
"const" @keyword
"continue" @keyword
"default" @keyword
"dyn" @keyword
"else" @keyword
"enum" @keyword
"extern" @keyword
"fn" @keyword
"for" @keyword
"if" @keyword
"impl" @keyword
"in" @keyword
"let" @keyword
"let" @keyword
"loop" @keyword
"macro_rules!" @keyword
"match" @keyword
"mod" @keyword
"move" @keyword
"pub" @keyword
"ref" @keyword
"return" @keyword
"static" @keyword
"struct" @keyword
"trait" @keyword
"type" @keyword
"union" @keyword
"unsafe" @keyword
"use" @keyword
"where" @keyword
"while" @keyword
(mutable_specifier) @keyword
(use_list (self) @keyword)
(scoped_use_list (self) @keyword)
(scoped_identifier (self) @keyword)
(super) @keyword
(self) @variable.builtin
(char_literal) @string
(string_literal) @string
(raw_string_literal) @string
(boolean_literal) @constant.builtin
(integer_literal) @constant.builtin
(float_literal) @constant.builtin
(escape_sequence) @escape
(attribute_item) @attribute
(inner_attribute_item) @attribute
"as" @operator
"*" @operator
"&" @operator
"'" @operator

@ -0,0 +1,9 @@
((macro_invocation
(token_tree) @injection.content)
(#set! injection.language "rust")
(#set! injection.include-children))
((macro_rule
(token_tree) @injection.content)
(#set! injection.language "rust")
(#set! injection.include-children))

@ -0,0 +1,21 @@
#!/bin/bash
set -e
function checkout() {
repo=$1; url=$2; sha=$3
if [ ! -d "$repo" ]; then
git clone "https://github.com/$url" "$repo"
fi
pushd "$repo"
git fetch && git reset --hard "$sha"
popd
}
checkout examples/bitflags rust-lang-nursery/bitflags 7ec3fe2d7cafb7f185c5785006efac94b88f42f0
checkout examples/libc rust-lang/libc 8318a3ec1c1f13aab21d0a74ac9a7cf618bb2261
checkout examples/regex rust-lang/regex.git 991ae1a4c69cd81ecf989119b9205a3204088e83
checkout examples/serde serde-rs/serde.git 4e54aaf7963c3580cc50b56842949b0ce6b3a997
checkout examples/tokio tokio-rs/tokio 0490280d662f000aff674593cc9a4f69a1cd1171

@ -0,0 +1 @@
examples/tokio/examples/connect.rs

@ -0,0 +1,20 @@
#!/bin/bash
set -e
cd "$(dirname "$0")/.."
known_failures="$(cat script/known_failures.txt)"
tree-sitter parse -q \
'examples/**/*.rs' \
$(for file in $known_failures; do echo "!${file}"; done)
example_count=$(find examples -name '*.rs' | wc -l)
failure_count=$(wc -w <<< "$known_failures")
success_count=$(( $example_count - $failure_count ))
success_percent=$(bc -l <<< "100*${success_count}/${example_count}")
printf \
"Successfully parsed %d of %d example files (%.1f%%)\n" \
$success_count $example_count $success_percent

@ -0,0 +1,3 @@
#!/bin/bash
rustc -Z ast-json-noexpand $@ | jq .

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

@ -0,0 +1,186 @@
#include <tree_sitter/parser.h>
#include <wctype.h>
enum TokenType {
STRING_CONTENT,
RAW_STRING_LITERAL,
FLOAT_LITERAL,
BLOCK_COMMENT,
};
void *tree_sitter_rust_external_scanner_create() { return NULL; }
void tree_sitter_rust_external_scanner_destroy(void *p) {}
void tree_sitter_rust_external_scanner_reset(void *p) {}
unsigned tree_sitter_rust_external_scanner_serialize(void *p, char *buffer) { return 0; }
void tree_sitter_rust_external_scanner_deserialize(void *p, const char *b, unsigned n) {}
static void advance(TSLexer *lexer) {
lexer->advance(lexer, false);
}
static bool is_num_char(int32_t c) {
return c == '_' || iswdigit(c);
}
bool tree_sitter_rust_external_scanner_scan(void *payload, TSLexer *lexer,
const bool *valid_symbols) {
if (valid_symbols[STRING_CONTENT] && !valid_symbols[FLOAT_LITERAL]) {
bool has_content = false;
for (;;) {
if (lexer->lookahead == '\"' || lexer->lookahead == '\\') {
break;
} else if (lexer->lookahead == 0) {
return false;
}
has_content = true;
advance(lexer);
}
lexer->result_symbol = STRING_CONTENT;
return has_content;
}
while (iswspace(lexer->lookahead)) lexer->advance(lexer, true);
if (
valid_symbols[RAW_STRING_LITERAL] &&
(lexer->lookahead == 'r' || lexer->lookahead == 'b')
) {
lexer->result_symbol = RAW_STRING_LITERAL;
if (lexer->lookahead == 'b') advance(lexer);
if (lexer->lookahead != 'r') return false;
advance(lexer);
unsigned opening_hash_count = 0;
while (lexer->lookahead == '#') {
advance(lexer);
opening_hash_count++;
}
if (lexer->lookahead != '"') return false;
advance(lexer);
for (;;) {
if (lexer->lookahead == 0) {
return false;
} else if (lexer->lookahead == '"') {
advance(lexer);
unsigned hash_count = 0;
while (lexer->lookahead == '#' && hash_count < opening_hash_count) {
advance(lexer);
hash_count++;
}
if (hash_count == opening_hash_count) {
return true;
}
} else {
advance(lexer);
}
}
}
if (valid_symbols[FLOAT_LITERAL] && iswdigit(lexer->lookahead)) {
lexer->result_symbol = FLOAT_LITERAL;
advance(lexer);
while (is_num_char(lexer->lookahead)) {
advance(lexer);
}
bool has_fraction = false, has_exponent = false;
if (lexer->lookahead == '.') {
has_fraction = true;
advance(lexer);
if (iswalpha(lexer->lookahead)) {
// The dot is followed by a letter: 1.max(2) => not a float but an integer
return false;
}
if (lexer->lookahead == '.') {
return false;
}
while (is_num_char(lexer->lookahead)) {
advance(lexer);
}
}
lexer->mark_end(lexer);
if (lexer->lookahead == 'e' || lexer->lookahead == 'E') {
has_exponent = true;
advance(lexer);
if (lexer->lookahead == '+' || lexer->lookahead == '-') {
advance(lexer);
}
if (!is_num_char(lexer->lookahead)) {
return true;
}
advance(lexer);
while (is_num_char(lexer->lookahead)) {
advance(lexer);
}
lexer->mark_end(lexer);
}
if (!has_exponent && !has_fraction) return false;
if (lexer->lookahead != 'u' && lexer->lookahead != 'i' && lexer->lookahead != 'f') {
return true;
}
advance(lexer);
if (!iswdigit(lexer->lookahead)) {
return true;
}
while (iswdigit(lexer->lookahead)) {
advance(lexer);
}
lexer->mark_end(lexer);
return true;
}
if (lexer->lookahead == '/') {
advance(lexer);
if (lexer->lookahead != '*') return false;
advance(lexer);
bool after_star = false;
unsigned nesting_depth = 1;
for (;;) {
switch (lexer->lookahead) {
case '\0':
return false;
case '*':
advance(lexer);
after_star = true;
break;
case '/':
if (after_star) {
advance(lexer);
after_star = false;
nesting_depth--;
if (nesting_depth == 0) {
lexer->result_symbol = BLOCK_COMMENT;
return true;
}
} else {
advance(lexer);
after_star = false;
if (lexer->lookahead == '*') {
nesting_depth++;
advance(lexer);
}
}
break;
default:
advance(lexer);
after_star = false;
break;
}
}
}
return false;
}

@ -0,0 +1,223 @@
#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 **symbol_names;
const char **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;
};
/*
* 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_