Share
Embed
先読みと後読みの可能な、O(N)の正規表現エンジンの実装
https://cybozu.connpass.com/event/53121/ での発表資料です。
TSUYUSATO Kitsune
March 30, 2017
Transcript
23 slides
-
先読みと後読みの可能な、 O(N)の正規表現エンジンの実装 @ m a k e _ n o
w _ j u s t @ M a k e N o w J u s t -
流れ 1. やりたいこと 2. どうやって? i. 先読み・ 後読みを予め処理する方法 ii. Boolean
Finite Automata(BFA) を使う方法 3. 現在までの進捗 4. 今後の展開 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 2 -
やりたいこと 「 正規表現の先読み・ 後読み」 A ・ B ・ C を含む文字列にマッチする正規表現は、
. * ( A . * B . * C | A . * C . * B | B . * A . * C | B . * C . * A | C . * A . * B | C . * B . * A ) . * のように書ける。(53 文字) 同じものを先読みを使って書くと、 ( ? = . * A ) ( ? = . * B ) ( ? = . * C ) . * のようになる。(23 文字) 複雑なものをより短かく書くことができる。 表現力が高い。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 6 -
どうやって? 正規表現で表現できるパター ンと決定性有限オー トマトン(DFA) で 受理できる文字列は等しい。 決定性有限オー トマトンは文字列の長さNに比例する時間で 受理するかどうかを判定できる。 →
正規表現から決定性有限オー トマトンに変換できればよい。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 8 -
どうやって? 正規表現から非決定性有限オー トマトン(NFA) に変換する方法は よく知られている。 Thompsonn 構成 Glushkov 構成 …
しかし、 これらは正規表現の先読み・ 後読みを考慮しない。 ※ 非決定性有限オー トマトンから決定性有限オー トマトンへはRabin‑Scott の Powerset 構成が利用できる。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 9 -
どうやって そこで、 先読み・ 後読みを含む正規表現を処理できる方法を 2 種類考えた。 1. 先読み・ 後読みを予め処理する方法 2.
Boolean Finite Automata(BFA) を使う方法 これらを説明する。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 10 -
先読み・ 後読みを予め処理する方法 具体例を挙げて説明します。 このような正規表現: ( ? = . * f
o o ) . * ( ? < = b a r . * ) に対して、 このような文字列: o o f o o a a b a r o o のマッチングを行ってみます。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 11 -
先読み・ 後読みを予め処理する方法 先読み・ 後読みを取り出す。 ( ? = . * f
o o ) . * ( ? < = b a r . * ) → 1 . * 2 1: ( ? = . * f o o ) 2: ( ? < = b a r . * ) 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 12 -
先読み・ 後読みを予め処理する方法 先読み・ 後読みの正規表現を入力文字列の各位置からマッチングし、 その結果を記録する。 1: ( ? = .
* f o o ) 2: ( ? < = b a r . * ) また、1 文字目より前の先読み、 最後の文字より後ろの後読みに 対応するため、 入力文字の前後に ^ と $ を追加する。 ^ o o f o o a a b a r o o $ 1 1 1 1 . . . . . . . . . . . . . . . . . . . . 2 2 2 2 ※ この処理は先読み・ 後読みがいくつあっても入力文字列の長さに 対して線形時間で行える。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 13 -
先読み・ 後読みを予め処理する方法 ^ o o f o o a a
b a r o o $ 1 1 1 1 . . . . . . . . . . . . . . . . . . . . 2 2 2 2 文字とその位置でマッチした先読み・ 後読みの組を列にする。 ( ' ^ ' , { 1 } ) , ( ' o ' , { 1 } ) , ( ' o ' , { 1 } ) , ( ' f ' , { 1 } ) , ( ' o ' , { } ) , … … 中略… … , ( ' a ' , { } ) , ( ' r ' , { 2 } ) , ( ' o ' , { 2 } ) , ( ' o ' , { 2 } ) , ( ' $ ' , { 2 } ) これを入力列として受理・ 非受理の判定のできる 決定性有限オー トマトンを 1 . * 2 から作る。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 14 -
先読み・ 後読みを予め処理する方法 2 段階に分けて行う。 1. まず非決定性有限オー トマトンに変換して(Thompson 構成)、 2. それを決定性有限オー
トマトンに変換する(Powerset 構成)。 Powerset 構成の際に少し工夫して、 1 や 2 を一文字も消費しない 特殊な文字として扱う。 そしてε 閉包に 1 や 2 も含めるようにし、 文字と組にして 遷移の条件とする。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 15 -
先読み・ 後読みを予め処理する方法 こうして出来たDFA は、 次のようなものになる。 s1 s2 (・, {1}) s3
(・, {1, 2}) (・, {}), (・, {1}) (・, {2}), (・, {1, 2}) (・, {}), (・, {1}) (・, {2}), (・, {1, 2}) 初期状態は s 1 、 終了状態は s 3 。 ・ は任意の一文字( ^ と $ も含む) を意味する。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 16 -
先読み・ 後読みを予め処理する方法( 問題点) これでO(N)で先読み・ 後読みを含む正規表現のマッチングができる。 ( 全体としてO(N)の処理しか含まないので) しかし、 いくつか問題点が存在する。 1.
先読み・ 後読みがネストすることができない。 2. O(N)とはいえ3 回もDFA によるマッチングをすることになる。 というわけで、 もう一つの方法を考えている。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 17 -
Boolean Finite Automata(BFA) を使う方法 Boolean Finite Automata(BFA) もしくは、 Alternating Finite
Automata(AFA) といわれるものがある。 これは有限オー トマトンを、 単一の状態の代わりに 論理式か論理値で状態を持つように拡張したもので、 有限オー トマトンの否定、 交差(intersection) を単純に表現できる。 オー トマトンの交差によって、 先読み・ 後読みを 簡潔に表現できることが期待できる。 しかも決定性有限オー トマトンに変換できる。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 18 -
Boolean Finite Automata(BFA) を使う方法( 問題点) バリエー ションがある。 状態を論理式で持つか、 論理値で持つか 文字列を先頭から読み込んでいくか、
末尾から読み込んでいくか 2×2 で4 通り。 このどれを選んでも、 先読みか後読みのどちらかしか 簡単に表現できない。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 19 -
Boolean Finite Automata(BFA) を使う方法( 問題点) 論理値 論理式 先頭から 後読み 先読み
末尾から 先読み 後読み 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 20 -
Boolean Finite Automata(BFA) を使う方法( 問題点) 先頭から、 論理値と論理式を同時に更新していって最後にそれを 適用するようにすれば先読みと後読みを同時に同じ枠組みで 処理できるかもしれない。 →
しかし、 その場合どうやって決定性有限オー トマトンに変換すれば 良いか( 現状) 分からない。 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 21 -
現在までの進捗 2017 年の1 月に開始。 「 先読み・ 後読みを予め処理する方法」 については実装して、 線形時間で処理できることなどを確認した。 「Boolean
Finite Automata(BFA) を使う方法」 については現在、 実装・ 考察を重ねている。 https://github.com/MakeNowJust/re‑research https://github.com/MakeNowJust/bfa 先読みと後読みの可能な、O(N) の正規表現エンジンの実装 22