# 機能設計書 14-Grammar

## 概要

本ドキュメントは、CoffeeScriptコンパイラにおけるGrammar機能の設計を記述する。GrammarはJisonパーサー用の文法規則を定義し、CoffeeScript言語の構文構造を形式的に記述するモジュールである。

### 本機能の処理概要

Grammar機能は、CoffeeScript言語の文法規則をJisonパーサージェネレーターが理解できる形式で定義する中核的な機能である。

**業務上の目的・背景**：CoffeeScriptのコンパイラは、ソースコードをトークン列に変換し（Lexer）、そのトークン列を構文木に変換する（Parser）というプロセスを経る。Grammarモジュールは、このパーサーが使用する文法規則を定義する。Jisonは、BNF（バッカス・ナウア記法）スタイルの文法定義からLALR(1)パーサーを自動生成するツールであり、CoffeeScriptはこれを活用してパーサーを構築している。適切な文法定義により、CoffeeScriptの豊富な構文機能（クラス、関数、内包表記、分割代入など）を正確にパースできる。

**機能の利用シーン**：
- コンパイル時：パーサーが文法規則に基づいてトークン列を構文木に変換
- ビルド時：`cake build:parser` でJisonが文法定義からparser.jsを生成
- 開発時：新しい言語機能を追加する際に文法規則を拡張

**主要な処理内容**：
1. 非終端記号（Root, Body, Expression, Class, Functionなど）の定義
2. 各非終端記号に対する生成規則（パターン）の定義
3. 各規則に対するアクション（構文木ノードの生成）の定義
4. 演算子の優先順位と結合性の定義
5. 位置情報（LOC関数）の付加
6. Jisonパーサーオブジェクトの生成

**関連システム・外部連携**：
- Jisonライブラリ：文法定義からパーサーを生成
- Nodesモジュール：アクション内で構文木ノードクラスをインスタンス化
- Rewriter：文法定義に合わせて暗黙のトークンを挿入

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | Annotated Source - Grammar | 主画面 | 文法定義grammar.coffeeのソースコード解説表示 |
| 27 | Annotated Source - Grammar | 主画面 | 文法定義grammar.coffeeのソースコード解説表示（v2） |

## 機能種別

文法定義 / パーサー生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| patternString | String | Yes | 生成規則のパターン（トークン列） | 有効なトークン名の空白区切り |
| action | Function | No | パース成功時に実行する関数 | 有効なJavaScript/CoffeeScript関数 |
| options | Object | No | 追加オプション（prec等） | 有効なオブジェクト |

### 入力データソース

Jisonパーサージェネレーターから呼び出される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| parser | Jison.Parser | 生成されたLALR(1)パーサーオブジェクト |
| grammar | Object | 文法規則のオブジェクト表現 |

### 出力先

lib/coffeescript/parser.jsとしてファイル出力される。

## 処理フロー

### 処理シーケンス

```
1. o関数によるDSL定義
   └─ 各文法規則をパターン、アクション、オプションで定義

2. 文法オブジェクトの構築
   ├─ Root: プログラムのルートノード
   ├─ Body: 文のリスト
   ├─ Expression: 式（Value, Operation, If, For等）
   ├─ Statement: 文（Return, Import, Export等）
   ├─ Class: クラス定義
   ├─ Code: 関数定義
   └─ その他多数の非終端記号

3. 演算子優先順位の定義
   └─ operators配列で優先順位と結合性を定義

4. トークンリストの自動抽出
   └─ 終端記号（トークン）を文法規則から抽出

5. Jison.Parserの生成
   └─ tokens, bnf, operators, startSymbolを渡してパーサー生成
```

### フローチャート

```mermaid
flowchart TD
    A[文法定義開始] --> B[o関数でDSL定義]
    B --> C[grammarオブジェクト構築]
    C --> D[Root, Body, Expression等を定義]
    D --> E[operators配列で優先順位定義]
    E --> F[tokens自動抽出]
    F --> G[Jison.Parser生成]
    G --> H[parser.jsとして出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-14-01 | ルートからの派生 | 全てのパースはRootから開始する | パース開始時 |
| BR-14-02 | 式と文の区別 | Expressionは値を持ち、Statementは値を持たない | 各構文要素 |
| BR-14-03 | 左結合演算子 | 算術演算子、比較演算子等は左結合 | 二項演算 |
| BR-14-04 | 右結合演算子 | 代入、累乗、yield等は右結合 | 代入、累乗 |
| BR-14-05 | 位置情報の付加 | LOC関数で内部ノードに位置情報を付加 | ノード生成時 |
| BR-14-06 | アクション未指定時 | アクションがない場合は$1をそのまま返す | 単純なルール |

### 計算ロジック

o関数のDSL処理:
```coffeescript
o = (patternString, action, options) ->
  patternString = patternString.replace /\s{2,}/g, ' '
  patternCount = patternString.split(' ').length
  if action
    action = if match = unwrap.exec action then match[1] else "(#{action}())"
    action = action.replace /\bnew /g, '$&yy.'
    action = action.replace /\b(?:Block\.wrap|extend)\b/g, 'yy.$&'
    # LOC関数の置換処理
    action = action.replace /LOC\(([0-9]*)\)/g, getAddDataToNodeFunctionString('$1')
```

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

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

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

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SyntaxError | パースエラー | 入力が文法に合致しない | Jisonがエラーメッセージを生成 |

### リトライ仕様

該当なし。

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

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

## パフォーマンス要件

特に定められていない。パーサー生成は一度のみ実行される。

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

特になし。

## 備考

- 文法規則は約200個以上定義されている
- 主要な非終端記号：Root, Body, Expression, Statement, Class, Code, Assign, If, For, While, Switch, Try, Operation等
- 演算子優先順位は低い順からoperators配列に定義（Jisonは逆順で処理）

---

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

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

### 推奨読解順序

#### Step 1: DSL関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | grammar.coffee | `src/grammar.coffee` | 17-86行目のJison DSL（unwrap、o関数）を理解する |

**読解のコツ**: o関数は文法規則を定義するためのDSL。パターン文字列、アクション関数、オプションを受け取り、Jisonが処理できる形式に変換する。

**主要処理フロー**:
- **26行目**: unwrapで関数本体を抽出
- **33-34行目**: パターン文字列を正規化
- **43行目**: `new`を`yy.new`に置換（Jison環境用）
- **76行目**: LOC関数を位置情報付加関数に置換

#### Step 2: 基本的な文法規則を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | grammar.coffee | `src/grammar.coffee` | 100-130行目のRoot, Body, Line, Statement定義を理解する |

**主要処理フロー**:
- **104-107行目**: Root - パースの開始点、空またはBodyを受け取る
- **110-114行目**: Body - 文のリスト、Block.wrapでラップ
- **119-124行目**: Line - Expression, Statement, FuncDirectiveのいずれか
- **132-137行目**: Statement - Return, Import, Export等

#### Step 3: 式と関数定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | grammar.coffee | `src/grammar.coffee` | 143-156行目のExpression定義を理解する |
| 3-2 | grammar.coffee | `src/grammar.coffee` | 328-347行目のCode（関数）定義を理解する |

**主要処理フロー**:
- **143-156行目**: Expression - Value, Code, Operation, Assign, If, Try, While, For, Switch, Class, Throw, Yield
- **330-333行目**: Code - パラメータリスト、関数グリフ（->, =>）、ブロックから関数を生成

#### Step 4: 演算子優先順位を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | grammar.coffee | `src/grammar.coffee` | 951-978行目の演算子優先順位定義を理解する |

**主要処理フロー**:
- **952行目**: 最も高い優先順位 - DO_IIFE
- **953行目**: プロパティアクセス - `.`, `?.`, `::`, `?::`
- **959行目**: 累乗 - `**`（右結合）
- **962行目**: 加減算 - `+`, `-`
- **974行目**: 代入 - `=`, `:`, `COMPOUND_ASSIGN`（右結合）

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

```
cake build:parser (Cakefile)
    │
    └─ buildParser() (Cakefile:53-58)
           │
           └─ require('./lib/coffeescript/grammar')
                  │
                  ├─ o() (grammar.coffee:33) - DSL関数
                  │      └─ 各文法規則を定義
                  │
                  ├─ grammar オブジェクト (grammar.coffee:100)
                  │      ├─ Root
                  │      ├─ Body
                  │      ├─ Expression
                  │      └─ ...
                  │
                  ├─ operators 配列 (grammar.coffee:951)
                  │
                  └─ new Jison.Parser (grammar.coffee:999-1003)
                         └─ parser.jsを生成
```

### データフロー図

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

grammar.coffee          Jison.Parser.generate()          parser.js
    │                        │                              │
文法規則定義 ───▶         パーステーブル生成 ───▶        パーサー関数
    │                        │                              │
├─ Root                 └─ LALR(1)アルゴリズム           ├─ parse()
├─ Body                                                   └─ tokenize
├─ Expression                                                結果を処理
└─ ...
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| grammar.coffee | `src/grammar.coffee` | ソース | 文法規則の定義 |
| parser.js | `lib/coffeescript/parser.js` | 生成物 | Jisonが生成したパーサー |
| nodes.coffee | `src/nodes.coffee` | ソース | 文法アクションで生成するノードクラス |
| Cakefile | `Cakefile` | ビルド | buildParser関数の定義 |
| rewriter.coffee | `src/rewriter.coffee` | ソース | 文法に合わせたトークン前処理 |
