|
|
@ -1,6 +1,6 @@ |
|
|
|
# はじめてのPEG |
|
|
|
# PEG記法を学ぼう |
|
|
|
|
|
|
|
|
|
|
|
PEGは言語の文法を定義するための言語で、2004年に[Bryan Ford][Link_Ford]によって発表されました。記法はBNFに似ていますが、言語の構文を定義するだけでなく字句の定義も同一のファイルでに含めることができます。 |
|
|
|
PEGは言語の文法を定義するための言語で、2004年に[Bryan Ford][Link_Ford]によって発表されました。記法はEBNFに似ていますが、言語の構文を定義するだけでなく字句の定義も同一のファイルでに含めることができます。 |
|
|
|
|
|
|
|
|
|
|
|
PEGの文法ファイルは「構文規則名(N) <- 式(e)」で表される複数の構文規則で構成されます。例えば簡単な日付フォーマットはこんな感じで定義できるでしょう。 |
|
|
|
PEGの文法ファイルは「構文規則名(N) <- 式(e)」で表される複数の構文規則で構成されます。例えば簡単な日付フォーマットはこんな感じで定義できるでしょう。 |
|
|
|
|
|
|
|
|
|
|
@ -32,9 +32,25 @@ PEGパーサーは,この文法ファイルの開始規則(DATE)に対し |
|
|
|
* `&e`(肯定先読み) |
|
|
|
* `&e`(肯定先読み) |
|
|
|
* `!e`(否定先読み) |
|
|
|
* `!e`(否定先読み) |
|
|
|
|
|
|
|
|
|
|
|
ではもう少し複雑な例を見てみましょう。 |
|
|
|
幾つか短い例をみてみましょう。 |
|
|
|
|
|
|
|
|
|
|
|
## CSVフォーマットの定義 |
|
|
|
``` |
|
|
|
|
|
|
|
# Ex) 大文字で始まる英単語 |
|
|
|
|
|
|
|
WORD <- [A-Z][A-Za-z-]+ |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
# Ex) 数列 [1,2,3...] |
|
|
|
|
|
|
|
NUMBER_LIST <- '[' (NUMBER (',' NUMBER)*)? ']' |
|
|
|
|
|
|
|
NUMBER <- [0-9]+ |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
正規表現ととても似ていますね。ではもう少し複雑な例として、CSVファイルための文法を定義してみましょう。 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
abc,"def ghi", jkl |
|
|
|
|
|
|
|
... |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
CSVには様々な方言があるので,今回は以下の仕様を満たすものとします。 |
|
|
|
CSVには様々な方言があるので,今回は以下の仕様を満たすものとします。 |
|
|
|
|
|
|
|
|
|
|
@ -100,7 +116,7 @@ NL <- '\r\n' / '\r' / '\n' |
|
|
|
|
|
|
|
|
|
|
|
## 空白の除去 |
|
|
|
## 空白の除去 |
|
|
|
|
|
|
|
|
|
|
|
PEGの問題の中で一番よく知られているのは「空白」扱いです。Yaccなどでは,Lexなど外部の字句解析器がテキストのトークン分割を行う際に不必要な空白を除去してくれます。PEGでは構文解析と字句解析が明確に分離されていないため,空白除去の処理も通常の構文規則を用いて行う必要があります。 |
|
|
|
PEGの問題の中で一番よく知られているのは「空白」の除去です。Yaccなどでは,Lexなど外部の字句解析器がテキストのトークン分割を行う際に不必要な空白を除去してくれます。PEGでは構文解析と字句解析が明確に分離されていないため,空白除去の処理も通常の構文規則を用いて行う必要があります。 |
|
|
|
|
|
|
|
|
|
|
|
`[123,456,789]`のような数字の配列は,次のように定義できます。 |
|
|
|
`[123,456,789]`のような数字の配列は,次のように定義できます。 |
|
|
|
|
|
|
|
|
|
|
@ -127,11 +143,11 @@ PEGの問題の中で一番よく知られているのは「空白」扱いで |
|
|
|
... |
|
|
|
... |
|
|
|
_ <- [ \t\r\n]* # 空白文字が0回以上 |
|
|
|
_ <- [ \t\r\n]* # 空白文字が0回以上 |
|
|
|
|
|
|
|
|
|
|
|
この文法で上の2つの例にマッチさせることができますが,`ifxtheny`にも誤ってマッチしてしまいます。トークン間に必ず空白が必要ということで'_'の規則を次のように変更してみます。 |
|
|
|
すこし複雑になりましたが、この文法で上の2つの例にマッチさせることができます。しかしこの文法には問題があり,`ifxtheny`にも誤ってマッチしてしまいます。トークン間に必ず空白が必要なので'_'の規則を次のように変更してみます。 |
|
|
|
|
|
|
|
|
|
|
|
_ <- [ \t\r\n]+ # 空白文字が1回以上 |
|
|
|
_ <- [ \t\r\n]+ # 空白文字が1回以上 |
|
|
|
|
|
|
|
|
|
|
|
今度は正しく`ifxtheny`がエラーとなります。しかし`if(x)then y`は空白を必要ないにもかかわらず,マッチしなくなってしまいました。こうした時は「否定先読み」を使用して,トークンの切れ目を明確にして解決することができます。 |
|
|
|
今度は正しく`ifxtheny`がエラーとなります。しかし今度は、`if(x)then y`は空白を必要ないにもかかわらず,マッチしなくなってしまいました。こうした時は「否定先読み」を使用して,トークンの切れ目を明確にして解決することができます。 |
|
|
|
|
|
|
|
|
|
|
|
IF <- 'if' __ ('(' _)? IDENT (')' _)? 'then' __ EXPR |
|
|
|
IF <- 'if' __ ('(' _)? IDENT (')' _)? 'then' __ EXPR |
|
|
|
IDENT <- [a-zA-Z][a-zA-Z0-9_-]* __ |
|
|
|
IDENT <- [a-zA-Z][a-zA-Z0-9_-]* __ |
|
|
@ -143,12 +159,12 @@ PEGの問題の中で一番よく知られているのは「空白」扱いで |
|
|
|
|
|
|
|
|
|
|
|
## Unicodeのサポート |
|
|
|
## Unicodeのサポート |
|
|
|
|
|
|
|
|
|
|
|
FordのPEGの論文ではUnicode文字については想定されていません。しかし多言語のテキストを扱うにはUnicodeのサポートが必須です。対応は処理系によってまちまちです。 |
|
|
|
FordのPEGの論文ではUnicodeについての言及はありません。しかし多言語のテキストを扱うにはUnicodeのサポートが必須です。Unicodeへの対応は、PEG処理系によってまちまちです。 |
|
|
|
|
|
|
|
|
|
|
|
この本で使用するPEGライブラリ(cpp-peglib)は正式にはUnicodeに未対応ですが,問題なくUTF8のテキストを扱うことができます。U+0800以上の全ての文字を規則名として使用することができます。 |
|
|
|
この本で使用するPEGライブラリ(cpp-peglib)は正式にはUnicodeに未対応ですが,問題なくUTF8のテキストを扱うことができます。U+0800以上の全ての文字を規則名として使用することができます。 |
|
|
|
|
|
|
|
|
|
|
|
このように幾つかの弱点はあるものの,PEGは十分に実用的な文法定義のための言語です。 |
|
|
|
このように幾つかの弱点はあるものの,PEGは十分に実用的な文法定義のための言語です。 |
|
|
|
|
|
|
|
|
|
|
|
次章では,ついにスクリプト言語の文法デザインに着手しましょう。 |
|
|
|
次章では,いよいよスクリプト言語のデザインに着手しましょう。 |
|
|
|
|
|
|
|
|
|
|
|
[Link_Ford]: http://pdos.csail.mit.edu/papers/parsing:popl04.pdf |
|
|
|
[Link_Ford]: http://www.brynosaurus.com/pub/lang/peg.pdf |
|
|
|