1

[\w]文字が同じ語彙素にない場合、文字が互いに直接隣接して表示されないようにする文法を設定しようとしています。つまり、単語はスペースまたは句読点で区切らなければなりません。

次の文法を考えてみましょう。

use Marpa::R2; use Data::Dump;

my $grammar = Marpa::R2::Scanless::G->new({source  => \<<'END_OF_GRAMMAR'});

:start ::= Rule
Rule ::= '9' 'september'

:discard ~ whitespace
whitespace ~ [\s]+

END_OF_GRAMMAR

my $recce = Marpa::R2::Scanless::R->new({grammar => $grammar});
dd $recce->read(\'9september');

これは正常に解析されます。ここで、文法を変更して、 と を強制的に分離したいと考えてい9ますseptember。一致する未使用の語彙素を導入することでこれを行うことを考えました[\w]+:

use Marpa::R2; use Data::Dump;

my $grammar = Marpa::R2::Scanless::G->new({source  => \<<'END_OF_GRAMMAR'});

:start ::= Rule
Rule ::= '9' 'september'

:discard ~ whitespace
whitespace ~ [\s]+

word ~ [\w]+      ### <== Add unused lexeme to match joined keywords
END_OF_GRAMMAR

my $recce = Marpa::R2::Scanless::R->new({grammar => $grammar});
dd $recce->read(\'9september');

残念ながら、この文法は次のように失敗します。

A lexeme is not accessible from the start symbol: word
Marpa::R2 exception at marpa.pl line 3.

lexeme defaultこれはステートメントを使用して解決できますが、次のようになります。

use Marpa::R2; use Data::Dump;

my $grammar = Marpa::R2::Scanless::G->new({source  => \<<'END_OF_GRAMMAR'});
lexeme default = action => [value]  ### <== Fix exception by adding lexeme default statement

:start ::= Rule
Rule ::= '9' 'september'

:discard ~ whitespace
whitespace ~ [\s]+

word ~ [\w]+
END_OF_GRAMMAR

my $recce = Marpa::R2::Scanless::R->new({grammar => $grammar});
dd $recce->read(\'9september');

これにより、次の出力が得られます。

Inaccessible symbol: word
Error in SLIF parse: No lexemes accepted at line 1, column 1
* String before error: 
* The error was at line 1, column 1, and at character 0x0039 '9', ...
* here: 9september
Marpa::R2 exception at marpa.pl line 16.

つまり、 と の間9にギャップがないという事実により、解析が失敗しましたseptember。これはまさに私が望んでいることです。軟膏の唯一の欠点は、語彙素が実際の文法で使用されていないInaccessible symbol: wordため、STDERR に迷惑なメッセージがあることです。word

コンストラクター オプションのようにMarpa::R2::Grammar宣言できたことがわかりましたが、 ではできません。wordinaccessible_okMarpa::R2::Scanless

次のようなこともできたはずです。

Rule ::= nine september
nine ~ word
september ~ word

次に、pauseカスタム コードを使用して実際の語彙素の値を調べ、値に応じて適切な語彙素を返します。

キーワードまたは数字と単語を使用するが、隣接する語彙素を空白や句読点で区切ることなく一緒に実行することを禁止する文法を構築する最良の方法は何ですか?

4

1 に答える 1

4

明らかな解決策は、間に空白を必要とすることです (G1 レベルで)。次の文法を使用すると

:default ::= action => ::array

:start ::= Rule
Rule ::= '9' (Ws) 'september'

Ws ::= [\s]+

:discard ~ whitespace
whitespace ~ [\s]+

その後9september失敗しますが、9 september解析されます。注意すべき重要な点:

  • 語彙素は、どちらも最長のトークンである場合、破棄することも要求することもできます。:discardこれが、とWsルールが互いに干渉しない理由です。マルパは、このような「あいまいさ」を気にしません。
  • Wsルールは括弧で囲まれており、結果の解析ツリーをクリーンに保つために値が破棄されます。
  • 通常、ファントム語彙素のようなトリックを使用してパーサーを誤った方向に導くことは望ましくありません。その方法は破損にあります。
  • すべての空白が重要な場合は、:discard ~ whitespace. これは、伝統的に空白が問題にならない C ライクな言語などで使用することを意図しています。
于 2013-09-08T23:35:35.453 に答える