# 通知設計書 24-RegexException

## 概要

本ドキュメントは、HH\Lib\Regex\Exception クラスの設計仕様を定義する。Regex\Exceptionは、正規表現処理においてエラーが発生した際にスローされる例外クラスであり、PCRE（Perl Compatible Regular Expressions）のエラーコードに対応する。

### 本通知の処理概要

Regex\Exceptionは、正規表現のコンパイルや実行時にエラーが発生した際に、呼び出し元に対してエラー状態を通知するための例外クラスである。PHPのPREG_*_ERRORコードを人間が読める形式に変換して提供する。

**業務上の目的・背景**：正規表現は文字列処理において強力なツールであるが、複雑なパターンや大きな入力に対して様々なエラーが発生する可能性がある。バックトラック制限超過、再帰制限超過、不正なUTF-8、JITスタック制限超過などのエラーを適切に通知することで、開発者は問題のあるパターンや入力を特定し、修正することができる。

**通知の送信タイミング**：Regex\Exceptionは以下のような状況でスローされる：
- PREG_INTERNAL_ERROR: PCREの内部エラー
- PREG_BACKTRACK_LIMIT_ERROR: バックトラック制限超過
- PREG_RECURSION_LIMIT_ERROR: 再帰制限超過
- PREG_BAD_UTF8_ERROR: 不正なUTF-8文字列
- PREG_BAD_UTF8_OFFSET_ERROR: 不正なUTF-8オフセット
- PREG_BAD_REGEX_ERROR: 正規表現のコンパイルエラー
- PREG_JIT_STACKLIMIT_ERROR: PCRE JITスタック制限超過

**通知の受信者**：例外をキャッチする呼び出し元コード（アプリケーション層）が受信者となる。開発者はcatch文でRegex\Exceptionを捕捉し、適切な処理を行う。

**通知内容の概要**：例外メッセージとして「{エラー説明}: {正規表現パターン}」形式のエラーメッセージが含まれる。エラー説明は人間が読める形式（例：「Backtrack limit error」）で提供される。

**期待されるアクション**：
- PREG_BACKTRACK_LIMIT_ERROR: 正規表現の最適化、入力サイズの制限
- PREG_RECURSION_LIMIT_ERROR: 再帰パターンの見直し
- PREG_BAD_UTF8_ERROR: 入力文字列のエンコーディング検証
- PREG_BAD_REGEX_ERROR: 正規表現の構文修正
- PREG_JIT_STACKLIMIT_ERROR: JIT設定の調整、パターンの簡素化

## 通知種別

例外（Exception） - プログラム実行時のエラー通知

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（throw文による例外スロー） |
| 優先度 | 高（処理を中断） |
| リトライ | 通常不要（同一入力で同一エラー発生） |

### 送信先決定ロジック

例外はコールスタックを遡って伝播し、最初にマッチするcatchブロックで捕捉される。捕捉されない場合はプログラムが異常終了する。

## 通知テンプレート

### 例外メッセージ形式

| 項目 | 内容 |
|-----|------|
| フォーマット | `{エラー説明}: {正規表現パターン}` |
| 例 | `Backtrack limit error: /a*a*a*a*a$/` |

### 本文テンプレート

```
{error_description}: {regex_pattern}
```

### 添付ファイル

なし（例外オブジェクトとしてスタックトレースを含む）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| error_code | PCREエラーコード | PREG_*_ERROR定数 | Yes |
| error_description | エラーの説明 | 内部マッピング | Yes |
| regex_pattern | 正規表現パターン | Regex\Pattern | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | Regex\first_match | マッチエラー | 最初のマッチ検索でエラー |
| API呼び出し | Regex\every_match | マッチエラー | 全マッチ検索でエラー |
| API呼び出し | Regex\matches | マッチエラー | マッチ判定でエラー |
| API呼び出し | Regex\replace | 置換エラー | 置換処理でエラー |
| API呼び出し | Regex\replace_with | 置換エラー | コールバック置換でエラー |
| API呼び出し | Regex\split | 分割エラー | 文字列分割でエラー |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 正常完了 | 正規表現処理が正常に完了した場合 |
| マッチなし | マッチがないこと自体はエラーではない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[正規表現関数呼び出し] --> B[PCREマッチ実行]
    B --> C{結果}
    C -->|成功| D[結果返却]
    C -->|マッチなし| D
    C -->|エラー| E[エラーコード取得]
    E --> F[Regex\Exception生成]
    F --> G[例外スロー]
    G --> H[呼び出し元でキャッチ]
```

## データベース参照・更新仕様

### 参照テーブル一覧

なし（例外クラスはデータベースを参照しない）

### 更新テーブル一覧

なし（例外クラスはデータベースを更新しない）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| Internal error | PCRE内部エラー | PCREバージョン確認 |
| Backtrack limit error | バックトラック過多 | パターン最適化 |
| Recursion limit error | 再帰過多 | パターン簡素化 |
| Bad UTF8 error | 不正UTF-8 | 入力検証 |
| Bad UTF8 offset error | 不正オフセット | オフセット検証 |
| Regex failed to compile | 構文エラー | パターン修正 |
| PCRE JIT stack limit error | JITスタック超過 | 設定調整 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 通常不要 |
| リトライ間隔 | N/A |
| リトライ対象エラー | なし（同一入力で同一エラー） |

## 配信設定

### レート制限

なし（例外の発生頻度に制限なし）

### 配信時間帯

なし（例外は発生時即座にスロー）

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

- 正規表現パターンが例外メッセージに含まれる点に注意
- ReDoS（正規表現サービス拒否）攻撃への対策としてバックトラック制限が機能
- 入力文字列は例外メッセージに含まれないが、ログ出力時は注意

## 備考

- Regex\Exceptionは\Exceptionを直接継承
- エラーコードからエラーメッセージへのマッピングは内部で行われる
- 未知のエラーコードは「Unknown regex error」として処理

---

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

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

### 推奨読解順序

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

まず、Regex\Exceptionクラスとエラーコードマッピングを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | exception.php | `src/regex/exception.php` | Exceptionクラスの定義（行15-37） |

**読解のコツ**: コンストラクタ内でエラーコードから人間が読めるメッセージへの変換が行われている。$errorsディクショナリがキーとなる。

#### Step 2: エントリーポイントを理解する

例外がスローされる箇所を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | private.php | `src/regex/private.php` | regex_match関数（行27-38） |

**主要処理フロー**:
1. **行27-31**: regex_match関数シグネチャ、Pattern<T>とoffsetを受け取る
2. **行32**: オフセットの検証
3. **行33**: _Regex\match呼び出し
4. **行34-36**: エラーがnullでなければException生成・スロー
5. **行37**: 正常時はマッチ結果を返却

#### Step 3: エラーコードマッピングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | exception.php | `src/regex/exception.php` | $errorsディクショナリ（行17-25） |

**主要処理フロー**:
- **行17-25**: 7種類のPREG_*_ERRORコードと対応するメッセージ
- **行26-35**: メッセージ生成、idx()で未知のエラーにも対応

#### Step 4: テストコードを参照する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | RegexTest.php | `tests/regex/RegexTest.php` | 再帰テスト（行121-128） |

**主要処理フロー**:
- **行121-128**: バックトラック制限に達するパターンでException発生を検証
- **行123-127**: `toThrow(Regex\Exception::class, 'Backtrack limit error')`

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

```
アプリケーションコード
    │
    ├─ Regex\first_match($haystack, $pattern, $offset)
    │      │
    │      └─ _Private\regex_match()
    │             │
    │             ├─ validate_offset()
    │             │
    │             └─ _Regex\match()
    │                    │
    │                    ├─ 成功：マッチ結果返却
    │                    │
    │                    └─ 失敗：エラーコード返却
    │                           │
    │                           └─ Regex\Exception生成・スロー
    │
    ├─ Regex\every_match() → 同様のフロー
    ├─ Regex\matches() → 同様のフロー
    ├─ Regex\replace() → 同様のフロー
    ├─ Regex\replace_with() → 同様のフロー
    └─ Regex\split() → 同様のフロー
```

### データフロー図

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

haystack (string)   ───▶ PCREマッチ実行
pattern (Pattern<T>)       │
offset (int)               ├─▶ 成功 ───▶ マッチ結果 (T | null)
                           │
                           └─▶ 失敗（エラーコード）
                                  │
                                  ▼
                           エラーコード → メッセージ変換
                                  │
                                  ▼
                           Regex\Exception生成
                                  │
                                  ▼
                           例外スロー ───▶ 呼び出し元でcatch
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| exception.php | `src/regex/exception.php` | ソース | Exceptionクラス定義 |
| private.php | `src/regex/private.php` | ソース | regex_match関数（例外スロー箇所） |
| RegexTest.php | `tests/regex/RegexTest.php` | テスト | バックトラック制限テスト |
| first_match.hack | `src/regex/first_match.hack` | ソース | first_match公開API（存在する場合） |
| every_match.hack | `src/regex/every_match.hack` | ソース | every_match公開API（存在する場合） |
| replace.hack | `src/regex/replace.hack` | ソース | replace公開API（存在する場合） |
