# 機能設計書 3-トークン化

## 概要

本ドキュメントは、CoffeeScriptソースコードをトークン列に分解する機能について、その処理内容、入出力仕様、およびコードリーディングガイドを記載したものである。

### 本機能の処理概要

トークン化機能は、CoffeeScriptソースコードを字句解析し、構文解析器が処理可能なトークン（語彙素）の配列に変換する機能である。

**業務上の目的・背景**：コンパイラの最初の段階として、ソースコードをパーサーが理解できる形式に変換する必要がある。トークン化によって、識別子、キーワード、演算子、リテラルなどの基本的な構文要素を識別し、後続の構文解析処理が効率的に行えるようになる。

**機能の利用シーン**：コンパイルパイプラインの第一段階として、CLIの`coffee --tokens`コマンドでトークン列を出力するデバッグ用途、構文ハイライトエンジンの実装、コードエディタの自動補完機能の実装時に利用される。

**主要な処理内容**：
1. ソースコードの前処理（BOM除去、改行正規化、Literate CoffeeScript変換）
2. 識別子・キーワードの認識
3. 数値リテラルの認識
4. 文字列リテラルの認識（補間を含む）
5. 正規表現リテラルの認識
6. コメントの抽出
7. 演算子・記号の認識
8. インデント/アウトデントの追跡
9. Rewriterによるトークン正規化

**関連システム・外部連携**：Rewriterモジュール（暗黙の括弧・ブレース補完）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLI | 主機能 | `coffee --tokens`コマンドでトークン列出力 |

## 機能種別

計算処理 / テキスト解析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| code | string | Yes | CoffeeScriptソースコード | 文字列であること |
| options.literate | boolean | No | Literate CoffeeScriptとして処理 | - |
| options.line | number | No | 開始行番号（デフォルト: 0） | 0以上の整数 |
| options.column | number | No | 開始列番号（デフォルト: 0） | 0以上の整数 |
| options.offset | number | No | 開始オフセット（デフォルト: 0） | 0以上の整数 |
| options.rewrite | boolean | No | Rewriter適用有無（デフォルト: true） | - |
| options.untilBalanced | boolean | No | バランス取れ次第終了（補間用） | - |

### 入力データソース

- 直接のソースコード文字列入力
- compile関数からの内部呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| tokens | array | トークンの配列 |
| tokens[n][0] | string | トークンタグ（種別） |
| tokens[n][1] | string | トークン値 |
| tokens[n][2] | object | 位置情報（locationData） |
| tokens[n][2].first_line | number | 開始行（0始まり） |
| tokens[n][2].first_column | number | 開始列（0始まり） |
| tokens[n][2].last_line | number | 終了行 |
| tokens[n][2].last_column | number | 終了列 |
| tokens[n][2].range | [number, number] | 文字位置範囲 |

### 出力先

- 戻り値として返却
- 標準出力（CLI使用時）

## 処理フロー

### 処理シーケンス

```
1. 初期化
   └─ インデント、スタック、フラグの初期化

2. ソースコード前処理（clean）
   └─ BOM除去、キャリッジリターン削除、Literate変換

3. メインループ開始
   └─ 各トークンマッチャーを優先順位で実行

4. トークンマッチング
   ├─ identifierToken: 識別子・キーワード
   ├─ commentToken: コメント
   ├─ whitespaceToken: 空白
   ├─ lineToken: 改行・インデント
   ├─ stringToken: 文字列リテラル
   ├─ numberToken: 数値リテラル
   ├─ jsxToken: JSX構文
   ├─ regexToken: 正規表現
   ├─ jsToken: バッククォートJS
   └─ literalToken: その他記号

5. 位置情報更新
   └─ 消費文字数に基づき行・列を更新

6. ループ終了判定
   └─ コード末尾到達またはバランス達成

7. インデントクローズ
   └─ 残りのインデントを閉じる

8. Rewriter適用（オプション）
   └─ 暗黙の括弧・ブレース補完

9. トークン列返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: tokenize] --> B[初期化]
    B --> C[clean: 前処理]
    C --> D{コード残り?}
    D -->|No| J[closeIndentation]
    D -->|Yes| E[トークンマッチング]
    E --> F{マッチ成功?}
    F -->|Yes| G[トークン追加]
    F -->|No| H[literalToken]
    G --> I[位置情報更新]
    H --> I
    I --> D
    J --> K{rewrite=on?}
    K -->|Yes| L[Rewriter適用]
    K -->|No| M[トークン返却]
    L --> M
    M --> N[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | トークンマッチ優先順位 | 識別子 > コメント > 空白 > 改行 > 文字列 > 数値 > JSX > 正規表現 > JS > リテラルの順 | 常時 |
| BR-02 | インデントベーススコープ | インデント増加でINDENT、減少でOUTDENTトークン生成 | 改行検出時 |
| BR-03 | import/export自動bare | IMPORTまたはEXPORTトークン検出でbareフラグ設定 | トークン生成時 |
| BR-04 | 予約語エラー | JavaScript予約語を識別子として使用するとエラー | 識別子検出時 |

### 計算ロジック

**インデントサイズ計算**:
```coffeescript
size = indent.length - 1 - indent.lastIndexOf '\n'
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SyntaxError | 予約語エラー | 予約語を識別子として使用 | 別の識別子名を使用 |
| SyntaxError | インデント不整合 | タブとスペースの混在 | 一貫したインデント文字を使用 |
| SyntaxError | 未閉じエラー | 括弧/文字列が閉じられていない | 対応する閉じ記号を追加 |
| SyntaxError | 不正な数値 | 不正な形式の数値リテラル | 正しい形式で記述 |
| SyntaxError | 不正なエスケープ | 不正なエスケープシーケンス | 正しいエスケープを使用 |

### リトライ仕様

リトライは行わない（同期処理）

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

本機能はトランザクション管理を行わない（ステートレスな変換処理）

## パフォーマンス要件

- O(n)の時間計算量（ソースコード長に比例）
- 大規模ファイルでも効率的に処理

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

- 入力コードの長さ制限なし（メモリ使用量に注意）

## 備考

- トークンタグの種類は数十種類存在
- Rewriter適用により暗黙の構文が補完される

---

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

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

### 推奨読解順序

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

まず、トークンの構造と関連する定数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lexer.coffee | `src/lexer.coffee` | 1-10行目のコメントでトークン形式 `[tag, value, locationData]` を確認 |
| 1-2 | lexer.coffee | `src/lexer.coffee` | 1226-1268行目でキーワード定義（JS_KEYWORDS, COFFEE_KEYWORDS, RESERVED等）を確認 |

**読解のコツ**: トークンは3要素配列で、追加のプロパティ（spaced, comments等）がオブジェクトプロパティとして付与される。

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

Lexerクラスのtokenizeメソッドを読み解く。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | lexer.coffee | `src/lexer.coffee` | `tokenize`メソッド（37-92行目）がエントリーポイント |

**主要処理フロー**:
1. **38-53行目**: 状態変数の初期化（インデント、スタック、フラグ）
2. **55-62行目**: 位置情報の初期化
3. **63行目**: `clean`メソッドで前処理
4. **68-85行目**: メインループ（各トークンマッチャー実行）
5. **89行目**: `closeIndentation`でインデント終了
6. **90行目**: 未閉じチェック
7. **92行目**: Rewriter適用

#### Step 3: 前処理を理解する

cleanメソッドによるソースコード正規化を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | lexer.coffee | `src/lexer.coffee` | `clean`メソッド（97-114行目） |

**主要処理フロー**:
- **99-102行目**: BOM (Byte Order Mark) 除去
- **103-107行目**: 先頭空白の処理
- **108-112行目**: キャリッジリターン除去、末尾空白除去
- **113行目**: Literate CoffeeScript変換（該当時）

#### Step 4: 各トークンマッチャーを理解する

主要なトークンマッチャーを優先順位順に理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | lexer.coffee | `src/lexer.coffee` | `identifierToken`（125-260行目）: 識別子・キーワード認識 |
| 4-2 | lexer.coffee | `src/lexer.coffee` | `numberToken`（264-287行目）: 数値リテラル認識 |
| 4-3 | lexer.coffee | `src/lexer.coffee` | `stringToken`（291-325行目）: 文字列リテラル認識 |
| 4-4 | lexer.coffee | `src/lexer.coffee` | `regexToken`（444-502行目）: 正規表現認識 |
| 4-5 | lexer.coffee | `src/lexer.coffee` | `lineToken`（514-565行目）: 改行・インデント処理 |
| 4-6 | lexer.coffee | `src/lexer.coffee` | `literalToken`（755-823行目）: 演算子・記号認識 |

**読解のコツ**:
- 各マッチャーは消費した文字数を返す
- 0を返した場合は次のマッチャーに処理が移る
- `@token`メソッドでトークン配列に追加

#### Step 5: インデント処理を理解する

インデントベースのスコープ管理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | lexer.coffee | `src/lexer.coffee` | `lineToken`（514-565行目）: インデント検出 |
| 5-2 | lexer.coffee | `src/lexer.coffee` | `outdentToken`（569-596行目）: アウトデント処理 |

**主要処理フロー**:
- **537-558行目**: インデント増加時の処理（INDENTトークン生成）
- **559-564行目**: インデント減少時の処理（OUTDENTトークン生成）

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

```
Lexer.tokenize (lexer.coffee:37)
    │
    ├─ clean (lexer.coffee:97)
    │      └─ invertLiterate (helpers.coffee:67) [Literate時]
    │
    ├─ メインループ
    │      ├─ identifierToken (lexer.coffee:125)
    │      ├─ commentToken (lexer.coffee:330)
    │      ├─ whitespaceToken (lexer.coffee:600)
    │      ├─ lineToken (lexer.coffee:514)
    │      │      └─ outdentToken (lexer.coffee:569)
    │      ├─ stringToken (lexer.coffee:291)
    │      │      └─ matchWithInterpolations (lexer.coffee:883)
    │      ├─ numberToken (lexer.coffee:264)
    │      ├─ jsxToken (lexer.coffee:626)
    │      ├─ regexToken (lexer.coffee:444)
    │      ├─ jsToken (lexer.coffee:431)
    │      └─ literalToken (lexer.coffee:755)
    │
    ├─ closeIndentation (lexer.coffee:861)
    │
    └─ Rewriter.rewrite (rewriter.coffee)
```

### データフロー図

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

CoffeeScript      ──▶  clean (前処理)           ──▶  正規化コード
ソースコード             │
                        ▼
                  identifierToken       ──▶  IDENTIFIER, KEYWORD
                  │                          トークン
                  ▼
                  numberToken           ──▶  NUMBER, INFINITY
                  │                          トークン
                  ▼
                  stringToken           ──▶  STRING, STRING_START/END
                  │                          トークン
                  ▼
                  lineToken             ──▶  INDENT, OUTDENT, TERMINATOR
                  │                          トークン
                  ▼
                  literalToken          ──▶  演算子・記号
                  │                          トークン
                  ▼
                  Rewriter              ──▶  正規化トークン列
                                            （暗黙の括弧補完済み）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lexer.coffee | `src/lexer.coffee` | ソース | Lexerクラス本体。トークン化のメインロジック |
| rewriter.coffee | `src/rewriter.coffee` | ソース | トークン列の正規化（暗黙の括弧補完等） |
| helpers.coffee | `src/helpers.coffee` | ソース | invertLiterate関数（Literate CoffeeScript変換） |
| coffeescript.coffee | `src/coffeescript.coffee` | ソース | tokens関数（公開API） |
