# 機能設計書 3-パーサー

## 概要

本ドキュメントは、F#コンパイラのパーサー機能の設計を記述する。パーサーは、F#ソースコードを構文木（AST: Abstract Syntax Tree）に変換する機能であり、字句解析（レキサー）と構文解析（パーサー）から構成される。

### 本機能の処理概要

パーサーは、F#ソースコードのテキストを読み込み、トークン列に分解（字句解析）した後、F#の文法規則に従って構文木（ParsedInput）に変換する機能である。

**業務上の目的・背景**：コンパイラの最初のフェーズとして、人間が記述したソースコードをコンピュータが処理可能な構造化されたデータ（構文木）に変換する必要がある。構文木はその後の型チェック、最適化、コード生成の基盤となる。F#は軽量構文（オフサイドルール）をサポートしており、インデントに基づいたブロック構造を正しく解析するために特別なレキサーフィルタが必要である。

**機能の利用シーン**：F#ソースファイル（.fs、.fsi、.fsx）のコンパイル時、IDE上でのシンタックスハイライト、IntelliSense、リファクタリング機能などで使用される。

**主要な処理内容**：
1. ソースコードの読み込みとUnicode処理
2. 字句解析（レキサー）によるトークン列生成
3. LexFilterによる軽量構文処理（オフサイドルール適用）
4. YACCベースのパーサーによる構文解析
5. ParsedInput（構文木）の生成
6. 構文エラーの検出と報告

**関連システム・外部連携**：fslex（字句解析器ジェネレータ）、fsyacc（パーサージェネレータ）を使用してlex.fslとpars.fsyから生成される。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | パーサーは直接的なUI画面を持たない |

## 機能種別

構文解析処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source | string/Stream/SourceText | Yes | F#ソースコード | UTF-8/UTF-16エンコーディング |
| fileName | string | Yes | ソースファイル名 | 有効なファイル名 |
| tcConfig | TcConfig | Yes | コンパイラ設定 | 初期化済み |
| lexResourceManager | LexResourceManager | Yes | レキサーリソース管理 | 初期化済み |
| isLastCompiland | bool * bool | Yes | 最終コンパイル単位フラグ | - |

### 入力データソース

- ファイルシステム上のF#ソースファイル
- IDE経由のテキストバッファ
- ストリーム入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ParsedInput | ParsedInput | 構文木（ImplFileまたはSigFile） |
| diagnostics | PhasedDiagnostic[] | パースエラー・警告 |

### 出力先

- コンパイラ内部データ構造（次フェーズへ渡される）

## 処理フロー

### 処理シーケンス

```
1. ソース読み込み
   ├─ UnicodeLexing.SourceTextAsLexbuf（SourceText入力）
   ├─ UnicodeLexing.StreamReaderAsLexbuf（Stream入力）
   └─ UnicodeLexing.StringAsLexbuf（文字列入力）

2. レキサー初期化
   ├─ Lexer.token関数準備
   └─ LexbufLocalXmlDocStore初期化

3. LexFilter適用
   ├─ LexFilterを通じたトークンストリーム
   └─ オフサイドルール（軽量構文）処理

4. パース実行
   ├─ Parser.signatureFile（.fsi）
   └─ Parser.implementationFile（.fs/.fsx）

5. 構文木生成
   ├─ ParsedInput.ImplFile
   └─ ParsedInput.SigFile
```

### フローチャート

```mermaid
flowchart TD
    A[ソースコード入力] --> B[Unicode正規化]
    B --> C[Lexbuf作成]
    C --> D[レキサーでトークン化]
    D --> E[LexFilter適用]
    E --> F{ファイル種別}
    F -->|.fsi| G[signatureFile パース]
    F -->|.fs/.fsx| H[implementationFile パース]
    G --> I[ParsedInput.SigFile]
    H --> J[ParsedInput.ImplFile]
    I --> K[構文木出力]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | オフサイドルール | インデントによりブロック構造を決定 | #lightまたはデフォルト |
| BR-002 | UTF-8/BOM | ソースファイルはUTF-8推奨、BOM許容 | 常時 |
| BR-003 | 行継続 | 長い行は\で継続可能 | 文字列リテラル内 |
| BR-004 | コメント保持 | ドキュメントコメント（///）は構文木に保持 | 常時 |

### 計算ロジック

オフサイドルールでは、キーワード（let、if、for等）の開始位置を基準として、それ以降の関連コードは同等以上のインデントが必要。インデントが浅くなった時点でブロック終了と判定。

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| FS0010 | 構文エラー | 予期しないトークン | コード修正 |
| FS0058 | インデントエラー | オフサイドルール違反 | インデント修正 |
| FS0515 | 不正文字 | 認識できない文字 | 文字削除または修正 |

### リトライ仕様

パーサーはエラー回復機能を持ち、エラー発生後も可能な限りパースを継続して複数エラーを報告する。

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

該当なし

## パフォーマンス要件

- 100KBのソースファイルで100ms以内のパース完了
- ストリーミング処理による大規模ファイル対応

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

- 悪意のある入力（極端に長い識別子、深いネスト等）に対するDoS対策

## 備考

F#のパーサーはfslexとfsyaccを使用して生成される。lex.fslは字句解析器定義、pars.fsyは文法定義を含む。LexFilterは軽量構文をサポートするための独自拡張。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SyntaxTree.fs | `src/Compiler/SyntaxTree/SyntaxTree.fs` | Ident、SynLongIdent、SynConst等の基本構文要素定義 |
| 1-2 | SyntaxTree.fsi | `src/Compiler/SyntaxTree/SyntaxTree.fsi` | ParsedInput、SynExpr、SynPat等の主要型定義 |
| 1-3 | SyntaxTrivia.fs | `src/Compiler/SyntaxTree/SyntaxTrivia.fs` | トリビア（空白、コメント）の定義 |

**読解のコツ**:
- ParsedInputはImplFile（実装ファイル）またはSigFile（シグネチャファイル）の判別共用体
- SynExprは式を表す大きな判別共用体で、すべての式構文を網羅
- 各構文要素はrangeフィールドでソース位置を追跡

#### Step 2: 字句解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | lex.fsl | `src/Compiler/lex.fsl` | fslex定義ファイル、トークン定義 |
| 2-2 | LexHelpers.fs | `src/Compiler/SyntaxTree/LexHelpers.fs` | レキサーヘルパー関数 |
| 2-3 | UnicodeLexing.fs | `src/Compiler/SyntaxTree/UnicodeLexing.fs` | Unicode処理、Lexbuf作成 |

**主要処理フロー**:
- lex.fslは正規表現ベースのトークン定義
- 文字列リテラル、コメント、識別子等の認識ルール

#### Step 3: 軽量構文処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | LexFilter.fs | `src/Compiler/SyntaxTree/LexFilter.fs` | オフサイドルール実装 |

**主要処理フロー**:
- **31-115行目**: Contextの定義（構文コンテキスト）
- **118-150行目**: isInfix関数（中置演算子判定）
- Contextスタックによるインデント追跡
- 暗黙のセミコロン・ブロック終了トークン挿入

#### Step 4: 構文解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | pars.fsy | `src/Compiler/pars.fsy` | fsyacc文法定義ファイル |
| 4-2 | ParseHelpers.fs | `src/Compiler/SyntaxTree/ParseHelpers.fs` | パーサーヘルパー関数 |

**主要処理フロー**:
- pars.fsyはLALR(1)文法定義
- 文法規則とセマンティックアクション

#### Step 5: 構文木操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | SyntaxTreeOps.fs | `src/Compiler/SyntaxTree/SyntaxTreeOps.fs` | 構文木操作ユーティリティ |

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

```
ParseOneInputFile / ParseOneInputSourceText
    │
    ├─ UnicodeLexing.SourceTextAsLexbuf
    │      └─ Lexbuf作成
    │
    ├─ Lexer.token（lex.fslから生成）
    │      └─ トークン生成
    │
    ├─ LexFilter
    │      ├─ Contextスタック管理
    │      └─ オフサイドルール適用
    │
    └─ Parser.implementationFile / Parser.signatureFile
           ├─ pars.fsyから生成
           └─ ParsedInput生成
```

### データフロー図

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

ソースコード       ──▶  UnicodeLexing           ──▶  Lexbuf
（テキスト）                  │
                              ▼
Lexbuf             ──▶  Lexer.token            ──▶  Token列
                              │
                              ▼
Token列            ──▶  LexFilter              ──▶  変換Token列
                              │                     （オフサイド対応）
                              ▼
変換Token列        ──▶  Parser                 ──▶  ParsedInput
                                                    （構文木）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SyntaxTree.fs | `src/Compiler/SyntaxTree/SyntaxTree.fs` | ソース | 構文木データ型定義 |
| SyntaxTree.fsi | `src/Compiler/SyntaxTree/SyntaxTree.fsi` | ソース | 構文木シグネチャ |
| SyntaxTreeOps.fs | `src/Compiler/SyntaxTree/SyntaxTreeOps.fs` | ソース | 構文木操作関数 |
| SyntaxTrivia.fs | `src/Compiler/SyntaxTree/SyntaxTrivia.fs` | ソース | トリビア定義 |
| lex.fsl | `src/Compiler/lex.fsl` | ソース | 字句解析器定義（fslex） |
| pars.fsy | `src/Compiler/pars.fsy` | ソース | パーサー定義（fsyacc） |
| LexFilter.fs | `src/Compiler/SyntaxTree/LexFilter.fs` | ソース | 軽量構文処理 |
| LexHelpers.fs | `src/Compiler/SyntaxTree/LexHelpers.fs` | ソース | レキサーヘルパー |
| UnicodeLexing.fs | `src/Compiler/SyntaxTree/UnicodeLexing.fs` | ソース | Unicode処理 |
| ParseHelpers.fs | `src/Compiler/SyntaxTree/ParseHelpers.fs` | ソース | パーサーヘルパー |
| XmlDoc.fs | `src/Compiler/SyntaxTree/XmlDoc.fs` | ソース | XMLドキュメントコメント解析 |
