# 機能設計書 9-文字列補間処理

## 概要

本ドキュメントは、ダブルクォート文字列内の#{...}による式展開を処理する機能について、その処理内容、入出力仕様、およびコードリーディングガイドを記載したものである。

### 本機能の処理概要

文字列補間処理機能は、CoffeeScriptのダブルクォート文字列（"..."）およびヒアドキュメント（"""..."""）内に埋め込まれた`#{...}`形式の式を検出し、実行時に評価される形式に変換する機能である。

**業務上の目的・背景**：文字列補間は、動的な文字列を簡潔に記述するための重要な言語機能である。従来の文字列連結（"Hello, " + name + "!"）に比べ、補間構文（"Hello, #{name}!"）は可読性が高く、コードの保守性を向上させる。

**機能の利用シーン**：動的なメッセージ生成、テンプレート文字列の作成、ログ出力、UI表示文字列の組み立てなど、文字列に変数や式の結果を埋め込むあらゆる場面で利用される。

**主要な処理内容**：
1. ダブルクォート文字列の検出
2. `#{` 補間開始の検出
3. 補間内の式の再帰的トークン化
4. `}` 補間終了の検出
5. 文字列セグメントと補間セグメントの分離
6. STRING_START/STRING_END トークンによるラップ
7. 補間トークンのマージ

**関連システム・外部連携**：Lexer（再帰呼び出し）、Rewriter

**権限による制御**：特になし（すべてのユーザーが利用可能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | Annotated Source - Lexer | 補助機能 | matchWithInterpolationsの解説を含む |
| 25 | Annotated Source - Lexer | 補助機能 | matchWithInterpolationsの解説を含む（v2） |

## 機能種別

計算処理 / テキスト解析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| chunk | string | Yes | 現在解析中の文字列（"から始まる） | ダブルクォートで開始 |

### 入力データソース

- LexerのstringTokenメソッドから呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| tokens | array | NEOSTRINGとTOKENSの混合配列 |
| index | number | 消費した文字数 |

### 出力先

- mergeInterpolationTokensに渡される

## 処理フロー

### 処理シーケンス

```
1. デリミタ確認
   └─ ", """, ', ''' のいずれかを検出

2. 文字列部分マッチ
   └─ 正規表現で補間なし部分をマッチ

3. エスケープ検証
   └─ 不正なエスケープシーケンスをチェック

4. NEOSTRINGトークン生成
   └─ 文字列部分をトークン化

5. 補間検出
   └─ #{ にマッチ

6. 再帰的トークン化
   └─ 新しいLexerインスタンスで補間内を解析

7. 補間トークン変換
   └─ {→(, }→) に変換

8. TOKENSトークン生成
   └─ 補間トークンを格納

9. ループ継続
   └─ 閉じデリミタまで繰り返し

10. マージ処理
    └─ mergeInterpolationTokensで最終統合
```

### フローチャート

```mermaid
flowchart TD
    A[開始: matchWithInterpolations] --> B{デリミタ確認}
    B -->|不一致| Z[null返却]
    B -->|一致| C[正規表現マッチ]
    C --> D[エスケープ検証]
    D --> E[NEOSTRINGトークン生成]
    E --> F{補間#{あり?}
    F -->|No| K[閉じデリミタ確認]
    F -->|Yes| G[補間オフセット計算]
    G --> H[新Lexer.tokenize 再帰]
    H --> I[{→(, }→) 変換]
    I --> J[TOKENSトークン追加]
    J --> C
    K --> L{閉じデリミタ?}
    L -->|Yes| M[tokens, index返却]
    L -->|No| N[エラー: missing delimiter]
    M --> O[終了]
    N --> P[エラースロー]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ダブルクォートのみ | シングルクォートでは補間なし | 文字列タイプ判定時 |
| BR-02 | ネスト可能 | 補間内で再度文字列+補間が可能 | 再帰処理 |
| BR-03 | バランス必須 | {と}のバランスが必要 | 補間解析時 |
| BR-04 | エスケープ可能 | \#{で補間を回避 | 文字列内 |

### 計算ロジック

**補間検出正規表現**:
```coffeescript
interpolators = /^#\{/
```

**ダブルクォート文字列正規表現**:
```coffeescript
STRING_DOUBLE = /^(?: [^\\"#] | \\[\s\S] | \#(?!\{) )*/
```

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SyntaxError | 未閉じデリミタ | 閉じクォートがない | クォートを追加 |
| SyntaxError | 不正なエスケープ | 不正なエスケープシーケンス | エスケープを修正 |

### リトライ仕様

リトライは行わない

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

本機能はトランザクション管理を行わない

## パフォーマンス要件

- 再帰呼び出しによりネストが深いと処理時間増加
- 通常の使用では問題なし

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

- 補間内の式は実行時に評価される
- ユーザー入力を直接補間しないこと

## 備考

- ES6テンプレートリテラル（`${}`）と類似の機能
- 正規表現の補間（///...///）でも同様の処理

---

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

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

### 推奨読解順序

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

まず、補間処理で使用される中間トークン形式を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lexer.coffee | `src/lexer.coffee` | NEOSTRING/TOKENSの2種類の中間トークン形式を確認 |

**読解のコツ**: NEOSTRINGは文字列部分、TOKENSは補間部分のトークン配列を格納する中間形式。

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

stringTokenメソッドからの呼び出しを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | lexer.coffee | `src/lexer.coffee` | stringToken（291-325行目） |
| 2-2 | lexer.coffee | `src/lexer.coffee` | 307行目のmatchWithInterpolations呼び出し |

**主要処理フロー**:
1. **292-293行目**: クォートタイプ検出
2. **301-305行目**: 正規表現選択（SINGLE/DOUBLE/HEREDOC）
3. **307行目**: matchWithInterpolations呼び出し
4. **319行目**: mergeInterpolationTokens呼び出し

#### Step 3: 補間マッチング処理を理解する

matchWithInterpolationsメソッドの詳細を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | lexer.coffee | `src/lexer.coffee` | matchWithInterpolations（883-947行目） |

**主要処理フロー**:
- **884行目**: tokens配列初期化
- **886行目**: デリミタ確認
- **888-897行目**: メインループ（文字列部分処理）
- **899-909行目**: 補間検出と再帰Lexer呼び出し
- **912-925行目**: 補間トークン変換（{→(, }→)）
- **939行目**: TOKENSトークン追加
- **944行目**: 閉じデリミタ確認

#### Step 4: トークンマージ処理を理解する

mergeInterpolationTokensメソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | lexer.coffee | `src/lexer.coffee` | mergeInterpolationTokens（953-1020行目） |

**主要処理フロー**:
- **957行目**: STRING_START生成（複数トークン時）
- **961-1002行目**: 各トークンの処理
- **978-986行目**: NEOSTRING→STRING変換
- **1020行目**: STRING_END生成

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

```
Lexer.stringToken (lexer.coffee:291)
    │
    ├─ matchWithInterpolations (lexer.coffee:883)
    │      │
    │      ├─ 正規表現マッチ (STRING_DOUBLE等)
    │      │
    │      ├─ validateEscapes (lexer.coffee:1152)
    │      │
    │      ├─ NEOSTRINGトークン生成
    │      │
    │      └─ [補間検出時]
    │             │
    │             └─ new Lexer().tokenize (再帰)
    │                    │
    │                    └─ untilBalanced: on
    │
    └─ mergeInterpolationTokens (lexer.coffee:953)
           │
           ├─ STRING_START生成
           │
           ├─ NEOSTRING→STRING変換
           │
           ├─ TOKENSトークン展開
           │
           └─ STRING_END生成
```

### データフロー図

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

"Hello, #{name}!"
       │
       ▼
  matchWithInterpolations
       │
       ├─ "Hello, "    ──▶  ['NEOSTRING', 'Hello, ', loc]
       │
       ├─ #{name}      ──▶  ['TOKENS', [
       │                        ['INTERPOLATION_START', '('],
       │                        ['IDENTIFIER', 'name'],
       │                        ['INTERPOLATION_END', ')']
       │                    ]]
       │
       └─ "!"          ──▶  ['NEOSTRING', '!', loc]
       │
       ▼
  mergeInterpolationTokens
       │
       └─ [
            ['STRING_START', '('],
            ['STRING', '"Hello, "'],
            ['INTERPOLATION_START', '('],
            ['IDENTIFIER', 'name'],
            ['INTERPOLATION_END', ')'],
            ['STRING', '"!"'],
            ['STRING_END', ')']
          ]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lexer.coffee | `src/lexer.coffee` | ソース | matchWithInterpolations, mergeInterpolationTokens |
| rewriter.coffee | `src/rewriter.coffee` | ソース | 補間トークンの後処理 |
