Re:VIEWの内部アーキテクチャを、現在の直接Builder呼び出し方式から、共通のAST(抽象構文木)を経由する方式に段階的に変更する計画です。
Re:VIEW文書 → Compiler → Builder(各フォーマット) → 出力
Re:VIEW文書 → Compiler → AST → ASTRenderer → Builder(各フォーマット) → 出力
lib/review/ast/
ディレクトリを作成- 基底ノードクラス
Node
を定義- 共通属性(位置情報、子ノード管理等)
- Visitor パターン対応
- 主要要素のノードクラスを作成:
HeadlineNode
- 見出し(レベル、ラベル、キャプション)ParagraphNode
- 段落(テキスト内容)ListNode
- リスト(順序付き/なし、ネスト対応)TableNode
- 表(ヘッダー、行、列)ImageNode
- 画像(ID、キャプション、メトリック)CodeBlockNode
- コードブロック(言語、行番号等)InlineNode
- インライン要素(タイプ、引数)
- 既存の直接Builder呼び出しを維持(後方互換性)
- 新しい
ast_mode
フラグで動作を切り替えfalse
(デフォルト):既存の動作true
:AST生成モード
- AST生成時は中間表現を構築、通常時は既存の動作を継続
- ASTのJSON シリアライゼーション
- 各ノードクラスに
to_json
メソッドを実装 - ノードタイプ、属性、子ノードの情報を含める
- 位置情報(ファイル名、行番号)も保持
- 各ノードクラスに
- JSONBuilderクラスの作成
- AST → JSON変換専用のBuilderクラス
review-compile --target=json
でJSON出力を可能に
- デバッグ・解析支援
- JSON形式での構文木可視化
- 外部ツールでの解析が容易に
- CI/CDでの構造検証に活用可能
現在の状況: 基本的なASTRendererは実装済み。ハイブリッドモードの段階的移行を実装する。
ASTRenderer
クラス実装済み ✅- ASTを受け取り、既存のBuilderメソッドを呼び出す ✅
- Visitor パターンでノードタイプごとに処理 ✅
- 既存のBuilderクラスとの完全互換性を保持 ✅
目標: 特定の要素のみAST経由で処理し、段階的に移行範囲を拡大
-
タスク1: ASTCompilerでのハイブリッドモード改良 ✅
ast_elements
配列による要素指定機能の詳細設計・実装 ✅- 要素タイプ(symbol)による細かい制御機能 ✅
- デバッグ用ログ機能(どの要素がAST経由か表示) ✅
-
タスク2: 段階的移行制御システム ✅
- 設定ファイルでの移行要素指定機能 ✅
- 環境変数での移行段階制御 ✅
- パフォーマンス測定用フラグ ✅
- パフォーマンストラッキングロジックの専用クラス化 ✅
各段階で以下を実行:
- 該当要素のAST処理有効化
- 既存テストスイート実行(回帰テスト)
- 新規テストケース追加(AST経由の動作確認)
- パフォーマンス測定・比較
- 次段階への判定
移行順序:
-
Stage 1: 見出し(
headline
) ✅ 完了ast_elements: [:headline]
での部分AST化 ✅- tagged section(column等)との互換性確認 ✅
-
Stage 2: 段落(
paragraph
) ✅ 完了- インライン要素との連携確認 ✅
- テキスト処理の互換性確認 ✅
-
Stage 3: リスト(
ulist
,olist
,dlist
) ✅ 完了- 基本的なリスト処理確認 ✅
- リスト間の切り替え処理確認 ✅
- ネストしたリストの処理(一部改善余地あり)
-
Stage 4: 表(
table
) ✅ 完了- ヘッダー分離処理の確認 ✅
- TableNodeクラスの実装 ✅
- 基本的な表レイアウトの互換性確認 ✅
-
Stage 5: 画像(
image
,indepimage
,numberlessimage
) ✅ 完了- 各種画像タイプの完全対応 ✅
- メトリック情報の正確な受け渡し確認 ✅
- AST経由での画像処理の完全実装 ✅
-
Stage 6: コードブロック(
list
,emlist
,cmd
,source
等) ✅ 完了- 行番号付き/なしの両対応確認 ✅
- 言語指定の正確な受け渡し確認 ✅
- listnum, emlistnum対応 ✅
-
Stage 7: インライン要素(
@<b>
,@<code>
等) ✅ 完了- 既存のparagraph/list AST処理経由で自動的に対応 ✅
- 複雑なネストしたインライン要素処理 ✅
- 特殊なインライン要素(ruby, href等)処理 ✅
-
タスク3: 全要素統合テスト ✅
- 複雑な文書での全要素AST処理確認 ✅
- AST list tests 全てpass ✅
- 各Stage の回帰テスト実行 ✅
-
タスク4: パフォーマンス最適化 ✅
- AST生成の安定性確認 ✅
- JSONBuilder参照エラー修正 ✅
- リスト処理構造の改善 ✅
- 継続タスク: 各段階での検証
- 既存のテストスイートを各段階で実行
- AST出力のデバッグ機能追加(JSON diff等)
- パフォーマンス測定の自動化
- 全要素がAST経由での処理に対応
- 既存の全テストがpassすること
- パフォーマンス劣化が許容範囲内(±10%以内)
- 各Builderでの出力結果が従来と同一であること
- すべての構文要素をAST経由で処理
- レガシーな直接呼び出しコードの無効化
- 既存のテストが全て通ることを確認
- ASTノード生成の最適化
- メモリ使用量の最適化
- パフォーマンス測定と改善
- 公開APIの確定
- ドキュメント整備
- 互換性ガイドの作成
- ASTの直接操作API
- ノードの追加・削除・変更
- 構造の検証
- プリプロセッサ・ポストプロセッサ
- AST変換フィルター
- カスタム処理の挿入点
- AST可視化ツール
- 構文解析デバッガー
- パフォーマンス分析ツール
- プラグインシステム(AST変換ベース)
- 静的解析機能
- 文書構造の検証・リファクタリング
module ReVIEW
module AST
class Node
attr_accessor :location, :parent, :children
def initialize(location = nil)
@location = location
@children = []
@parent = nil
end
def accept(visitor)
visitor.visit(self)
end
# JSON出力用
def to_h
{
type: self.class.name.split('::').last,
location: location_to_h,
children: children.map(&:to_h)
}
end
def to_json(*args)
to_h.to_json(*args)
end
private
def location_to_h
return nil unless location
{
filename: location.filename,
lineno: location.lineno
}
end
end
class DocumentNode < Node
attr_accessor :title, :chapters
def to_h
super.merge(
title: title,
chapters: chapters&.map(&:to_h)
)
end
end
class HeadlineNode < Node
attr_accessor :level, :label, :caption
def to_h
super.merge(
level: level,
label: label,
caption: caption
)
end
end
class ParagraphNode < Node
attr_accessor :content
def to_h
super.merge(
content: content
)
end
end
class ListNode < Node
attr_accessor :list_type, :items
def to_h
super.merge(
list_type: list_type, # :ul, :ol, :dl
items: items&.map(&:to_h)
)
end
end
class TableNode < Node
attr_accessor :id, :caption, :headers, :rows
def to_h
super.merge(
id: id,
caption: caption,
headers: headers,
rows: rows
)
end
end
class ImageNode < Node
attr_accessor :id, :caption, :metric
def to_h
super.merge(
id: id,
caption: caption,
metric: metric
)
end
end
class CodeBlockNode < Node
attr_accessor :lang, :id, :caption, :lines, :line_numbers
def to_h
super.merge(
lang: lang,
id: id,
caption: caption,
lines: lines,
line_numbers: line_numbers
)
end
end
class InlineNode < Node
attr_accessor :inline_type, :args
def to_h
super.merge(
inline_type: inline_type,
args: args
)
end
end
end
end
module ReVIEW
class JSONBuilder < Builder
def initialize
super
@ast_nodes = []
end
def bind(compiler, chapter, location)
super
@document_node = AST::DocumentNode.new(location)
@current_node = @document_node
end
def result
@document_node.to_json
end
def headline(level, label, caption)
node = AST::HeadlineNode.new(@location)
node.level = level
node.label = label
node.caption = caption
add_node(node)
end
def paragraph(lines)
node = AST::ParagraphNode.new(@location)
node.content = lines.join("\n")
add_node(node)
end
# その他のメソッドも同様に実装...
private
def add_node(node)
@current_node.children << node
node.parent = @current_node
end
end
end
class Compiler
def initialize(builder, ast_mode: false)
@builder = builder
@ast_mode = ast_mode
@ast_root = nil if @ast_mode
end
def compile(chap)
if @ast_mode
@ast_root = build_ast(chap)
renderer = ASTRenderer.new(@builder)
renderer.render(@ast_root)
else
# 既存の処理
do_compile
end
@builder.result
end
end
- API互換性:既存のBuilderクラスのAPIは変更しない
- 動作互換性:出力結果は既存と同一であることを保証
- 設定互換性:既存の設定ファイルはそのまま使用可能
- プラグイン互換性:既存のプラグインは動作を継続
- 既存テストの継続実行:全フェーズで既存テストが通ることを確認
- AST特有のテスト追加:ノード生成、変換の正確性をテスト
- パフォーマンステスト:処理速度、メモリ使用量の回帰テスト
- 統合テスト:実際の書籍プロジェクトでの動作確認
- フェーズ1:2-3週間(基盤実装 + JSON出力機能) ✅ 完了
- フェーズ2:4-6週間(段階的移行)
- フェーズ3:2-3週間(全面移行・最適化)
- フェーズ4:継続的開発(新機能追加)
- Week 1: ASTノードクラス設計・実装 ✅
- Week 2: Compiler のAST生成機能追加 ✅
- Week 3: JSON出力機能(JSONBuilder)実装・テスト ✅
- Day 1-2: タスク1 - ASTCompilerのハイブリッドモード改良
ast_elements
配列による要素指定機能の詳細設計- デバッグ用ログ機能の実装
- 要素タイプによる細かい制御の実装
- Day 3-5: タスク2 - 段階的移行制御システム
- 設定ファイル対応の実装
- 環境変数による制御の実装
- パフォーマンス測定基盤の整備
- Week 2: ✅ 完了
- Stage 1: 見出し(headline)のAST化 ✅
- Stage 2: 段落(paragraph)のAST化 ✅
- 各段階での回帰テスト実行 ✅
- Week 3: ✅ 完了
- Stage 3: リスト(ulist, olist, dlist)のAST化 ✅
- インライン要素との連携テスト ✅
- パフォーマンス測定・比較 ✅
- Week 4: ✅ 完了
- Stage 4: 表(table)のAST化 ✅
- Stage 5: 画像(image)のAST化 ✅
- 複雑な要素での互換性確認 ✅
- Week 5: 🔄 進行中
- Stage 6: コードブロック(list, emlist, cmd, source等)のAST化 🔄
- Stage 7: インライン要素のAST化
- 統合テストの実行
- Day 1-3: 全要素統合テスト
- samples/配下での全面テスト
- 各Builder(HTML, LaTeX, EPUB等)での互換性確認
- Day 4-5: パフォーマンス最適化
- ボトルネック特定・改善
- メモリ使用量最適化
- 最終的な回帰テスト実行
-
ハイブリッドモード基盤 ✅
ASTConfig
による段階的移行制御システム- YAML設定ファイルでの
ast.stage
指定 - 環境変数(
REVIEW_AST_MODE
等)での制御 - デバッグログ機能(
REVIEW_DEBUG_AST=true
) - パフォーマンス測定機能(
ASTPerformanceTracker
)
-
Stage 1-7 完全実装 ✅
- Stage 1: headline要素 ✅
- Stage 2: paragraph要素 ✅
- Stage 3: ulist, olist, dlist要素 ✅
- Stage 4: table要素 ✅
- Stage 5: image, indepimage, numberlessimage要素 ✅
- Stage 6: list, emlist, cmd, source, listnum, emlistnum要素 ✅
- Stage 7: 全インライン要素(既存AST経由で自動対応) ✅
-
AST Node クラス ✅
HeadlineNode
,ParagraphNode
,ListNode
,ListItemNode
TableNode
,ImageNode
,CodeBlockNode
InlineNode
,TextNode
,EmbedNode
- すべてキーワード引数ベースで統一
-
支援機能 ✅
CompilerAdapter
による review-compile の AST 処理抽出SnapshotLocation
による固定行番号管理- JSONBuilder でのキャプション配列対応
- 包括的なテストケースとフィクスチャ
全7段階のAST移行が完了しました!
- Stage 1-7: 全て実装完了 ✅
- ハイブリッドモード: 完全動作 ✅
- テストスイート: 全てpass ✅
- パフォーマンス: 安定動作確認 ✅
- Stage 4: emtable, imgtable の AST対応(中優先度)
- Stage 3: ネストしたリストの設計改善(中優先度)
- 定義リスト: 空
<dt>
タグの微調整(低優先度) - 全般: パフォーマンス最適化の継続
AST機能の詳細な使用方法については、ast-usage.md をご参照ください。
# config.yml
ast:
stage: 3 # 推奨開始設定(headline + paragraph + lists)
debug: true
# コマンドライン実行
review-compile --yaml=config.yml --target=html chapter.re
stage: 1-7
: 段階的AST移行(1=最小、7=完全)mode: auto|traditional|hybrid
: 動作モードdebug: true
: デバッグログ有効化performance: true
: パフォーマンス測定有効化
- 保守性向上:構文解析と出力生成の分離
- 拡張性向上:AST操作による柔軟な変換
- デバッグ支援:中間表現の可視化
- 新機能開発:静的解析、最適化等の新機能が容易に
- テスタビリティ:各段階での単体テストが可能
- JSON出力による外部連携:
- 構文解析結果の外部ツールでの活用
- CI/CDパイプラインでの文書構造検証
- エディタープラグインでのリアルタイム解析支援
- 文書メトリクス収集・分析
# ハイブリッドモードの改良から開始
# 現在のast_elementsの動作確認
bundle exec rake test
bundle exec bin/review-compile --target=html samples/sample-book/src/ch01.re
# Stage 1: headline のみAST化のテスト例
# Compilerに ast_elements: [:headline] を指定
# 出力結果が従来と同一であることを確認
- 機能検証: 出力結果が従来と同一
- パフォーマンス検証: 処理時間の測定
- メモリ検証: メモリ使用量の測定
- 互換性検証: 各Builderでの動作確認
- 従来モードでの動作確認
- 差分の詳細分析(JSON出力での比較)
- 必要に応じてAST構造の修正
- テストケースの追加・修正
- 全要素のAST化完了: 7つのStageすべてでAST経由処理が可能
- 回帰テストpass: 既存の全テストケースが成功
- 出力同一性: 各Builderで従来と同じ出力結果
- パフォーマンス基準: 処理時間の劣化が10%以内
- メモリ基準: メモリ使用量の増加が20%以内
- 該当要素のAST処理実装完了
- 単体テスト追加・pass
- 回帰テストpass
- パフォーマンス測定完了
- 次Stageへの移行可否判定
フェーズ3への移行は以下の条件をすべて満たした場合:
- フェーズ2の全タスク完了
- 安定性確認期間(1週間)での問題なし
- パフォーマンス・品質基準達成
- チームでの移行可否判定会議での承認
- パフォーマンス:中間表現生成のオーバーヘッド
- メモリ使用量:ASTノードによる使用量増加
- 複雑性:アーキテクチャの複雑化
- 移行期間:段階的移行中の保守コスト
- テスト負荷:各段階での包括的テストの実行コスト