# 機能設計書 3-パーサー（構文解析）

## 概要

本ドキュメントは、Nimコンパイラのパーサー（構文解析器）の機能設計について記載する。パーサーはトークン列からAST（抽象構文木）を構築する構文解析機能を提供する。

### 本機能の処理概要

パーサーは、レキサーから提供されるトークン列を入力として受け取り、Nim言語の文法規則に従ってAST（Abstract Syntax Tree、抽象構文木）を構築する。パーサーは文法ファイル（doc/grammar.txt）を生成するソースとしても機能し、文法仕様と実装の一貫性を保証する。

**業務上の目的・背景**：プログラミング言語のコンパイルにおいて、構文解析はソースコードの構造を理解するために必須のステップである。Nimパーサーは標準Nim構文を反映し、効率的な演算子優先順位アルゴリズムを採用している。ASTはセマンティック解析、コード生成など後続のコンパイルフェーズの入力となる重要な中間表現である。

**機能の利用シーン**：
- Nimソースコードのコンパイル時（全コマンドで使用）
- シンタックスチェック（`nim check`コマンド）
- ドキュメント生成時
- IDEサポート（nimsuggestでの構文解析）
- コードフォーマッタ（nimpretty）

**主要な処理内容**：
1. パーサーの初期化とレキサーとの連携
2. トップレベル文の解析（モジュール構造）
3. 式の解析（演算子優先順位に基づく）
4. 文の解析（制御構造、宣言など）
5. 型記述の解析
6. プラグマの解析
7. インデントベースのブロック構造解析
8. コメントのAST付加

**関連システム・外部連携**：
- レキサー（lexer.nim）からトークン列を受け取る
- AST（ast.nim）でノード構造を定義
- セマンティック解析（sem.nim）にASTを提供
- nimpretty（コードフォーマッタ）との連携
- nimsuggest（IDE連携）との連携

**権限による制御**：パーサー自体には権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | コマンドラインインターフェース | 参照画面 | 構文エラー時のエラー位置表示 |

## 機能種別

構文解析処理 / AST構築処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| inputStream | PLLStream | Yes | ソースコードのストリーム | 有効なストリーム |
| fileIdx | FileIndex | Yes | ファイルインデックス | 有効なインデックス |
| cache | IdentCache | Yes | 識別子キャッシュ | 非nil |
| config | ConfigRef | Yes | コンパイラ設定 | 非nil |

### 入力データソース

- レキサーからのトークン列（Token構造体）
- ソースファイル情報（FileIndex）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | PNode | 構文木のルートノード |
| node.kind | TNodeKind | ノードの種類（式、文、宣言等） |
| node.info | TLineInfo | ソース位置情報 |
| node.sons | seq[PNode] | 子ノードのシーケンス |
| node.comment | string | 付加されたコメント |

### 出力先

- ASTノード（PNode）としてセマンティック解析に渡される
- エラーメッセージ（標準エラー出力）

## 処理フロー

### 処理シーケンス

```
1. パーサーのオープン（openParser）
   └─ レキサーのオープン、最初のトークン取得
2. トップレベル解析（parseTopLevelStmt/parseAll）
   └─ モジュール構造の解析
3. 文の解析（parseStmt）
   ├─ 複合文（complexOrSimpleStmt）
   └─ 単純文（simpleStmt）
4. 式の解析（parseExpr）
   ├─ simpleExpr（演算子式）
   ├─ primary（一次式）
   └─ identOrLiteral（識別子・リテラル）
5. 宣言の解析
   ├─ proc/func/iterator定義
   ├─ type定義
   ├─ var/let/const定義
   └─ import/include/export
6. パーサーのクローズ（closeParser）
```

### フローチャート

```mermaid
flowchart TD
    A[openParser] --> B[getTok: 最初のトークン]
    B --> C[parseTopLevelStmt]
    C --> D{トークン種別}
    D -->|import/include等| E[インポート解析]
    D -->|proc/func等| F[ルーチン定義解析]
    D -->|type| G[型定義解析]
    D -->|var/let/const| H[変数定義解析]
    D -->|その他| I[complexOrSimpleStmt]
    I --> J[simpleExpr]
    J --> K[primary]
    K --> L[identOrLiteral]
    L --> M[primarySuffix]
    M --> N[parseOperators]
    N --> O{次のトークン?}
    O -->|あり| C
    O -->|EOF| P[closeParser]
    E --> O
    F --> O
    G --> O
    H --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | インデント規則 | インデントがブロック構造を決定 | 全ての複合文 |
| BR-02 | 演算子優先順位 | 演算子の先頭文字で優先順位決定 | 二項演算子解析時 |
| BR-03 | 右結合演算子 | `^`で始まる演算子は右結合 | 演算子解析時 |
| BR-04 | コマンド構文 | スペース後の引数はコマンド呼び出しとして解釈 | 式解析時 |
| BR-05 | プラグマ解析 | `{.`で始まり`.}`で終わる | プラグマ検出時 |
| BR-06 | コメント付加 | コメントは直前のASTノードに付加 | コメント検出時 |

### 計算ロジック

**演算子優先順位**（getPrecedence関数より）:
| 優先順位 | 演算子 |
|---------|--------|
| 10 | `$`, `^` |
| 9 | `*`, `/`, `%`, `\`, `div`, `mod`, `shl`, `shr` |
| 8 | `+`, `-`, `|`, `~` |
| 7 | `&` |
| 6 | `.`, `..` |
| 5 | `=`, `<`, `>`, `!`, `in`, `notin`, `is`, `isnot`, `of`, `as`, `from` |
| 4 | `and` |
| 3 | `or`, `xor` |
| 2 | `?` |
| 1 | 代入演算子（末尾が`=`） |
| 0 | 矢印演算子（末尾が`->`、`~>`、`=>`） |

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

該当なし（パーサーはデータベースを使用しない）

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| N/A | N/A | N/A | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| errInvalidIndentation | インデントエラー | 不正なインデント | インデントを修正 |
| errIdentifierExpected | 識別子エラー | 識別子が必要な位置に他のトークン | 識別子を追加 |
| errExprExpected | 式エラー | 式が必要な位置に他のトークン | 式を追加 |
| errGenerated | 一般エラー | 予期しないトークン | 構文を確認 |
| warnInconsistentSpacing | 警告 | 演算子の前後のスペースが不整合 | スペースを統一 |

### リトライ仕様

パーサーはリトライを行わない。エラー発生時は可能な限り回復して解析を継続する（エラーリカバリー）。

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

該当なし

## パフォーマンス要件

- 再帰下降パーサーによる線形時間解析
- 演算子優先順位解析（Pratt parser）による効率的な式解析
- インデント先読みによるブロック構造の効率的処理

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

- 深い入れ子構造に対するスタックオーバーフロー対策（Nimのスタック制限）
- 悪意のある入力に対する安全な処理

## 備考

- パーサーは文法ファイル（doc/grammar.txt）を自動生成する
- `#|`で始まるコメントが文法定義として抽出される
- nimpretty用の拡張（Emitter連携）
- nimsuggest用の拡張（位置追跡）
- customast定義により代替AST実装が可能

---

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

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

### 推奨読解順序

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

まず、パーサーとASTのデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | parser.nim | `compiler/parser.nim` | Parser構造体（68-84行目）でパーサーの状態管理を理解 |
| 1-2 | ast.nim | `compiler/ast.nim` | PNode、TNodeKindの定義を理解 |

**読解のコツ**:
- `Parser`構造体は`currInd`（現在のインデント）、`lex`（レキサー）、`tok`（現在のトークン）を保持
- `inPragma`フィールドでプラグマ内の解析を追跡
- `when defined(nimpretty)`と`when defined(nimsuggest)`で条件付き機能がある

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | parser.nim | `compiler/parser.nim` | openParser（149-164行目）でパーサーの初期化を理解 |
| 2-2 | parser.nim | `compiler/parser.nim` | getTok（133-147行目）でトークン取得を理解 |
| 2-3 | parser.nim | `compiler/parser.nim` | closeParser（166-168行目）で後処理を理解 |

**主要処理フロー**:
1. **153行目**: `reset(p.tok)`でトークンを初期化
2. **154行目**: `openLexer`でレキサーをオープン
3. **157行目**: `getTok(p)`で最初のトークンを取得
4. **158行目**: `p.firstTok = true`で初期状態フラグ設定

#### Step 3: 式解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | parser.nim | `compiler/parser.nim` | parseExpr（1317-1347行目）で式解析のエントリを理解 |
| 3-2 | parser.nim | `compiler/parser.nim` | simpleExpr/simpleExprAux（970-988行目）で演算子式を理解 |
| 3-3 | parser.nim | `compiler/parser.nim` | parseOperators（945-968行目）で演算子優先順位解析を理解 |
| 3-4 | parser.nim | `compiler/parser.nim` | primary（1353-1407行目）で一次式を理解 |

**主要処理フロー**:
- **1325-1346行目**: トークン種別に応じてblock/if/for/when/case/try/simpleExprに分岐
- **970-972行目**: `simpleExprAux`で`primary`を呼び出し、`parseOperators`で二項演算子を処理
- **949-967行目**: 演算子優先順位に基づくwhile ループで式を構築

#### Step 4: 一次式と識別子・リテラル解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | parser.nim | `compiler/parser.nim` | identOrLiteral（731-847行目）で識別子・リテラル解析を理解 |
| 4-2 | parser.nim | `compiler/parser.nim` | primarySuffix（883-943行目）で後置演算を理解 |

**主要処理フロー**:
- **744-847行目**: トークン種別でシンボル、各種リテラル、括弧構造に分岐
- **894-943行目**: ドット、括弧、インデックスなどの後置演算を処理

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | lexer.nim | `compiler/lexer.nim` | getPrecedence（970-1010行目）で優先順位計算を理解 |
| 5-2 | parser.nim | `compiler/parser.nim` | isRightAssociative（299-302行目）で結合性を理解 |

**主要処理フロー**:
- **953行目**: `opPrec >= limit`の間、演算子をパース
- **955行目**: 左結合なら`leftAssoc = 1`、右結合なら`leftAssoc = 0`
- **962行目**: `simpleExprAux(p, opPrec + leftAssoc, modeB)`で右辺を再帰解析

#### Step 6: 文の解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | parser.nim | `compiler/parser.nim` | parseStmt、complexOrSimpleStmt（後半部分）を理解 |
| 6-2 | parser.nim | `compiler/parser.nim` | parseFor（1286-1308行目）でfor文を理解 |

**主要処理フロー**:
- 各制御構造（if/when/case/for/while/try等）に対応する解析関数
- `colcom`でコロン後のコメントを処理
- インデントベースのブロック構造

#### Step 7: 型解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 7-1 | parser.nim | `compiler/parser.nim` | parseTypeDesc（1422-1458行目）で型記述解析を理解 |
| 7-2 | parser.nim | `compiler/parser.nim` | parseTuple（1089-1132行目）でタプル型解析を理解 |
| 7-3 | parser.nim | `compiler/parser.nim` | parseParamList（1134-1184行目）でパラメータリスト解析を理解 |

**主要処理フロー**:
- **1432-1456行目**: tuple/proc/iterator/enum/object/var/ref/ptr/distinctに分岐
- **1094-1131行目**: `tuple[...]`または`tuple`+インデントブロック形式をサポート

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

```
openParser
    └─ openLexer (lexer.nim)
    └─ getTok
           └─ rawGetTok (lexer.nim)

parseTopLevelStmt / parseAll
    │
    ├─ complexOrSimpleStmt
    │      ├─ parseIf / parseWhen / parseCase / parseFor / parseWhile
    │      ├─ parseProc / parseFunc / parseIterator
    │      ├─ parseType
    │      ├─ parseVar / parseLet / parseConst
    │      └─ simpleStmt
    │             └─ parseExprStmt
    │                    └─ simpleExpr
    │
    └─ simpleExpr
           ├─ simpleExprAux
           │      ├─ primary
           │      │      ├─ identOrLiteral
           │      │      │      ├─ newIdentNodeP
           │      │      │      ├─ newIntNodeP / newFloatNodeP / newStrNodeP
           │      │      │      ├─ parsePar
           │      │      │      └─ setOrTableConstr
           │      │      │
           │      │      └─ primarySuffix
           │      │             ├─ namedParams (関数呼び出し)
           │      │             ├─ dotExpr (ドット演算)
           │      │             └─ commandExpr (コマンド構文)
           │      │
           │      └─ parseOperators
           │             └─ simpleExprAux (再帰)
           │
           └─ parsePragma (プラグマ式)

closeParser
    └─ closeLexer (lexer.nim)
```

### データフロー図

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

トークン列 ────────────────────▶ parseExpr ──────────────────────▶ 式ノード (nkInfix等)
(Token)                          (式解析)
       │
       ▼
simpleExpr ───────────────────▶ primary ─────────────────────────▶ 一次式ノード
                                (一次式解析)
       │
       ▼
識別子/リテラル ──────────────▶ identOrLiteral ──────────────────▶ リーフノード
                                (リテラル解析)
       │
       ▼
後置演算 ─────────────────────▶ primarySuffix ───────────────────▶ 呼び出し/インデックス
                                (後置解析)
       │
       ▼
演算子 ───────────────────────▶ parseOperators ──────────────────▶ 二項演算ノード
                                (演算子解析)
       │
       ▼
AST (PNode) ──────────────────▶ sem.nim ─────────────────────────▶ 型付きAST
                                (セマンティック解析)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| parser.nim | `compiler/parser.nim` | ソース | パーサー本体（構文解析） |
| lexer.nim | `compiler/lexer.nim` | ソース | レキサー（トークン供給） |
| ast.nim | `compiler/ast.nim` | ソース | ASTノード定義 |
| idents.nim | `compiler/idents.nim` | ソース | 識別子キャッシュ |
| msgs.nim | `compiler/msgs.nim` | ソース | メッセージ出力 |
| lineinfos.nim | `compiler/lineinfos.nim` | ソース | 行情報 |
| layouter.nim | `compiler/layouter.nim` | ソース | nimpretty用レイアウタ |
| grammar.txt | `doc/grammar.txt` | 文法 | Nim文法定義（自動生成） |
