# 機能設計書 36-strscans

## 概要

本ドキュメントは、Nimプログラミング言語のscanf風文字列スキャンモジュールである`strscans`モジュールの機能設計を記載する。strscansモジュールはC言語のscanfに似た構文で文字列からデータを抽出するマクロを提供する。

### 本機能の処理概要

strscansモジュールは`scanf`マクロと`scanp`マクロを提供し、パターンマッチングによる文字列からのデータ抽出を可能にする。正規表現よりもシンプルで、より読みやすいコードでテキスト解析ができる。

**業務上の目的・背景**：テキストデータからの情報抽出は多くのアプリケーションで必要とされる。正規表現は強力だが複雑になりがち。strscansモジュールはC言語プログラマに馴染みのあるscanf風の構文で、型安全なデータ抽出を実現する。コンパイル時にパターンが解析されるため、実行時エラーを防げる。

**機能の利用シーン**：
- ログファイルの解析
- 設定ファイルの読み込み
- データファイルのパース
- 日付・時刻文字列の解析
- ネットワークプロトコルのパース

**主要な処理内容**：
1. scanfマクロ（パターンマッチングと値の抽出）
2. scanpマクロ（EBNF/PEG風の文法でのパース）
3. 組み込みパターン（$i, $f, $w, $s, $c, $b, $o, $h等）
4. ユーザー定義マッチャー（${foo}）
5. オプショナルスキッパー（$[foo]）
6. 終端マッチング（$.）
7. ワイルドカード（$*, $+）

**関連システム・外部連携**：parseutilsモジュールを内部で使用。macrosモジュールでマクロを実装。

**権限による制御**：権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面には関連しない（ライブラリモジュール） |

## 機能種別

テキスト解析 / パターンマッチング / データ抽出 / マクロ処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | string | Yes | 解析対象の文字列 | なし |
| pattern | static[string] | Yes | パターン文字列 | コンパイル時解析 |
| results | varargs[typed] | No | 抽出結果を格納する変数 | 型マッチング |

### 入力データソース

プログラム内の文字列データ。パターン文字列はコンパイル時定数。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| マッチ結果 | bool | パターンマッチの成功/失敗 |
| 抽出値 | 各変数の型 | パターンから抽出された値 |

### 出力先

戻り値としてboolを返す。抽出値は参照パラメータに格納。

## 処理フロー

### 処理シーケンス

```
1. パターン解析（コンパイル時）
   └─ $記法を解析してコードを生成
2. マッチング実行（実行時）
   └─ 入力文字列をパターンに従って走査
3. 値の抽出
   └─ マッチした部分を変数に格納
4. 結果の返却
   └─ マッチ成功/失敗をboolで返す
```

### フローチャート

```mermaid
flowchart TD
    A[scanf呼び出し] --> B[パターン解析]
    B --> C{$で始まる?}
    C -->|Yes| D[特殊パターン処理]
    C -->|No| E[リテラルマッチ]
    D --> F{パターン種別}
    F -->|$i| G[parseInt呼び出し]
    F -->|$f| H[parseFloat呼び出し]
    F -->|$w| I[parseIdent呼び出し]
    F -->|$s| J[skipWhitespace呼び出し]
    G --> K{マッチ成功?}
    H --> K
    I --> K
    J --> K
    E --> K
    K -->|Yes| L[次のパターンへ]
    K -->|No| M[false返却]
    L --> N{パターン終了?}
    N -->|Yes| O[true返却]
    N -->|No| C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 先頭マッチ | scanfは入力の先頭からマッチ | scanf |
| BR-02 | 非貪欲マッチ | $*と$+は非貪欲（最短マッチ） | ワイルドカード |
| BR-03 | バックトラックなし | マッチ失敗時にバックトラックしない | scanf/scanp |
| BR-04 | 型安全 | パターンと変数の型が一致する必要あり | コンパイル時 |

### 計算ロジック

組み込みパターンと対応するparseutils関数:
- `$b` → parseBin
- `$o` → parseOct
- `$i` → parseInt
- `$h` → parseHex
- `$f` → parseFloat
- `$w` → parseIdent
- `$c` → parseChar
- `$s` → skipWhitespace

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

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

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

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

データベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| false（戻り値） | マッチ失敗 | パターンが一致しない | 戻り値のチェック |
| コンパイルエラー | 型不一致 | パターンと変数の型が不一致 | 型の修正 |

### リトライ仕様

リトライは不要。戻り値でマッチ成功・失敗を判定。

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

トランザクション管理は不要。

## パフォーマンス要件

- コンパイル時にパターンを解析するため実行時オーバーヘッドが小さい
- 正規表現エンジンを使用しないため軽量
- バックトラックなしで線形時間

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

- パターンはコンパイル時定数のため、インジェクション攻撃は不可能
- 信頼できない入力の解析に適している

## 備考

scanfは入力文字列の先頭からマッチを試みる。完全一致を確認したい場合は`$.`を末尾に追加すること。

---

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

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

### 推奨読解順序

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

モジュールには特別なデータ構造はない。パターン文字列の構文を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | strscans.nim | `lib/pure/strscans.nim` | パターン構文一覧（34-53行目） |

**読解のコツ**: $記法の各パターンがparseutilsのどの関数にマッピングされるかを理解する。

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

モジュール冒頭のドキュメントを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | strscans.nim | `lib/pure/strscans.nim` | モジュールドキュメント（10-283行目） |
| 2-2 | strscans.nim | `lib/pure/strscans.nim` | インポート文（286-290行目） |

**主要処理フロー**:
1. **10-29行目**: scanfマクロの基本的な使用例
2. **31-53行目**: 組み込みパターンの一覧
3. **66-72行目**: $.による完全マッチ
4. **74-118行目**: ユーザー定義マッチャー

#### Step 3: scanfマクロの実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | strscans.nim | `lib/pure/strscans.nim` | scanfマクロ定義（316行目以降） |

**主要処理フロー**:
- **316行目**: scanfマクロの定義開始
- **329-337行目**: 初期化（idx, res変数の生成）
- **338-399行目**: パターン解析ループ
- **341行目**: $で始まるパターンの分岐
- **348-353行目**: $w（識別子）の処理
- **372-377行目**: $i（整数）の処理

#### Step 4: scanpマクロを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | strscans.nim | `lib/pure/strscans.nim` | scanpマクロの説明（121-193行目） |

**主要処理フロー**:
- **121-142行目**: scanp構文の説明（EBNF/PEG風）
- **147-168行目**: scanpの使用例
- **170-193行目**: カスタムatomとnxtテンプレート

#### Step 5: ユーザー定義マッチャーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | strscans.nim | `lib/pure/strscans.nim` | ユーザー定義マッチャー（74-118行目） |

**主要処理フロー**:
- **77-81行目**: ${foo}と$[foo]の違い
- **84-95行目**: someSepヘルパーの例
- **97-118行目**: ndigitsヘルパーの例（引数付き）

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

```
strscans.nim (メインモジュール)
    │
    ├─ scanf マクロ
    │      │
    │      ├─ $i → parseutils.parseInt
    │      ├─ $f → parseutils.parseFloat
    │      ├─ $w → parseutils.parseIdent
    │      ├─ $c → parseutils.parseChar
    │      ├─ $s → parseutils.skipWhitespace
    │      ├─ $b → parseutils.parseBin
    │      ├─ $o → parseutils.parseOct
    │      ├─ $h → parseutils.parseHex
    │      ├─ $* → parseutils.parseUntil
    │      └─ ${foo} → ユーザー定義関数
    │
    └─ scanp マクロ
           │
           ├─ atom テンプレート (文字/文字集合のマッチ)
           ├─ nxt テンプレート (位置の進行)
           └─ -> (アクション束縛)
```

### データフロー図

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

"(1,2,4)"              ───▶  scanf("($i,$i,$i)", x, y, z)  ───▶  true
パターン: "($i,$i,$i)"        (パターン解析 + parseInt)            x=1, y=2, z=4

"2023-01-15"           ───▶  scanf("$i-$i-$i", y, m, d)    ───▶  true
パターン: "$i-$i-$i"          (日付フォーマット解析)               y=2023, m=1, d=15

"abc123"               ───▶  scanf("$w$i", s, n)           ───▶  true
パターン: "$w$i"              (識別子 + 整数)                      s="abc", n=123
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| strscans.nim | `lib/pure/strscans.nim` | ソース | メインモジュール、scanf/scanpマクロ |
| parseutils.nim | `lib/pure/parseutils.nim` | ソース | 解析プリミティブ（parseBin, parseInt等） |
| macros.nim | `lib/core/macros.nim` | ソース | マクロ処理基盤 |
