Настройка синтаксического парсера: parser

SWC использует модульный синтаксический парсер, реализованный на Rust, который отвечает за преобразование исходного кода JavaScript и TypeScript в абстрактное синтаксическое дерево (AST). Конфигурация парсера задаётся через поле jsc.parser в .swcrc и определяет, какие языковые расширения включаются при разборе исходного кода.

Парсер SWC строго разделяет базовый синтаксис ECMAScript и дополнительные расширения: JSX, TypeScript, декораторы и экспериментальные возможности. Это позволяет управлять точностью разбора и производительностью компиляции.


Базовая конфигурация parser

Основная структура конфигурации выглядит следующим образом:

{
  "jsc": {
    "parser": {
      "syntax": "ecmascript"
    }
  }
}

Параметр syntax определяет основной режим разбора:

  • ecmascript — стандартный JavaScript
  • typescript — TypeScript
  • jsx — JavaScript с JSX

Выбор режима влияет на доступные опции внутри парсера.


Режим ECMAScript

При выборе syntax: “ecmascript” активируется классический JavaScript-парсер с расширениями через дополнительные флаги.

{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": true,
      "dynamicImport": true,
      "privateMethod": true,
      "functionBind": true
    }
  }
}

JSX в ECMAScript

Опция jsx включает поддержку JSX-выражений без переключения на TypeScript:

"jsx": true

Поддерживаются конструкции:

const element = <div className="root">Text</div>;

Dynamic Import

Флаг dynamicImport активирует поддержку динамического импорта:

"dynamicImport": true

Разбор конструкции:

import("./module").then(m => m.run());

Без включения этой опции подобный синтаксис считается ошибкой.


Private Methods и поля классов

SWC поддерживает приватные элементы классов:

"privateMethod": true

Пример синтаксиса:

class A {
  
    return 42;
  }
}

Также часто используется вместе с:

"privateProperty": true

для полей:

class A {
  #value = 10;
}

Function bind syntax

Поддержка оператора привязки:

"functionBind": true

Синтаксис:

const bound = obj::obj.method;

Режим TypeScript

При выборе syntax: “typescript” активируется полноценный TypeScript-парсер:

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true,
      "decorators": true,
      "dynamicImport": true
    }
  }
}

TSX (TypeScript + JSX)

"tsx": true

Поддержка TSX позволяет использовать JSX внутри TypeScript-файлов:

const App = () => <div>Hello</div>;

TSX требует включённого JSX-парсинга и корректной обработки типов.


Decorators

"decorators": true

Декораторы используются для метапрограммирования:

@sealed
class Service {
  execute() {}
}

SWC поддерживает современную спецификацию decorators (stage 3/ECMAScript proposal), включая декораторы классов и членов класса.


TypeScript-specific syntax

При включении typescript автоматически поддерживаются:

  • аннотации типов
  • интерфейсы
  • enums
  • type aliases
  • generics

Пример:

function identity<T>(value: T): T {
  return value;
}

JSX-режим

При использовании syntax: “jsx” парсер ориентирован на JavaScript с JSX без TypeScript:

{
  "jsc": {
    "parser": {
      "syntax": "jsx",
      "dynamicImport": true
    }
  }
}

Этот режим часто используется в React-проектах без TypeScript.

Пример AST-совместимого кода:

const Page = () => (
  <section>
    <h1>Title</h1>
  </section>
);

Взаимодействие опций парсера

Некоторые параметры являются кросс-синтаксическими и работают в разных режимах:

Опция ECMAScript JSX TypeScript
dynamicImport да да да
decorators нет нет да
privateMethod да да да
functionBind да да частично
tsx нет нет да

Строгие ограничения парсинга

SWC использует строгую модель синтаксического анализа:

  • запрещены неизвестные токены вне включённых флагов
  • JSX не распознаётся без явного включения
  • TypeScript не активируется автоматически
  • экспериментальные фичи требуют явной конфигурации

Ошибки парсинга часто возникают из-за несоответствия syntax и дополнительных флагов.


Конфигурация .swcrc для реальных сценариев

React + JavaScript

{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": true,
      "dynamicImport": true
    }
  }
}

React + TypeScript

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true,
      "decorators": true,
      "dynamicImport": true
    }
  }
}

Node.js ESM проект

{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "dynamicImport": true
    }
  }
}

Влияние парсера на трансформации

AST, построенный парсером SWC, напрямую влияет на последующие стадии компиляции:

  • трансформация JSX в React.createElement или автоматические runtime-функции
  • удаление TypeScript-типов
  • преобразование class fields
  • транспиляция современных ECMAScript-операторов

Корректная настройка парсера определяет, какие узлы AST будут доступны для трансформеров.


Ошибки конфигурации и поведение парсера

Типичные проблемы:

Несоответствие syntax и кода

"syntax": "ecmascript"

при наличии TypeScript приводит к ошибкам разбора типов.


Отсутствие JSX-флага

const x = <div />;

без “jsx”: true интерпретируется как оператор сравнения.


Decorators без поддержки

@log
class A {}

без “decorators”: true вызывает синтаксическую ошибку.


Производительность парсера

Парсер SWC оптимизирован для высокой скорости:

  • однопроходный разбор
  • минимизация аллокаций AST-узлов
  • использование Rust-ориентированной памяти
  • отсутствие интерпретируемых этапов

Конфигурация парсера влияет на производительность: чем больше включённых фич, тем выше сложность грамматики, но влияние остаётся минимальным по сравнению с трансформациями.


Расширяемость синтаксиса

Парсер SWC не является полностью динамическим, но поддерживает расширения через флаги:

  • включение экспериментальных ECMAScript proposal
  • частичная поддержка будущих стандартов
  • гибкая комбинация JSX/TS/ESM

Каждая комбинация строго проверяется на грамматическую совместимость до запуска трансформаций.