# 機能設計書 6-CSSセレクタパーサー（SelectorParser）

## 概要

本ドキュメントは、CSSセレクタをcombinator・function・selector・separator等のノードに分解するSelectorParserの機能設計書である。バリアント処理に使用される。

### 本機能の処理概要

**業務上の目的・背景**：Tailwind CSSではバリアント（`:hover`、`:focus`等）を適用する際にCSSセレクタを解析・操作する必要がある。セレクタ文字列を構造化されたASTに変換することで、セレクタの個別要素の検出・変換・再構築が可能になる。

**機能の利用シーン**：バリアントシステム（variants.ts）でセレクタの解析・操作に使用される。特に、`:not()`、`:where()`、`:has()`、`:is()`等の擬似クラス関数内のセレクタを再帰的に解析する際に利用される。

**主要な処理内容**：
1. CSSセレクタ文字列を1文字ずつスキャンし、トークンを識別する
2. コンビネーター（スペース、`>`、`+`、`~`）をcombinatorノードとして分離する
3. カンマをseparatorノードとして分離する
4. `.`、`:`、`#`で始まるセレクタ要素を個別のselectorノードとして分離する
5. `:not()`、`:where()`、`:has()`、`:is()`をfunctionノードとしてネスト構造で表現する
6. その他の関数は内容を単一のvalueノードとしてまとめる
7. `&`（ネスティング）と`*`（ユニバーサル）を独立したselectorノードとして分離する
8. 属性セレクタ（`[...]`）をまとめてselectorノードとする
9. 解析結果のASTをCSS文字列に逆変換するtoCss関数を提供する

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

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | バリアント処理の内部で間接的に使用される |

## 機能種別

データ変換処理（CSSセレクタ文字列 -> SelectorAstNode配列）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | string | Yes | CSSセレクタ文字列 | CRLF改行はLFに正規化される |

### 入力データソース

- バリアントシステムからセレクタ文字列が渡される

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ast | SelectorAstNode[] | パース済みのセレクタASTノード配列 |

### 出力先

- バリアントシステムに返却される

## 処理フロー

### 処理シーケンス

```
1. 前処理
   └─ CRLF改行をLFに正規化
2. 文字スキャンループ
   ├─ コンビネーター/カンマ(スペース,>,+,~,カンマ,改行,タブ):
   │   ├─ バッファをselectorとして確定
   │   ├─ 連続するコンビネーター文字をまとめる
   │   └─ カンマはseparator、それ以外はcombinatorノードに
   ├─ 開き丸括弧(: functionノード生成
   │   ├─ :not/:where/:has/:is の場合: 子ノードを再帰的にパース
   │   └─ その他の関数: 内容をvalueノードとしてまとめる
   ├─ 閉じ丸括弧): スタックポップ
   ├─ ドット/コロン/ハッシュ(.,:,#): 複合セレクタの分割
   ├─ 開き角括弧([): 属性セレクタの一括処理
   ├─ 引用符('/"): 文字列リテラル処理
   ├─ アンパサンド/アスタリスク(&,*): 独立selectorノード化
   ├─ バックスラッシュ: エスケープ処理
   └─ その他: バッファに蓄積
3. 後処理
   └─ 残りバッファをselectorとして確定
```

### フローチャート

```mermaid
flowchart TD
    A[セレクタ文字列入力] --> B[CRLF正規化]
    B --> C{文字スキャンループ}
    C --> D{文字種判定}
    D -->|コンビネーター| E{カンマ?}
    E -->|Yes| F[separatorノード]
    E -->|No| G[combinatorノード]
    D -->|開き括弧| H{:not/:where/:has/:is?}
    H -->|Yes| I[functionノード+再帰パース]
    H -->|No| J[functionノード+valueノード]
    D -->|./:/#| K[複合セレクタ分割]
    D -->|角括弧| L[属性セレクタ一括処理]
    D -->|&/*| M[独立selectorノード]
    D -->|その他| N[バッファ蓄積]
    C -->|完了| O[SelectorAstNode配列返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 擬似クラス関数の特別処理 | `:not`、`:where`、`:has`、`:is`の4つの擬似クラス関数のみ子ノードを再帰的にパースする | これらの関数名が出現した場合 |
| BR-02 | その他の関数のまとめ | 上記4つ以外の関数は内容をvalueノードとして一括処理する | 上記以外の関数名の場合 |
| BR-03 | 複合セレクタの分割 | `.class`、`:pseudo`、`#id`の境界でselectorノードを分割する | `.`、`:`、`#`が出現した場合 |
| BR-04 | ネスティングとユニバーサル | `&`と`*`は常に独立したselectorノードとして扱われる | `&`または`*`が出現した場合 |
| BR-05 | カンマのseparator分類 | カンマを含むコンビネーターはseparatorとして分類される | コンビネーター文字列のtrim結果が`,`の場合 |

### 計算ロジック

特になし。

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

該当なし

## エラー処理

### エラーケース一覧

本パーサーは明示的なエラーをスローしない。不正な入力に対してもベストエフォートでパースを行う。

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- charCodeAtによる数値比較で高速な文字種判定を実現
- 属性セレクタはネスティング深度管理により一括処理

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

特になし。

## 備考

- SelectorAstNodeは5種類: `combinator`、`function`、`selector`、`separator`、`value`
- ValueParserと異なり、`:not()`等の擬似クラス関数のみ子ノードを再帰的にパースする設計になっている

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | selector-parser.ts | `packages/tailwindcss/src/selector-parser.ts` | SelectorAstNode型（1-32行目）: 5種類のノード型を理解する |

**読解のコツ**: `SelectorFunctionNode`は`:not()`等の擬似クラス関数用で、子ノードを持つ。`SelectorValueNode`はそれ以外の関数の引数内容を保持する。両者の使い分けがパーサーの設計意図を理解する鍵である。

#### Step 2: parse関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | selector-parser.ts | `packages/tailwindcss/src/selector-parser.ts` | `parse`関数（109-421行目）のswitch文による文字種ごとの処理 |

**主要処理フロー**:
1. **135-181行目**: コンビネーター/カンマ処理。カンマはseparator、それ以外はcombinator
2. **191-246行目**: 関数呼び出し処理。:not/:where/:has/:isのみ再帰パース
3. **256-273行目**: 閉じ丸括弧処理
4. **283-298行目**: 複合セレクタ分割（`.`, `:`, `#`）
5. **308-342行目**: 属性セレクタ処理（`[...]`のネスティング管理）
6. **379-399行目**: アンパサンド/アスタリスク処理

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

```
SelectorParser.parse(input)
    |
    +-- combinator(value)       ... combinatorノード生成
    +-- fun(value, nodes)       ... functionノード生成
    +-- selector(value)         ... selectorノード生成
    +-- separator(value)        ... separatorノード生成
    +-- value(value)            ... valueノード生成

SelectorParser.toCss(ast)       ... AST→CSS文字列変換
```

### データフロー図

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

".foo:hover > .bar"
                   ──▶  parse()              ──▶  [
                                                    {kind:'selector', value:'.foo'},
                                                    {kind:'selector', value:':hover'},
                                                    {kind:'combinator', value:' > '},
                                                    {kind:'selector', value:'.bar'}
                                                  ]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| selector-parser.ts | `packages/tailwindcss/src/selector-parser.ts` | ソース | SelectorParser本体 |
| variants.ts | `packages/tailwindcss/src/variants.ts` | ソース | 主要な利用元（バリアント処理） |
| compile.ts | `packages/tailwindcss/src/compile.ts` | ソース | applyVariant関数で間接的に使用 |
