# 機能設計書 4-構文解析

## 概要

本ドキュメントは、トークン列をパースして構文木（ノード）を生成する機能について、その処理内容、入出力仕様、およびコードリーディングガイドを記載したものである。

### 本機能の処理概要

構文解析機能は、字句解析で生成されたトークン列を入力として受け取り、文法規則に従って構文木（AST: Abstract Syntax Tree）を生成する機能である。

**業務上の目的・背景**：トークン列だけではプログラムの構造を表現できない。構文解析によってトークン間の関係性を解析し、式、文、クラス、関数などの階層構造を持つ構文木を構築することで、後続のコード生成処理が可能になる。

**機能の利用シーン**：コンパイルパイプラインの中核処理として、CLIの`coffee --nodes`コマンドで構文木を出力するデバッグ用途、コード変換ツールの開発時、IDE/エディタでの構文解析機能実装時に利用される。

**主要な処理内容**：
1. Jisonパーサーによるトークン列の解析
2. 文法規則に基づく構文木ノードの生成
3. 位置情報（locationData）の付与
4. コメントのノードへの付与
5. 構文エラーの検出と報告

**関連システム・外部連携**：Jison（パーサー生成ツール）、nodesモジュール（ノードクラス群）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLI | 主機能 | `coffee --nodes`コマンドで構文木出力 |

## 機能種別

計算処理 / 構造解析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source | string or array | Yes | ソースコードまたはトークン配列 | 文字列または配列 |
| options.filename | string | No | ソースファイル名（エラー表示用） | - |
| options.literate | boolean | No | Literate CoffeeScriptとして処理 | - |

### 入力データソース

- lexer.tokenize()の出力（トークン配列）
- 直接のソースコード文字列（内部でトークン化）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| nodes | Block | ルートノード（Blockクラスのインスタンス） |
| nodes.expressions | array | 最上位の式/文の配列 |
| nodes.locationData | object | 位置情報 |

### 出力先

- 戻り値として返却
- 標準出力（CLI使用時、ノード表示）

## 処理フロー

### 処理シーケンス

```
1. 入力判定
   └─ 文字列ならトークン化、配列ならそのまま使用

2. パーサー初期化
   └─ lexerオブジェクト設定、トークン配列セット

3. 構文解析実行
   └─ parser.parse()でLALR(1)解析

4. 文法規則マッチング
   └─ 各トークンを文法規則に照合

5. ノード生成
   └─ アクションでNodeインスタンス生成

6. 位置情報付与
   └─ 各ノードにlocationData設定

7. コメント付与
   └─ トークンに付いたコメントをノードに転送

8. エラー検出
   └─ 文法違反時に構文エラー生成

9. 構文木返却
   └─ ルートノード（Block）を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: nodes関数] --> B{入力が文字列?}
    B -->|Yes| C[lexer.tokenize実行]
    B -->|No| D[トークン配列として使用]
    C --> D
    D --> E[parser.lexer設定]
    E --> F[setInput: トークンセット]
    F --> G[parser.parse実行]
    G --> H{文法マッチ?}
    H -->|Yes| I[ノード生成]
    H -->|No| J[parseError呼び出し]
    I --> K[位置情報付与]
    J --> L[SyntaxError生成]
    K --> M[コメント付与]
    M --> N[次のトークン]
    N --> G
    L --> O[エラースロー]
    G --> P{全トークン処理?}
    P -->|Yes| Q[ルートノード返却]
    P -->|No| G
    Q --> R[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | LALR(1)解析 | 1トークン先読みの上向き解析 | 常時 |
| BR-02 | 左再帰許容 | 左再帰的な文法規則をサポート | 文法定義時 |
| BR-03 | エラー回復なし | 構文エラー時は即座に停止 | エラー発生時 |

### 計算ロジック

特になし（文法規則に基づく）

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SyntaxError | 予期しないトークン | 文法規則に合わないトークン | コードを修正 |
| SyntaxError | 予期しない入力終了 | 式/文が未完了のまま終了 | 続きを記述 |
| SyntaxError | インデントエラー | 不正なインデント | インデントを修正 |

### リトライ仕様

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

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

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

## パフォーマンス要件

- LALR(1)解析によりO(n)の時間計算量
- 大規模ファイルでも効率的に処理

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

- 構文解析のみで、コード実行は行わない

## 備考

- パーサーはJisonで自動生成
- grammar.coffeeが文法定義の源泉

---

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

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

### 推奨読解順序

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

まず、構文木ノードの基本構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | nodes.coffee | `src/nodes.coffee` | Baseクラス（すべてのノードの基底クラス）の構造を確認 |
| 1-2 | nodes.coffee | `src/nodes.coffee` | Blockクラス（ルートノード）の構造を確認 |

**読解のコツ**: 各ノードクラスにはcompileNode（コード生成）、ast（AST変換）、children（子ノード）等のメソッドがある。

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

nodes関数とパーサー接続を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | coffeescript.coffee | `src/coffeescript.coffee` | `nodes`関数（189-191行目）がエントリーポイント |
| 2-2 | coffeescript.coffee | `src/coffeescript.coffee` | `parser.lexer`オブジェクト（207-224行目）がパーサーとの接続層 |

**主要処理フロー**:
1. **189行目**: 入力が文字列ならトークン化
2. **190行目**: トークン配列をそのまま使用
3. **191行目**: parser.parseで構文解析

#### Step 3: パーサーインターフェースを理解する

パーサーとLexerの接続を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | coffeescript.coffee | `src/coffeescript.coffee` | `parser.lexer`オブジェクト（207-224行目） |

**主要処理フロー**:
- **212-220行目**: `lex`メソッド - 次のトークンを返す
- **221-223行目**: `setInput`メソッド - トークン配列をセット
- **224行目**: `upcomingInput`メソッド - 未使用

#### Step 4: 文法定義を理解する

grammar.coffeeの文法規則を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | grammar.coffee | `src/grammar.coffee` | 文法規則の形式（Jison形式）を確認 |

**読解のコツ**:
- 文法規則は `非終端記号: [['パターン', 'アクション'], ...]` の形式
- アクションでノードインスタンスを生成（`$$ = new Nodes.XXX(...)`）
- `$1`, `$2`, ... で各要素を参照

#### Step 5: エラー処理を理解する

構文エラー処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | coffeescript.coffee | `src/coffeescript.coffee` | `parser.yy.parseError`（230-251行目） |

**主要処理フロー**:
- **234-235行目**: エラートークン取得
- **237-245行目**: エラーメッセージ生成
- **251行目**: SyntaxError生成

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

```
CoffeeScript.nodes (coffeescript.coffee:189)
    │
    ├─ lexer.tokenize (lexer.coffee:37) [文字列入力時]
    │
    └─ parser.parse (parser.coffee - 自動生成)
           │
           ├─ parser.lexer.setInput (coffeescript.coffee:221)
           │
           ├─ parser.lexer.lex (coffeescript.coffee:212)
           │      └─ トークン取得
           │
           ├─ 文法規則マッチング
           │      └─ grammar.coffee の各規則
           │
           ├─ ノード生成
           │      └─ parser.yy (nodes.coffee)
           │             ├─ new Block(...)
           │             ├─ new Code(...)
           │             ├─ new Call(...)
           │             └─ ... (各ノードクラス)
           │
           └─ parser.yy.parseError (coffeescript.coffee:230)
                  └─ helpers.throwSyntaxError
```

### データフロー図

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

トークン配列       ──▶  parser.lexer.setInput   ──▶  パーサー状態初期化
[tag, value, loc]        │
                        ▼
                  parser.lexer.lex          ──▶  1トークン取得
                        │
                        ▼
                  文法規則マッチング         ──▶  還元/シフト判定
                        │
                        ▼
                  アクション実行            ──▶  Nodeインスタンス生成
                  (grammar.coffee)              Block, Code, Call, etc.
                        │
                        ▼
                  位置情報付与              ──▶  locationData設定
                  (addDataToNode)
                        │
                        ▼
                  コメント付与              ──▶  comments配列設定
                        │
                        ▼
                  ルートノード              ──▶  Block {
                                               expressions: [...],
                                               locationData: {...}
                                             }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| coffeescript.coffee | `src/coffeescript.coffee` | ソース | nodes関数、parser.lexer定義 |
| grammar.coffee | `src/grammar.coffee` | ソース | Jison文法定義。パーサー生成元 |
| parser.js | `lib/coffeescript/parser.js` | 生成物 | Jison自動生成パーサー |
| nodes.coffee | `src/nodes.coffee` | ソース | 各ノードクラス定義 |
| helpers.coffee | `src/helpers.coffee` | ソース | addDataToNode、throwSyntaxError等 |
