新・ReVIEWパーサについて

Post on 02-Nov-2014

10 views 3 download

Tags:

description

ReVIEW開発者カンファレンスで使用した発表資料です。

Transcript of 新・ReVIEWパーサについて

新・ReVIEWパーサについて

  ReVIEW開発者カンファレンス 2014/03/08株式会社達人出版会

高橋征義

自己紹介•高橋征義 (@takahashim), ReVIEWコミッタ

•古参Rubyist (1997年くらいから)

•~2010年 Web制作会社のプログラマ

•@kdmsnrの同僚

• 2010年~ 電子書籍の制作と販売

(今日はこの話じゃなくて、実装の話)

本日のあらすじ•パーサを書き換え中

•いろいろスッキリした(はず)

•わりと動いている(はず)

•そもそもの仕様を決めないとダメ

•すごく内部実装の技術的な話ですみません…

本発表の話題

•パーサ (Parser)

パーサとは•構文解析をするひと

•どこがブロックで、どこがインラインで…というのを解析する

• ReVIEWではReVIEW::Compiler

• lib/review/compiler.rb

• …だけではなく、実はBuilderの中でも構文解析しているのが問題だったり

== fooXXXYYYZZZ//list[foo1][foo2]{AAA@<b>{BBB}CCCDDD@<raw>{EEE{FFF\}GGG}IIIJJJ//}@<ruby>{KKK,LLL}MMMNNN

== fooXXXYYYZZZ//list[foo1][foo2]{AAA@<b>{BBB}CCCDDD@<raw>{EEE{FFF\}GGG}IIIJJJ//}@<ruby>{KKK,LLL}LLLMMM

Headline

Paragraph

BlockElement

Paragraph

== fooXXXYYYZZZ//list[foo1][foo2]{AAA@<b>{BBB}CCCDDD@<raw>{EEE{FFF\}GGG}IIIJJJ//}@<ruby>{KKK,LLL}LLLMMM

== fooXXXYYYZZZ//list[foo1][foo2]{AAA@<b>{BBB}CCCDDD@<raw>{EEE{FFF\}GGG}IIIJJJ//}@<ruby>{KKK,LLL}LLLMMM

※細かい要素に分割するだけ→各要素をどう扱うかは パーサではなくBuilderが 担当する

なぜ新パーサなのか•現状のパーサがいろいろつらい•拡張しづらい•「ブロックのネストをさせたい」etc•修正しづらい• Builder/インラインごとにエンバグetc•パーサから仕様がリバースできない•(他に仕様があればいいんですが…)

• ReVIEW.jsみたいなのを作るにもつらそうな予感

つらい点

//emlist{def foo(a) if a>1 bar(a) endend//}

R::Compiler+

R::Builder<div class="emlist-code"><pre class="emlist">def foo(a) if a&gt;1 bar(a) endend</pre></div>

☆escape

つらい点

//emlist{def foo(a) if @<b>{a>1} bar(a) endend//}

<div class="emlist-code"><pre class="emlist">def foo(a) if <b>a&gt;1</b> bar(a) endend</pre></div>

☆インラインを入れたい→escapeした文字列の連結

つらい点

//emlist{def foo(a) if a>1 bar(a) endend//}

<div class="emlist-code"><pre class="emlist">def foo(a) if a&gt;1 bar(a) endend</pre></div>

☆ソースハイライトもしたい→unescape??

???

現パーサの問題点•正規表現で頑張っている

•パーサがReVIEW::CompilerとReVIEW::BuilderとReVIEW::*Builderに分割されている

•各Builderでの解析方法が統一されていない(ような気がする)

新パーサの方針•基本的には書き直し

• ad hocな書き方をせず、ちゃんとパーサを実装する(既存パーサライブラリor自作パーサ)

•ネストは実現できるようにしたい

• APIはあまり非互換にしない(変えすぎるといろいろつらい)

• ReVIEW文法の再定義(明確化)も狙いたい

新パーサの現状• kpegブランチで開発中(Github Issues #235)

• それなりに動くが、完璧ではない

新パーサの特徴•パーサジェネレータ(PEG)を使って書き直し

•実装としてはkpegを採用

• Ruby 1.8~2.1まで対応(してるといいな…)

•外部gemへの依存なしで動く

•現状はUTF-8のみだが、それ以外の文字コードにも対応可能かも

•現状のAPIに合わせている(kpegとしては不自然かもしれないが、互換性は高いはず)

新パーサの実装• lib/review/review.kpegで定義

•生成されたパーサはlib/review/compiler.rbになる(現状と同名のファイル)

•いったんAST(抽象構文木)を作成したあと、それを元に各nodeに対する処理を呼び出す

•処理内容は現状同様*Builderに書かれている

• *BuilderのAPIは一部非互換(inline_*)

== fooXXXYYYZZZ//list[foo1][foo2]{AAA@<b>{BBB}CCCDDD@<raw>{EEE{FFF\}GGG}IIIJJJ//}@<ruby>{KKK,LLL}LLLMMM

ParagraphHeadline Paragraph

BlockElement

root

Text Text Textfoo XXXYYY ZZZ

InlineElementlevel2

name args contentslist

InlineElement

Text

KKK

LLLMMMnameruby

Text TextLLL

SinglelineContent SinglelineContent SinglelineContent

Text Text

AAA BBB CCC

RawText

DDD EEE{FFF}GGG

Text

IIIJJJ

contents

foo1 foo2☆escapeはツリーを作った後で行える

新パーサの課題•パーサより文法が決まっていないのが課題

•複雑なケースに対する処理がこれで正しいのかどうかよく分からない

• //list[t1][@<b>{\\\\}] 

• highlightingとかの制御方法・具体的なルール

•インライン+ハイライトは死ぬ

• ReVIEWドキュメントの互換性は完璧ではない(むしろ非互換にしたい)

• ReVIEW.jsとのマージ

リリーススケジュール•未定

•今日の流れ次第で

• 2.0で?

• 1.xにはしない方が良さそう(互換性の問題もあるし)

まとめ•パーサを書き換え中

•いろいろスッキリした(はず)

•わりと動いている(はず)

•そもそもの仕様を決めないとダメ

•良い機会なので整理したい