13 примеров быстрого старта абстрактных синтаксических деревьев JS

Node.js внешний интерфейс JavaScript Babel

Больше сообщений в блоге, добро пожаловать в StarGithub/Blog

Дерево абстрактного синтаксиса JS Подробное объяснение см. в сопутствующей статье:Дерево абстрактного синтаксиса Javascript для продвинутого внешнего интерфейса

Javascript-кодРазобратьШаг (Parse) делится на две фазы:Лексический анализа такжеСинтаксический анализ. Этот шаг получает код и выводитабстрактное синтаксическое дерево, также известный как АСТ.

По мере того, как экология Babel становится все более и более полной, мы обычно используем Babel для анализа процесса разбора кода. Вавилон используетESTreeи модифицированный AST, документацию по его ядру можно найти [здесь](https://github.com/babel/babel/blob/master/doc/ast/spec.md).

В процессе анализа AST Javascript с помощью инструментовAST ExplorerЭто может помочь нам лучше понять восприятие узлов AST.

Чтобы помочь вам лучше совместить анализ примеров и понять состав основных типов узлов Babylon AST, здесь перечислены 13 распространенных примеров, а также соответствующие узлы AST и подробный анализ типов узлов соответственно.

AST всего следующего кода основан наBabylon7

объявление переменной

код

let a  = 'hello'

AST

image

VariableDeclaration

объявление переменной,kindКакой тип объявления представляет свойство с момента введения ES6const/let.declarationsПредставляет несколько описаний объявления, поскольку мы можем:let a = 1, b = 2;.

interface VariableDeclaration <: Declaration {
    type: "VariableDeclaration";
    declarations: [ VariableDeclarator ];
    kind: "var";
}

VariableDeclarator

описание объявления переменной,idпредставляет узел имени переменной,initВыражение, представляющее начальное значение, которое может бытьnull.

interface VariableDeclarator <: Node {
    type: "VariableDeclarator";
    id: Pattern;
    init: Expression | null;
} 

Identifier

Идентификаторы, как я думаю, должны называться — это имена, которые мы настраиваем при написании JS, такие как имена переменных, имена функций и имена атрибутов, которые классифицируются как идентификаторы. Соответствующий интерфейс выглядит следующим образом:

interface Identifier <: Expression, Pattern {
    type: "Identifier";
    name: string;
}

Идентификатор может быть выражением или шаблоном деструктурирования (синтаксис деструктурирования в ES6). мы увидим позжеExpressionа такжеPatternсвязанный контент.

Literal

Буквально, не имелось в виду здесь[]или{}Эти, но литералы, которые семантически представляют значение, такие как1,“hello”, trueэти и регулярные выражения (есть расширенныйNodeдля представления регулярных выражений), например/\d?/. Давайте посмотрим на определение документа:

interface Literal <: Expression {
    type: "Literal";
    value: string | boolean | null | number | RegExp;
}

valueЭто соответствует значению литерала, мы можем видеть тип литерального значения, строка, логическое значение, значение,nullи регулярный.

двоичные арифметические выражения

код

let a = 3+4

AST

image

BinaryExpression

Узел выражения бинарного оператора,leftа такжеrightпредставляет два выражения слева и справа от оператора,operatorПредставляет бинарный оператор.

interface BinaryExpression <: Expression {
    type: "BinaryExpression";
    operator: BinaryOperator;
    left: Expression;
    right: Expression;
}

BinaryOperator

Бинарный оператор, все значения следующие:

enum BinaryOperator {
    "==" | "!=" | "===" | "!=="
         | "<" | "<=" | ">" | ">="
         | "<<" | ">>" | ">>>"
         | "+" | "-" | "*" | "/" | "%"
         | "|" | "^" | "&" | "in"
         | "instanceof"
}

выражение присваивания

код

Этот пример будет немного сложнее и будет включать больше типов узлов.

    this.state = {date: new Date()};

AST

image

ExpressionStatement

узел оператора выражения,a = a + 1илиa++там будетexpressionСвойство указывает на объект узла выражения (выражения будут упомянуты позже).

interface ExpressionStatement <: Statement {
    type: "ExpressionStatement";
    expression: Expression;
}

AssignmentExpression

узел выражения присваивания,operatorсвойство представляет оператор присваивания,leftа такжеrightэто выражение вокруг оператора присваивания.

interface AssignmentExpression <: Expression {
    type: "AssignmentExpression";
    operator: AssignmentOperator;
    left: Pattern | Expression;
    right: Expression;
}
AssignmentOperator

Оператор присваивания, все значения следующие: (не так много часто используемых)

enum AssignmentOperator {
    "=" | "+=" | "-=" | "*=" | "/=" | "%="
        | "<<=" | ">>=" | ">>>="
        | "|=" | "^=" | "&="
}

MemberExpression

Узел выражения члена, то есть оператор, который ссылается на член объекта,objectузел выражения, ссылающийся на объект,propertyимя атрибута,computedеслиfalse, что значит.обращаться к членам,propertyдолжно бытьIdentifierузел, еслиcomputedсобственностьtrue, тогда[]цитировать, т.propertyЯвляетсяExpressionУзел, имя которого является результирующим значением выражения.

interface MemberExpression <: Expression, Pattern {
    type: "MemberExpression";
    object: Expression;
    property: Expression;
    computed: boolean;
}

ThisExpression

выражатьthis.

interface ThisExpression <: Expression {
    type: "ThisExpression";
}

ObjectExpression

узел выражения объекта,propertyСвойство — это массив, который представляет каждую пару ключ-значение объекта, а каждый элемент — это узел свойства.

interface ObjectExpression <: Expression {
    type: "ObjectExpression";
    properties: [ Property ];
}

Property

Узлы свойств в выражениях объектов.keyпредставляет ключ,valueпредставляет собой значение, поскольку синтаксис ES5 имеетget/setсуществует, значит, естьkindАтрибут, используемый для обозначения нормальной инициализации илиget/set.

interface Property <: Node {
    type: "Property";
    key: Literal | Identifier;
    value: Expression;
    kind: "init" | "get" | "set";
}

NewExpression

newвыражение.

interface NewExpression <: CallExpression {
    type: "NewExpression";
}

выражение вызова функции

код

	console.log(`Hello ${name}`)

AST

image

CallExpression

выражение вызова функции, что означаетfunc(1, 2)заявления этого типа.calleeСвойство — это узел выражения, представляющий функцию,argumentsпредставляет собой массив, элементами которого являются узлы выражений, представляющие список аргументов функции.

interface CallExpression <: Expression {
    type: "CallExpression";
    callee: Expression;
    arguments: [ Expression ];
}

TemplateLiteral

interface TemplateLiteral <: Expression {
  type: "TemplateLiteral";
  quasis: [ TemplateElement ];
  expressions: [ Expression ];
}

TemplateElement

interface TemplateElement <: Node {
  type: "TemplateElement";
  tail: boolean;
  value: {
    cooked: string | null;
    raw: string;
  };
}

стрелочная функция

код

i => i++

AST

image

ArrowFunctionExpression

Выражения стрелочных функций.

interface ArrowFunctionExpression <: Function, Expression {
  type: "ArrowFunctionExpression";
  body: BlockStatement | Expression;
  expression: boolean;
}

UpdateExpression

узел выражения оператора обновления, т.е.++/--, который похож на унарный оператор, за исключениемoperatorТип объекта узла, на который указывает другой, здесь оператор обновления.

interface UpdateExpression <: Expression {
    type: "UpdateExpression";
    operator: UpdateOperator;
    argument: Expression;
    prefix: boolean;
}
UpdateOperator

оператор обновления, значение равно++или--, с узлом выражения обновленияprefixсвойство указывать до и после.

enum UpdateOperator {
    "++" | "--"
}

объявление функции

код

function Hello(name = 'Lily'){
    
}

AST

image

FunctionDeclaration

Объявления функций, в отличие от ранее упомянутой функции,idне может бытьnull.

interface FunctionDeclaration <: Function, Declaration {
    type: "FunctionDeclaration";
    id: Identifier;
}

AssignmentPattern

interface AssignmentPattern <: Pattern {
  type: "AssignmentPattern";
  left: Pattern;
  right: Expression;
}

BlockStatement

Узел оператора блока, например:if (...) { // 这里是块语句的内容 }, блок может содержать несколько других операторов, поэтомуbodyСвойство, представляющее собой массив, представляет несколько операторов в блоке.

interface BlockStatement <: Statement {
    type: "BlockStatement";
    body: [ Statement ];
}

объявление класса

код

class Clock extends Component{
	render(){
    }
}

AST

image

Classes

interface Class <: Node {
  id: Identifier | null;
  superClass: Expression | null;
  body: ClassBody;
  decorators: [ Decorator ];
}

ClassBody

interface ClassBody <: Node {
  type: "ClassBody";
  body: [ ClassMethod | ClassPrivateMethod | ClassProperty | ClassPrivateProperty ];
}

ClassMethod

interface ClassMethod <: Function {
  type: "ClassMethod";
  key: Expression;
  kind: "constructor" | "method" | "get" | "set";
  computed: boolean;
  static: boolean;
  decorators: [ Decorator ];
}

если оператор

код

if(a === 0){
}

AST

image

IfStatement

ifУзлы операторов, очень распространенные, будут иметь три атрибута:testпредставление атрибутаif (...)выражения в скобках.

consequentатрибутом является то, что условиеtrueКогда оператор выполнения, как правило, оператор блока.

alternateатрибуты используются для представленияelseПоследующий узел оператора обычно представляет собой блочный оператор, но может быть и другим.ifУзлы операторов, то есть структуры, подобные этой:if (a) { //... } else if (b) { // ... }.alternateКонечно, это также может бытьnull.

interface IfStatement <: Statement {
    type: "IfStatement";
    test: Expression;
    consequent: Statement;
    alternate: Statement | null;
}

оператор переключения

код

switch(num){
  case 0:
    x = 'Sunday'
    break;
  default:
    x = 'Weekday'
}

AST

image

SwitchStatement

switchУзел оператора имеет два свойства:discriminantпредставление атрибутаswitchВыражение, следующее за оператором, обычно переменная,casesсобственность - этоcaseмассив узлов, представляющих каждыйcaseутверждение.

interface SwitchStatement <: Statement {
    type: "SwitchStatement";
    discriminant: Expression;
    cases: [ SwitchCase ];
}

SwitchCase

switchизcaseузел.testатрибут представляет этоcaseВыражение суждения ,consequentэтоcaseзаявление об исполнении.

когдаtestсобственностьnull, это значитdefaultэтоcaseузел.

interface SwitchCase <: Node {
    type: "SwitchCase";
    test: Expression | null;
    consequent: [ Statement ];
}

для заявления

код

for (var i = 0; i < 9; i++) {
}

AST

ForStatement

forузел оператора цикла, атрибутinit/test/updateсоответственно указаноforТри выражения в скобках оператора, значение инициализации, условие оценки цикла и оператор обновления переменной, выполняемый в каждом цикле (initМожет быть объявлением переменной или выражением). Все три свойства могут бытьnull,Прямо сейчасfor(;;){}.bodyАтрибут используется для представления оператора, который должен выполняться в цикле.

interface ForStatement <: Statement {
    type: "ForStatement";
    init: VariableDeclaration | Expression | null;
    test: Expression | null;
    update: Expression | null;
    body: Statement;
}

импорт модуля

код

import React from 'react'

AST

ImportDeclaration

объявление модуля.

interface ImportDeclaration <: ModuleDeclaration {
  type: "ImportDeclaration";
  specifiers: [ ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier ];
  source: Literal;
}

ImportDefaultSpecifier

interface ImportDefaultSpecifier <: ModuleSpecifier {
  type: "ImportDefaultSpecifier";
}

экспорт модуля

код

export default Clock

AST

image

ExportDefaultDeclaration

interface OptFunctionDeclaration <: FunctionDeclaration {
  id: Identifier | null;
}

interface OptClasDeclaration <: ClassDeclaration {
  id: Identifier | null;
}

interface ExportDefaultDeclaration <: ModuleDeclaration {
  type: "ExportDefaultDeclaration";
  declaration: OptFunctionDeclaration | OptClassDeclaration | Expression;
}

Метод рендеринга JSX

Код:

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }

AST

Ссылаться на