| # Appendix A. Syntax Tree Format |
| |
| Esprima syntax tree format is derived from the original version of [Mozilla Parser API](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API), which is then formalized and expanded as the [ESTree specification](https://github.com/estree/estree). |
| |
| **Note**: In the following sections, interfaces are described using the syntax of [TypeScript interface](https://www.typescriptlang.org/docs/handbook/interfaces.html). |
| |
| Each node is represented as a regular JavaScript object that implements the interface: |
| |
| ```js |
| interface Node { |
| type: string; |
| } |
| ``` |
| |
| The `type` property is a string that contains the variant type of the node. Each subtype of _Node_ is explained in the subsequent sections. |
| |
| When the node is annotated with [its location](syntactic-analysis.html#node-location), the interface becomes: |
| |
| ```js |
| interface Node { |
| type: string; |
| range?: [number, number]; |
| loc?: SourceLocation; |
| } |
| ``` |
| |
| with the source location defined as: |
| |
| ```js |
| interface Position { |
| line: number; |
| column: number; |
| } |
| |
| interface SourceLocation { |
| start: Position; |
| end: Position; |
| source?: string | null; |
| } |
| ``` |
| |
| ## Expressions and Patterns |
| |
| A binding pattern can be one of the following: |
| |
| ```js |
| type BindingPattern = ArrayPattern | ObjectPattern; |
| ``` |
| |
| An expression can be one of the following: |
| |
| ```js |
| 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 |
| |
| ```js |
| interface ArrayPattern { |
| type: 'ArrayPattern'; |
| elements: ArrayPatternElement[]; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| type ArrayPatternElement = AssignmentPattern | Identifier | BindingPattern | RestElement | null; |
| |
| interface RestElement { |
| type: 'RestElement'; |
| argument: Identifier | BindingPattern; |
| } |
| ``` |
| |
| ### Assignment Pattern |
| |
| ```js |
| interface AssignmentPattern { |
| type: 'AssignmentPattern'; |
| left: Identifier | BindingPattern; |
| right: Expression; |
| } |
| ``` |
| |
| ### Object Pattern |
| |
| ```js |
| interface ObjectPattern { |
| type: 'ObjectPattern'; |
| properties: Property[]; |
| } |
| ``` |
| |
| ### This Expression |
| |
| ```js |
| interface ThisExpression { |
| type: 'ThisExpression'; |
| } |
| ``` |
| |
| ### Identifier |
| |
| ```js |
| interface Identifier { |
| type: 'Identifier'; |
| name: string; |
| } |
| ``` |
| |
| ### Literal |
| |
| ```js |
| interface 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 |
| |
| ```js |
| interface ArrayExpression { |
| type: 'ArrayExpression'; |
| elements: ArrayExpressionElement[]; |
| } |
| ``` |
| |
| where |
| |
| ```js |
| type ArrayExpressionElement = Expression | SpreadElement; |
| ``` |
| |
| ### Object Expression |
| |
| ```js |
| interface ObjectExpression { |
| type: 'ObjectExpression'; |
| properties: Property[]; |
| } |
| ``` |
| |
| where |
| |
| ```js |
| interface Property { |
| type: 'Property'; |
| key: Expression; |
| computed: boolean; |
| value: Expression | null; |
| kind: 'get' | 'set' | 'init'; |
| method: false; |
| shorthand: boolean; |
| } |
| ``` |
| |
| ### Function Expression |
| |
| ```js |
| interface FunctionExpression { |
| type: 'FunctionExpression'; |
| id: Identifier | null; |
| params: FunctionParameter[]; |
| body: BlockStatement; |
| generator: boolean; |
| async: boolean; |
| expression: boolean; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| type FunctionParameter = AssignmentPattern | Identifier | BindingPattern; |
| ``` |
| |
| The value of `generator` is true for a generator expression. |
| |
| ### Arrow Function Expression |
| |
| ```js |
| interface ArrowFunctionExpression { |
| type: 'ArrowFunctionExpression'; |
| id: Identifier | null; |
| params: FunctionParameter[]; |
| body: BlockStatement | Expression; |
| generator: boolean; |
| async: boolean; |
| expression: false; |
| } |
| ``` |
| |
| ### Class Expression |
| |
| ```js |
| interface ClassExpression { |
| type: 'ClassExpression'; |
| id: Identifier | null; |
| superClass: Identifier | null; |
| body: ClassBody; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| interface ClassBody { |
| type: 'ClassBody'; |
| body: MethodDefinition[]; |
| } |
| |
| interface MethodDefinition { |
| type: 'MethodDefinition'; |
| key: Expression | null; |
| computed: boolean; |
| value: FunctionExpression | null; |
| kind: 'method' | 'constructor'; |
| static: boolean; |
| } |
| ``` |
| |
| ### Tagged Template Expression |
| |
| ```js |
| interface TaggedTemplateExpression { |
| type: 'TaggedTemplateExpression'; |
| readonly tag: Expression; |
| readonly quasi: TemplateLiteral; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| interface TemplateElement { |
| type: 'TemplateElement'; |
| value: { cooked: string; raw: string }; |
| tail: boolean; |
| } |
| |
| interface TemplateLiteral { |
| type: 'TemplateLiteral'; |
| quasis: TemplateElement[]; |
| expressions: Expression[]; |
| } |
| ``` |
| |
| ### Member Expression |
| |
| ```js |
| interface MemberExpression { |
| type: 'MemberExpression'; |
| computed: boolean; |
| object: Expression; |
| property: Expression; |
| } |
| ``` |
| |
| ### Super |
| |
| ```js |
| interface Super { |
| type: 'Super'; |
| } |
| ``` |
| |
| ### MetaProperty |
| |
| ```js |
| interface MetaProperty { |
| type: 'MetaProperty'; |
| meta: Identifier; |
| property: Identifier; |
| } |
| ``` |
| |
| ### Call and New Expressions |
| |
| ```js |
| interface CallExpression { |
| type: 'CallExpression'; |
| callee: Expression | Import; |
| arguments: ArgumentListElement[]; |
| } |
| |
| interface NewExpression { |
| type: 'NewExpression'; |
| callee: Expression; |
| arguments: ArgumentListElement[]; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| interface Import { |
| type: 'Import'; |
| } |
| |
| type ArgumentListElement = Expression | SpreadElement; |
| |
| interface SpreadElement { |
| type: 'SpreadElement'; |
| argument: Expression; |
| } |
| ``` |
| |
| ### Update Expression |
| |
| ```js |
| interface UpdateExpression { |
| type: 'UpdateExpression'; |
| operator: '++' | '--'; |
| argument: Expression; |
| prefix: boolean; |
| } |
| ``` |
| |
| ### Await Expression |
| |
| ```js |
| interface AwaitExpression { |
| type: 'AwaitExpression'; |
| argument: Expression; |
| } |
| ``` |
| |
| ### Unary Expression |
| |
| ```js |
| interface UnaryExpression { |
| type: 'UnaryExpression'; |
| operator: '+' | '-' | '~' | '!' | 'delete' | 'void' | 'typeof'; |
| argument: Expression; |
| prefix: true; |
| } |
| ``` |
| |
| ### Binary Expression |
| |
| ```js |
| interface BinaryExpression { |
| type: 'BinaryExpression'; |
| operator: 'instanceof' | 'in' | '+' | '-' | '*' | '/' | '%' | '**' | |
| '|' | '^' | '&' | '==' | '!=' | '===' | '!==' | |
| '<' | '>' | '<=' | '<<' | '>>' | '>>>'; |
| left: Expression; |
| right: Expression; |
| } |
| ``` |
| |
| ### Logical Expression |
| |
| ```js |
| interface LogicalExpression { |
| type: 'LogicalExpression'; |
| operator: '||' | '&&'; |
| left: Expression; |
| right: Expression; |
| } |
| ``` |
| |
| ### Conditional Expression |
| |
| ```js |
| interface ConditionalExpression { |
| type: 'ConditionalExpression'; |
| test: Expression; |
| consequent: Expression; |
| alternate: Expression; |
| } |
| ``` |
| |
| ### Yield Expression |
| |
| ```js |
| interface YieldExpression { |
| type: 'YieldExpression'; |
| argument: Expression | null; |
| delegate: boolean; |
| } |
| ``` |
| |
| ### Assignment Expression |
| |
| ```js |
| interface AssignmentExpression { |
| type: 'AssignmentExpression'; |
| operator: '=' | '*=' | '**=' | '/=' | '%=' | '+=' | '-=' | |
| '<<=' | '>>=' | '>>>=' | '&=' | '^=' | '|='; |
| left: Expression; |
| right: Expression; |
| } |
| ``` |
| |
| ### Sequence Expression |
| |
| ```js |
| interface SequenceExpression { |
| type: 'SequenceExpression'; |
| expressions: Expression[]; |
| } |
| ``` |
| |
| ## Statements and Declarations |
| |
| A statement can be one of the following: |
| |
| ```js |
| 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: |
| |
| ```js |
| type Declaration = ClassDeclaration | FunctionDeclaration | VariableDeclaration; |
| ``` |
| |
| A statement list item is either a statement or a declaration: |
| |
| ```js |
| type StatementListItem = Declaration | Statement; |
| ``` |
| |
| ### Block Statement |
| |
| A series of statements enclosed by a pair of curly braces form a block statement: |
| |
| ```js |
| interface BlockStatement { |
| type: 'BlockStatement'; |
| body: StatementListItem[]; |
| } |
| ``` |
| |
| ### Break Statement |
| |
| ```js |
| interface BreakStatement { |
| type: 'BreakStatement'; |
| label: Identifier | null; |
| } |
| ``` |
| |
| ### Class Declaration |
| |
| ```js |
| interface ClassDeclaration { |
| type: 'ClassDeclaration'; |
| id: Identifier | null; |
| superClass: Identifier | null; |
| body: ClassBody; |
| } |
| ``` |
| |
| ### Continue Statement |
| |
| ```js |
| interface ContinueStatement { |
| type: 'ContinueStatement'; |
| label: Identifier | null; |
| } |
| ``` |
| |
| ### Debugger Statement |
| |
| ```js |
| interface DebuggerStatement { |
| type: 'DebuggerStatement'; |
| } |
| ``` |
| |
| ### Do-While Statement |
| |
| ```js |
| interface DoWhileStatement { |
| type: 'DoWhileStatement'; |
| body: Statement; |
| test: Expression; |
| } |
| ``` |
| |
| ### Empty Statement |
| |
| ```js |
| interface EmptyStatement { |
| type: 'EmptyStatement'; |
| } |
| ``` |
| |
| ### Expression Statement |
| |
| ```js |
| interface 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 |
| |
| ```js |
| interface ForStatement { |
| type: 'ForStatement'; |
| init: Expression | VariableDeclaration | null; |
| test: Expression | null; |
| update: Expression | null; |
| body: Statement; |
| } |
| ``` |
| |
| ### For-In Statement |
| |
| ```js |
| interface ForInStatement { |
| type: 'ForInStatement'; |
| left: Expression; |
| right: Expression; |
| body: Statement; |
| each: false; |
| } |
| ``` |
| |
| ### For-Of Statement |
| |
| ```js |
| interface ForOfStatement { |
| type: 'ForOfStatement'; |
| left: Expression; |
| right: Expression; |
| body: Statement; |
| } |
| ``` |
| |
| ### Function Declaration |
| |
| ```js |
| interface FunctionDeclaration { |
| type: 'FunctionDeclaration'; |
| id: Identifier | null; |
| params: FunctionParameter[]; |
| body: BlockStatement; |
| generator: boolean; |
| async: boolean; |
| expression: false; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| type FunctionParameter = AssignmentPattern | Identifier | BindingPattern; |
| ``` |
| |
| ### If Statement |
| |
| ```js |
| interface IfStatement { |
| type: 'IfStatement'; |
| test: Expression; |
| consequent: Statement; |
| alternate?: Statement; |
| } |
| ``` |
| |
| ### Labelled Statement |
| |
| A statement prefixed by a label becomes a labelled statement: |
| |
| ```js |
| interface LabeledStatement { |
| type: 'LabeledStatement'; |
| label: Identifier; |
| body: Statement; |
| } |
| ``` |
| |
| ### Return Statement |
| |
| ```js |
| interface ReturnStatement { |
| type: 'ReturnStatement'; |
| argument: Expression | null; |
| } |
| ``` |
| |
| ### Switch Statement |
| |
| ```js |
| interface SwitchStatement { |
| type: 'SwitchStatement'; |
| discriminant: Expression; |
| cases: SwitchCase[]; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| interface SwitchCase { |
| type: 'SwitchCase'; |
| test: Expression | null; |
| consequent: Statement[]; |
| } |
| ``` |
| |
| ### Throw Statement |
| |
| ```js |
| interface ThrowStatement { |
| type: 'ThrowStatement'; |
| argument: Expression; |
| } |
| ``` |
| |
| ### Try Statement |
| |
| ```js |
| interface TryStatement { |
| type: 'TryStatement'; |
| block: BlockStatement; |
| handler: CatchClause | null; |
| finalizer: BlockStatement | null; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| interface CatchClause { |
| type: 'CatchClause'; |
| param: Identifier | BindingPattern; |
| body: BlockStatement; |
| } |
| ``` |
| |
| ### Variable Declaration |
| |
| ```js |
| interface VariableDeclaration { |
| type: 'VariableDeclaration'; |
| declarations: VariableDeclarator[]; |
| kind: 'var' | 'const' | 'let'; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| interface VariableDeclarator { |
| type: 'VariableDeclarator'; |
| id: Identifier | BindingPattern; |
| init: Expression | null; |
| } |
| ``` |
| |
| ### While Statement |
| |
| ```js |
| interface WhileStatement { |
| type: 'WhileStatement'; |
| test: Expression; |
| body: Statement; |
| } |
| ``` |
| |
| ### With Statement |
| |
| ```js |
| interface WithStatement { |
| type: 'WithStatement'; |
| object: Expression; |
| body: Statement; |
| } |
| ``` |
| |
| ## Scripts and Modules |
| |
| A program can be either a script or a module. |
| |
| ```js |
| interface Program { |
| type: 'Program'; |
| sourceType: 'script'; |
| body: StatementListItem[]; |
| } |
| |
| interface Program { |
| type: 'Program'; |
| sourceType: 'module'; |
| body: ModuleItem[]; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| type StatementListItem = Declaration | Statement; |
| type ModuleItem = ImportDeclaration | ExportDeclaration | StatementListItem; |
| ``` |
| |
| ### Import Declaration |
| |
| ```js |
| type ImportDeclaration { |
| type: 'ImportDeclaration'; |
| specifiers: ImportSpecifier[]; |
| source: Literal; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| interface 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. |
| |
| ```js |
| type ExportDeclaration = ExportAllDeclaration | ExportDefaultDeclaration | ExportNamedDeclaration; |
| ``` |
| |
| Each possible export declaration is described as follows: |
| |
| ```js |
| interface ExportAllDeclaration { |
| type: 'ExportAllDeclaration'; |
| source: Literal; |
| } |
| |
| interface ExportDefaultDeclaration { |
| type: 'ExportDefaultDeclaration'; |
| declaration: Identifier | BindingPattern | ClassDeclaration | Expression | FunctionDeclaration; |
| } |
| |
| interface ExportNamedDeclaration { |
| type: 'ExportNamedDeclaration'; |
| declaration: ClassDeclaration | FunctionDeclaration | VariableDeclaration; |
| specifiers: ExportSpecifier[]; |
| source: Literal; |
| } |
| ``` |
| |
| with |
| |
| ```js |
| interface ExportSpecifier { |
| type: 'ExportSpecifier'; |
| exported: Identifier; |
| local: Identifier; |
| }; |
| ``` |