一、什么是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