# 機能設計書 15-パーサー生成

## 概要

本ドキュメントは、CoffeeScriptコンパイラにおけるパーサー生成機能の設計を記述する。この機能は、Jison文法定義からLALR(1)パーサーを生成し、lib/coffeescript/parser.jsとして出力するビルドプロセスを担当する。

### 本機能の処理概要

パーサー生成機能は、grammar.coffeeで定義された文法規則からJisonを使用してパーサーを自動生成するビルドタイムの機能である。

**業務上の目的・背景**：CoffeeScriptのパーサーは、トークン列を受け取り、構文木（AST）を生成する重要なコンポーネントである。文法規則を手動でパーサーに変換するのは複雑でエラーが発生しやすいため、Jisonパーサージェネレーターを使用して自動生成する。これにより、文法定義の変更が容易になり、言語の拡張がシンプルになる。Jisonは、YaccやBisonに似たボトムアップパーサージェネレーターであり、BNFスタイルの文法定義からLALR(1)パーサーを生成できる。

**機能の利用シーン**：
- CoffeeScriptのビルド時：`cake build` または `cake build:parser` コマンド実行時
- 文法変更後：grammar.coffeeを修正した後にパーサーを再生成
- 開発環境セットアップ時：初回ビルド時にパーサーを生成

**主要な処理内容**：
1. grammar.coffeeの読み込みとコンパイル
2. 文法オブジェクトの取得（grammar, tokens, operators）
3. Jison.Parserインスタンスの生成
4. パーステーブルの計算（LALR(1)アルゴリズム）
5. パーサーJavaScriptコードの生成
6. lib/coffeescript/parser.jsへの書き出し

**関連システム・外部連携**：
- Jisonライブラリ：パーサー生成エンジン
- Cakefile：ビルドタスクの定義
- grammar.coffee：入力となる文法定義

**権限による制御**：特になし。ビルドプロセスの一部として実行される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | Annotated Source - Grammar | 補助機能 | Jisonパーサー生成の解説を含む |
| 27 | Annotated Source - Grammar | 補助機能 | Jisonパーサー生成の解説を含む（v2） |

## 機能種別

ビルド処理 / コード生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| grammar | Object | Yes | 文法規則のオブジェクト（非終端記号をキー） | 有効なJison文法オブジェクト |
| tokens | String | Yes | 終端記号（トークン）の空白区切りリスト | 有効なトークン名 |
| operators | Array | Yes | 演算子優先順位の配列 | [結合性, 演算子...]の形式 |
| startSymbol | String | Yes | 開始記号（通常'Root'） | 有効な非終端記号名 |

### 入力データソース

grammar.coffeeのexports.parserから取得される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| parser.js | File | 生成されたパーサーのJavaScriptコード |

### 出力先

lib/coffeescript/parser.js

## 処理フロー

### 処理シーケンス

```
1. cake build:parser コマンドの実行
   └─ Cakefileのbuild:parserタスクを呼び出し

2. buildParser関数の実行
   ├─ global拡張（util.inspectなど）
   └─ jisonモジュールのrequire

3. grammar.coffeeのrequire
   └─ grammar.parser.generate()を呼び出し

4. Jisonによるパーサー生成
   ├─ 文法規則の解析
   ├─ First/Follow集合の計算
   ├─ LR(0)項目の生成
   ├─ LALR(1)パーステーブルの構築
   └─ JavaScriptコードの生成

5. parser.jsの書き出し
   └─ fs.writeFileSyncでファイル出力
```

### フローチャート

```mermaid
flowchart TD
    A[cake build:parser] --> B[buildParser関数呼び出し]
    B --> C[Jisonモジュール読み込み]
    C --> D[grammar.coffee読み込み]
    D --> E[grammar.parser取得]
    E --> F[parser.generate実行]
    F --> G{生成成功?}
    G -->|Yes| H[parser.jsに書き出し]
    G -->|No| I[エラー出力]
    H --> J[完了]
    I --> K[ビルド失敗]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-15-01 | LALR(1)文法 | 文法はLALR(1)で解析可能である必要がある | 文法定義時 |
| BR-15-02 | コンフリクト解決 | シフト/還元コンフリクトは演算子優先順位で解決 | パーステーブル構築時 |
| BR-15-03 | moduleMain省略 | パーサーはスタンドアロンで実行されないためmoduleMainを省略 | パーサー生成時 |
| BR-15-04 | 優先順位逆順 | Jisonは優先順位を低い方から処理するため逆順にする | 演算子定義時 |

### 計算ロジック

Jisonパーサー生成（Cakefile）:
```coffeescript
buildParser = ->
  helpers.extend global, require 'util'
  require 'jison'
  # moduleMainは不要（スタンドアロン実行しない）
  parser = require('./lib/coffeescript/grammar').parser.generate(moduleMain: ->)
  fs.writeFileSync 'lib/coffeescript/parser.js', parser
```

grammar.coffeeでのパーサー生成:
```coffeescript
exports.parser = new Parser
  tokens      : tokens.join ' '
  bnf         : grammar
  operators   : operators.reverse()
  startSymbol : 'Root'
```

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

### 操作別データベース影響一覧

データベースは使用しない。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Shift/Reduce Conflict | 文法エラー | 文法が曖昧な場合 | 演算子優先順位を定義するか文法を修正 |
| Reduce/Reduce Conflict | 文法エラー | 同じ入力に対して複数の還元が可能 | 文法を修正して一意にする |

### リトライ仕様

該当なし。文法エラーは修正が必要。

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

トランザクションは使用しない。

## パフォーマンス要件

ビルド時の一度きりの処理であり、特に要件なし。

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

特になし。

## 備考

- 生成されたparser.jsはgitで管理される（.gitignoreに含まれていない）
- パーサーサイズは数百KB程度になる
- 文法変更時は必ずパーサーを再生成する必要がある

---

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

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

### 推奨読解順序

#### Step 1: ビルドタスクを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Cakefile | `Cakefile` | 53-58行目のbuildParser関数を理解する |
| 1-2 | Cakefile | `Cakefile` | 124-128行目のtask定義を理解する |

**読解のコツ**: CakefileはCoffeeScriptのMakefileに相当。task関数でビルドタスクを定義する。

**主要処理フロー**:
- **53行目**: `buildParser = ->` でビルド関数を定義
- **54行目**: `helpers.extend global, require 'util'` でutilをグローバルに追加
- **55行目**: `require 'jison'` でJisonを読み込み
- **57行目**: `parser = require(...).parser.generate(...)` でパーサー生成
- **58行目**: `fs.writeFileSync` でファイル出力

#### Step 2: Jison Parserインスタンス化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | grammar.coffee | `src/grammar.coffee` | 999-1003行目のJison.Parser生成を理解する |

**主要処理フロー**:
- **999行目**: `exports.parser = new Parser` でパーサーを生成
- **1000行目**: `tokens: tokens.join ' '` でトークンリストを渡す
- **1001行目**: `bnf: grammar` で文法規則を渡す
- **1002行目**: `operators: operators.reverse()` で優先順位を逆順にして渡す
- **1003行目**: `startSymbol: 'Root'` で開始記号を指定

#### Step 3: トークン自動抽出を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | grammar.coffee | `src/grammar.coffee` | 987-993行目のトークン抽出処理を理解する |

**主要処理フロー**:
- **987行目**: `tokens = []` で空の配列を初期化
- **988-993行目**: 文法規則から非終端記号でないトークンを抽出

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

```
cake build:parser (コマンドライン)
    │
    └─ task 'build:parser' (Cakefile:126)
           │
           └─ buildParser() (Cakefile:53)
                  │
                  ├─ require 'jison' (Cakefile:55)
                  │
                  ├─ require './lib/coffeescript/grammar' (Cakefile:57)
                  │      │
                  │      └─ exports.parser = new Parser (grammar.coffee:999)
                  │             │
                  │             └─ Jison.Parser (jison/lib/jison.js)
                  │
                  ├─ parser.generate(moduleMain: ->) (Cakefile:57)
                  │      │
                  │      └─ LALR(1)パーステーブル生成
                  │
                  └─ fs.writeFileSync (Cakefile:58)
                         │
                         └─ lib/coffeescript/parser.js
```

### データフロー図

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

grammar.coffee           Jison.Parser                    parser.js
    │                        │                              │
├─ grammar ───────────▶  ├─ BNF解析                     ├─ parse()
├─ tokens ────────────▶  ├─ First/Follow計算  ─────▶    ├─ parseError()
├─ operators ─────────▶  ├─ LALR(1)構築                 └─ lexer統合
└─ startSymbol ───────▶  └─ JS生成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Cakefile | `Cakefile` | ビルド | buildParser関数とタスク定義 |
| grammar.coffee | `src/grammar.coffee` | ソース | 文法定義とParserインスタンス |
| parser.js | `lib/coffeescript/parser.js` | 生成物 | 生成されたパーサー |
| jison | `node_modules/jison` | 依存 | パーサージェネレーター |
