Add 'vendor/tree-sitter-javascript/' from commit 'bc2eb3994fd7cc605d27a32f9fcbee80bbb57f6d'

git-subtree-dir: vendor/tree-sitter-javascript
git-subtree-mainline: dd92c10ce9
git-subtree-split: bc2eb3994f
ida_star
Wilfred Hughes 2021-08-16 00:06:39 +07:00
commit 48ac079685
44 changed files with 90104 additions and 0 deletions

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

@ -0,0 +1,31 @@
---
name: Bug report
about: Report unexpected parsing results
title: ''
labels: 'bug'
assignees: ''
---
The following piece of code is valid but it is parsed incorrectly:
```javascript
```
Here's a link to the TypeScript Playground showing that the snippet above is valid JavaScript or TypeScript:
<!-- Please check your code at https://www.typescriptlang.org/play
and paste the URL below. -->
<!-- Please run `tree-sitter parse YOUR_FILE` and show us the output. -->
The output of `tree-sitter parse` is the following:
```
```
<!-- If there is no `ERROR` or `MISSING` node in the output above,
explain what you were expecting: -->
<!-- Name of the broken/missing feature, link to official
documentation, and any other relevant info is appreciated: -->

@ -0,0 +1,13 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
<!--
The tree-sitter-javascript project is a JavaScript and JSX parser only.
How can we improve it?
-->

@ -0,0 +1,8 @@
Checklist:
- [ ] All tests pass in CI.
- [ ] There are sufficient tests for the new fix/feature.
- [ ] Grammar rules have not been renamed unless absolutely necessary.
- [ ] The conflicts section hasn't grown too much.
- [ ] The parser size hasn't grown too much (check the value of STATE_COUNT in src/parser.c).

@ -0,0 +1,30 @@
name: CI
on:
workflow_dispatch:
pull_request:
push:
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,9 @@
Cargo.lock
node_modules
.node-version
build
*.log
/test.js
/examples/npm
package-lock.json
/target/

@ -0,0 +1,7 @@
test
build
script
examples
*.log
test.js
target

@ -0,0 +1,31 @@
[package]
name = "tree-sitter-javascript"
description = "JavaScript grammar for the tree-sitter parsing library"
version = "0.19.0"
authors = [
"Max Brunsfeld <maxbrunsfeld@gmail.com>",
"Douglas Creager <dcreager@dcreager.net>",
]
license = "MIT"
readme = "bindings/rust/README.md"
keywords = ["incremental", "parsing", "javascript"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/tree-sitter/tree-sitter-javascript"
edition = "2018"
build = "bindings/rust/build.rs"
include = [
"bindings/rust/*",
"grammar.js",
"queries/*",
"src/*",
]
[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) 2014 Max Brunsfeld
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,14 @@
tree-sitter-javascript
===========================
[![CI Status](https://github.com/tree-sitter/tree-sitter-javascript/actions/workflows/ci.yml/badge.svg)](https://github.com/tree-sitter/tree-sitter-javascript/actions/workflows/ci.yml)
JavaScript and JSX grammar for [tree-sitter][]. For TypeScript, see [tree-sitter-typescript][].
[tree-sitter]: https://github.com/tree-sitter/tree-sitter
[tree-sitter-typescript]: https://github.com/tree-sitter/tree-sitter-typescript
References
* [The ESTree Spec](https://github.com/estree/estree)
* [The ECMAScript 2015 Spec](http://www.ecma-international.org/ecma-262/6.0/)

@ -0,0 +1,19 @@
{
"targets": [
{
"target_name": "tree_sitter_javascript_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_javascript();
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_javascript());
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("javascript").ToLocalChecked());
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
}
NODE_MODULE(tree_sitter_javascript_binding, Init)
} // namespace

@ -0,0 +1,19 @@
try {
module.exports = require("../../build/Release/tree_sitter_javascript_binding");
} catch (error1) {
if (error1.code !== 'MODULE_NOT_FOUND') {
throw error1;
}
try {
module.exports = require("../../build/Debug/tree_sitter_javascript_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,47 @@
# tree-sitter-javascript
This crate provides a JavaScript 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.19"
tree-sitter-javascript = "0.19"
```
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.
The below example demonstrates a simple program that parses a JavaScript
function and prints the result to your terminal.
``` rust
use tree_sitter::Parser;
fn main() {
let code = r#"
function double(x) {
return x * 2;
}
"#;
let mut parser = Parser::new();
parser
.set_language(tree_sitter_javascript::language())
.expect("Error loading JavaScript grammar");
let parsed = parser.parse(code, None);
println!("{:#?}", parsed);
}
```
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-javascript/*/tree_sitter_javascript/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,19 @@
use std::path::Path;
extern crate cc;
fn main() {
let src_dir = 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);
let scanner_path = src_dir.join("scanner.c");
c_config.file(&scanner_path);
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
c_config.compile("parser-scanner");
}

@ -0,0 +1,78 @@
// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2020, tree-sitter-javascript authors.
// See the LICENSE file in this repo for license details.
// ------------------------------------------------------------------------------------------------
//! This crate provides a JavaScript 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#"
//! function double(x) {
//! return x * 2;
//! }
//! "#;
//! let mut parser = Parser::new();
//! parser.set_language(tree_sitter_javascript::language()).expect("Error loading JavaScript 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_javascript() -> 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_javascript() }
}
/// The source of the JavaScript tree-sitter grammar description.
pub const GRAMMAR: &'static str = include_str!("../../grammar.js");
/// The syntax highlighting query for this language.
pub const HIGHLIGHT_QUERY: &'static str = include_str!("../../queries/highlights.scm");
/// The syntax highlighting query for languages injected into this one.
pub const INJECTION_QUERY: &'static str = include_str!("../../queries/injections.scm");
/// The syntax highlighting query for JSX.
pub const JSX_HIGHLIGHT_QUERY: &'static str = include_str!("../../queries/highlights-jsx.scm");
/// The local-variable syntax highlighting query for this language.
pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.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: &'static str = include_str!("../../src/node-types.json");
/// The symbol tagging query for this language.
pub const TAGGING_QUERY: &'static str = include_str!("../../queries/tags.scm");
#[cfg(test)]
mod tests {
#[test]
fn can_load_grammar() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(super::language())
.expect("Error loading JavaScript grammar");
}
}

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,36 @@
{
"name": "tree-sitter-javascript",
"version": "0.19.0",
"description": "Javascript grammar for node-tree-sitter",
"main": "bindings/node",
"keywords": [
"parser",
"lexer"
],
"author": "Max Brunsfeld",
"license": "MIT",
"dependencies": {
"nan": "^2.12.1"
},
"devDependencies": {
"tree-sitter-cli": "^0.19.2"
},
"scripts": {
"test": "tree-sitter test && script/parse-examples",
"test-windows": "tree-sitter test"
},
"tree-sitter": [
{
"scope": "source.js",
"file-types": [
"js"
],
"highlights": [
"queries/highlights-jsx.scm",
"queries/highlights-params.scm",
"queries/highlights.scm"
],
"injection-regex": "^(js|javascript)$"
}
]
}

@ -0,0 +1,4 @@
(jsx_opening_element (identifier) @tag)
(jsx_closing_element (identifier) @tag)
(jsx_self_closing_element (identifier) @tag)
(jsx_attribute (property_identifier) @attribute)

@ -0,0 +1,12 @@
(formal_parameters
[
(identifier) @variable.parameter
(array_pattern
(identifier) @variable.parameter)
(object_pattern
[
(pair_pattern value: (identifier) @variable.parameter)
(shorthand_property_identifier_pattern) @variable.parameter
])
]
)

@ -0,0 +1,205 @@
; Special identifiers
;--------------------
([
(identifier)
(shorthand_property_identifier)
(shorthand_property_identifier_pattern)
] @constant
(#match? @constant "^[A-Z_][A-Z\\d_]+$"))
((identifier) @constructor
(#match? @constructor "^[A-Z]"))
((identifier) @variable.builtin
(#match? @variable.builtin "^(arguments|module|console|window|document)$")
(#is-not? local))
((identifier) @function.builtin
(#eq? @function.builtin "require")
(#is-not? local))
; Function and method definitions
;--------------------------------
(function
name: (identifier) @function)
(function_declaration
name: (identifier) @function)
(method_definition
name: (property_identifier) @function.method)
(pair
key: (property_identifier) @function.method
value: [(function) (arrow_function)])
(assignment_expression
left: (member_expression
property: (property_identifier) @function.method)
right: [(function) (arrow_function)])
(variable_declarator
name: (identifier) @function
value: [(function) (arrow_function)])
(assignment_expression
left: (identifier) @function
right: [(function) (arrow_function)])
; Function and method calls
;--------------------------
(call_expression
function: (identifier) @function)
(call_expression
function: (member_expression
property: (property_identifier) @function.method))
; Variables
;----------
(identifier) @variable
; Properties
;-----------
(property_identifier) @property
; Literals
;---------
(this) @variable.builtin
(super) @variable.builtin
[
(true)
(false)
(null)
(undefined)
] @constant.builtin
(comment) @comment
[
(string)
(template_string)
] @string
(regex) @string.special
(number) @number
; Tokens
;-------
(template_substitution
"${" @punctuation.special
"}" @punctuation.special) @embedded
[
";"
"?."
"."
","
] @punctuation.delimiter
[
"-"
"--"
"-="
"+"
"++"
"+="
"*"
"*="
"**"
"**="
"/"
"/="
"%"
"%="
"<"
"<="
"<<"
"<<="
"="
"=="
"==="
"!"
"!="
"!=="
"=>"
">"
">="
">>"
">>="
">>>"
">>>="
"~"
"^"
"&"
"|"
"^="
"&="
"|="
"&&"
"||"
"??"
"&&="
"||="
"??="
] @operator
[
"("
")"
"["
"]"
"{"
"}"
] @punctuation.bracket
[
"as"
"async"
"await"
"break"
"case"
"catch"
"class"
"const"
"continue"
"debugger"
"default"
"delete"
"do"
"else"
"export"
"extends"
"finally"
"for"
"from"
"function"
"get"
"if"
"import"
"in"
"instanceof"
"let"
"new"
"of"
"return"
"set"
"static"
"switch"
"target"
"throw"
"try"
"typeof"
"var"
"void"
"while"
"with"
"yield"
] @keyword

@ -0,0 +1,20 @@
; Parse the contents of tagged template literals using
; a language inferred from the tag.
(call_expression
function: [
(identifier) @injection.language
(member_expression
property: (property_identifier) @injection.language)
]
arguments: (template_string) @injection.content)
; Parse regex syntax within regex literals
((regex_pattern) @injection.content
(#set! injection.language "regex"))
; Parse JSDoc annotations in comments
((comment) @injection.content
(#set! injection.language "jsdoc"))

@ -0,0 +1,23 @@
; Scopes
;-------
[
(statement_block)
(function)
(arrow_function)
(function_declaration)
(method_definition)
] @local.scope
; Definitions
;------------
(pattern/identifier)@local.definition
(variable_declarator
name: (identifier) @local.definition)
; References
;------------
(identifier) @local.reference

@ -0,0 +1,88 @@
(
(comment)* @doc
.
(method_definition
name: (property_identifier) @name) @definition.method
(#not-eq? @name "constructor")
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
(#select-adjacent! @doc @definition.method)
)
(
(comment)* @doc
.
[
(class
name: (_) @name)
(class_declaration
name: (_) @name)
] @definition.class
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
(#select-adjacent! @doc @definition.class)
)
(
(comment)* @doc
.
[
(function
name: (identifier) @name)
(function_declaration
name: (identifier) @name)
(generator_function
name: (identifier) @name)
(generator_function_declaration
name: (identifier) @name)
] @definition.function
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
(#select-adjacent! @doc @definition.function)
)
(
(comment)* @doc
.
(lexical_declaration
(variable_declarator
name: (identifier) @name
value: [(arrow_function) (function)]) @definition.function)
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
(#select-adjacent! @doc @definition.function)
)
(
(comment)* @doc
.
(variable_declaration
(variable_declarator
name: (identifier) @name
value: [(arrow_function) (function)]) @definition.function)
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
(#select-adjacent! @doc @definition.function)
)
(assignment_expression
left: [
(identifier) @name
(member_expression
property: (property_identifier) @name)
]
right: [(arrow_function) (function)]
) @definition.function
(pair
key: (property_identifier) @name
value: [(arrow_function) (function)]) @definition.function
(
(call_expression
function: (identifier) @name) @reference.call
(#not-match? @name "^(require)$")
)
(call_expression
function: (member_expression
property: (property_identifier) @name)
arguments: (_) @reference.call)
(new_expression
constructor: (_) @name) @reference.class

@ -0,0 +1,65 @@
#!/usr/bin/env node
const fs = require('fs')
const assert = require('assert')
const babylon = require('babylon')
const esprima = require('esprima')
const {Document} = require('tree-sitter-cli/node_modules/tree-sitter')
const jsLanguage = require('..')
const ITERATION_COUNT = 50
if (process.argv.length < 3) {
console.log('Usage: script/benchmark.js <javascript-file>')
process.exit(1)
}
const fileName = process.argv[2]
const code = fs.readFileSync(fileName, 'utf8')
profile("Babylon", () => {
let rootNode = babylon.parse(code);
assert(rootNode.type === 'File');
});
profile("Esprima", () => {
let rootNode = esprima.parse(code);
assert(rootNode.type === 'Program');
});
let document = null
profile('Tree-sitter', () => {
document = new Document()
.setInputString(code)
.setLanguage(jsLanguage)
document.parse()
assert(document.rootNode.type === 'program')
})
assert(!/ERROR/.test(document.rootNode.toString()))
function profile (name, action) {
console.log(name + ':')
let durations = []
for (let i = 0; i < ITERATION_COUNT; i++) {
let startTime = Date.now()
try {
action()
} catch (e) {
console.log('FAILED', e.message)
return
}
let endTime = Date.now()
durations.push(endTime - startTime)
}
durations.sort((a, b) => a - b)
const average = durations.reduce((sum, term) => sum + term) / ITERATION_COUNT
const min = durations[0]
const max = durations[durations.length - 1]
console.log('Average:', average, 'Min:', min, 'Max:', max)
}

@ -0,0 +1 @@
examples/npm/node_modules/slide/lib/async-map-ordered.js

@ -0,0 +1,43 @@
#!/bin/bash
set -eu
cd "$(dirname "$0")/.."
function clone_repo {
owner=$1
name=$2
sha=$3
path=examples/$name
if [ ! -d "$path" ]; then
echo "Cloning $owner/$name"
git clone "https://github.com/$owner/$name" "$path"
fi
pushd "$path" > /dev/null
actual_sha=$(git rev-parse HEAD)
if [ "$actual_sha" != "$sha" ]; then
echo "Updating $owner/$name to $sha"
git fetch
git reset --hard $sha
fi
popd > /dev/null
}
clone_repo npm npm ee147fbbca6f2707d3b16f4fa78f4c4606b2d9b1
known_failures="$(cat script/known_failures.txt)"
tree-sitter parse -q \
'examples/**/*.js' \
$(for failure in $known_failures; do echo "!${failure}"; done)
example_count=$(find examples -name '*.js' | 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

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,145 @@
#include <tree_sitter/parser.h>
#include <wctype.h>
enum TokenType {
AUTOMATIC_SEMICOLON,
TEMPLATE_CHARS
};
void *tree_sitter_javascript_external_scanner_create() { return NULL; }
void tree_sitter_javascript_external_scanner_destroy(void *p) {}
void tree_sitter_javascript_external_scanner_reset(void *p) {}
unsigned tree_sitter_javascript_external_scanner_serialize(void *p, char *buffer) { return 0; }
void tree_sitter_javascript_external_scanner_deserialize(void *p, const char *b, unsigned n) {}
static void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
static bool scan_whitespace_and_comments(TSLexer *lexer) {
for (;;) {
while (iswspace(lexer->lookahead)) {
advance(lexer);
}
if (lexer->lookahead == '/') {
advance(lexer);
if (lexer->lookahead == '/') {
advance(lexer);
while (lexer->lookahead != 0 && lexer->lookahead != '\n') {
advance(lexer);
}
} else if (lexer->lookahead == '*') {
advance(lexer);
while (lexer->lookahead != 0) {
if (lexer->lookahead == '*') {
advance(lexer);
if (lexer->lookahead == '/') {
advance(lexer);
break;
}
} else {
advance(lexer);
}
}
} else {
return false;
}
} else {
return true;
}
}
}
bool tree_sitter_javascript_external_scanner_scan(void *payload, TSLexer *lexer,
const bool *valid_symbols) {
if (valid_symbols[TEMPLATE_CHARS]) {
if (valid_symbols[AUTOMATIC_SEMICOLON]) return false;
lexer->result_symbol = TEMPLATE_CHARS;
for (bool has_content = false;; has_content = true) {
lexer->mark_end(lexer);
switch (lexer->lookahead) {
case '`':
return has_content;
case '\0':
return false;
case '$':
advance(lexer);
if (lexer->lookahead == '{') return has_content;
break;
case '\\':
return has_content;
default:
advance(lexer);
}
}
} else {
lexer->result_symbol = AUTOMATIC_SEMICOLON;
lexer->mark_end(lexer);
for (;;) {
if (lexer->lookahead == 0) return true;
if (lexer->lookahead == '}') return true;
if (lexer->is_at_included_range_start(lexer)) return true;
if (!iswspace(lexer->lookahead)) return false;
if (lexer->lookahead == '\n') break;
advance(lexer);
}
advance(lexer);
if (!scan_whitespace_and_comments(lexer)) return false;
switch (lexer->lookahead) {
case ',':
case '.':
case ':':
case ';':
case '*':
case '%':
case '>':
case '<':
case '=':
case '[':
case '(':
case '?':
case '^':
case '|':
case '&':
case '/':
return false;
// Insert a semicolon before `--` and `++`, but not before binary `+` or `-`.
case '+':
advance(lexer);
return lexer->lookahead == '+';
case '-':
advance(lexer);
return lexer->lookahead == '-';
// Don't insert a semicolon before `!=`, but do insert one before a unary `!`.
case '!':
advance(lexer);
return lexer->lookahead != '=';
// Don't insert a semicolon before `in` or `instanceof`, but do insert one
// before an identifier.
case 'i':
advance(lexer);
if (lexer->lookahead != 'n') return true;
advance(lexer);
if (!iswalpha(lexer->lookahead)) return false;
for (unsigned i = 0; i < 8; i++) {
if (lexer->lookahead != "stanceof"[i]) return true;
advance(lexer);
}
if (!iswalpha(lexer->lookahead)) return false;
break;
}
return true;
}
}

@ -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 * 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;
};
/*
* 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_

@ -0,0 +1,107 @@
============================================
Object destructuring assignments
============================================
({a, b} = object);
let {a, b, ...c} = object
const {a, b: {c, d}} = object
---
(program
(expression_statement (parenthesized_expression (assignment_expression
(object_pattern
(shorthand_property_identifier_pattern)
(shorthand_property_identifier_pattern))
(identifier))))
(lexical_declaration (variable_declarator
(object_pattern
(shorthand_property_identifier_pattern)
(shorthand_property_identifier_pattern)
(rest_pattern (identifier)))
(identifier)))
(lexical_declaration (variable_declarator
(object_pattern
(shorthand_property_identifier_pattern)
(pair_pattern
(property_identifier)
(object_pattern
(shorthand_property_identifier_pattern)
(shorthand_property_identifier_pattern))))
(identifier))))
============================================
Object destructuring parameters
============================================
function a ({b, c}, {d}) {}
---
(program
(function_declaration (identifier)
(formal_parameters
(object_pattern (shorthand_property_identifier_pattern) (shorthand_property_identifier_pattern))
(object_pattern (shorthand_property_identifier_pattern)))
(statement_block)))
============================================
Array destructuring assignments
============================================
[a, b] = array;
[a, b, ...c] = array;
[,, c,, d,] = array;
---
(program
(expression_statement (assignment_expression
(array_pattern
(identifier)
(identifier))
(identifier)))
(expression_statement (assignment_expression
(array_pattern
(identifier)
(identifier)
(rest_pattern (identifier)))
(identifier)))
(expression_statement (assignment_expression
(array_pattern
(identifier)
(identifier))
(identifier))))
================================================
Object destructuring patterns w/ default values
================================================
let {a: b = c} = object;
for await (var {a: {b} = object} of asyncIter) {}
function a({b = true}, [c, d = false]) {}
function b({c} = {}) {}
---
(program
(lexical_declaration (variable_declarator
(object_pattern (pair_pattern
(property_identifier)
(assignment_pattern (identifier) (identifier))))
(identifier)))
(for_in_statement
(object_pattern (pair_pattern
(property_identifier)
(assignment_pattern (object_pattern (shorthand_property_identifier_pattern)) (identifier))))
(identifier)
(statement_block))
(function_declaration (identifier)
(formal_parameters
(object_pattern (object_assignment_pattern (shorthand_property_identifier_pattern) (true)))
(array_pattern (identifier) (assignment_pattern (identifier) (false))))
(statement_block))
(function_declaration (identifier)
(formal_parameters
(assignment_pattern (object_pattern (shorthand_property_identifier_pattern)) (object)))
(statement_block)))

File diff suppressed because it is too large Load Diff

@ -0,0 +1,153 @@
============================================
Numbers
============================================
04000
400
100n
0xffffffffn
0b00111n
0o1234n
0xa_b_c
0o1_1
0b1_000_000
1_2_3
12_3.4_5e6_7
0b1_000_000n
01
00000123
---
(program
(expression_statement (number))
(expression_statement (number))
(expression_statement (number))
(expression_statement (number))
(expression_statement (number))
(expression_statement (number))
(expression_statement (number))
(expression_statement (number))
(expression_statement (number))
(expression_statement (number))
(expression_statement (number))
(expression_statement (number))
(expression_statement (number))
(expression_statement (number)))
============================================
Unicode identifiers
============================================
const últimaVez = 1
{ 県: '大阪府', '': '' }
---
(program
(lexical_declaration (variable_declarator (identifier) (number)))
(expression_statement
(object
(pair (property_identifier) (string (string_fragment)))
(pair (string) (string)))))
==========================================
Strings containing comment-like content
==========================================
"//ok\n//what"
---
(program
(expression_statement
(string (string_fragment) (escape_sequence) (string_fragment))))
==========================================
Quote escaping
==========================================
"";
'';
"\"";
"a\"b";
'\'';
'a\'b';
"it's a tiny tiny world";
'"hello"';
---
(program
(expression_statement (string))
(expression_statement (string))
(expression_statement (string (escape_sequence)))
(expression_statement
(string (string_fragment) (escape_sequence) (string_fragment)))
(expression_statement (string (escape_sequence)))
(expression_statement
(string (string_fragment) (escape_sequence) (string_fragment)))
(expression_statement (string (string_fragment)))
(expression_statement (string (string_fragment))))
==========================================
Line continuations
==========================================
"hello\
world";
'hello\
world';
---
(program
(expression_statement
(string (string_fragment) (escape_sequence) (string_fragment)))
(expression_statement
(string (string_fragment) (escape_sequence) (string_fragment))))
============================================================
Non-standard unescaped newlines legal in TSX attributes
============================================================
"hello
world";
'hello
world';
---
(program
(expression_statement (string (string_fragment)))
(expression_statement (string (string_fragment))))
=========================================================
JSX strings with unescaped newlines for TSX attributes
=========================================================
<Element Attribute="hello
world"></Element>;
<Element Attribute='hello
world'></Element>;
---
(program
(expression_statement
(jsx_element
(jsx_opening_element
(identifier)
(jsx_attribute (property_identifier) (string (string_fragment))))
(jsx_closing_element
(identifier))))
(expression_statement
(jsx_element
(jsx_opening_element
(identifier)
(jsx_attribute (property_identifier) (string (string_fragment))))
(jsx_closing_element
(identifier)))))

@ -0,0 +1,289 @@
============================================
Automatic semicolon insertion
============================================
if (a) {
var b = c
d()
e()
return f
}
---
(program
(if_statement
(parenthesized_expression (identifier))
(statement_block
(variable_declaration (variable_declarator (identifier) (identifier)))
(expression_statement (call_expression (identifier) (arguments)))
(expression_statement (call_expression (identifier) (arguments)))
(return_statement (identifier)))))
============================================
Semicolon insertion before update expressions
============================================
if (a)
d()
++b
if (a)
d()
--b
---
(program
(if_statement
(parenthesized_expression (identifier))
(expression_statement
(call_expression (identifier) (arguments))))
(expression_statement (update_expression (identifier)))
(if_statement
(parenthesized_expression (identifier))
(expression_statement
(call_expression (identifier) (arguments))))
(expression_statement (update_expression (identifier))))
==========================================
property access across lines
==========================================
object
.someProperty
.otherProperty
---
(program (expression_statement
(member_expression
(member_expression (identifier) (property_identifier))
(property_identifier))))
===========================================
indented code after blocks
===========================================
function x() {}
return z;
---
(program
(function_declaration
(identifier)
(formal_parameters)
(statement_block))
(return_statement (identifier)))
================================================
operator expressions split across lines
================================================
a
? b
: c
a
|| b
a
^ b
a
!== b
a
!b; // standalone statement
---
(program
(expression_statement (ternary_expression (identifier) (identifier) (identifier)))
(expression_statement (binary_expression (identifier) (identifier)))
(expression_statement (binary_expression (identifier) (identifier)))
(expression_statement (binary_expression (identifier) (identifier)))
(expression_statement (identifier))
(expression_statement (unary_expression (identifier)))
(comment))
================================================
Alphabetical infix operators split across lines
================================================
a
i;
a
in b;
a
ins;
a
inst;
a
instanceof b;
a
instanceofX;
---
(program
(expression_statement (identifier))
(expression_statement (identifier))
(expression_statement (binary_expression (identifier) (identifier)))
(expression_statement (identifier))
(expression_statement (identifier))
(expression_statement (identifier))
(expression_statement (identifier))
(expression_statement (binary_expression (identifier) (identifier)))
(expression_statement (identifier))
(expression_statement (identifier)))
===========================================
Single-line if/else statements
===========================================
if (a) {b} else {c}
---
(program
(if_statement (parenthesized_expression (identifier))
(statement_block (expression_statement (identifier)))
(else_clause
(statement_block (expression_statement (identifier))))))
===========================================
single-line blocks without semicolons
===========================================
function a() {b}
function c() {return d}
---
(program
(function_declaration (identifier) (formal_parameters) (statement_block
(expression_statement (identifier))))
(function_declaration (identifier) (formal_parameters) (statement_block
(return_statement (identifier)))))
==============================================
Multi-line chained expressions in var declarations
==============================================
var a = new A()
.b({c: 'd'})
.e()
---
(program
(variable_declaration (variable_declarator
(identifier)
(call_expression
(member_expression
(call_expression
(member_expression
(new_expression (identifier) (arguments))
(property_identifier))
(arguments
(object
(pair (property_identifier) (string (string_fragment))))))
(property_identifier))
(arguments)))))
==============================================
if/for/while/do statements without semicolons
==============================================
if (a) { if (b) return c }
if (d) { for (;;) break }
if (e) { for (f in g) break }
if (h) { for (i of j) continue }
if (k) { while (l) break }
if (m) { do { n; } while (o) }
if (p) { var q }
---
(program
(if_statement (parenthesized_expression (identifier)) (statement_block
(if_statement
(parenthesized_expression (identifier))
(return_statement (identifier)))))
(if_statement (parenthesized_expression (identifier)) (statement_block
(for_statement
(empty_statement)
(empty_statement)
(break_statement))))
(if_statement (parenthesized_expression (identifier)) (statement_block
(for_in_statement (identifier) (identifier)
(break_statement))))
(if_statement (parenthesized_expression (identifier)) (statement_block
(for_in_statement (identifier) (identifier)
(continue_statement))))
(if_statement (parenthesized_expression (identifier)) (statement_block
(while_statement
(parenthesized_expression (identifier))
(break_statement))))
(if_statement (parenthesized_expression (identifier)) (statement_block
(do_statement
(statement_block (expression_statement (identifier)))
(parenthesized_expression (identifier)))))
(if_statement (parenthesized_expression (identifier)) (statement_block
(variable_declaration (variable_declarator (identifier))))))
=====================================================
Single-line declarations without semicolons
=====================================================
function a () { function b () {} function *c () {} class D {} return }
---
(program
(function_declaration (identifier) (formal_parameters) (statement_block
(function_declaration (identifier) (formal_parameters) (statement_block))
(generator_function_declaration (identifier) (formal_parameters) (statement_block))
(class_declaration (identifier) (class_body))
(return_statement))))
=====================================================
Comments after statements without semicolons
=====================================================
let a // comment at end of declaration
// comment outside of declaration
let b /* comment between declarators */, c
/** comment with *stars* **/ /* comment with /slashes/ */
/* third comment in a row */
let d
---
(program
(lexical_declaration
(variable_declarator (identifier))
(comment))
(comment)
(lexical_declaration
(variable_declarator (identifier))
(comment)
(variable_declarator (identifier)))
(comment)
(comment)
(comment)
(lexical_declaration (variable_declarator (identifier))))

@ -0,0 +1,830 @@
============================================
Assignments
============================================
a = 0;
var b = 0;
const c = 0;
let d = 0;
---
(program
(expression_statement
(assignment_expression (identifier) (number)))
(variable_declaration (variable_declarator (identifier) (number)))
(lexical_declaration
(variable_declarator (identifier) (number)))
(lexical_declaration (variable_declarator (identifier) (number))))
============================================
'undefined' is a variable
============================================
undefined = 42;
var undefined = 42;
const undefined = 42;
let undefined = 42;
---
(program
(expression_statement (assignment_expression (undefined) (number)))
(variable_declaration (variable_declarator (identifier) (number)))
(lexical_declaration (variable_declarator (identifier) (number)))
(lexical_declaration (variable_declarator (identifier) (number))))
============================================
Imports
============================================
import defaultMember from "module-name";
import * as name from "module-name";
import { member } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 } from "module-name";
import defaultMember, { member1, member2 as alias2 } from "module-name";
import defaultMember, * as name from "module-name";
import "module-name";
import { member1 , member2 as alias2, } from "module-name";
import("a");
import("a").then((m) => {});
import.meta.url;
----
(program
(import_statement
(import_clause (identifier)) (string (string_fragment)))
(import_statement
(import_clause (namespace_import (identifier))) (string (string_fragment)))
(import_statement
(import_clause (named_imports (import_specifier (identifier)))) (string (string_fragment)))
(import_statement
(import_clause (named_imports (import_specifier (identifier)) (import_specifier (identifier)))) (string (string_fragment)))
(import_statement
(import_clause (named_imports (import_specifier (identifier)) (import_specifier (identifier) (identifier)))) (string (string_fragment)))
(import_statement
(import_clause (identifier) (named_imports (import_specifier (identifier)) (import_specifier (identifier) (identifier)))) (string (string_fragment)))
(import_statement
(import_clause (identifier) (namespace_import (identifier))) (string (string_fragment)))
(import_statement
(string (string_fragment)))
(import_statement
(import_clause (named_imports (import_specifier (identifier)) (import_specifier (identifier) (identifier)))) (string (string_fragment)))
(expression_statement
(call_expression
(import)
(arguments (string (string_fragment)))))
(expression_statement
(call_expression
(member_expression
(call_expression
(import)
(arguments (string (string_fragment))))
(property_identifier))
(arguments (arrow_function (formal_parameters (identifier)) (statement_block)))))
(expression_statement
(member_expression
(member_expression
(import)
(property_identifier))
(property_identifier))))
============================================
Exports
============================================
export { name1, name2, name3, nameN };
export { variable1 as name1, variable2 as name2, nameN };
export let name1, name2, nameN;
export let name1 = value1, name2 = value2, name3, nameN;
export default expression;
export default { field1: 42, field2: [] }
export default function () { }
export default function name1() { }
export { name1 as default };
export * from 'foo';
export * as someIdentifier from "someModule";
export { name1, name2, nameN } from 'foo';
export { import1 as name1, import2 as name2, nameN } from 'foo';
----
(program
(export_statement
(export_clause
(export_specifier name: (identifier))
(export_specifier name: (identifier))
(export_specifier name: (identifier))
(export_specifier name: (identifier))))
(export_statement
(export_clause
(export_specifier name: (identifier) alias: (identifier))
(export_specifier name: (identifier) alias: (identifier))
(export_specifier name: (identifier))))
(export_statement
declaration: (lexical_declaration
(variable_declarator name: (identifier))
(variable_declarator name: (identifier))
(variable_declarator name: (identifier))))
(export_statement
declaration: (lexical_declaration
(variable_declarator name: (identifier) value: (identifier))
(variable_declarator name: (identifier) value: (identifier))
(variable_declarator name: (identifier))
(variable_declarator name: (identifier))))
(export_statement
value: (identifier))
(export_statement
value: (object
(pair key: (property_identifier) value: (number))
(pair key: (property_identifier) value: (array))))
(export_statement
value: (function parameters: (formal_parameters) body: (statement_block)))
(export_statement
declaration: (function_declaration name: (identifier) parameters: (formal_parameters) body: (statement_block)))
(export_statement
(export_clause (export_specifier name: (identifier) alias: (identifier))))
(export_statement
source: (string (string_fragment)))
(export_statement
(namespace_import (identifier))
source: (string (string_fragment)))
(export_statement
(export_clause
(export_specifier name: (identifier))
(export_specifier name: (identifier))
(export_specifier name: (identifier)))
source: (string (string_fragment)))
(export_statement
(export_clause
(export_specifier name: (identifier) alias: (identifier))
(export_specifier name: (identifier) alias: (identifier))
(export_specifier name: (identifier)))
source: (string (string_fragment))))
============================================
Decorators before exports
============================================
@injectable()
export class Foo {
}
---
(program
(export_statement
decorator: (decorator
(call_expression
function: (identifier)
arguments: (arguments)))
declaration: (class_declaration
name: (identifier)
body: (class_body))))
============================================
If statements
============================================
if (x)
log(y);
if (a.b) {
log(c);
d;
}
----
(program
(if_statement
condition: (parenthesized_expression (identifier))
consequence: (expression_statement
(call_expression
function: (identifier)
arguments: (arguments (identifier)))))
(if_statement
condition: (parenthesized_expression (member_expression
object: (identifier)
property: (property_identifier)))
consequence: (statement_block
(expression_statement
(call_expression
function: (identifier)
arguments: (arguments (identifier))))
(expression_statement
(identifier)))))
============================================
If-else statements
============================================
if (x)
y;
else if (a)
b;
if (a) {
c;
d;
} else {
e;
}
----
(program
(if_statement
condition: (parenthesized_expression (identifier))
consequence: (expression_statement (identifier))
alternative: (else_clause
(if_statement
condition: (parenthesized_expression (identifier))
consequence: (expression_statement (identifier)))))
(if_statement
condition: (parenthesized_expression (identifier))
consequence: (statement_block
(expression_statement (identifier))
(expression_statement (identifier)))
alternative: (else_clause
(statement_block
(expression_statement (identifier))))))
============================================
For statements
============================================
for (var a, b; c; d)
e;
for (i = 0, init(); i < 10; i++)
log(y);
for (;;) {
z;
continue;
}
for (var i = 0
; i < l
; i++) {
}
---
(program
(for_statement
initializer: (variable_declaration
(variable_declarator name: (identifier))
(variable_declarator name: (identifier)))
condition: (expression_statement (identifier))
increment: (identifier)
body: (expression_statement (identifier)))
(for_statement
initializer: (expression_statement (sequence_expression
left: (assignment_expression
left: (identifier)
right: (number))
right: (call_expression
function: (identifier)
arguments: (arguments))))
condition: (expression_statement (binary_expression
left: (identifier)
right: (number)))
increment: (update_expression argument: (identifier))
body: (expression_statement (call_expression
function: (identifier)
arguments: (arguments (identifier)))))
(for_statement
initializer: (empty_statement)
condition: (empty_statement)
body: (statement_block
(expression_statement (identifier))
(continue_statement)))
(for_statement
initializer: (variable_declaration (variable_declarator
name: (identifier)
value: (number)))
condition: (expression_statement (binary_expression
left: (identifier)
right: (identifier)))
increment: (update_expression
argument: (identifier))
body: (statement_block)))
============================================
For-in statements
============================================
for (item in items)
item();
for (var item in items || {})
item();
for (const {thing} in things)
thing();
for (x in a, b, c)
foo();
for (x[i] in a) {}
for (x.y in a) {}
for ([a, b] in c) {}
for ((a) in b) {}
---
(program
(for_in_statement (identifier) (identifier)
(expression_statement (call_expression (identifier) (arguments))))
(for_in_statement (identifier) (binary_expression (identifier) (object))
(expression_statement (call_expression (identifier) (arguments))))
(for_in_statement
(object_pattern (shorthand_property_identifier_pattern))
(identifier)
(expression_statement (call_expression (identifier) (arguments))))
(for_in_statement
(identifier)
(sequence_expression (identifier) (sequence_expression (identifier) (identifier)))
(expression_statement (call_expression (identifier) (arguments))))
(for_in_statement
(subscript_expression (identifier) (identifier))
(identifier)
(statement_block))
(for_in_statement
(member_expression (identifier) (property_identifier))
(identifier)
(statement_block))
(for_in_statement
(array_pattern (identifier) (identifier))
(identifier)
(statement_block))
(for_in_statement
(parenthesized_expression (identifier))
(identifier)
(statement_block)))
==========================================
For loops beginning with an in-expression
==========================================
for (key in something && i = 0; i < n; i++) {
doSomething();
}
---
(program (for_statement
(expression_statement
(binary_expression
(binary_expression (identifier) (identifier))
(assignment_expression (identifier) (number))))
(expression_statement (binary_expression (identifier) (identifier)))
(update_expression (identifier))
(statement_block
(expression_statement (call_expression (identifier) (arguments))))))
============================================
For-of statements
============================================
for (a of b)
process(a);
for (let {a, b} of items || [])
process(a, b);
---
(program
(for_in_statement
(identifier)
(identifier)
(expression_statement (call_expression (identifier) (arguments (identifier)))))
(for_in_statement
(object_pattern (shorthand_property_identifier_pattern) (shorthand_property_identifier_pattern))
(binary_expression (identifier) (array))
(expression_statement (call_expression (identifier) (arguments (identifier) (identifier))))))
============================================
For-await-of statements
============================================
for await (const chunk of stream) {
str += chunk;
}
---
(program
(for_in_statement
(identifier)
(identifier)
(statement_block
(expression_statement (augmented_assignment_expression (identifier) (identifier))))))
============================================
While statements
============================================
while (a)
b();
while (a) {
}
---
(program
(while_statement
condition: (parenthesized_expression (identifier))
body: (expression_statement (call_expression
function: (identifier)
arguments: (arguments))))
(while_statement
condition: (parenthesized_expression (identifier))
body: (statement_block)))
============================================
Do statements
============================================
do {
a;
} while (b)
do a; while (b)
do {} while (b)
---
(program
(do_statement
body: (statement_block (expression_statement (identifier)))
condition: (parenthesized_expression (identifier)))
(do_statement
body: (expression_statement (identifier))
condition: (parenthesized_expression (identifier)))
(do_statement
body: (statement_block)
condition: (parenthesized_expression (identifier))))
============================================
Return statements
============================================
return;
return 5;
return 1,2;
return async;
return a;
---
(program
(return_statement)
(return_statement (number))
(return_statement (sequence_expression (number) (number)))
(return_statement (identifier))
(return_statement (identifier)))
============================================
Variable declarations
============================================
var x = 1;
var x, y = {}, z;
---
(program
(variable_declaration
(variable_declarator (identifier) (number)))
(variable_declaration
(variable_declarator (identifier))
(variable_declarator (identifier) (object))
(variable_declarator (identifier))))
============================================
Comments
============================================
{
// This is a property
aProperty: 1,
/*
* This is a method
*/
aMethod: function() {}
};
---
(program
(expression_statement (object
(comment)
(pair (property_identifier) (number))
(comment)
(pair (property_identifier) (function (formal_parameters) (statement_block))))))
==========================================
Comments between statements
==========================================
// this is the beginning of the script.
// here we go.
var thing = {
// this is a property.
// its value is a function.
key: function(x /* this is a parameter */) {
// this is one statement
one();
// this is another statement
two();
}
};
---
(program
(comment)
(comment)
(variable_declaration (variable_declarator
(identifier)
(object
(comment)
(comment)
(pair (property_identifier) (function
(formal_parameters (identifier) (comment))
(statement_block
(comment)
(expression_statement
(call_expression (identifier) (arguments)))
(comment)
(expression_statement
(call_expression (identifier) (arguments))))))))))
============================================
Comments with asterisks
============================================
/* a */
const a = 1;
/* b **/
const b = 1;
/* c ***/
const c = 1;
/* d
***/
const d = 1;
---
(program
(comment)
(lexical_declaration (variable_declarator (identifier) (number)))
(comment)
(lexical_declaration (variable_declarator (identifier) (number)))
(comment)
(lexical_declaration (variable_declarator (identifier) (number)))
(comment)
(lexical_declaration (variable_declarator (identifier) (number))))
==========================================
Comments within expressions
==========================================
y // comment
* z;
---
(program (expression_statement
(binary_expression (identifier) (comment) (identifier))))
============================================
Switch statements
============================================
switch (x) {
case 1:
case 2:
something();
break;
case "three":
somethingElse();
break;
default:
return 4;
}
---
(program
(switch_statement (parenthesized_expression (identifier)) (switch_body
(switch_case (number))
(switch_case (number)
(expression_statement (call_expression (identifier) (arguments)))
(break_statement))
(switch_case (string (string_fragment))
(expression_statement (call_expression (identifier) (arguments)))
(break_statement))
(switch_default
(return_statement (number))))))
============================================
Throw statements
============================================
throw new Error("uh oh");
---
(program
(throw_statement
(new_expression (identifier) (arguments (string (string_fragment))))))
============================================
Throw statements with sequence expressions
============================================
throw f = 1, f;
throw g = 2, g
---
(program
(throw_statement
(sequence_expression (assignment_expression (identifier) (number)) (identifier)))
(throw_statement
(sequence_expression (assignment_expression (identifier) (number)) (identifier))))
============================================
Try catch finally statements
============================================
try { a; } catch (b) { c; }
try { d; } finally { e; }
try { f; } catch { g; } finally { h; }
try { throw [a, b] } catch ([c, d]) { }
---
(program
(try_statement
(statement_block (expression_statement (identifier)))
(catch_clause (identifier)
(statement_block (expression_statement (identifier)))))
(try_statement
(statement_block (expression_statement (identifier)))
(finally_clause
(statement_block (expression_statement (identifier)))))
(try_statement
(statement_block (expression_statement (identifier)))
(catch_clause
(statement_block (expression_statement (identifier))))
(finally_clause
(statement_block (expression_statement (identifier)))))
(try_statement
(statement_block (throw_statement (array (identifier) (identifier))))
(catch_clause
(array_pattern (identifier) (identifier))
(statement_block))))
============================================
Empty statements
============================================
if (true) { ; };;;
if (true) {} else {}
---
(program
(if_statement
(parenthesized_expression (true))
(statement_block (empty_statement)))
(empty_statement)
(empty_statement)
(empty_statement)
(if_statement
(parenthesized_expression (true))
(statement_block)
(else_clause
(statement_block))))
============================================
Labeled statements
============================================
theLoop:
for (;;) {
if (a) {
break theLoop;
} else {
continue theLoop;
}
}
label
: {
break label;
}
async:
while (true) {
continue async;
}
---
(program
(labeled_statement
label: (statement_identifier)
(for_statement
initializer: (empty_statement)
condition: (empty_statement)
body: (statement_block
(if_statement
condition: (parenthesized_expression (identifier))
consequence: (statement_block
(break_statement label: (statement_identifier)))
alternative: (else_clause
(statement_block
(continue_statement label: (statement_identifier))))))))
(labeled_statement
label: (statement_identifier)
(statement_block
(break_statement label: (statement_identifier))))
(labeled_statement
label: (statement_identifier)
(while_statement
condition: (parenthesized_expression (true))
body: (statement_block
(continue_statement label: (statement_identifier))))))
============================================
Debugger statements
============================================
debugger;
debugger
---
(program (debugger_statement) (debugger_statement))
============================================
With statements
============================================
with (x) { i; }
with (x) { }
---
(program
(with_statement
object: (parenthesized_expression (identifier))
body: (statement_block (expression_statement (identifier))))
(with_statement
object: (parenthesized_expression (identifier))
body: (statement_block)))
==========================================
Hash bang lines
==========================================
#!/usr/bin/env node
console.log("HI")
---
(program
(hash_bang_line)
(expression_statement
(call_expression
(member_expression
(identifier)
(property_identifier))
(arguments
(string (string_fragment))))))

@ -0,0 +1,48 @@
var a = 'a';
// ^ variable
var b = function() {};
// ^ function
var c = () => {};
// ^ function
var d = async () => {};
// ^ function
module.e = 'e';
// ^ property
module.f = function() {};
// ^ function.method
module.g = async function() {};
// ^ function.method
module.h = () => {};
// ^ function.method
function i() {
// ^ function
}
class Person {
static foo = bar;
// ^ property
getName() {
// ^ function.method
}
}
foo(function callback() {
// ^ keyword
// ^ function
})
c();
// <- function
module.e();
// ^ function.method

@ -0,0 +1,5 @@
eval(js `var foo`)
// <- function
// ^ function
// ^ keyword
// ^ variable

@ -0,0 +1,12 @@
do {} while (a);
// <- keyword
// ^ keyword
try {} catch (e) {} finally {}
// <- keyword
// ^ keyword
// ^ keyword
throw e
// <- keyword
// ^ variable

@ -0,0 +1,48 @@
class A {}
// ^ constructor
const ABC = 1
// ^ constant
const AB_C1 = 2
// ^ constant
const {AB_C2_D3} = x
// ^ constant
module.exports = function(one, two) {
// <- variable.builtin
// ^ variable.parameter
if (something()) {
let module = null, one = 1;
// ^ variable
// ^ variable
console.log(module, one, two);
// ^ variable.builtin
// ^ variable
// ^ variable
// ^ variable.parameter
}
console.log(module, one, two);
// ^ variable.builtin
// ^ variable.builtin
// ^ variable.parameter
// ^ variable.parameter
};
console.log(module, one, two);
// ^ variable.builtin
// ^ variable.builtin
// ^ variable
// ^ variable
function one({two: three}, [four]) {
// ^ property
// ^ variable.parameter
// ^ variable.parameter
console.log(two, three, four)
// ^ variable
// ^ variable.parameter
// ^ variable.parameter
}