1

Treetop や Citrus よりもはるかに使いやすいと思うので、現在、Ruby を使用して Ruby パーサーを作成しています。より正確には Parslet を使用しています。私は公式の仕様を使用してルールを作成していますが、一部の構文を「除外」しているため、記述できないステートメントがいくつかあり、その方法がわかりません... さて、理解するための例を次に示します。 ..

基本的なルールは次のとおりです。

foo::=
any-character+ BUT NOT (foo* escape_character barbar*)
# Knowing that (foo* escape_character barbar*) is included in any-character

Parslet を使用してどのように翻訳できますか? たぶん不在?/現在?もの ?

どうもありがとう、誰かがアイデアを持っていることを願っています....

良い1日を!

編集:私はあなたが言ったことを試したので、これが私のパーレットを使用したRuby言語への翻訳です:

  rule(:line_comment){(source_character.repeat >> line_terminator >> source_character.repeat).absent? >> source_character.repeat(1)}

ただし、機能していないようです (括弧内のシーケンス)。私はいくつかのテストを行い、括弧に書かれていることが間違っているという結論に達しました。

これは非常に簡単な例です。これらのルールを考えてみましょう:

# Parslet rules
rule(:source_character) {any}
rule(:line_terminator){ str("\n") >> str("\r").maybe }  

rule(:not){source_character.repeat >> line_terminator }
# Which looks like what I try to "detect" up there

私はこれらのルールをこのコードで使用します:

# Code to test : 
code = "test
"

しかし、私はそれを取得します:

行 2 の文字 1 でシーケンス (SOURCE_CHARACTER{0, } LINE_TERMINATOR)- Failed to match sequence (SOURCE_CHARACTER{0, } LINE_TERMINATOR) at line 2 char 1.の一致に失敗しました。 - 行 2 の文字 1 でシーケンス (' ' ' '?) の一致に失敗しました。

このシーケンスが機能しない場合、そこにある私の「完全な」ルールは機能しません...誰かがアイデアを持っているなら、それは素晴らしいことです.

ありがとうございました !

4

2 に答える 2

5

Parslet マッチングは本質的に貪欲です。これは、次のようなことを繰り返すと、

foo.repeat

parslet は、失敗するまで foo に一致します。foo の場合

rule(:foo) { any }

any.repeat は常にドキュメントの残り全体と一致するため、失敗する道をたどることになります!

探しているのは、examples/string_parser.rb (パーレット ソース ツリー) の文字列マッチャーのようなものです。

rule :string do
  str('"') >> 
  (
    (str('\\') >> any) |
    (str('"').absent? >> any)
  ).repeat.as(:string) >> 
  str('"')
end

これが何を意味するか: 'match " の場合、バックスラッシュの後に続く任意の文字に一致するか、または末尾の ".' 以外の任意の文字に一致します。

それで、不在ですか?実際には、次の一致から物事を除外する方法です:

str('foo').absent? >> (str('foo') | str('bar'))

'bar' のみに一致します。それが理解できれば、あなたの悩みはきっと解決できると思います。Ruby パーサーへの道のりはこれで最後ではありませんが...

于 2011-11-23T14:19:45.643 に答える
5

次のようなことができます。

rule(:word) { match['^")(\\s'].repeat(1) } # normal word
rule(:op) { str('AND') | str('OR') | str('NOT') }
rule(:keyword) { str('all:') | str('any:') }
rule(:searchterm) { keyword.absent? >> op.absent? >>  word }

この場合、 はabsent?先読みを行い、次のトークンがキーワードでないことを確認します。そうでない場合は、演算子ではないことを確認します。そうでない場合は、最終的にそれが有効かどうかを確認してくださいword

同等のルールは次のようになります。

rule(:searchterm) { (keyword | op).absent? >> word }
于 2011-11-22T14:20:44.830 に答える