Javscript中的AST

415 阅读2分钟

一、什么是AST

在计算机科学中,抽象语法树(Abstract Syntax Tree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。
JavaScript Parser 是把js源码转化为抽象语法树(AST)的解析器。这个步骤分为两个阶段:词法分析(Lexical Analysis)和 语法分析(Syntactic Analysis)。

1,词法分析

词法分析阶段把字符串形式的代码转换为 令牌(tokens)流。你可以把令牌看作是一个扁平的语法片段数组

n * n

转化后

[
    {type: {...}, value: "n", start: 0, end: 1, loc: {...}}
    ...
]

2,语法分析

语法分析就是根据词法分析的结果,也就是令牌tokens,将其转换成AST。主要分为statement和expressions。expressions会希望产生一个值,我们会在编写的地方希望得到这个值,举例来说就像是调用function中的引数,或者“=”右边都属于expressions。下文为ast的结构。

二、Scripts and Modules

type ModuleItem = ImportDeclaration | ExportDeclaration | StatementListItem;

1,ImportDeclaration

type ImportDeclaration {
    type: 'ImportDeclaration';
    specifiers: ImportSpecifier[];
    source: Literal;
}
interface ImportSpecifier {
    type: 'ImportSpecifier' | 'ImportDefaultSpecifier' | 'ImportNamespaceSpecifier';
    local: Identifier;
    imported?: Identifier;
}

代码:
(1)ImportDefaultSpecifier

import React from 'react'

(2)ImportSpecifier

import { a, b } from 'react'

(3)ImportNamespaceSpecifier

import * as react from 'react'

2,ExportDeclaration

type ExportDeclaration = ExportAllDeclaration | ExportDefaultDeclaration | ExportNamedDeclaration;
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;
}
interface ExportSpecifier {
    type: 'ExportSpecifier';
    exported: Identifier;
    local: Identifier;
};

(1) ExportAllDeclaration

export * from 'c'

(2)ExportDefaultDeclaration

export default a;

(3)ExportNamedDeclaration

export * from 'c'

三、Statements and Declarations

Statements:

type Statement = BlockStatement | BreakStatement | ContinueStatement |
    DebuggerStatement | DoWhileStatement | EmptyStatement |
    ExpressionStatement | ForStatement | ForInStatement |
    ForOfStatement | FunctionDeclaration | IfStatement |
    LabeledStatement | ReturnStatement | SwitchStatement |
    ThrowStatement | TryStatement | VariableDeclaration |
    WhileStatement | WithStatement;

Declaration:

type Declaration = ClassDeclaration | FunctionDeclaration |  VariableDeclaration;

1,BlockStatement

interface BlockStatement {
    type: 'BlockStatement';
    body: StatementListItem[];
}
block: {
    xxx
}

2,BreakStatement

interface BreakStatement {
    type: 'BreakStatement';
    label: Identifier | null;
}
break block;

3,ContinueStatement

interface ContinueStatement {
    type: 'ContinueStatement';
    label: Identifier | null;
}
Loop1:
for(let i = 0; i < 10; i++){
  Loop2:
  for(let j = 0; j < 5; j++){
    console.log(j);
    if(j === 2) continue Loop1;
  }
}

4,DebuggerStatement

interface DebuggerStatement {
    type: 'DebuggerStatement';
}
debugger

5,DoWhileStatement

interface DoWhileStatement {
    type: 'DoWhileStatement';
    body: Statement;
    test: Expression;
}
do {
} while(xxx)

6,EmptyStatement

interface EmptyStatement {
    type: 'EmptyStatement';
}
if(a === 1);

7,ExpressionStatement

interface ExpressionStatement {
    type: 'ExpressionStatement';
    expression: Expression;
    directive?: string;
}
a()

8,ForStatement

interface ForStatement {
    type: 'ForStatement';
    init: Expression | VariableDeclaration | null;
    test: Expression | null;
    update: Expression | null;
    body: Statement;
}
for(xxx)

9,ForInStatement

interface ForInStatement {
    type: 'ForInStatement';
    left: Expression;
    right: Expression;
    body: Statement;
    each: false;
}
for(let i in dict)

10,ForOfStatement

interface ForOfStatement {
    type: 'ForOfStatement';
    left: Expression;
    right: Expression;
    body: Statement;
}
for(i of dict){}

11,FunctionDeclaration

interface FunctionDeclaration {
    type: 'FunctionDeclaration';
    id: Identifier | null;
    params: FunctionParameter[];
    body: BlockStatement;
    generator: boolean;
    async: boolean;
    expression: false;
}
function a(){
}

12,IfStatement

interface IfStatement {
    type: 'IfStatement';
    test: Expression;
    consequent: Statement;
    alternate?: Statement;
}
if(a = 1){}

13,LabeledStatement

interface LabeledStatement {
    type: 'LabeledStatement';
    label: Identifier;
    body: Statement;
}
a: {
  xxx
}
loop:
for(let i = 0; i < 10; i++){}

14,ReturnStatement

interface ReturnStatement {
    type: 'ReturnStatement';
    argument: Expression | null;
}
return xx

15,SwitchStatement

interface SwitchStatement {
    type: 'SwitchStatement';
    discriminant: Expression;
    cases: SwitchCase[];
}
interface SwitchCase {
    type: 'SwitchCase';
    test: Expression | null;
    consequent: Statement[];
}
switch(a){
  case 1: break;
  case 2: break;
}

16,ThrowStatemen

interface ThrowStatement {
    type: 'ThrowStatement';
    argument: Expression;
}
throw 'error';

17,TryStatement

interface TryStatement {
    type: 'TryStatement';
    block: BlockStatement;
    handler: CatchClause | null;
    finalizer: BlockStatement | null;
}
interface CatchClause {
    type: 'CatchClause';
    param: Identifier | BindingPattern;
    body: BlockStatement;
}
try {
}catch{
}

18,VariableDeclaration

interface VariableDeclaration {
    type: 'VariableDeclaration';
    declarations: VariableDeclarator[];
    kind: 'var' | 'const' | 'let';
}
interface VariableDeclarator {
    type: 'VariableDeclarator';
    id: Identifier | BindingPattern;
    init: Expression | null;
}
const a = 1;

19,WhileStatement

interface WhileStatement {
    type: 'WhileStatement';
    test: Expression;
    body: Statement;
}
while(1){}

20,WithStatement

interface WithStatement {
    type: 'WithStatement';
    object: Expression;
    body: Statement;
}
const a = {}
with(a){
    b = 2;
}

21,ClassDeclaration

interface ClassDeclaration {
    type: 'ClassDeclaration';
    id: Identifier | null;
    superClass: Identifier | null;
    body: ClassBody;
}
class a {
  
}

四、Expressions and Patterns

type BindingPattern = ArrayPattern | ObjectPattern;
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;

1,ArrayPattern

interface ArrayPattern {
    type: 'ArrayPattern';
    elements: ArrayPatternElement[];
}
type ArrayPatternElement = AssignmentPattern | Identifier | BindingPattern | RestElement | null;

interface RestElement {
    type: 'RestElement';
    argument: Identifier | BindingPattern;
}
interface AssignmentPattern {
    type: 'AssignmentPattern';
    left: Identifier | BindingPattern;
    right: Expression;
}

(1)Identifier

const [a, b] = [1, 2]

(2)RestElement

const [a, ...b] = [1, [1, 2]]

(3)AssignmentPattern

const [a, b = 4] = [1, 2]

2,ObjectPattern

interface ObjectPattern {
    type: 'ObjectPattern';
    properties: Property[];
}
const {a: c, b = 1, d} = {}

3,ThisExpression

interface ThisExpression {
    type: 'ThisExpression';
}
this.a

4,Identifier

interface Identifier {
    type: 'Identifier';
    name: string;
}
标识符,就是我们写 JS 时自定义的名称,如变量名,函数名,属性名,都归为标识符

5,Literal

interface Literal {
    type: 'Literal';
    value: boolean | number | string | RegExp | null;
    raw: string;
    regex?: { pattern: string, flags: string };
}
1 false /\d/ '1'

6,ArrayExpression

interface ArrayExpression {
    type: 'ArrayExpression';
    elements: ArrayExpressionElement[];
}
type ArrayExpressionElement = Expression | SpreadElement;
[1, 2, 3]

SpreadElement

[1, 2, ...a]

7,ObjectExpression

interface ObjectExpression {
    type: 'ObjectExpression';
    properties: Property[];
}
interface Property {
    type: 'Property';
    key: Expression;
    computed: boolean;
    value: Expression | null;
    kind: 'get' | 'set' | 'init';
    method: false;
    shorthand: boolean;
}
const a = {
    foo: 'foo',
    bar: function(){},
    noop() {},
    ['computed']: 'computed'
}

8,FunctionExpression

interface FunctionExpression {
    type: 'FunctionExpression';
    id: Identifier | null;
    params: FunctionParameter[];
    body: BlockStatement;
    generator: boolean;
    async: boolean;
    expression: boolean;
}
const a = function(){}
const b = function *(){}
const c = async function(){}

9,ArrowFunctionExpression

interface ArrowFunctionExpression {
    type: 'ArrowFunctionExpression';
    id: Identifier | null;
    params: FunctionParameter[];
    body: BlockStatement | Expression;
    generator: boolean;
    async: boolean;
    expression: false;
}
const a = () => {}

10,ClassExpression

interface ClassExpression {
    type: 'ClassExpression';
    id: Identifier | null;
    superClass: Identifier | null;
    body: ClassBody;
}
interface ClassBody {
    type: 'ClassBody';
    body: MethodDefinition[];
}

interface MethodDefinition {
    type: 'MethodDefinition';
    key: Expression | null;
    computed: boolean;
    value: FunctionExpression | null;
    kind: 'method' | 'constructor';
    static: boolean;
}
const a = class {
}

11, TaggedTemplateExpression

interface TaggedTemplateExpression {
    type: 'TaggedTemplateExpression';
    readonly tag: Expression;
    readonly quasi: TemplateLiteral;
}
interface TemplateElement {
    type: 'TemplateElement';
    value: { cooked: string; raw: string };
    tail: boolean;
}

interface TemplateLiteral {
    type: 'TemplateLiteral';
    quasis: TemplateElement[];
    expressions: Expression[];
}
const a = `a${c}dds`

12,MemberExpression

interface MemberExpression {
    type: 'MemberExpression';
    computed: boolean;
    object: Expression;
    property: Expression;
}
foo.a
foo['a']

13,Super

interface Super {
    type: 'Super';
}
class a extends b{
  constructor(){super()}
}

14,MetaProperty

interface MetaProperty {
    type: 'MetaProperty';
    meta: Identifier;
    property: Identifier;
}
import.meta

15,CallExpression

interface CallExpression {
    type: 'CallExpression';
    callee: Expression;
    arguments: ArgumentListElement[];
}
a()

16,NewExpression

interface NewExpression {
    type: 'NewExpression';
    callee: Expression;
    arguments: ArgumentListElement[];
}
new a()

17,UpdateExpression

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

18,AwaitExpression

interface AwaitExpression {
    type: 'AwaitExpression';
    argument: Expression;
}
await a()

19,UnaryExpression

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

20,BinaryExpression

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

21,LogicalExpression

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

22,ConditionalExpression

interface ConditionalExpression {
    type: 'ConditionalExpression';
    test: Expression;
    consequent: Expression;
    alternate: Expression;
}
a === 1 ? '1' : '2'

23,YieldExpression

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

24,AssignmentExpression

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

25,SequenceExpression

interface SequenceExpression {
    type: 'SequenceExpression';
    expressions: Expression[];
}
a = 1, b = 2

五,参考资料

1,ast explorer
2,esprima
3,segmentfault
4,cndn