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

## 概要

本ドキュメントは、Nushellのパーサー機能について定義する。パーサーはユーザーが入力したNushellスクリプトを構文解析し、抽象構文木（AST）と型情報を生成する。字句解析（Lexer）から構文解析、型チェックまでを一貫して処理する。

### 本機能の処理概要

**業務上の目的・背景**：Nushellは静的型付けに近い型推論システムを持ち、コマンドのシグネチャに基づいて引数の型チェックを行う。これによりランタイムエラーを事前に検出し、より信頼性の高いスクリプト実行を実現する。パーサーはこの型システムの中核を担う。

**機能の利用シーン**：ユーザーがコマンドを入力するたびにパーサーが呼び出される。REPLでの対話的入力、スクリプトファイルの読み込み、補完候補の生成、シンタックスハイライトなど、あらゆる入力処理の起点となる。

**主要な処理内容**：
1. 字句解析（Lexing） - 入力テキストをトークン列に分解
2. 軽量パース（Lite Parsing） - トークン列をパイプラインとコマンドの構造に変換
3. 構文解析（Parsing） - コマンドシグネチャに基づいた引数解析とAST生成
4. 型チェック（Type Checking） - 引数と戻り値の型整合性検証
5. キーワード解析 - def, let, if 等のパーサーキーワードの特殊処理
6. エラー報告 - パースエラーの収集と報告

**関連システム・外部連携**：nu-engine（評価実行）、nu-cli（REPL・補完）、nu-lsp（言語サーバー）と連携する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインREPL | 主画面 | 入力されたコマンドの構文解析・型チェックをリアルタイムで実行 |
| 2 | 補完メニュー | 補助画面 | 補完対象の構文解析とコンテキスト判定 |
| 7 | Tryビュー | 参照画面 | 入力コマンドの構文解析 |
| 10 | LSP言語サーバ | 参照画面 | ドキュメント変更時の構文解析・セマンティック解析 |

## 機能種別

構文解析 / 型チェック / AST生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source | &[u8] | Yes | パース対象のソースコード（バイト列） | UTF-8エンコード |
| working_set | StateWorkingSet | Yes | 作業用の状態セット | 有効な状態オブジェクト |
| span_offset | usize | No | スパンのオフセット（デフォルト0） | 非負整数 |

### 入力データソース

- ユーザーからのコマンドライン入力
- スクリプトファイル（.nuファイル）
- モジュールファイル（use/module時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Block | Block | パース結果の抽象構文木 |
| Pipeline | Pipeline | パイプライン構造 |
| Expression | Expression | 式の表現（型情報付き） |
| ParseError | Vec<ParseError> | パースエラーのリスト |

### 出力先

- EngineState（宣言、ブロック、モジュールの登録）
- nu-engine（評価用AST）
- エラー表示（パースエラー）

## 処理フロー

### 処理シーケンス

```
1. 字句解析 (lex)
   └─ 入力バイト列をトークン列に分解
2. 軽量パース (lite_parse)
   └─ トークン列をLitePipeline/LiteCommandに構造化
3. 構文解析 (parse_block, parse_pipeline)
   └─ コマンドシグネチャに基づく引数解析
4. キーワード処理 (parse_keywords)
   └─ def, let, if, for 等の特殊構文処理
5. 型チェック (type_check)
   └─ 引数と戻り値の型整合性検証
6. AST生成
   └─ Block, Pipeline, Expression の構築
```

### フローチャート

```mermaid
flowchart TD
    A[ソースコード入力] --> B[lex: 字句解析]
    B --> C[Token列]
    C --> D[lite_parse: 軽量パース]
    D --> E[LitePipeline]
    E --> F{コマンド種別判定}
    F -->|キーワード| G[parse_keywords]
    F -->|通常コマンド| H[parse_internal_call]
    F -->|外部コマンド| I[parse_external_call]
    G --> J[parse_def / parse_let / parse_if etc.]
    H --> K[引数パース]
    I --> L[外部引数パース]
    J --> M[AST生成]
    K --> M
    L --> M
    M --> N{型チェック}
    N -->|エラー| O[ParseError追加]
    N -->|OK| P[Block返却]
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | キーワード優先 | def, let等のキーワードはコマンドより優先して解析 | パイプライン先頭要素 |
| BR-002 | 型推論 | 引数の型はコマンドシグネチャから推論 | すべての関数呼び出し |
| BR-003 | スパン追跡 | すべてのASTノードにソース位置情報を付与 | パース全体 |
| BR-004 | エラー継続 | パースエラー発生時も可能な限り継続 | エラーリカバリ時 |

### 計算ロジック

特になし。

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Expected | 構文エラー | 期待されるトークンがない | 構文を確認 |
| UnexpectedEof | 構文エラー | 入力が途中で終了 | 入力を完成させる |
| UnknownCommand | 解決エラー | コマンドが見つからない | コマンド名を確認 |
| MissingPositional | 引数エラー | 必須引数がない | 引数を追加 |
| TypeMismatch | 型エラー | 引数の型が不一致 | 型を確認 |
| UnknownFlag | フラグエラー | 未定義のフラグ | フラグ名を確認 |

### リトライ仕様

パーサーはリトライを行わない。エラーは収集され一括で報告される。

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

パーサーはStateWorkingSetを通じて変更を管理し、成功時のみEngineStateにマージされる。

## パフォーマンス要件

- インクリメンタルパースによる効率的な再パース
- 補完時の部分パース対応

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

- 入力サイズの制限なし（OSのメモリ制限に依存）
- 悪意のある入力への耐性（パニックしない設計）

## 備考

- StateWorkingSetはEngineStateの差分として機能
- パースエラーはVec<ParseError>として収集

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lex.rs | `crates/nu-parser/src/lex.rs` | Token, TokenContents の定義。字句解析の基本単位 |
| 1-2 | lite_parser.rs | `crates/nu-parser/src/lite_parser.rs` | LitePipeline, LiteCommand の定義。軽量パース結果 |
| 1-3 | ast/ | `crates/nu-protocol/src/ast/` | Expression, Block, Pipeline 等のAST定義 |

**読解のコツ**: TokenContents（Item, Comment, Pipe等）がパイプライン構造の区切りを定義する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | lib.rs | `crates/nu-parser/src/lib.rs` | 公開API。parse, parse_blockの呼び出し関係 |
| 2-2 | parser.rs | `crates/nu-parser/src/parser.rs` | メインパーサーロジック |

**主要処理フロー**:
1. **lex関数**: 入力を Token 列に変換
2. **lite_parse関数**: Token を LitePipeline に構造化
3. **parse_block関数**: LitePipeline を Block（AST）に変換

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | lex.rs | `crates/nu-parser/src/lex.rs` | lex_item関数の処理フロー |

**主要処理フロー**:
- **87-150行目**: `lex_item` - 単一トークンの切り出し。引用符、ブラケットのネスト追跡
- **56-71行目**: `is_item_terminator` - トークン終端の判定（空白、パイプ、セミコロン）
- **75-77行目**: `is_assignment_operator` - 代入演算子の判定

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | parser.rs | `crates/nu-parser/src/parser.rs` | parse_pipeline, parse_call 等のメイン処理 |
| 4-2 | parse_keywords.rs | `crates/nu-parser/src/parse_keywords.rs` | def, let, if 等のキーワード処理 |

**主要処理フロー**:
- **26-28行目**: `garbage` - パースエラー時のプレースホルダー生成
- **52-125行目**: `is_math_expression_like` - 数式的な式かどうかの判定
- **185-200行目**: `check_call` - コールの妥当性チェック

#### Step 5: 型チェックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | type_check.rs | `crates/nu-parser/src/type_check.rs` | 型互換性チェックと型推論 |

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

```
parse (lib.rs)
    │
    ├─ lex (lex.rs)
    │      └─ lex_item (個別トークン)
    │
    ├─ lite_parse (lite_parser.rs)
    │      └─ LitePipeline/LiteCommand 生成
    │
    └─ parse_block (parser.rs)
           │
           ├─ parse_pipeline
           │      │
           │      ├─ parse_builtin_commands (キーワード)
           │      │      ├─ parse_def
           │      │      ├─ parse_let
           │      │      ├─ parse_if
           │      │      └─ ...
           │      │
           │      └─ parse_call (通常コマンド)
           │             ├─ parse_internal_call
           │             └─ parse_external_call
           │
           └─ type_check (type_check.rs)
```

### データフロー図

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

ソースコード ───▶ lex ─────────────────▶ Token列
  (bytes)                                   │
                                            ▼
                 lite_parse ◀───────────────┘
                     │
                     ▼
               LitePipeline
                     │
                     ▼
                parse_block ──────────────▶ Block (AST)
                     │                         │
                     ├─ キーワード処理            │
                     ├─ コマンド解決             │
                     └─ 型チェック              │
                                               ▼
                                    StateWorkingSet
                                    (宣言・ブロック登録)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lib.rs | `crates/nu-parser/src/lib.rs` | ソース | パーサーモジュールの公開API |
| lex.rs | `crates/nu-parser/src/lex.rs` | ソース | 字句解析（トークナイザー） |
| lite_parser.rs | `crates/nu-parser/src/lite_parser.rs` | ソース | 軽量パーサー |
| parser.rs | `crates/nu-parser/src/parser.rs` | ソース | メインパーサーロジック |
| parse_keywords.rs | `crates/nu-parser/src/parse_keywords.rs` | ソース | キーワード構文の処理 |
| type_check.rs | `crates/nu-parser/src/type_check.rs` | ソース | 型チェック処理 |
| parse_patterns.rs | `crates/nu-parser/src/parse_patterns.rs` | ソース | パターンマッチ構文の処理 |
| parse_shape_specs.rs | `crates/nu-parser/src/parse_shape_specs.rs` | ソース | 型シェイプの解析 |
| flatten.rs | `crates/nu-parser/src/flatten.rs` | ソース | ASTのフラット化（補完用） |
| deparse.rs | `crates/nu-parser/src/deparse.rs` | ソース | ASTからソースへの逆変換 |
