JAW uses the Esprima syntax tree format, which is derived from the original version of the Mozilla Parser API, and then formalized and expanded as the ESTree specification.
Each AST PGNode
contains at its base the following parameters. Depending on the type
of the node, certain properties will have a value or will be empty. These properties include: raw
, value
, code
, semanticType
, and kind
. Each property is shown in the corresponding PGNode
type. For example, kind
shows the type of a VariableDeclarator
(i.e, const
, let
or var
). The rest of the properties are detailed next.
PGNode Node {
id: int;
type: string;
range?: [number, number];
loc?: SourceLocation;
semanticType: string;
raw: string;
value: string;
code: string;
kind: string;
}
with the source location defined as:
JSON Position {
line: number;
column: number;
}
JSON SourceLocation {
start: Position;
end: Position;
source?: string | null;
}
A binding pattern can be one of the following:
type BindingPattern = ArrayPattern | ObjectPattern;
An expression can be one of the following:
type Expression = ThisExpression | Identifier | Literal |
ArrayExpression | ObjectExpression | FunctionExpression | ArrowFunctionExpression | ClassExpression |
TaggedTemplateExpression | MemberExpression | Super | MetaProperty |
NewExpression | CallExpression | UpdateExpression | AwaitExpression | UnaryExpression |
BinaryExpression | LogicalExpression | ConditionalExpression |
YieldExpression | AssignmentExpression | SequenceExpression;
PGNode ArrayPattern {
type: 'ArrayPattern';
elements: ArrayPatternElement[];
}
with
type ArrayPatternElement = AssignmentPattern | Identifier | BindingPattern | RestElement | null;
PGNode RestElement {
type: 'RestElement';
argument: Identifier | BindingPattern;
}
PGNode AssignmentPattern {
type: 'AssignmentPattern';
left: Identifier | BindingPattern;
right: Expression;
}
PGNode ObjectPattern {
type: 'ObjectPattern';
properties: Property[];
}
PGNode ThisExpression {
type: 'ThisExpression';
}
PGNode Identifier {
type: 'Identifier';
code: string;
}
PGNode Literal {
type: 'Literal';
value: boolean | number | string | RegExp | null;
raw: string;
regex?: { pattern: string, flags: string };
}
The regex
property only applies to regular expression literals.
PGNode ArrayExpression {
type: 'ArrayExpression';
elements: ArrayExpressionElement[];
}
where
type ArrayExpressionElement = Expression | SpreadElement;
PGNode ObjectExpression {
type: 'ObjectExpression';
properties: Property[];
}
where
PGNode Property {
type: 'Property';
key: Expression;
computed: boolean;
value: Expression | null;
kind: 'get' | 'set' | 'init';
method: false;
shorthand: boolean;
}
PGNode FunctionExpression {
type: 'FunctionExpression';
id: Identifier | null;
params: FunctionParameter[];
body: BlockStatement;
generator: boolean;
async: boolean;
expression: boolean;
}
with
type FunctionParameter = AssignmentPattern | Identifier | BindingPattern;
The value of generator
is true for a generator expression.
PGNode ArrowFunctionExpression {
type: 'ArrowFunctionExpression';
id: Identifier | null;
params: FunctionParameter[];
body: BlockStatement | Expression;
generator: boolean;
async: boolean;
expression: false;
}
PGNode ClassExpression {
type: 'ClassExpression';
id: Identifier | null;
superClass: Identifier | null;
body: ClassBody;
}
with
PGNode ClassBody {
type: 'ClassBody';
body: MethodDefinition[];
}
PGNode MethodDefinition {
type: 'MethodDefinition';
key: Expression | null;
computed: boolean;
value: FunctionExpression | null;
kind: 'method' | 'constructor';
static: boolean;
}
PGNode TaggedTemplateExpression {
type: 'TaggedTemplateExpression';
readonly tag: Expression;
readonly quasi: TemplateLiteral;
}
with
PGNode TemplateElement {
type: 'TemplateElement';
value: { cooked: string; raw: string };
tail: boolean;
}
PGNode TemplateLiteral {
type: 'TemplateLiteral';
quasis: TemplateElement[];
expressions: Expression[];
}
PGNode MemberExpression {
type: 'MemberExpression';
computed: boolean;
object: Expression;
property: Expression;
}
PGNode Super {
type: 'Super';
}
PGNode MetaProperty {
type: 'MetaProperty';
meta: Identifier;
property: Identifier;
}
PGNode CallExpression {
type: 'CallExpression';
callee: Expression | Import;
arguments: ArgumentListElement[];
}
PGNode NewExpression {
type: 'NewExpression';
callee: Expression;
arguments: ArgumentListElement[];
}
with
PGNode Import {
type: 'Import';
}
type ArgumentListElement = Expression | SpreadElement;
PGNode SpreadElement {
type: 'SpreadElement';
argument: Expression;
}
PGNode UpdateExpression {
type: 'UpdateExpression';
operator: '++' | '--';
argument: Expression;
prefix: boolean;
}
PGNode AwaitExpression {
type: 'AwaitExpression';
argument: Expression;
}
PGNode UnaryExpression {
type: 'UnaryExpression';
operator: '+' | '-' | '~' | '!' | 'delete' | 'void' | 'typeof';
argument: Expression;
prefix: true;
}
PGNode BinaryExpression {
type: 'BinaryExpression';
operator: 'instanceof' | 'in' | '+' | '-' | '*' | '/' | '%' | '**' |
'|' | '^' | '&' | '==' | '!=' | '===' | '!==' |
'<' | '>' | '<=' | '<<' | '>>' | '>>>';
left: Expression;
right: Expression;
}
PGNode LogicalExpression {
type: 'LogicalExpression';
operator: '||' | '&&';
left: Expression;
right: Expression;
}
PGNode ConditionalExpression {
type: 'ConditionalExpression';
test: Expression;
consequent: Expression;
alternate: Expression;
}
PGNode YieldExpression {
type: 'YieldExpression';
argument: Expression | null;
delegate: boolean;
}
PGNode AssignmentExpression {
type: 'AssignmentExpression';
operator: '=' | '*=' | '**=' | '/=' | '%=' | '+=' | '-=' |
'<<=' | '>>=' | '>>>=' | '&=' | '^=' | '|=';
left: Expression;
right: Expression;
}
PGNode SequenceExpression {
type: 'SequenceExpression';
expressions: Expression[];
}
A statement can be one of the following:
type Statement = BlockStatement | BreakStatement | ContinueStatement |
DebuggerStatement | DoWhileStatement | EmptyStatement |
ExpressionStatement | ForStatement | ForInStatement |
ForOfStatement | FunctionDeclaration | IfStatement |
LabeledStatement | ReturnStatement | SwitchStatement |
ThrowStatement | TryStatement | VariableDeclaration |
WhileStatement | WithStatement;
A declaration can be one of the following:
type Declaration = ClassDeclaration | FunctionDeclaration | VariableDeclaration;
A statement list item is either a statement or a declaration:
type StatementListItem = Declaration | Statement;
A series of statements enclosed by a pair of curly braces form a block statement:
PGNode BlockStatement {
type: 'BlockStatement';
body: StatementListItem[];
}
PGNode BreakStatement {
type: 'BreakStatement';
label: Identifier | null;
}
PGNode ClassDeclaration {
type: 'ClassDeclaration';
id: Identifier | null;
superClass: Identifier | null;
body: ClassBody;
}
PGNode ContinueStatement {
type: 'ContinueStatement';
label: Identifier | null;
}
PGNode DebuggerStatement {
type: 'DebuggerStatement';
}
PGNode DoWhileStatement {
type: 'DoWhileStatement';
body: Statement;
test: Expression;
}
PGNode EmptyStatement {
type: 'EmptyStatement';
}
PGNode ExpressionStatement {
type: 'ExpressionStatement';
expression: Expression;
directive?: string;
}
When the expression statement represents a directive (such as "use strict"
), then the directive
property will contain the directive string.
PGNode ForStatement {
type: 'ForStatement';
init: Expression | VariableDeclaration | null;
test: Expression | null;
update: Expression | null;
body: Statement;
}
PGNode ForInStatement {
type: 'ForInStatement';
left: Expression | VariableDeclaration;
right: Expression;
body: Statement;
each: false;
}
PGNode ForOfStatement {
type: 'ForOfStatement';
await: boolean;
left: Expression | VariableDeclaration;
right: Expression;
body: Statement;
}
PGNode FunctionDeclaration {
type: 'FunctionDeclaration';
id: Identifier | null;
params: FunctionParameter[];
body: BlockStatement;
generator: boolean;
async: boolean;
expression: false;
}
with
type FunctionParameter = AssignmentPattern | Identifier | BindingPattern;
PGNode IfStatement {
type: 'IfStatement';
test: Expression;
consequent: Statement;
alternate?: Statement;
}
A statement prefixed by a label becomes a labelled statement:
PGNode LabeledStatement {
type: 'LabeledStatement';
label: Identifier;
body: Statement;
}
PGNode ReturnStatement {
type: 'ReturnStatement';
argument: Expression | null;
}
PGNode SwitchStatement {
type: 'SwitchStatement';
discriminant: Expression;
cases: SwitchCase[];
}
with
PGNode SwitchCase {
type: 'SwitchCase';
test: Expression | null;
consequent: Statement[];
}
PGNode ThrowStatement {
type: 'ThrowStatement';
argument: Expression;
}
PGNode TryStatement {
type: 'TryStatement';
block: BlockStatement;
handler: CatchClause | null;
finalizer: BlockStatement | null;
}
with
PGNode CatchClause {
type: 'CatchClause';
param: Identifier | BindingPattern;
body: BlockStatement;
}
PGNode VariableDeclaration {
type: 'VariableDeclaration';
declarations: VariableDeclarator[];
kind: 'var' | 'const' | 'let';
}
with
PGNode VariableDeclarator {
type: 'VariableDeclarator';
id: Identifier | BindingPattern;
init: Expression | null;
}
PGNode WhileStatement {
type: 'WhileStatement';
test: Expression;
body: Statement;
}
PGNode WithStatement {
type: 'WithStatement';
object: Expression;
body: Statement;
}
A program can be either a script or a module.
PGNode Program {
type: 'Program';
sourceType: 'script';
body: StatementListItem[];
}
PGNode Program {
type: 'Program';
sourceType: 'module';
body: ModuleItem[];
}
with
type StatementListItem = Declaration | Statement;
type ModuleItem = ImportDeclaration | ExportDeclaration | StatementListItem;
type ImportDeclaration {
type: 'ImportDeclaration';
specifiers: ImportSpecifier[];
source: Literal;
}
with
PGNode ImportSpecifier {
type: 'ImportSpecifier' | 'ImportDefaultSpecifier' | 'ImportNamespaceSpecifier';
local: Identifier;
imported?: Identifier;
}
An export declaration can be in the form of a batch, a default, or a named declaration.
type ExportDeclaration = ExportAllDeclaration | ExportDefaultDeclaration | ExportNamedDeclaration;
Each possible export declaration is described as follows:
PGNode ExportAllDeclaration {
type: 'ExportAllDeclaration';
source: Literal;
}
PGNode ExportDefaultDeclaration {
type: 'ExportDefaultDeclaration';
declaration: Identifier | BindingPattern | ClassDeclaration | Expression | FunctionDeclaration;
}
PGNode ExportNamedDeclaration {
type: 'ExportNamedDeclaration';
declaration: ClassDeclaration | FunctionDeclaration | VariableDeclaration;
specifiers: ExportSpecifier[];
source: Literal;
}
with
PGNode ExportSpecifier {
type: 'ExportSpecifier';
exported: Identifier;
local: Identifier;
};