Merge commit 'fdeb68ac8d2bd5a78b943528bb68ceda3aade2eb'

pull/70/head
Wilfred Hughes 2021-11-19 23:52:49 +07:00
commit f8427c6970
13 changed files with 54655 additions and 40931 deletions

@ -1,5 +1,9 @@
## 0.13 (unreleased)
### Parsing
Updated C parser to latest upstream version.
No changes.
## 0.12

@ -2,6 +2,7 @@
Checklist:
- [ ] All tests pass in CI.
- [ ] The script/parse-examples passes without issues.
- [ ] 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.

@ -1,7 +1,7 @@
[package]
name = "tree-sitter-javascript"
description = "JavaScript grammar for the tree-sitter parsing library"
version = "0.19.0"
version = "0.20.0"
authors = [
"Max Brunsfeld <maxbrunsfeld@gmail.com>",
"Douglas Creager <dcreager@dcreager.net>",
@ -25,7 +25,7 @@ include = [
path = "bindings/rust/lib.rs"
[dependencies]
tree-sitter = "0.19"
tree-sitter = ">= 0.19, < 0.21"
[build-dependencies]
cc = "1.0"

@ -8,8 +8,8 @@ way.)
``` toml
[dependencies]
tree-sitter = "0.19"
tree-sitter-javascript = "0.19"
tree-sitter = "0.20"
tree-sitter-javascript = "0.20"
```
Typically, you will use the [language][language func] function to add this

@ -3,12 +3,13 @@ module.exports = grammar({
externals: $ => [
$._automatic_semicolon,
$._template_chars
$._template_chars,
$._ternary_qmark,
],
extras: $ => [
$.comment,
/[\s\uFEFF\u2060\u200B\u00A0]/
/[\s\p{Zs}\uFEFF\u2060\u200B]/,
],
supertypes: $ => [
@ -42,22 +43,23 @@ module.exports = grammar({
'member',
'call',
$.update_expression,
'unary_not',
'unary_void',
'binary_exp',
'binary_times',
'binary_plus',
'binary_shift',
'binary_compare',
'binary_relation',
'binary_in',
'binary_and',
'binary_or',
'binary_equality',
'bitwise_and',
'bitwise_xor',
'bitwise_or',
'logical_and',
'logical_or',
'ternary',
$.await_expression,
$.sequence_expression,
$.arrow_function
],
[$.rest_pattern, 'assign'],
['assign', $.primary_expression],
['member', 'new', 'call', $.expression],
['declaration', 'literal'],
@ -80,6 +82,7 @@ module.exports = grammar({
[$.assignment_expression, $.object_assignment_pattern],
[$.labeled_statement, $._property_name],
[$.computed_property_name, $.array],
[$.binary_expression, $._initializer],
],
word: $ => $.identifier,
@ -101,7 +104,7 @@ module.exports = grammar({
'export',
choice(
seq('*', $._from_clause, $._semicolon),
seq($.namespace_import, $._from_clause, $._semicolon),
seq(alias($.namespace_import_export, $.namespace_export), $._from_clause, $._semicolon),
seq($.export_clause, $._from_clause, $._semicolon),
seq($.export_clause, $._semicolon)
)
@ -164,14 +167,14 @@ module.exports = grammar({
),
import_clause: $ => choice(
$.namespace_import,
alias($.namespace_import_export, $.namespace_import),
$.named_imports,
seq(
$.identifier,
optional(seq(
',',
choice(
$.namespace_import,
alias($.namespace_import_export, $.namespace_import),
$.named_imports
)
))
@ -182,7 +185,7 @@ module.exports = grammar({
"from", field('source', $.string)
),
namespace_import: $ => seq(
namespace_import_export: $ => seq(
"*", "as", $.identifier
),
@ -234,7 +237,7 @@ module.exports = grammar({
),
lexical_declaration: $ => seq(
choice('let', 'const'),
field('kind', choice('let', 'const')),
commaSep1($.variable_declarator),
$._semicolon
),
@ -299,14 +302,22 @@ module.exports = grammar({
$.parenthesized_expression,
)),
seq(
choice('var', 'let', 'const'),
field('kind', 'var'),
field('left', choice(
$.identifier,
$._destructuring_pattern
)),
optional($._initializer)
),
seq(
field('kind', choice('let', 'const')),
field('left', choice(
$.identifier,
$._destructuring_pattern
))
)
),
choice('in', 'of'),
field('operator', choice('in', 'of')),
field('right', $._expressions),
')',
),
@ -372,7 +383,7 @@ module.exports = grammar({
labeled_statement: $ => prec.dynamic(-1, seq(
field('label', alias(choice($.identifier, $._reserved_identifier), $.statement_identifier)),
':',
$.statement
field('body', $.statement)
)),
//
@ -389,13 +400,13 @@ module.exports = grammar({
'case',
field('value', $._expressions),
':',
repeat($.statement)
field('body', repeat($.statement))
),
switch_default: $ => seq(
'default',
':',
repeat($.statement)
field('body', repeat($.statement))
),
catch_clause: $ => seq(
@ -712,14 +723,14 @@ module.exports = grammar({
new_expression: $ => prec.right('new', seq(
'new',
field('constructor', $.primary_expression),
field('constructor', choice($.primary_expression, $.new_expression)),
field('arguments', optional(prec.dynamic(1, $.arguments)))
)),
await_expression: $ => seq(
await_expression: $ => prec('unary_void', seq(
'await',
$.expression
),
)),
member_expression: $ => prec('member', seq(
field('object', choice($.expression, $.primary_expression)),
@ -759,8 +770,8 @@ module.exports = grammar({
augmented_assignment_expression: $ => prec.right('assign', seq(
field('left', $._augmented_assignment_lhs),
choice('+=', '-=', '*=', '/=', '%=', '^=', '&=', '|=', '>>=', '>>>=',
'<<=', '**=', '&&=', '||=', '??='),
field('operator', choice('+=', '-=', '*=', '/=', '%=', '^=', '&=', '|=', '>>=', '>>>=',
'<<=', '**=', '&&=', '||=', '??=')),
field('right', $.expression)
)),
@ -778,7 +789,7 @@ module.exports = grammar({
ternary_expression: $ => prec.right('ternary', seq(
field('condition', $.expression),
'?',
alias($._ternary_qmark, '?'),
field('consequence', $.expression),
':',
field('alternative', $.expression)
@ -786,14 +797,14 @@ module.exports = grammar({
binary_expression: $ => choice(
...[
['&&', 'binary_and'],
['||', 'binary_or'],
['>>', 'binary_times'],
['>>>', 'binary_times'],
['<<', 'binary_times'],
['&', 'binary_and'],
['^', 'binary_or'],
['|', 'binary_or'],
['&&', 'logical_and'],
['||', 'logical_or'],
['>>', 'binary_shift'],
['>>>', 'binary_shift'],
['<<', 'binary_shift'],
['&', 'bitwise_and'],
['^', 'bitwise_xor'],
['|', 'bitwise_or'],
['+', 'binary_plus'],
['-', 'binary_plus'],
['*', 'binary_times'],
@ -802,15 +813,15 @@ module.exports = grammar({
['**', 'binary_exp'],
['<', 'binary_relation'],
['<=', 'binary_relation'],
['==', 'binary_relation'],
['===', 'binary_relation'],
['!=', 'binary_relation'],
['!==', 'binary_relation'],
['==', 'binary_equality'],
['===', 'binary_equality'],
['!=', 'binary_equality'],
['!==', 'binary_equality'],
['>=', 'binary_relation'],
['>', 'binary_relation'],
['??', 'ternary'],
['instanceof', 'binary_relation'],
['in', 'binary_in'],
['in', 'binary_relation'],
].map(([operator, precedence]) =>
prec.left(precedence, seq(
field('left', $.expression),
@ -820,19 +831,9 @@ module.exports = grammar({
)
),
unary_expression: $ => choice(...[
['!', 'unary_not'],
['~', 'unary_not'],
['-', 'unary_not'],
['+', 'unary_not'],
['typeof', 'unary_void'],
['void', 'unary_void'],
['delete', 'unary_void'],
].map(([operator, precedence]) =>
prec.left(precedence, seq(
field('operator', operator),
field('argument', $.expression)
))
unary_expression: $ => prec.left('unary_void', seq(
field('operator', choice('!', '~', '-', '+', 'typeof', 'void', 'delete')),
field('argument', $.expression)
)),
update_expression: $ => prec.left(choice(
@ -1001,14 +1002,14 @@ module.exports = grammar({
),
identifier: $ => {
const alpha = /[^\x00-\x1F\s0-9:;`"'@#.,|^&<=>+\-*/\\%?!~()\[\]{}\uFEFF\u2060\u200B\u00A0]|\\u[0-9a-fA-F]{4}|\\u\{[0-9a-fA-F]+\}/
const alphanumeric = /[^\x00-\x1F\s:;`"'@#.,|^&<=>+\-*/\\%?!~()\[\]{}\uFEFF\u2060\u200B\u00A0]|\\u[0-9a-fA-F]{4}|\\u\{[0-9a-fA-F]+\}/
const alpha = /[^\x00-\x1F\s\p{Zs}0-9:;`"'@#.,|^&<=>+\-*/\\%?!~()\[\]{}\uFEFF\u2060\u200B]|\\u[0-9a-fA-F]{4}|\\u\{[0-9a-fA-F]+\}/
const alphanumeric = /[^\x00-\x1F\s\p{Zs}:;`"'@#.,|^&<=>+\-*/\\%?!~()\[\]{}\uFEFF\u2060\u200B]|\\u[0-9a-fA-F]{4}|\\u\{[0-9a-fA-F]+\}/
return token(seq(alpha, repeat(alphanumeric)))
},
private_property_identifier: $ => {
const alpha = /[^\x00-\x1F\s0-9:;`"'@#.,|^&<=>+\-*/\\%?!~()\[\]{}\uFEFF\u2060\u200B\u00A0]|\\u[0-9a-fA-F]{4}|\\u\{[0-9a-fA-F]+\}/
const alphanumeric = /[^\x00-\x1F\s:;`"'@#.,|^&<=>+\-*/\\%?!~()\[\]{}\uFEFF\u2060\u200B\u00A0]|\\u[0-9a-fA-F]{4}|\\u\{[0-9a-fA-F]+\}/
const alpha = /[^\x00-\x1F\s\p{Zs}0-9:;`"'@#.,|^&<=>+\-*/\\%?!~()\[\]{}\uFEFF\u2060\u200B]|\\u[0-9a-fA-F]{4}|\\u\{[0-9a-fA-F]+\}/
const alphanumeric = /[^\x00-\x1F\s\p{Zs}:;`"'@#.,|^&<=>+\-*/\\%?!~()\[\]{}\uFEFF\u2060\u200B]|\\u[0-9a-fA-F]{4}|\\u\{[0-9a-fA-F]+\}/
return token(seq('#', alpha, repeat(alphanumeric)))
},
@ -1086,19 +1087,14 @@ module.exports = grammar({
// unfinished constructs are generally treated as literal expressions,
// not patterns.
pattern: $ => prec.dynamic(-1, choice(
$.identifier,
alias($._reserved_identifier, $.identifier),
$._destructuring_pattern,
$._lhs_expression,
$.rest_pattern
)),
rest_pattern: $ => seq(
rest_pattern: $ => prec.right(seq(
'...',
choice(
$.identifier,
$._destructuring_pattern,
)
),
$._lhs_expression
)),
method_definition: $ => seq(
repeat(field('decorator', $.decorator)),

@ -1,19 +1,23 @@
{
"name": "tree-sitter-javascript",
"version": "0.19.0",
"version": "0.20.0",
"description": "Javascript grammar for node-tree-sitter",
"main": "bindings/node",
"keywords": [
"parser",
"lexer"
],
"repository": {
"type": "git",
"url": "https://github.com/tree-sitter/tree-sitter-javascript.git"
},
"author": "Max Brunsfeld",
"license": "MIT",
"dependencies": {
"nan": "^2.12.1"
},
"devDependencies": {
"tree-sitter-cli": "^0.19.2"
"tree-sitter-cli": "^0.20.0"
},
"scripts": {
"test": "tree-sitter test && script/parse-examples",

File diff suppressed because it is too large Load Diff

@ -95,6 +95,10 @@
"type": "identifier",
"named": true
},
{
"type": "member_expression",
"named": true
},
{
"type": "object_pattern",
"named": true
@ -102,6 +106,14 @@
{
"type": "rest_pattern",
"named": true
},
{
"type": "subscript_expression",
"named": true
},
{
"type": "undefined",
"named": true
}
]
},
@ -488,6 +500,72 @@
}
]
},
"operator": {
"multiple": false,
"required": true,
"types": [
{
"type": "%=",
"named": false
},
{
"type": "&&=",
"named": false
},
{
"type": "&=",
"named": false
},
{
"type": "**=",
"named": false
},
{
"type": "*=",
"named": false
},
{
"type": "+=",
"named": false
},
{
"type": "-=",
"named": false
},
{
"type": "/=",
"named": false
},
{
"type": "<<=",
"named": false
},
{
"type": ">>=",
"named": false
},
{
"type": ">>>=",
"named": false
},
{
"type": "??=",
"named": false
},
{
"type": "^=",
"named": false
},
{
"type": "|=",
"named": false
},
{
"type": "||=",
"named": false
}
]
},
"right": {
"multiple": false,
"required": true,
@ -1054,7 +1132,7 @@
"named": true
},
{
"type": "namespace_import",
"type": "namespace_export",
"named": true
}
]
@ -1161,6 +1239,24 @@
}
]
},
"kind": {
"multiple": false,
"required": false,
"types": [
{
"type": "const",
"named": false
},
{
"type": "let",
"named": false
},
{
"type": "var",
"named": false
}
]
},
"left": {
"multiple": false,
"required": true,
@ -1195,6 +1291,20 @@
}
]
},
"operator": {
"multiple": false,
"required": true,
"types": [
{
"type": "in",
"named": false
},
{
"type": "of",
"named": false
}
]
},
"right": {
"multiple": false,
"required": true,
@ -1208,6 +1318,16 @@
"named": true
}
]
},
"value": {
"multiple": false,
"required": false,
"types": [
{
"type": "expression",
"named": true
}
]
}
}
},
@ -1820,6 +1940,16 @@
"type": "labeled_statement",
"named": true,
"fields": {
"body": {
"multiple": false,
"required": true,
"types": [
{
"type": "statement",
"named": true
}
]
},
"label": {
"multiple": false,
"required": true,
@ -1830,22 +1960,27 @@
}
]
}
},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "statement",
"named": true
}
]
}
},
{
"type": "lexical_declaration",
"named": true,
"fields": {},
"fields": {
"kind": {
"multiple": false,
"required": true,
"types": [
{
"type": "const",
"named": false
},
{
"type": "let",
"named": false
}
]
}
},
"children": {
"multiple": true,
"required": true,
@ -1969,6 +2104,21 @@
]
}
},
{
"type": "namespace_export",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": true,
"types": [
{
"type": "identifier",
"named": true
}
]
}
},
{
"type": "namespace_import",
"named": true,
@ -2021,6 +2171,10 @@
"multiple": false,
"required": true,
"types": [
{
"type": "new_expression",
"named": true
},
{
"type": "primary_expression",
"named": true
@ -2285,9 +2439,21 @@
"type": "identifier",
"named": true
},
{
"type": "member_expression",
"named": true
},
{
"type": "object_pattern",
"named": true
},
{
"type": "subscript_expression",
"named": true
},
{
"type": "undefined",
"named": true
}
]
}
@ -2443,6 +2609,16 @@
"type": "switch_case",
"named": true,
"fields": {
"body": {
"multiple": true,
"required": false,
"types": [
{
"type": "statement",
"named": true
}
]
},
"value": {
"multiple": false,
"required": true,
@ -2457,31 +2633,22 @@
}
]
}
},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "statement",
"named": true
}
]
}
},
{
"type": "switch_default",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "statement",
"named": true
}
]
"fields": {
"body": {
"multiple": true,
"required": false,
"types": [
{
"type": "statement",
"named": true
}
]
}
}
},
{

File diff suppressed because it is too large Load Diff

@ -3,7 +3,8 @@
enum TokenType {
AUTOMATIC_SEMICOLON,
TEMPLATE_CHARS
TEMPLATE_CHARS,
TERNARY_QMARK,
};
void *tree_sitter_javascript_external_scanner_create() { return NULL; }
@ -13,32 +14,54 @@ unsigned tree_sitter_javascript_external_scanner_serialize(void *p, char *buffer
void tree_sitter_javascript_external_scanner_deserialize(void *p, const char *b, unsigned n) {}
static void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
static void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
static bool scan_template_chars(TSLexer *lexer) {
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);
}
}
}
static bool scan_whitespace_and_comments(TSLexer *lexer) {
for (;;) {
while (iswspace(lexer->lookahead)) {
advance(lexer);
skip(lexer);
}
if (lexer->lookahead == '/') {
advance(lexer);
skip(lexer);
if (lexer->lookahead == '/') {
advance(lexer);
skip(lexer);
while (lexer->lookahead != 0 && lexer->lookahead != '\n') {
advance(lexer);
skip(lexer);
}
} else if (lexer->lookahead == '*') {
advance(lexer);
skip(lexer);
while (lexer->lookahead != 0) {
if (lexer->lookahead == '*') {
advance(lexer);
skip(lexer);
if (lexer->lookahead == '/') {
advance(lexer);
skip(lexer);
break;
}
} else {
advance(lexer);
skip(lexer);
}
}
} else {
@ -50,96 +73,115 @@ static bool scan_whitespace_and_comments(TSLexer *lexer) {
}
}
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);
static bool scan_automatic_semicolon(TSLexer *lexer) {
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;
for (;;) {
if (lexer->lookahead == 0) return true;
if (lexer->lookahead == '}') return true;
if (lexer->is_at_included_range_start(lexer)) return true;
if (lexer->lookahead == '\n') break;
if (!iswspace(lexer->lookahead)) return false;
skip(lexer);
}
switch (lexer->lookahead) {
case ',':
case '.':
case ':':
case ';':
case '*':
case '%':
case '>':
case '<':
case '=':
case '[':
case '(':
case '?':
case '^':
case '|':
case '&':
case '/':
return false;
skip(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 '+':
skip(lexer);
return lexer->lookahead == '+';
case '-':
skip(lexer);
return lexer->lookahead == '-';
// Don't insert a semicolon before `!=`, but do insert one before a unary `!`.
case '!':
skip(lexer);
return lexer->lookahead != '=';
// Don't insert a semicolon before `in` or `instanceof`, but do insert one
// before an identifier.
case 'i':
skip(lexer);
if (lexer->lookahead != 'n') return true;
skip(lexer);
if (!iswalpha(lexer->lookahead)) return false;
for (unsigned i = 0; i < 8; i++) {
if (lexer->lookahead != "stanceof"[i]) return true;
skip(lexer);
}
// Insert a semicolon before `--` and `++`, but not before binary `+` or `-`.
case '+':
advance(lexer);
return lexer->lookahead == '+';
case '-':
advance(lexer);
return lexer->lookahead == '-';
if (!iswalpha(lexer->lookahead)) return false;
break;
}
// Don't insert a semicolon before `!=`, but do insert one before a unary `!`.
case '!':
advance(lexer);
return lexer->lookahead != '=';
return true;
}
// Don't insert a semicolon before `in` or `instanceof`, but do insert one
// before an identifier.
case 'i':
advance(lexer);
static bool scan_ternary_qmark(TSLexer *lexer) {
for(;;) {
if (!iswspace(lexer->lookahead)) break;
skip(lexer);
}
if (lexer->lookahead != 'n') return true;
advance(lexer);
if (lexer->lookahead == '?') {
advance(lexer);
if (!iswalpha(lexer->lookahead)) return false;
if (lexer->lookahead == '?') return false;
for (unsigned i = 0; i < 8; i++) {
if (lexer->lookahead != "stanceof"[i]) return true;
advance(lexer);
}
lexer->mark_end(lexer);
lexer->result_symbol = TERNARY_QMARK;
if (!iswalpha(lexer->lookahead)) return false;
break;
if (lexer->lookahead == '.') {
advance(lexer);
if (iswdigit(lexer->lookahead)) return true;
return false;
}
return true;
}
return false;
}
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;
return scan_template_chars(lexer);
} else if (valid_symbols[AUTOMATIC_SEMICOLON]) {
bool ret = scan_automatic_semicolon(lexer);
if (!ret && valid_symbols[TERNARY_QMARK] && lexer->lookahead == '?')
return scan_ternary_qmark(lexer);
return ret;
}
if (valid_symbols[TERNARY_QMARK]) {
return scan_ternary_qmark(lexer);
}
return false;
}

@ -2,7 +2,7 @@
Object destructuring assignments
============================================
({a, b} = object);
({a, b: c.d, ...e[f]} = object);
let {a, b, ...c} = object
const {a, b: {c, d}} = object
@ -12,7 +12,10 @@ const {a, b: {c, d}} = object
(expression_statement (parenthesized_expression (assignment_expression
(object_pattern
(shorthand_property_identifier_pattern)
(shorthand_property_identifier_pattern))
(pair_pattern
(property_identifier)
(member_expression (identifier) (property_identifier)))
(rest_pattern (subscript_expression (identifier) (identifier))))
(identifier))))
(lexical_declaration (variable_declarator
(object_pattern
@ -49,7 +52,7 @@ function a ({b, c}, {d}) {}
Array destructuring assignments
============================================
[a, b] = array;
[a, b.c, ...c[d]] = array;
[a, b, ...c] = array;
[,, c,, d,] = array;
@ -59,7 +62,8 @@ Array destructuring assignments
(expression_statement (assignment_expression
(array_pattern
(identifier)
(identifier))
(member_expression (identifier) (property_identifier))
(rest_pattern (subscript_expression (identifier) (identifier))))
(identifier)))
(expression_statement (assignment_expression
(array_pattern

@ -812,6 +812,8 @@ Constructor calls
new module.Klass(1, "two");
new Thing;
new new module.Klass(1)("two");
new new Thing;
---
@ -820,7 +822,14 @@ new Thing;
(member_expression (identifier) (property_identifier))
(arguments (number) (string (string_fragment)))))
(expression_statement (new_expression
(identifier))))
(identifier)))
(expression_statement (new_expression
(new_expression
(member_expression (identifier) (property_identifier))
(arguments (number)))
(arguments (string (string_fragment)))))
(expression_statement (new_expression
(new_expression (identifier)))))
============================================
Await Expressions
@ -1069,17 +1078,39 @@ condition ? case1 : case2;
x.y = some.condition ?
some.case :
some.other.case;
a?.1:.2
---
(program
(expression_statement (ternary_expression
(identifier) (identifier) (identifier)))
(expression_statement (assignment_expression
(member_expression (identifier) (property_identifier))
(expression_statement
(ternary_expression
(member_expression (identifier) (property_identifier))
(member_expression (identifier) (property_identifier))
(member_expression (member_expression (identifier) (property_identifier)) (property_identifier))))))
(identifier)
(identifier)
(identifier)))
(expression_statement
(assignment_expression
(member_expression
(identifier)
(property_identifier))
(ternary_expression
(member_expression
(identifier)
(property_identifier))
(member_expression
(identifier)
(property_identifier))
(member_expression
(member_expression
(identifier)
(property_identifier))
(property_identifier)))))
(expression_statement
(ternary_expression
(identifier)
(number)
(number))))
==============================================
Type operators
@ -1168,6 +1199,10 @@ a.b = c ? d : e;
a && b(c) && d;
a && new b(c) && d;
typeof a == b && c instanceof d
a && b | c;
a - b << c;
a in b != c in d;
await a || b;
---
@ -1192,7 +1227,19 @@ typeof a == b && c instanceof d
(binary_expression
(unary_expression (identifier))
(identifier))
(binary_expression (identifier) (identifier)))))
(binary_expression (identifier) (identifier))))
(expression_statement (binary_expression
(identifier)
(binary_expression (identifier) (identifier))))
(expression_statement (binary_expression
(binary_expression (identifier) (identifier))
(identifier)))
(expression_statement (binary_expression
(binary_expression (identifier) (identifier))
(binary_expression (identifier) (identifier))))
(expression_statement (binary_expression
(await_expression (identifier))
(identifier))))
==============================================
Simple JSX elements
@ -1294,12 +1341,15 @@ Expressions with rest elements
==============================================
foo(...rest)
foo = [...[bar] = [baz]]
---
(program
(expression_statement
(call_expression (identifier) (arguments (spread_element (identifier))))))
(call_expression (identifier) (arguments (spread_element (identifier)))))
(expression_statement
(assignment_expression (identifier) (array (spread_element (assignment_expression (array_pattern (identifier)) (array (identifier))))))))
==============================================
Forward slashes after parenthesized expressions

@ -149,7 +149,7 @@ export { import1 as name1, import2 as name2, nameN } from 'foo';
(export_statement
source: (string (string_fragment)))
(export_statement
(namespace_import (identifier))
(namespace_export (identifier))
source: (string (string_fragment)))
(export_statement
(export_clause
@ -341,6 +341,8 @@ for ([a, b] in c) {}
for ((a) in b) {}
for (var foo = bar in baz) {}
---
(program
@ -371,6 +373,11 @@ for ((a) in b) {}
(for_in_statement
(parenthesized_expression (identifier))
(identifier)
(statement_block))
(for_in_statement
(identifier)
(identifier)
(identifier)
(statement_block)))
==========================================
@ -758,7 +765,7 @@ while (true) {
(program
(labeled_statement
label: (statement_identifier)
(for_statement
body: (for_statement
initializer: (empty_statement)
condition: (empty_statement)
body: (statement_block
@ -771,11 +778,11 @@ while (true) {
(continue_statement label: (statement_identifier))))))))
(labeled_statement
label: (statement_identifier)
(statement_block
body: (statement_block
(break_statement label: (statement_identifier))))
(labeled_statement
label: (statement_identifier)
(while_statement
body: (while_statement
condition: (parenthesized_expression (true))
body: (statement_block
(continue_statement label: (statement_identifier))))))