Skip to content

Latest commit

 

History

History
779 lines (613 loc) · 13.4 KB

syntax-tree.md

File metadata and controls

779 lines (613 loc) · 13.4 KB

Syntax Tree

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.

Abstract Syntax Tree: PGNodes

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;
}

Expressions and Patterns

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;

Array Pattern

PGNode ArrayPattern {
    type: 'ArrayPattern';
    elements: ArrayPatternElement[];
}

with

type ArrayPatternElement = AssignmentPattern | Identifier | BindingPattern | RestElement | null;

PGNode RestElement {
    type: 'RestElement';
    argument: Identifier | BindingPattern;
}

Assignment Pattern

PGNode AssignmentPattern {
    type: 'AssignmentPattern';
    left: Identifier | BindingPattern;
    right: Expression;
}

Object Pattern

PGNode ObjectPattern {
    type: 'ObjectPattern';
    properties: Property[];
}

This Expression

PGNode ThisExpression {
    type: 'ThisExpression';
}

Identifier

PGNode Identifier {
    type: 'Identifier';
    code: string;
}

Literal

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.

Array Expression

PGNode ArrayExpression {
    type: 'ArrayExpression';
    elements: ArrayExpressionElement[];
}

where

type ArrayExpressionElement = Expression | SpreadElement;

Object Expression

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;
}

Function Expression

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.

Arrow Function Expression

PGNode ArrowFunctionExpression {
    type: 'ArrowFunctionExpression';
    id: Identifier | null;
    params: FunctionParameter[];
    body: BlockStatement | Expression;
    generator: boolean;
    async: boolean;
    expression: false;
}

Class Expression

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;
}

Tagged Template Expression

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[];
}

Member Expression

PGNode MemberExpression {
    type: 'MemberExpression';
    computed: boolean;
    object: Expression;
    property: Expression;
}

Super

PGNode Super {
    type: 'Super';
}

MetaProperty

PGNode MetaProperty {
    type: 'MetaProperty';
    meta: Identifier;
    property: Identifier;
}

Call and New Expressions

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;
}

Update Expression

PGNode UpdateExpression {
    type: 'UpdateExpression';
    operator: '++' | '--';
    argument: Expression;
    prefix: boolean;
}

Await Expression

PGNode AwaitExpression {
    type: 'AwaitExpression';
    argument: Expression;
}

Unary Expression

PGNode UnaryExpression {
    type: 'UnaryExpression';
    operator: '+' | '-' | '~' | '!' | 'delete' | 'void' | 'typeof';
    argument: Expression;
    prefix: true;
}

Binary Expression

PGNode BinaryExpression {
    type: 'BinaryExpression';
    operator: 'instanceof' | 'in' | '+' | '-' | '*' | '/' | '%' | '**' |
        '|' | '^' | '&' | '==' | '!=' | '===' | '!==' |
        '<' | '>' | '<=' | '<<' | '>>' | '>>>';
    left: Expression;
    right: Expression;
}

Logical Expression

PGNode LogicalExpression {
    type: 'LogicalExpression';
    operator: '||' | '&&';
    left: Expression;
    right: Expression;
}

Conditional Expression

PGNode ConditionalExpression {
    type: 'ConditionalExpression';
    test: Expression;
    consequent: Expression;
    alternate: Expression;
}

Yield Expression

PGNode YieldExpression {
    type: 'YieldExpression';
    argument: Expression | null;
    delegate: boolean;
}

Assignment Expression

PGNode AssignmentExpression {
    type: 'AssignmentExpression';
    operator: '=' | '*=' | '**=' | '/=' | '%=' | '+=' | '-=' |
        '<<=' | '>>=' | '>>>=' | '&=' | '^=' | '|=';
    left: Expression;
    right: Expression;
}

Sequence Expression

PGNode SequenceExpression {
    type: 'SequenceExpression';
    expressions: Expression[];
}

Statements and Declarations

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;

Block Statement

A series of statements enclosed by a pair of curly braces form a block statement:

PGNode BlockStatement {
    type: 'BlockStatement';
    body: StatementListItem[];
}

Break Statement

PGNode BreakStatement {
    type: 'BreakStatement';
    label: Identifier | null;
}

Class Declaration

PGNode ClassDeclaration {
    type: 'ClassDeclaration';
    id: Identifier | null;
    superClass: Identifier | null;
    body: ClassBody;
}

Continue Statement

PGNode ContinueStatement {
    type: 'ContinueStatement';
    label: Identifier | null;
}

Debugger Statement

PGNode DebuggerStatement {
    type: 'DebuggerStatement';
}

Do-While Statement

PGNode DoWhileStatement {
    type: 'DoWhileStatement';
    body: Statement;
    test: Expression;
}

Empty Statement

PGNode EmptyStatement {
    type: 'EmptyStatement';
}

Expression Statement

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.

For Statement

PGNode ForStatement {
    type: 'ForStatement';
    init: Expression | VariableDeclaration | null;
    test: Expression | null;
    update: Expression | null;
    body: Statement;
}

For-In Statement

PGNode ForInStatement {
    type: 'ForInStatement';
    left: Expression | VariableDeclaration;
    right: Expression;
    body: Statement;
    each: false;
}

For-Of Statement

PGNode ForOfStatement {
    type: 'ForOfStatement';
    await: boolean;
    left: Expression | VariableDeclaration;
    right: Expression;
    body: Statement;
}

Function Declaration

PGNode FunctionDeclaration {
    type: 'FunctionDeclaration';
    id: Identifier | null;
    params: FunctionParameter[];
    body: BlockStatement;
    generator: boolean;
    async: boolean;
    expression: false;
}

with

type FunctionParameter = AssignmentPattern | Identifier | BindingPattern;

If Statement

PGNode IfStatement {
    type: 'IfStatement';
    test: Expression;
    consequent: Statement;
    alternate?: Statement;
}

Labelled Statement

A statement prefixed by a label becomes a labelled statement:

PGNode LabeledStatement {
    type: 'LabeledStatement';
    label: Identifier;
    body: Statement;
}

Return Statement

PGNode ReturnStatement {
    type: 'ReturnStatement';
    argument: Expression | null;
}

Switch Statement

PGNode SwitchStatement {
    type: 'SwitchStatement';
    discriminant: Expression;
    cases: SwitchCase[];
}

with

PGNode SwitchCase {
    type: 'SwitchCase';
    test: Expression | null;
    consequent: Statement[];
}

Throw Statement

PGNode ThrowStatement {
    type: 'ThrowStatement';
    argument: Expression;
}

Try Statement

PGNode TryStatement {
    type: 'TryStatement';
    block: BlockStatement;
    handler: CatchClause | null;
    finalizer: BlockStatement | null;
}

with

PGNode CatchClause {
    type: 'CatchClause';
    param: Identifier | BindingPattern;
    body: BlockStatement;
}

Variable Declaration

PGNode VariableDeclaration {
    type: 'VariableDeclaration';
    declarations: VariableDeclarator[];
    kind: 'var' | 'const' | 'let';
}

with

PGNode VariableDeclarator {
    type: 'VariableDeclarator';
    id: Identifier | BindingPattern;
    init: Expression | null;
}

While Statement

PGNode WhileStatement {
    type: 'WhileStatement';
    test: Expression;
    body: Statement;
}

With Statement

PGNode WithStatement {
    type: 'WithStatement';
    object: Expression;
    body: Statement;
}

Scripts and Modules

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;

Import Declaration

type ImportDeclaration {
    type: 'ImportDeclaration';
    specifiers: ImportSpecifier[];
    source: Literal;
}

with

PGNode ImportSpecifier {
    type: 'ImportSpecifier' | 'ImportDefaultSpecifier' | 'ImportNamespaceSpecifier';
    local: Identifier;
    imported?: Identifier;
}

Export Declaration

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;
};