# Minimal

0

==>

Script(ExpressionStatement(Number))

# Strings

"A string with \"double\" and 'single' quotes";
'A string with "double" and \'single\' quotes';
'\\';
"\\";

'A string with new \
line';

==>

Script(ExpressionStatement(String(Escape,Escape)),
       ExpressionStatement(String(Escape,Escape)),
       ExpressionStatement(String(Escape)),
       ExpressionStatement(String(Escape)),
       ExpressionStatement(String(Escape)))

# Numbers

101;
3.14;
3.14e+1;
0x1ABCDEFabcdef;
0o7632157312;
0b1010101001;
1e+3;

==>

Script(
  ExpressionStatement(Number),
  ExpressionStatement(Number),
  ExpressionStatement(Number),
  ExpressionStatement(Number),
  ExpressionStatement(Number),
  ExpressionStatement(Number),
  ExpressionStatement(Number))

# Identifiers

theVar;
theVar2;
$_;
é象𫝄;
últimaVez;
県;

==>

Script(
  ExpressionStatement(VariableName),
  ExpressionStatement(VariableName),
  ExpressionStatement(VariableName),
  ExpressionStatement(VariableName),
  ExpressionStatement(VariableName),
  ExpressionStatement(VariableName))

# RegExps

/one\\/;
/one/g;
/one/i;
/one/gim;
/on\/e/gim;
/on[^/]afe/gim;
/[\]/]/;

==>

Script(
  ExpressionStatement(RegExp),
  ExpressionStatement(RegExp),
  ExpressionStatement(RegExp),
  ExpressionStatement(RegExp),
  ExpressionStatement(RegExp),
  ExpressionStatement(RegExp),
  ExpressionStatement(RegExp))

# Arrays

[];
[ "item1" ];
[ "item1", ];
[ "item1", item2 ];
[ , item2 ];
[ item2 = 5 ];
[ a, ...b, c ];

==>

Script(
  ExpressionStatement(ArrayExpression),
  ExpressionStatement(ArrayExpression(String)),
  ExpressionStatement(ArrayExpression(String)),
  ExpressionStatement(ArrayExpression(String,VariableName)),
  ExpressionStatement(ArrayExpression(VariableName)),
  ExpressionStatement(ArrayExpression(AssignmentExpression(VariableName,Equals,Number))),
  ExpressionStatement(ArrayExpression(VariableName, Spread, VariableName, VariableName)))

# Functions

[
  function() {},
  function(arg1, ...arg2) {
    arg2;
  },
  function stuff() {},
  function trailing(a,) {},
  function trailing(a,b,) {}
]

==>

Script(ExpressionStatement(ArrayExpression(
  FunctionExpression(function,ParamList,Block),
  FunctionExpression(function,ParamList(VariableDefinition,Spread,VariableDefinition), Block(ExpressionStatement(VariableName))),
  FunctionExpression(function,VariableDefinition,ParamList,Block),
  FunctionExpression(function,VariableDefinition,ParamList(VariableDefinition), Block),
  FunctionExpression(function,VariableDefinition,ParamList(VariableDefinition,VariableDefinition),Block))))

# Arrow functions

a => 1;
() => 2;
(d, e) => 3;
(f, g,) => {
  return h;
};
async () => 4;

==>

Script(
  ExpressionStatement(ArrowFunction(ParamList(VariableDefinition),Arrow,Number)),
  ExpressionStatement(ArrowFunction(ParamList,Arrow,Number)),
  ExpressionStatement(ArrowFunction(ParamList(VariableDefinition,VariableDefinition),Arrow,Number)),
  ExpressionStatement(ArrowFunction(ParamList(VariableDefinition,VariableDefinition),Arrow,Block(ReturnStatement(return,VariableName)))),
  ExpressionStatement(ArrowFunction(async,ParamList,Arrow,Number)))

# Arrow function followed by comma

({
  a: () => 1,
  b: "x"
})

==>

Script(ExpressionStatement(ParenthesizedExpression(ObjectExpression(
  Property(PropertyDefinition,ArrowFunction(ParamList,Arrow,Number)),
  Property(PropertyDefinition,String)))))

# Long potential arrow function

(assign = [to, from], from = assign[0], to = assign[1]);

==>

Script(ExpressionStatement(ParenthesizedExpression(SequenceExpression(
  AssignmentExpression(VariableName,Equals,ArrayExpression(VariableName,VariableName)),
  AssignmentExpression(VariableName,Equals,MemberExpression(VariableName,Number)),
  AssignmentExpression(VariableName,Equals,MemberExpression(VariableName,Number))))))

# Ternary operator

condition ? case1 : case2;

x.y = some.condition ? 2**x : 1 - 2;

==>

Script(
  ExpressionStatement(ConditionalExpression(VariableName,LogicOp,VariableName,LogicOp,VariableName)),
  ExpressionStatement(AssignmentExpression(
    MemberExpression(VariableName,PropertyName),Equals,
    ConditionalExpression(
      MemberExpression(VariableName,PropertyName),LogicOp,
      BinaryExpression(Number,ArithOp,VariableName),LogicOp,
      BinaryExpression(Number,ArithOp,Number)))))

# Type operators

typeof x;
x instanceof String;

==>

Script(ExpressionStatement(UnaryExpression(typeof,VariableName)),
       ExpressionStatement(BinaryExpression(VariableName,instanceof,VariableName)))

# Delete

delete thing['prop'];
true ? delete thing.prop : null;

==>

Script(
  ExpressionStatement(UnaryExpression(delete,MemberExpression(VariableName,String))),
  ExpressionStatement(ConditionalExpression(BooleanLiteral,LogicOp,
    UnaryExpression(delete,MemberExpression(VariableName,PropertyName)),LogicOp,null)))

# Void

a = void b();

==>

Script(ExpressionStatement(AssignmentExpression(VariableName,Equals,UnaryExpression(void,CallExpression(VariableName,ArgList)))))

# Augmented assignment

s |= 1;
t %= 2;
w ^= 3;
x += 4;
y.z *= 5;
z += 1;
a >>= 1;
b >>>= 1;
c <<= 1;

==>

Script(
  ExpressionStatement(AssignmentExpression(VariableName,UpdateOp,Number)),
  ExpressionStatement(AssignmentExpression(VariableName,UpdateOp,Number)),
  ExpressionStatement(AssignmentExpression(VariableName,UpdateOp,Number)),
  ExpressionStatement(AssignmentExpression(VariableName,UpdateOp,Number)),
  ExpressionStatement(AssignmentExpression(MemberExpression(VariableName,PropertyName),UpdateOp,Number)),
  ExpressionStatement(AssignmentExpression(VariableName,UpdateOp,Number)),
  ExpressionStatement(AssignmentExpression(VariableName,UpdateOp,Number)),
  ExpressionStatement(AssignmentExpression(VariableName,UpdateOp,Number)),
  ExpressionStatement(AssignmentExpression(VariableName,UpdateOp,Number)))

# Operator precedence

a <= b && c >= d;
a.b = c ? d : e;
a && b(c) && d;
a && new b(c) && d;
typeof a == b && c instanceof d;

==>

Script(
  ExpressionStatement(BinaryExpression(BinaryExpression(VariableName,CompareOp,VariableName),LogicOp,
    BinaryExpression(VariableName,CompareOp,VariableName))),
  ExpressionStatement(AssignmentExpression(MemberExpression(VariableName,PropertyName),Equals,
    ConditionalExpression(VariableName,LogicOp,VariableName,LogicOp,VariableName))),
  ExpressionStatement(BinaryExpression(BinaryExpression(VariableName,LogicOp,CallExpression(VariableName,ArgList(VariableName))),LogicOp,
    VariableName)),
  ExpressionStatement(BinaryExpression(BinaryExpression(VariableName,LogicOp,NewExpression(new,VariableName,ArgList(VariableName))),LogicOp,
    VariableName)),
  ExpressionStatement(BinaryExpression(BinaryExpression(UnaryExpression(typeof,VariableName),CompareOp,VariableName),LogicOp,
    BinaryExpression(VariableName,instanceof,VariableName))))

# Rest args

foo(...rest);

==>

Script(ExpressionStatement(CallExpression(VariableName,ArgList(Spread,VariableName))))

# Forward slashes after parenthesized expressions

(foo - bar) / baz;
if (foo - bar) /baz/;
(this.a() / this.b() - 1) / 2;

==>

Script(
  ExpressionStatement(BinaryExpression(ParenthesizedExpression(BinaryExpression(VariableName,ArithOp,VariableName)),ArithOp,VariableName)),
  IfStatement(if,ParenthesizedExpression(BinaryExpression(VariableName,ArithOp,VariableName)),
    ExpressionStatement(RegExp)),
  ExpressionStatement(BinaryExpression(ParenthesizedExpression(
    BinaryExpression(
      BinaryExpression(
        CallExpression(MemberExpression(this,PropertyName),ArgList),ArithOp,
        CallExpression(MemberExpression(this,PropertyName),ArgList)),ArithOp,Number)),ArithOp,Number)))

# Yield expressions

yield db.users.where('[endpoint+email]');
yield* a;
yield [22];

==>

Script(
  ExpressionStatement(YieldExpression(yield,
    CallExpression(MemberExpression(MemberExpression(VariableName,PropertyName),PropertyName),ArgList(String)))),
  ExpressionStatement(YieldExpression(yield,Star,VariableName)),
  ExpressionStatement(YieldExpression(yield,ArrayExpression(Number))))

# Template strings

`one line`;
`multi
  line`;

`multi
  ${2 + 2}
  hello
  ${1, 2}
  line`;

`$$$$`;
`$`;
`$$$$${ async }`;

`\\\``;

`one${`two${`three`}`}`;

f`hi${there}`;

==>

Script(
  ExpressionStatement(TemplateString),
  ExpressionStatement(TemplateString),
  ExpressionStatement(TemplateString(
    Interpolation(InterpolationStart,BinaryExpression(Number,ArithOp,Number),InterpolationEnd),
    Interpolation(InterpolationStart,SequenceExpression(Number,Number),InterpolationEnd))),
  ExpressionStatement(TemplateString),
  ExpressionStatement(TemplateString),
  ExpressionStatement(TemplateString(Interpolation(InterpolationStart,VariableName,InterpolationEnd))),
  ExpressionStatement(TemplateString(Escape,Escape)),
  ExpressionStatement(TemplateString(Interpolation(InterpolationStart,TemplateString(
    Interpolation(InterpolationStart,TemplateString,InterpolationEnd)),InterpolationEnd))),
  ExpressionStatement(TaggedTemplateExpression(VariableName,TemplateString(
    Interpolation(InterpolationStart,VariableName,InterpolationEnd)))))

# Atoms

this;
null;
undefined;
true;
false;

==>

Script(
  ExpressionStatement(this),
  ExpressionStatement(null),
  ExpressionStatement(VariableName),
  ExpressionStatement(BooleanLiteral),
  ExpressionStatement(BooleanLiteral))

# Objects

foo({},
    { a: "b" },
    { c: "d", "e": f, 1: 2 },
    {
      g,
      [methodName]() {}
    },
    {b, get},
    {a,});

==>

Script(ExpressionStatement(CallExpression(VariableName,ArgList(
  ObjectExpression,
  ObjectExpression(Property(PropertyDefinition,String)),
  ObjectExpression(Property(PropertyDefinition,String),Property(String,VariableName),Property(Number,Number)),
  ObjectExpression(Property(PropertyDefinition),Property(VariableName,ParamList,Block)),
  ObjectExpression(Property(PropertyDefinition),Property(PropertyDefinition)),
  ObjectExpression(Property(PropertyDefinition))))))

# Method definitions

({
  foo: true,

  add(a, b) {
    return a + b;
  },

  get bar() { return c; },

  set bar(a) { c = a; },

  *barGenerator() { yield c; },

  get() { return 1; }
});

==>

Script(ExpressionStatement(ParenthesizedExpression(ObjectExpression(
  Property(PropertyDefinition,BooleanLiteral),
  Property(PropertyDefinition,ParamList(VariableDefinition,VariableDefinition),
    Block(ReturnStatement(return,BinaryExpression(VariableName,ArithOp,VariableName)))),
  Property(get,PropertyDefinition,ParamList,Block(ReturnStatement(return,VariableName))),
  Property(set,PropertyDefinition,ParamList(VariableDefinition),
    Block(ExpressionStatement(AssignmentExpression(VariableName,Equals,VariableName)))),
  Property(Star,PropertyDefinition,ParamList,Block(ExpressionStatement(YieldExpression(yield,VariableName)))),
  Property(PropertyDefinition,ParamList,Block(ReturnStatement(return,Number)))))))

# Keyword property names

({
  finally() {},
  catch() {},
  get: function () {},
  set() {},
  static: true,
  async: true,
});

==>

Script(ExpressionStatement(ParenthesizedExpression(ObjectExpression(
  Property(PropertyDefinition,ParamList,Block),
  Property(PropertyDefinition,ParamList,Block),
  Property(PropertyDefinition,FunctionExpression(function,ParamList,Block)),
  Property(PropertyDefinition,ParamList,Block),
  Property(PropertyDefinition,BooleanLiteral),
  Property(PropertyDefinition,BooleanLiteral)))))

# Generator functions

[
  function *() {},
  function *generateStuff(arg1, arg2) {
    yield;
    yield arg2;
  }
];

==>

Script(ExpressionStatement(ArrayExpression(
  FunctionExpression(function,Star,ParamList,Block),
  FunctionExpression(function,Star,VariableDefinition,ParamList(VariableDefinition,VariableDefinition),Block(
    ExpressionStatement(VariableName),
    ExpressionStatement(YieldExpression(yield,VariableName)))))))

# Member expressions

x.someProperty;
x?.other;
x[someVariable];
f()["some-string"];
return returned.promise().done(a).fail(b);

==>

Script(
  ExpressionStatement(MemberExpression(VariableName,PropertyName)),
  ExpressionStatement(MemberExpression(VariableName,PropertyName)),
  ExpressionStatement(MemberExpression(VariableName,VariableName)),
  ExpressionStatement(MemberExpression(CallExpression(VariableName,ArgList),String)),
  ReturnStatement(return,CallExpression(MemberExpression(CallExpression(MemberExpression(CallExpression(
    MemberExpression(VariableName,PropertyName),ArgList),PropertyName),ArgList(VariableName)),PropertyName),ArgList(VariableName))))

# Callback chain

return this.map(function (a) {
  return a.b;
})

// a comment

.filter(function (c) {
  return 2;
});

==>

Script(ReturnStatement(return,CallExpression(MemberExpression(CallExpression(MemberExpression(this,PropertyName),
  ArgList(FunctionExpression(function,ParamList(VariableDefinition),Block(ReturnStatement(return,MemberExpression(VariableName,PropertyName)))))),
  LineComment,PropertyName),ArgList(FunctionExpression(function,ParamList(VariableDefinition),Block(ReturnStatement(return,Number)))))))

# Function calls

x.someMethod(arg1, "arg2");
(function(x, y) {

}(a, b));
f(new foo.bar(1), 2);

==>

Script(
  ExpressionStatement(CallExpression(MemberExpression(VariableName,PropertyName),ArgList(VariableName,String))),
  ExpressionStatement(ParenthesizedExpression(CallExpression(FunctionExpression(function,ParamList(VariableDefinition,VariableDefinition),Block),
    ArgList(VariableName,VariableName)))),
  ExpressionStatement(CallExpression(VariableName,ArgList(NewExpression(new,MemberExpression(VariableName,PropertyName),ArgList(Number)),Number))))

# Constructor calls

new foo(1);
new module.Klass(1, "two");
new Thing;

==>

Script(
  ExpressionStatement(NewExpression(new,VariableName,ArgList(Number))),
  ExpressionStatement(NewExpression(new,MemberExpression(VariableName,PropertyName),ArgList(Number,String))),
  ExpressionStatement(NewExpression(new,VariableName)))

# Await Expressions

await asyncFunction();
await asyncPromise;

==>

Script(
  ExpressionStatement(AwaitExpression(await,CallExpression(VariableName,ArgList))),
  ExpressionStatement(AwaitExpression(await,VariableName)))

# Numeric operators

i++;
i--;
i + j * 3 - j % 5;
2 ** i * 3;
2 * i ** 3;
+x;
-x;

==>

Script(
  ExpressionStatement(PostfixExpression(VariableName,ArithOp)),
  ExpressionStatement(PostfixExpression(VariableName,ArithOp)),
  ExpressionStatement(BinaryExpression(BinaryExpression(VariableName,ArithOp,BinaryExpression(VariableName,ArithOp,Number)),ArithOp,BinaryExpression(VariableName,ArithOp,Number))),
  ExpressionStatement(BinaryExpression(BinaryExpression(Number,ArithOp,VariableName),ArithOp,Number)),
  ExpressionStatement(BinaryExpression(Number,ArithOp,BinaryExpression(VariableName,ArithOp,Number))),
  ExpressionStatement(UnaryExpression(ArithOp,VariableName)),
  ExpressionStatement(UnaryExpression(ArithOp,VariableName)))

# Boolean operators

i || j;
i && j;
i ?? j;
!a && !b || !c && !d;

==>

Script(
  ExpressionStatement(BinaryExpression(VariableName,LogicOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,LogicOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,LogicOp,VariableName)),
  ExpressionStatement(BinaryExpression(BinaryExpression(UnaryExpression(LogicOp,VariableName),LogicOp,
    UnaryExpression(LogicOp,VariableName)),LogicOp,BinaryExpression(UnaryExpression(LogicOp,VariableName),LogicOp,
      UnaryExpression(LogicOp,VariableName)))))

# Bitwise operators

i >> j;
i >>> j;
i << j;
i & j;
i | j;
~i ^ ~j;

==>

Script(
  ExpressionStatement(BinaryExpression(VariableName,BitOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,BitOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,BitOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,BitOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,BitOp,VariableName)),
  ExpressionStatement(BinaryExpression(UnaryExpression(BitOp,VariableName),BitOp,UnaryExpression(BitOp,VariableName))))

# Relational operators

x < y;
x <= y;
x == y;
x === y;
x != y;
x !== y;
x > y;
x >= y;

==>

Script(
  ExpressionStatement(BinaryExpression(VariableName,CompareOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,CompareOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,CompareOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,CompareOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,CompareOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,CompareOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,CompareOp,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,CompareOp,VariableName)))

# Word operators

x in y;
x instanceof y;
!x instanceof y;

==>

Script(
  ExpressionStatement(BinaryExpression(VariableName,in,VariableName)),
  ExpressionStatement(BinaryExpression(VariableName,instanceof,VariableName)),
  ExpressionStatement(BinaryExpression(UnaryExpression(LogicOp,VariableName),instanceof,VariableName)))

# Assignments

x = 0;
x.y = 0;
x["y"] = 0;
async = 0;
[a, b = 2] = foo;
({a, b, ...d} = c);

==>

Script(
  ExpressionStatement(AssignmentExpression(VariableName,Equals,Number)),
  ExpressionStatement(AssignmentExpression(MemberExpression(VariableName,PropertyName),Equals,Number)),
  ExpressionStatement(AssignmentExpression(MemberExpression(VariableName,String),Equals,Number)),
  ExpressionStatement(AssignmentExpression(VariableName,Equals,Number)),
  ExpressionStatement(AssignmentExpression(ArrayPattern(VariableDefinition,VariableDefinition,Equals,Number),Equals,VariableName)),
  ExpressionStatement(ParenthesizedExpression(AssignmentExpression(ObjectPattern(
    PatternProperty(PropertyName),PatternProperty(PropertyName),PatternProperty(Spread,VariableDefinition)),Equals,VariableName))))

# Comma operator

a = 1, b = 2;
c = {d: (3, 4 + 5)};

==>

Script(
  ExpressionStatement(SequenceExpression(AssignmentExpression(VariableName,Equals,Number),AssignmentExpression(VariableName,Equals,Number))),
  ExpressionStatement(AssignmentExpression(VariableName,Equals,ObjectExpression(
    Property(PropertyDefinition,ParenthesizedExpression(SequenceExpression(Number,BinaryExpression(Number,ArithOp,Number))))))))

# Punctuation

(foo(1, 2), bar);

==>

Script(ExpressionStatement(ParenthesizedExpression(
  "(",SequenceExpression(CallExpression(VariableName,ArgList("(",Number,Number,")")),",",VariableName),")")))

# Doesn't choke on unfinished ternary operator

1?1

==>

Script(ExpressionStatement(ConditionalExpression(Number,LogicOp,Number,⚠)))

# Can handle unterminated template literals

`f

==>

Script(ExpressionStatement(TemplateString(⚠)))

# Ternary with leading-dot number

a?.2:.3

==>

Script(ExpressionStatement(ConditionalExpression(VariableName,LogicOp,Number,LogicOp,Number)))
