Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
PEGの回文っぽいExpression
@chiguri
このスライドはなんのため?
 一時期(ごくごく一部で)話題になったPEG
(Parsing Expression Grammar)による回文っ
ぽいものがどういう言語を受理するか、を考える
ための資料
 PEGの動きを理解するのに使えるかも...
背景
 aとbからなる回文をCFG(BNF)で書くと以下の
ようになる。
 S ::= “a” S “a” | “b” S “b” | “”
 偶数長の回文だけだが、簡単に拡張できるので無視
 PEGのParsing Expressio...
このPEは受理しない回文がある
 この式は、“aa”、“abba”、“abbbaabbba”を受理
する。
 それぞれ“a”、“ab”、“abbba”を折り返した回文。
 しかし、“abbaabba”を受理しない。
 これは“abba”...
注意
 私はPackrat Parsing(PEGを有用に、有名にした
構文解析手法)を知らない。
 メモ化や遅延評価を使うことで入力長のオーダーで構
文解析できる手法である、くらいまで
 したがって、これ以降Packrat Parsin...
Recursive Descent Parsing
 元々のPEGの特徴付けに用いられていたもの。
 解釈方法が若干特殊なため、CFGの考え方を引き
ずるとこんがらがるが、動きはシンプル。
 大きく違う点は、|ではなく/を使う部分、特にこ...
表現のしかた
 以降では、与えられた文字列を
「読んだが規則が成功するか決まっていない部分」
「読んだ結果規則が成功した部分」
「まだ読んでいない部分」
の三つに分ける。
 それぞれ赤、青、黒で表す。
必ずこの順序で現れるが、可視性のため矢...
回文っぽいものを例に
 S ::= “a” S “a” / “b” S “b” / “”
 対象は”abba”、全体はS !.とする(S以外は何も含
まない)
“abba”
一文字目
 S ::= “a” S “a” / “b” S “b” / “”
 まずaを読み、Sの最初の規則を試す。
 “a”にマッチするのでS “a”がスタックに積まれ、次へ。
“abba”
二文字目
 S ::= “a” S “a” / “b” S “b” / “”
 次の文字bを読み、Sの最初の規則を試す。
 “a”にマッチしないので失敗する
“abba”
二文字目
 S ::= “a” S “a” / “b” S “b” / “”
 次の規則を試す。
 “b”にマッチするのでS “b”がスタックに積まれ、次へ。
“abba”
三文字目
 S ::= “a” S “a” / “b” S “b” / “”
 次の文字bを読み、Sの最初の規則を試す。
 失敗する。
“abba”
三文字目
 S ::= “a” S “a” / “b” S “b” / “”
 次の規則を試す。
 S “b”がスタックに積まれ、次へ。
“abba”
四文字目
 S ::= “a” S “a” / “b” S “b” / “”
 次の文字aを読み、Sの最初の規則を試す。
 S “a”がスタックに積まれ、次へ。
“abba”
終端
 S ::= “a” S “a” / “b” S “b” / “”
 次の文字はないが、Sの最初の規則を試す。
 aがないので失敗。
“abba”
終端
 S ::= “a” S “a” / “b” S “b” / “”
 次の規則を試す。
 bがないので失敗。
“abba”
終端
 S ::= “a” S “a” / “b” S “b” / “”
 次の規則を試す。
 何も読まないので成功。
“abba”
スタックを一つ戻す
 S ::= “a” S “a” / “b” S “b” / “”
 スタックを戻して、成功していた規則を続ける。
 Sの次にaがないので失敗。状態を規則を試す前に戻す。
“abba”
失敗から次の試行へ
 S ::= “a” S “a” / “b” S “b” / “”
 成功していた規則をやめて次の規則へ移る。
 次はbではないので失敗。
“abba”
最後の規則へ
 S ::= “a” S “a” / “b” S “b” / “”
 次の規則へ移る。
 何も読まなくて良いので成功。
“abba”
スタックを一つ戻す
 S ::= “a” S “a” / “b” S “b” / “”
 スタックを戻して、成功していた規則を続ける。
 Sの次にbがないので失敗。状態を規則を試す前に戻す。
“abba”
失敗から次の試行へ
 S ::= “a” S “a” / “b” S “b” / “”
 成功していた規則をやめて次の規則へ移る。
 何も読まなくて良いので成功。
“abba”
スタックを一つ戻す
 S ::= “a” S “a” / “b” S “b” / “”
 スタックを戻して、成功していた規則を続ける。
 次がbなので成功。規則全体が完成。bbは読み終え。
“abba”
スタックを一つ戻す
 S ::= “a” S “a” / “b” S “b” / “”
 スタックを戻して、成功していた規則を続ける。
 次がaなので成功。規則全体が完成。
“abba”
終了
 S ::= “a” S “a” / “b” S “b” / “”
 スタックが空なので、解析全体が成功。
“abba”
成功時→失敗時
 成功する場合の挙動はCFGとほぼ同じだが、失敗
時の巻き戻し方が少し違う。
 規則が失敗した場合、青になった部分(一度決定した
部分)について他の規則を試さずに赤の部分ごと戻す。
失敗する例
 S ::= “a” S “a” / “b” S “b” / “”
 対象は”aaaa”、全体はS !.とする
 以下、二つ目の規則は絶対に失敗するので無視する。
“aaaa”
一文字目
 S ::= “a” S “a” / “b” S “b” / “”
 まずaを読み、Sの最初の規則を試す。
 “a”にマッチするのでS “a”がスタックに積まれ、次へ。
“aaaa”
二文字目
 S ::= “a” S “a” / “b” S “b” / “”
 aを読み、Sの最初の規則を試す。
 “a”にマッチするのでS “a”がスタックに積まれ、次へ。
“aaaa”
三文字目
 S ::= “a” S “a” / “b” S “b” / “”
 aを読み、Sの最初の規則を試す。
 “a”にマッチするのでS “a”がスタックに積まれ、次へ。
“aaaa”
四文字目
 S ::= “a” S “a” / “b” S “b” / “”
 aを読み、Sの最初の規則を試す。
 “a”にマッチするのでS “a”がスタックに積まれ、次へ。
“aaaa”
終端
 S ::= “a” S “a” / “b” S “b” / “”
 文字がないので、最後の規則のみマッチする。
“aaaa”
スタックを一つ戻す
 S ::= “a” S “a” / “b” S “b” / “”
 スタックを戻して、成功していた規則を続ける。
 Sの次にaがないので失敗。状態を規則を試す前に戻す。
“aaaa”
失敗から次の試行へ
 S ::= “a” S “a” / “b” S “b” / “”
 成功していた規則をやめて次の規則へ移る。
 何も読まなくて良いので成功。
“aaaa”
スタックを一つ戻す
 S ::= “a” S “a” / “b” S “b” / “”
 スタックを戻して、成功していた規則を続ける。
 次がaなので成功。規則全体が完成、読み終えへ。
“aaaa”
スタックを一つ戻す
 S ::= “a” S “a” / “b” S “b” / “”
 スタックを戻して、成功していた規則を続ける。
 次がないので失敗。この規則を試す前の状態へ戻す。
 二文字目を読む前
“aaaa”
失敗から次の試行へ
 S ::= “a” S “a” / “b” S “b” / “”
 成功していた規則をやめて次の規則へ移る。
 何も読まなくて良いので成功。
“aaaa”
スタックを一つ戻す
 S ::= “a” S “a” / “b” S “b” / “”
 スタックを戻して、成功していた規則を続ける。
 次がaなので成功。規則全体が完成、読み終えへ。
“aaaa”
S全体の終了、失敗
 S ::= “a” S “a” / “b” S “b” / “”
 全体を読み終えたが、末尾に文字があるので失敗。
 これはマッチしない。
“aaaa”
本来成功するには
 S ::= “a” S “a” / “b” S “b” / “”
 以下の状態で、最後の規則を試す必要がある。
 「折り返し地点まで繰り返し規則で読むこと」
“aaaa”
失敗例では
 S ::= “a” S “a” / “b” S “b” / “”
 折り返し地点を飛ばした状態へ巻き戻される。
 「折り返し地点にはもう到達できない」
“aaaa” “aaaa”
 「成功した部分が他の規則を使えた場合に」
「他の規則を試行しないため」真ん中を折り返し
とみなす規則が適用されなかった。
 “abbaabba”の場合も、後ろの”abba”が成功して
しまうせいで全体がうまくいかなくなる。
 下の赤部分...
 部分的に回文があると、そこにマッチして折り返
し地点ごと規則が巻き戻される場合がある。これ
が原因で失敗している。
 PEGで
S ::= “a” S “a” / “”
が2^n-2の長さしか読めないのも失敗の巻き戻しが
まとめて行われる...
結局元のPEは何を受理するか
 「後ろから順に、言語に含まれる文字列を見つけ
ては排除して、その中に折り返し地点が含まれた
ら拒否されるがそれ以外の回文は受理する」とい
うよく分からない言語。
 面倒な例を挙げれば“aabbaabbaa”は...
おまけ:HOPEG
 kmizuさんが考えている、パラメータ付きの非終
端記号(rule constructor)を導入したPEG
 REP(s) ::= s REP(s) / “” のような式が書ける。
 REP(“a”)で“a”*のよ...
HOPEGのパラメータ
 パラメータには任意のParsing Expressionを渡し
て良いので、こんなものも書ける。
 S(r) ::= ... S(“a” r) ...
 再帰呼び出しの度にrの先頭で”a”のチェックが増える。
...
HOPEGによる回文
 HOPEGで回文を受理する式は以下のように書ける。
 PAL(s) ::= “a” PAL(“a” s) / “b” PAL(“b” s) / r
 PEGで失敗していたのと違い、「最初に全てのrで
成功した一番後...
Upcoming SlideShare
Loading in …5
×

PEGの回文っぽいExpression

PEGで書いた、傍目には回文のように見える式が、なぜ回文を受理しないのかの説明。PEGの入門に・・・どうでしょうかね?

  • Be the first to comment

  • Be the first to like this

PEGの回文っぽいExpression

  1. 1. PEGの回文っぽいExpression @chiguri
  2. 2. このスライドはなんのため?  一時期(ごくごく一部で)話題になったPEG (Parsing Expression Grammar)による回文っ ぽいものがどういう言語を受理するか、を考える ための資料  PEGの動きを理解するのに使えるかもしれない。 使えないかもしれない。  http://togetter.com/li/899899 で私とkmizuさ んがいろいろ考えているやつ
  3. 3. 背景  aとbからなる回文をCFG(BNF)で書くと以下の ようになる。  S ::= “a” S “a” | “b” S “b” | “”  偶数長の回文だけだが、簡単に拡張できるので無視  PEGのParsing Expressionで似た式を書くと以下 のようになる。  S ::= “a” S “a” / “b” S “b” / “”  |が/になっている。
  4. 4. このPEは受理しない回文がある  この式は、“aa”、“abba”、“abbbaabbba”を受理 する。  それぞれ“a”、“ab”、“abbba”を折り返した回文。  しかし、“abbaabba”を受理しない。  これは“abba”を折り返した回文。  なぜ?
  5. 5. 注意  私はPackrat Parsing(PEGを有用に、有名にした 構文解析手法)を知らない。  メモ化や遅延評価を使うことで入力長のオーダーで構 文解析できる手法である、くらいまで  したがって、これ以降Packrat Parsingの話はしな いし、できない。  個人的な感想だが、多くの場合、高速化手法は人間の 解釈に向かない。
  6. 6. Recursive Descent Parsing  元々のPEGの特徴付けに用いられていたもの。  解釈方法が若干特殊なため、CFGの考え方を引き ずるとこんがらがるが、動きはシンプル。  大きく違う点は、|ではなく/を使う部分、特にこ れが絡んだ再帰的な場合の動き。  他にも先読みなどがあるのだが、割と直感的なのでこ こでは無視することにする。
  7. 7. 表現のしかた  以降では、与えられた文字列を 「読んだが規則が成功するか決まっていない部分」 「読んだ結果規則が成功した部分」 「まだ読んでいない部分」 の三つに分ける。  それぞれ赤、青、黒で表す。 必ずこの順序で現れるが、可視性のため矢印でも 区切り箇所を表す。  下からの矢印が最初の、上からの矢印が次の区切り。 “aaaaaaaaaaaaaaaaaaaaa”
  8. 8. 回文っぽいものを例に  S ::= “a” S “a” / “b” S “b” / “”  対象は”abba”、全体はS !.とする(S以外は何も含 まない) “abba”
  9. 9. 一文字目  S ::= “a” S “a” / “b” S “b” / “”  まずaを読み、Sの最初の規則を試す。  “a”にマッチするのでS “a”がスタックに積まれ、次へ。 “abba”
  10. 10. 二文字目  S ::= “a” S “a” / “b” S “b” / “”  次の文字bを読み、Sの最初の規則を試す。  “a”にマッチしないので失敗する “abba”
  11. 11. 二文字目  S ::= “a” S “a” / “b” S “b” / “”  次の規則を試す。  “b”にマッチするのでS “b”がスタックに積まれ、次へ。 “abba”
  12. 12. 三文字目  S ::= “a” S “a” / “b” S “b” / “”  次の文字bを読み、Sの最初の規則を試す。  失敗する。 “abba”
  13. 13. 三文字目  S ::= “a” S “a” / “b” S “b” / “”  次の規則を試す。  S “b”がスタックに積まれ、次へ。 “abba”
  14. 14. 四文字目  S ::= “a” S “a” / “b” S “b” / “”  次の文字aを読み、Sの最初の規則を試す。  S “a”がスタックに積まれ、次へ。 “abba”
  15. 15. 終端  S ::= “a” S “a” / “b” S “b” / “”  次の文字はないが、Sの最初の規則を試す。  aがないので失敗。 “abba”
  16. 16. 終端  S ::= “a” S “a” / “b” S “b” / “”  次の規則を試す。  bがないので失敗。 “abba”
  17. 17. 終端  S ::= “a” S “a” / “b” S “b” / “”  次の規則を試す。  何も読まないので成功。 “abba”
  18. 18. スタックを一つ戻す  S ::= “a” S “a” / “b” S “b” / “”  スタックを戻して、成功していた規則を続ける。  Sの次にaがないので失敗。状態を規則を試す前に戻す。 “abba”
  19. 19. 失敗から次の試行へ  S ::= “a” S “a” / “b” S “b” / “”  成功していた規則をやめて次の規則へ移る。  次はbではないので失敗。 “abba”
  20. 20. 最後の規則へ  S ::= “a” S “a” / “b” S “b” / “”  次の規則へ移る。  何も読まなくて良いので成功。 “abba”
  21. 21. スタックを一つ戻す  S ::= “a” S “a” / “b” S “b” / “”  スタックを戻して、成功していた規則を続ける。  Sの次にbがないので失敗。状態を規則を試す前に戻す。 “abba”
  22. 22. 失敗から次の試行へ  S ::= “a” S “a” / “b” S “b” / “”  成功していた規則をやめて次の規則へ移る。  何も読まなくて良いので成功。 “abba”
  23. 23. スタックを一つ戻す  S ::= “a” S “a” / “b” S “b” / “”  スタックを戻して、成功していた規則を続ける。  次がbなので成功。規則全体が完成。bbは読み終え。 “abba”
  24. 24. スタックを一つ戻す  S ::= “a” S “a” / “b” S “b” / “”  スタックを戻して、成功していた規則を続ける。  次がaなので成功。規則全体が完成。 “abba”
  25. 25. 終了  S ::= “a” S “a” / “b” S “b” / “”  スタックが空なので、解析全体が成功。 “abba”
  26. 26. 成功時→失敗時  成功する場合の挙動はCFGとほぼ同じだが、失敗 時の巻き戻し方が少し違う。  規則が失敗した場合、青になった部分(一度決定した 部分)について他の規則を試さずに赤の部分ごと戻す。
  27. 27. 失敗する例  S ::= “a” S “a” / “b” S “b” / “”  対象は”aaaa”、全体はS !.とする  以下、二つ目の規則は絶対に失敗するので無視する。 “aaaa”
  28. 28. 一文字目  S ::= “a” S “a” / “b” S “b” / “”  まずaを読み、Sの最初の規則を試す。  “a”にマッチするのでS “a”がスタックに積まれ、次へ。 “aaaa”
  29. 29. 二文字目  S ::= “a” S “a” / “b” S “b” / “”  aを読み、Sの最初の規則を試す。  “a”にマッチするのでS “a”がスタックに積まれ、次へ。 “aaaa”
  30. 30. 三文字目  S ::= “a” S “a” / “b” S “b” / “”  aを読み、Sの最初の規則を試す。  “a”にマッチするのでS “a”がスタックに積まれ、次へ。 “aaaa”
  31. 31. 四文字目  S ::= “a” S “a” / “b” S “b” / “”  aを読み、Sの最初の規則を試す。  “a”にマッチするのでS “a”がスタックに積まれ、次へ。 “aaaa”
  32. 32. 終端  S ::= “a” S “a” / “b” S “b” / “”  文字がないので、最後の規則のみマッチする。 “aaaa”
  33. 33. スタックを一つ戻す  S ::= “a” S “a” / “b” S “b” / “”  スタックを戻して、成功していた規則を続ける。  Sの次にaがないので失敗。状態を規則を試す前に戻す。 “aaaa”
  34. 34. 失敗から次の試行へ  S ::= “a” S “a” / “b” S “b” / “”  成功していた規則をやめて次の規則へ移る。  何も読まなくて良いので成功。 “aaaa”
  35. 35. スタックを一つ戻す  S ::= “a” S “a” / “b” S “b” / “”  スタックを戻して、成功していた規則を続ける。  次がaなので成功。規則全体が完成、読み終えへ。 “aaaa”
  36. 36. スタックを一つ戻す  S ::= “a” S “a” / “b” S “b” / “”  スタックを戻して、成功していた規則を続ける。  次がないので失敗。この規則を試す前の状態へ戻す。  二文字目を読む前 “aaaa”
  37. 37. 失敗から次の試行へ  S ::= “a” S “a” / “b” S “b” / “”  成功していた規則をやめて次の規則へ移る。  何も読まなくて良いので成功。 “aaaa”
  38. 38. スタックを一つ戻す  S ::= “a” S “a” / “b” S “b” / “”  スタックを戻して、成功していた規則を続ける。  次がaなので成功。規則全体が完成、読み終えへ。 “aaaa”
  39. 39. S全体の終了、失敗  S ::= “a” S “a” / “b” S “b” / “”  全体を読み終えたが、末尾に文字があるので失敗。  これはマッチしない。 “aaaa”
  40. 40. 本来成功するには  S ::= “a” S “a” / “b” S “b” / “”  以下の状態で、最後の規則を試す必要がある。  「折り返し地点まで繰り返し規則で読むこと」 “aaaa”
  41. 41. 失敗例では  S ::= “a” S “a” / “b” S “b” / “”  折り返し地点を飛ばした状態へ巻き戻される。  「折り返し地点にはもう到達できない」 “aaaa” “aaaa”
  42. 42.  「成功した部分が他の規則を使えた場合に」 「他の規則を試行しないため」真ん中を折り返し とみなす規則が適用されなかった。  “abbaabba”の場合も、後ろの”abba”が成功して しまうせいで全体がうまくいかなくなる。  下の赤部分の最後、aが読まれた規則に失敗して戻る。 “abbaabba”
  43. 43.  部分的に回文があると、そこにマッチして折り返 し地点ごと規則が巻き戻される場合がある。これ が原因で失敗している。  PEGで S ::= “a” S “a” / “” が2^n-2の長さしか読めないのも失敗の巻き戻しが まとめて行われるため。
  44. 44. 結局元のPEは何を受理するか  「後ろから順に、言語に含まれる文字列を見つけ ては排除して、その中に折り返し地点が含まれた ら拒否されるがそれ以外の回文は受理する」とい うよく分からない言語。  面倒な例を挙げれば“aabbaabbaa”は受理されないが、 “aabbaaaaaabbaa”は受理される。  下線部は回文でしかも折り返し地点を含むが、青い部分がよ り後ろにあり優先されるためその部分の回文は受理されない。  青の失敗時に折り返し地点の直後まで戻される。  嗚呼面倒臭・・・だれか定式化してください。
  45. 45. おまけ:HOPEG  kmizuさんが考えている、パラメータ付きの非終 端記号(rule constructor)を導入したPEG  REP(s) ::= s REP(s) / “” のような式が書ける。  REP(“a”)で“a”*のような動きをする。  処理系はここに https://github.com/kmizu/hopeg  HO(Higher Order)といっているがパラメータ はParsing expressionのみ想定。  kmizuさんは元々Parametricと言っていたが、私が横 から「HOっぽい」と言ったためこの名前に。
  46. 46. HOPEGのパラメータ  パラメータには任意のParsing Expressionを渡し て良いので、こんなものも書ける。  S(r) ::= ... S(“a” r) ...  再帰呼び出しの度にrの先頭で”a”のチェックが増える。  ある種の「残りをスタックに積む」ようなことが可能に。
  47. 47. HOPEGによる回文  HOPEGで回文を受理する式は以下のように書ける。  PAL(s) ::= “a” PAL(“a” s) / “b” PAL(“b” s) / r  PEGで失敗していたのと違い、「最初に全てのrで 成功した一番後ろ」が取られる。  折り返し地点より後ろでは(文字数が足りないため) 必ず失敗する。  中央で必ず成功する。  「折り返し全体が成功するまで部分的な成功がない」 ことでPEGで起こった問題を回避している。

×