# 機能設計書 4-CSSパーサー

## 概要

本ドキュメントは、CSS文字列を独自のAST（抽象構文木）にパースする高速CSSパーサーの機能設計書である。StyleRule、AtRule、Declaration、Comment等のノードタイプを持つAST配列を生成する。

### 本機能の処理概要

**業務上の目的・背景**：Tailwind CSSのコンパイルパイプラインでは、入力CSSを解析して内部表現（AST）に変換する必要がある。標準的なCSSパーサー（PostCSS等）を使用せず、独自の高速パーサーを実装することで、パフォーマンスの最適化とTailwind CSS固有のディレクティブ対応を実現している。

**機能の利用シーン**：compile関数の最初のステップとして呼び出され、CSS文字列をASTに変換する。また、substituteAtImportsで読み込まれた外部スタイルシートのパースにも使用される。

**主要な処理内容**：
1. CSS文字列を1文字ずつスキャンし、トークンを識別する
2. `{` と `}` でネスト構造を管理するスタック機構を使用
3. セレクタ/at-ruleをルールノード、`property: value`を宣言ノードとして生成
4. コメント（`/* ... */`）をスキップし、ライセンスコメント（`/*! ... */`）を保持
5. カスタムプロパティ（`--*`）を特別に処理（セミコロンなしの終端を許容）
6. 文字列リテラル（引用符内）のエスケープを正しく処理
7. BOM付きUTF-8入力を自動的に処理
8. ソースロケーション情報をASTノードに付与（from指定時）

**関連システム・外部連携**：特になし。純粋な文字列処理。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 全画面のCSSコンパイルで間接的に使用される |

## 機能種別

データ変換処理（CSS文字列 -> AstNode配列）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | string | Yes | CSS文字列 | UTF-8エンコーディング。BOM付き許容 |
| opts.from | string | No | ソースファイルパス。ソースロケーション生成に使用 | ファイルパス文字列 |

### 入力データソース

- compile関数からCSS文字列が渡される
- substituteAtImportsから外部スタイルシートの内容が渡される

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ast | AstNode[] | パース済みのASTノード配列 |

### 出力先

- compile関数に返却される

## 処理フロー

### 処理シーケンス

```
1. 初期化
   ├─ BOM除去（先頭の\uFEFFをスペースに置換）
   ├─ AST配列・スタック・バッファの初期化
   └─ ソース情報の設定（from指定時）
2. 文字スキャンループ
   ├─ CR+LF処理（CRスキップ）
   ├─ バックスラッシュ: エスケープ文字処理
   ├─ /*: コメント開始〜終了検出
   │   └─ /*! で始まるライセンスコメントを保持
   ├─ 引用符: 文字列リテラル処理
   ├─ ホワイトスペース: 連続スペースの圧縮
   ├─ --: カスタムプロパティの特別処理
   │   └─ ブラケットバランスを考慮した終端検出
   ├─ ; + @: ボディなしat-rule
   ├─ ;: 宣言の終端
   ├─ {: ブロック開始（ルールノード生成、スタックプッシュ）
   ├─ }: ブロック終了（スタックポップ）
   ├─ (: 括弧開始
   ├─ ): 括弧終了
   └─ その他: バッファに蓄積
3. 後処理
   ├─ 残りバッファの処理（未終端at-rule）
   ├─ バランスチェック（未閉じブロックのエラー）
   └─ ライセンスコメントをAST先頭に追加
```

### フローチャート

```mermaid
flowchart TD
    A[CSS文字列入力] --> B[BOM除去・初期化]
    B --> C{文字スキャンループ}
    C --> D{文字種判定}
    D -->|バックスラッシュ| E[エスケープ処理]
    D -->|/*| F[コメント処理]
    D -->|引用符| G[文字列リテラル処理]
    D -->|--| H[カスタムプロパティ処理]
    D -->|;| I{バッファが@で始まる?}
    I -->|Yes| J[at-ruleノード生成]
    I -->|No| K[宣言ノード生成]
    D -->|開き波括弧| L[ルールノード生成・スタックプッシュ]
    D -->|閉じ波括弧| M[スタックポップ・ブロック完了]
    D -->|その他| N[バッファ蓄積]
    E --> C
    F --> C
    G --> C
    H --> C
    J --> C
    K --> C
    L --> C
    M --> C
    N --> C
    C -->|完了| O[後処理・バランスチェック]
    O --> P[AstNode配列返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | カスタムプロパティの特別処理 | `--`で始まるプロパティはセミコロンなしでの終端を許容し、ブラケットバランスを考慮する | プロパティ名が`--`で始まる場合 |
| BR-02 | ライセンスコメントの保持 | `/*!`で始まるコメントはAST先頭にホイストされる | コメントが`!`で始まる場合 |
| BR-03 | ホワイトスペース圧縮 | 連続するスペース・タブ・改行は1つに圧縮される | ホワイトスペースが連続する場合 |
| BR-04 | 改行のスペース変換 | 改行はスペースに変換される（バッファ内） | バッファ内に改行がある場合 |
| BR-05 | CRLFの正規化 | CR+LF（Windows改行）はLFに正規化される | CR+LFが出現した場合 |
| BR-06 | at-rule名の最小長 | at-rule名のパースはインデックス5（`@page`の長さ）から開始する最適化がある | at-ruleのパース時 |

### 計算ロジック

特になし。文字列のパターンマッチングによる解析処理。

## データベース操作仕様

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | CssSyntaxError | カスタムプロパティに値がない | `Invalid custom property, expected a value` |
| - | CssSyntaxError | 無効な宣言 | `Invalid declaration: \`{buffer}\`` |
| - | CssSyntaxError | 閉じ括弧`}`に対応する開き括弧がない | `Missing opening {` |
| - | CssSyntaxError | 閉じ丸括弧`)`に対応する開き丸括弧がない | `Missing opening (` |
| - | CssSyntaxError | ブロックの閉じ括弧が欠落 | `Missing closing } at {selector/name}` |
| - | CssSyntaxError | 文字列リテラルが未終端（セミコロン付き） | `Unterminated string: {string}` |
| - | CssSyntaxError | 文字列リテラルが未終端（改行） | `Unterminated string: {string}` |

### リトライ仕様

リトライは行わない。構文エラー時は即座にCssSyntaxErrorをスローする。

## トランザクション仕様

該当なし

## パフォーマンス要件

- 文字単位のスキャンにcharCodeAtを使用し、文字列比較よりも高速な数値比較を行う
- 定数として文字コードを事前定義し、繰り返しの文字コード変換を回避
- スタックベースのネスト管理により、再帰呼び出しのオーバーヘッドを回避

## セキュリティ考慮事項

- 不正なCSS入力に対してCssSyntaxErrorをスローし、無限ループを防止する

## 備考

- `parseAtRule`関数と`parseDeclaration`関数はエクスポートされており、他のモジュールからも使用される
- `CssSyntaxError`クラスはソースロケーション付きのエラーメッセージを提供する

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ast.ts | `packages/tailwindcss/src/ast.ts` | 出力となるAstNode型（StyleRule, AtRule, Declaration, Comment）の構造 |
| 1-2 | css-parser.ts | `packages/tailwindcss/src/css-parser.ts` | 定数定義（15-34行目）で使用する文字コードの一覧を確認 |

**読解のコツ**: パーサーは`charCodeAt`を使用した数値比較で文字種を判定する。定数名（BACKSLASH, SLASH, ASTERISK等）と対応する文字コードを把握しておくと読みやすい。

#### Step 2: parse関数のメインループを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | css-parser.ts | `packages/tailwindcss/src/css-parser.ts` | `parse`関数（64-594行目）のメインスキャンループの全体構造 |

**主要処理フロー**:
1. **64-66行目**: Sourceオブジェクトの初期化
2. **70行目**: BOM除去処理
3. **88行目**: メインのforループ開始
4. **94-97行目**: CRLF正規化（CRをスキップ）
5. **109-113行目**: バックスラッシュによるエスケープ処理
6. **131-162行目**: コメント処理（ライセンスコメントの保持を含む）
7. **165-171行目**: 文字列リテラル処理
8. **175-186行目**: 連続ホワイトスペースの圧縮
9. **204-316行目**: カスタムプロパティの特別処理（ブラケットバランス管理）
10. **326-347行目**: ボディなしat-ruleの処理（セミコロン + @で始まるバッファ）
11. **360-385行目**: 宣言の終端処理（セミコロン）
12. **388-419行目**: ブロック開始（{）の処理
13. **422-522行目**: ブロック終了（}）の処理

#### Step 3: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | css-parser.ts | `packages/tailwindcss/src/css-parser.ts` | `parseAtRule`（596-627行目）、`parseDeclaration`（629-640行目）、`parseString`（642-717行目） |

**主要処理フロー**:
- **596-627行目**: parseAtRule - at-rule名とパラメータの分離。5文字目から空白を探索する最適化
- **629-640行目**: parseDeclaration - コロンでプロパティと値を分離、!importantの検出
- **642-717行目**: parseString - 引用符内のエスケープと未終端文字列の検出

### プログラム呼び出し階層図

```
parse(input, opts)
    |
    +-- parseString()          ... 文字列リテラルの処理
    |
    +-- parseAtRule(buffer)    ... at-ruleの名前/パラメータ分離
    |
    +-- parseDeclaration(buffer) ... 宣言のプロパティ/値分離
    |
    +-- createLineTable()      ... ソースロケーション用行テーブル
```

### データフロー図

```
[入力]                    [処理]                           [出力]

CSS文字列         ──▶  parse()                ──▶  AstNode[]
                       (文字スキャン)
                       ├─ コメント            ──▶  Comment[]（ライセンスのみ）
                       ├─ セレクタ + {        ──▶  StyleRule / AtRule
                       ├─ プロパティ: 値;     ──▶  Declaration
                       └─ ネスト構造          ──▶  nodes[] 内にネスト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| css-parser.ts | `packages/tailwindcss/src/css-parser.ts` | ソース | CSSパーサー本体 |
| ast.ts | `packages/tailwindcss/src/ast.ts` | ソース | 出力ASTノード型定義とファクトリ関数 |
| source-maps/line-table.ts | `packages/tailwindcss/src/source-maps/line-table.ts` | ソース | ソースロケーション用行テーブル |
| source-maps/source.ts | `packages/tailwindcss/src/source-maps/source.ts` | ソース | Source型とSourceLocation型定義 |
