Skip to content

raiga0310/LR_parser

Repository files navigation

LR(0) Parser GUI — Rust implementation

LR(0) 構文解析器と AST ベースの Rust コードジェネレーターを備えた GUI アプリケーション。

概要

このプロジェクトは デュアルクレート構成 を採用しています。

クレート 名前 役割
ライブラリ lr0_parser_rs 純粋な構文解析ロジック(GUI・I/O なし)
バイナリ lr0-parser-gui egui GUI(ライブラリのラッパー)

機能

  • LR(0) 構文解析: 文法規則に基づくパース処理、Shift/Reduce および Reduce/Reduce コンフリクトをハードエラーとして検出
  • ステップアニメーション: パース過程をステップごとに再生・早送り可能
  • パーステーブル表示: Action/Goto テーブルを 2D グリッドで表示
  • AST 生成: 抽象構文木の自動生成・ツリー描画
  • コードジェネレーター: AST から実行可能な Rust コードを生成・実行
  • 終端記号ロール設定: 各終端記号に演算子・数値などのロールを割り当て

使い方

ビルド・実行

# ビルド
cargo build

# GUI アプリケーションを起動
cargo run

# テストをすべて実行
cargo test

# 特定のテストを実行
cargo test <test_name>

# モジュール単位でテストを実行
cargo test grammar::tests
cargo test runtime::tests

GUI の使い方

Parser ページ

  1. Production フィールドに文法規則を入力(デフォルト: 算術文法)
  2. Target String にパース対象の文字列を入力
  3. Parse ボタンを押してパース実行
  4. ステップアニメーションで Parse Trace を確認、パーステーブルと AST を参照

Generator ページ

  1. Parser ページで文法と入力文字列を設定した後、Generator タブに切り替える
  2. Terminal Symbols セクションで各終端記号にロールを割り当てる
  3. Generate Code ボタンで AST → Rust コードを生成
  4. Run ボタンで生成コードを rustc でコンパイル・実行

文法記述フォーマット

LHS -> RHS
  • LHS: 大文字 ASCII 1 文字(非終端記号)
  • RHS: 大文字(非終端記号)と他の文字(終端記号)の列、空白は自動除去
  • $ は EOF 終端記号として予約済み(入力末尾に自動付加)
  • LR コンフリクトが発生した場合はコンパイルエラーとなる

デフォルト文法

E -> E*B
E -> E+B
E -> B
B -> 0
B -> 1

コンフリクト検証用サンプル

リポジトリルートにサンプルファイルを同梱:

ファイル 内容
reducer 算術文法(LR(0) 適合、テストで使用)
paren_reducer 非 LR(0) 文法(EE->E による S/R コンフリクトを意図的に含む)

終端記号ロール一覧

Generator ページで各終端記号に設定可能なロール:

ロール 対象文字(デフォルト)
Add +
Sub -
Mul *
Div /
Mod %
LParen ( < [ {
RParen ) > ] }
Num 09
Token その他

アーキテクチャ

ライブラリパイプライン

grammar::parse_grammar_text(text)  →  Grammar
lr::compile(&grammar)              →  CompiledParser
runtime::run(&machine, &symbols)   →  ParserResult { ast: AstNode }
runtime::build_trace(...)          →  Vec<ParseStep>   (アニメーション用ステップ列)

モジュール構成

src/
├── lib.rs                 # ライブラリルート(pub re-export)
├── grammar.rs             # テキスト → Grammar(生成規則・終端/非終端記号)
├── lr.rs                  # Grammar → CompiledParser(LR(0) 項集合・Action/Goto テーブル)
├── runtime.rs             # CompiledParser + 入力 → ParserResult、build_trace
├── ast.rs                 # AstNode: Terminal(char) | NonTerminal(char, Vec<AstNode>)
├── validation.rs          # 入力バリデーション
├── main.rs                # ウィンドウセットアップ(初期サイズ 1200×800、最小 800×600)
├── app.rs                 # ParserApp 状態構造体 + eframe App 実装
│                          #   Page enum (Parser | Generator)
│                          #   ParseArtifacts, TraceCursorView, SmHighlightView
│                          #   build_parse_table(), build_animation_trace()
├── generator_engine.rs    # GeneratorEngine: AST → Rust ソース生成
│                          #   run_generated_code(): temp ファイルに書き出して rustc 実行
└── pages/
    ├── mod.rs             # ページモジュール宣言
    ├── parser.rs          # Parser タブ UI(入力パネル・アニメーション・AST・パーステーブル)
    ├── generator.rs       # Generator タブ UI(ロールセレクター・コードプレビューカード)
    └── tree.rs            # 共有ツリーレンダラー(LayoutNode, layout_ast, draw_tree)
                           #   pub(super): pages モジュール内のみ参照可能

設計方針

  • LR コンフリクトはエラー: lr::compile はコンフリクト発生時に Err(ParserError::ConflictReducer) を返す。UI では UiError::Compile として表示。
  • Functional core / imperative shell: ライブラリモジュール(grammar, lr, runtime)は純粋関数。副作用(ファイル I/O・プロセス起動)は generator_engine::run_generated_code に限定。
  • アルゴリズムスタブ: ParserKind::Slr / Lalr / Lr1 は拡張ポイントとして存在。選択すると "not yet implemented" を表示。
  • 共有ツリーレンダラー: pages/tree.rsparser.rsgenerator.rs の両方から利用。

依存関係

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
eframe = "0.32.3"
egui  = "0.32.3"
  • Rust edition 2024
  • rustc が PATH に存在する場合、Generator の Run 機能が利用可能

インストールと実行

# リポジトリをクローン
git clone https://github.com/raiga0310/LR_parser.git
cd LR_parser

# ビルド
cargo build

# GUI を起動
cargo run

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages