# 通知設計書 7-unexpected_character

## 概要

本ドキュメントは、CoffeeScriptコンパイラが予期しない文字やトークンを検出した際に発生する構文エラー「unexpected character」の通知仕様を定義する。

### 本通知の処理概要

CoffeeScriptコンパイラのパーサー（構文解析器）またはレキサー（字句解析器）において、文法規則に合致しない文字やトークンが検出された場合に、構文エラーとして通知を行う処理である。これには予期しないセミコロン、正規表現の不正な開始文字、予期しないトークンタイプなどが含まれる。

**業務上の目的・背景**：CoffeeScriptは独自の構文規則を持っており、JavaScriptとは異なる記法が求められる場合がある。予期しない文字やトークンの検出は、ソースコードが文法規則に違反していることを示す。この通知により、開発者は構文エラーを早期に発見・修正できる。

**通知の送信タイミング**：以下の複数の箇所で発生する：
1. literalToken()でセミコロン（;）が予期しない位置に検出された場合（797行目、1174行目）
2. regexToken()で正規表現が不正な文字で始まっている場合（447行目）
3. パーサーで文法規則に合致しないトークンが検出された場合

**通知の受信者**：CoffeeScriptソースコードをコンパイルしている開発者。

**通知内容の概要**：エラーメッセージとして「unexpected {character}」という形式で、問題となった文字やトークンを特定できるようにしている。

**期待されるアクション**：開発者は該当する文字を削除するか、正しい構文に修正する。

## 通知種別

コンパイラ出力（標準エラー出力 / SyntaxError例外）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（コンパイル処理中に即座に発生） |
| 優先度 | 高（コンパイルを中断） |
| リトライ | 無（即時エラーとして処理） |

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

CoffeeScriptコンパイラを呼び出しているコンテキストに依存する。

## 通知テンプレート

### エラーメッセージ形式

| 項目 | 内容 |
|-----|------|
| 形式 | テキスト |

### 本文テンプレート

```
[filename]:[line]:[column]: error: unexpected {character}
[source_code_line]
[marker]
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| character | 予期しない文字またはトークン（;、*、その他のトークンタイプ） | エラー発生箇所に依存 | Yes |
| filename | ソースファイル名 | コンパイルオプション | No |
| line | エラー発生行番号 | locationData.first_line | Yes |
| column | エラー発生列番号 | locationData.first_column | Yes |
| source_code_line | エラーが発生した行のソースコード | 入力ソースコード | Yes |
| marker | エラー位置を示すマーカー | 計算により生成 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コンパイル処理 | literalToken()実行中 | セミコロンが'='または未完了のトークンの後に来た場合 | 予期しないセミコロン検出 |
| コンパイル処理 | regexToken()実行中 | 正規表現が*で始まっている場合 | 正規表現の不正な開始文字 |
| コンパイル処理 | suppressSemicolons()実行中 | セミコロンが'='または未完了のトークンの後に来た場合 | 末尾セミコロンの抑止中 |
| パーサー処理 | パーサー実行中 | 文法規則に合致しないトークンが検出された場合 | 構文解析エラー |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | 予期しない文字は必ずエラーとなる |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[トークン処理] --> B{セミコロン?}
    B -->|Yes| C{前のトークンが'='またはUNFINISHED?}
    C -->|Yes| D[error: unexpected ;]
    C -->|No| E[TERMINATORとして処理]
    B -->|No| F{正規表現開始?}
    F -->|Yes| G{*で始まる?}
    G -->|Yes| H[error: regular expressions cannot begin with *]
    G -->|No| I[正規表現処理継続]
    F -->|No| J[他のトークン処理]
    D --> K[throwSyntaxError]
    H --> K
```

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

### 参照テーブル一覧

該当なし

### 内部データ構造

| 構造名 | 用途 | 備考 |
|--------|------|------|
| UNFINISHED配列 | 未完了を示すトークンタイプ | rewriter.coffeeで定義 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| SyntaxError | 予期しないセミコロン | セミコロンを削除 |
| SyntaxError | 正規表現の不正な開始 | 正規表現を修正 |
| SyntaxError | 予期しないトークン | 構文を修正 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし

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

- エラーメッセージにはソースコードの一部が含まれる

## 備考

- CoffeeScriptではセミコロンは不要であり、使用すると多くの場合エラーとなる
- 正規表現は/または///で始まるが、直後に*が来ることは許可されない

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | rewriter.coffee | `src/rewriter.coffee` | UNFINISHED配列の定義 |

**読解のコツ**: UNFINISHED配列にはステートメントが完了していないことを示すトークンタイプが格納されている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | lexer.coffee | `src/lexer.coffee` | literalToken()内のセミコロンチェック（796-799行目） |

**主要処理フロー**:
1. **796行目**: valueが';'かどうかチェック
2. **797行目**: 前のトークンが'='またはUNFINISHED配列に含まれていればエラー

#### Step 3: 正規表現の開始文字チェックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | lexer.coffee | `src/lexer.coffee` | regexToken()内のREGEX_ILLEGALチェック（446-448行目） |

**主要処理フロー**:
- **446行目**: REGEX_ILLEGALパターンでマッチ
- **447-448行目**: マッチした場合「regular expressions cannot begin with {character}」エラー

#### Step 4: セミコロン抑止処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | lexer.coffee | `src/lexer.coffee` | suppressSemicolons()メソッド（1171-1174行目） |

**主要処理フロー**:
- **1172-1174行目**: 末尾のセミコロンを削除しつつ、不正な位置のセミコロンにはエラーを発生

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

```
Lexer.tokenize()
    |
    +-- literalToken()
    |       |
    |       +-- セミコロンチェック (796-799行目)
    |               |
    |               +-- [不正な位置] error("unexpected ;")
    |
    +-- regexToken()
    |       |
    |       +-- REGEX_ILLEGALチェック (446-448行目)
    |               |
    |               +-- [*で開始] error("regular expressions cannot begin with *")
    |
    +-- outdentToken()
            |
            +-- suppressSemicolons()
                    |
                    +-- セミコロンチェック (1172-1174行目)
                            |
                            +-- [不正な位置] error("unexpected ;")
```

### データフロー図

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

ソースコード  -----> literalToken()     -----> トークンストリーム
    |                     |
    |                     v
    |               セミコロン検出
    |                     |
    |                     v
    |               前のトークン確認
    |                     |
    |              [不正な位置]
    |                     |
    |                     v
    +------------> error() + throwSyntaxError()
                          |
                          v
                   SyntaxError例外
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lexer.coffee | `src/lexer.coffee` | ソース | セミコロンと正規表現開始文字のチェック |
| rewriter.coffee | `src/rewriter.coffee` | ソース | UNFINISHED配列の定義 |
| helpers.coffee | `src/helpers.coffee` | ソース | throwSyntaxError関数 |
| coffeescript.coffee | `src/coffeescript.coffee` | ソース | パーサーエラー処理（251行目） |
| error_messages.coffee | `test/error_messages.coffee` | テスト | unexpected ;テスト（160-178行目） |
