3

文法:

rule: (a b)? a c ;

入力:

a d

質問: 与えられた入力の位置 2 で正しいエラー メッセージはどれですか?

1. expected "b", "c".
2. expected "c".

PS

私はパーサーを書き、「b」が位置で期待されるかどうかを考慮に入れる選択(ジレンマ)を持っています。

#1エラー(「b」、「c」が予想される)は、入力「a b」が予想されることを言いたいのですが、オプションであるため、予想されていないが可能である可能性があります。

可能性が予想と同じかどうかわかりませんか?

#1 と #2 のどちらのエラー メッセージが適切で、正しいですか?

回答ありがとうございます。

PS

最初のケースでは、マーカーをtesting位置の限界として定義します。

if(_inputPos > testing) {
  _failure(_inputPos, _code[cp + {{OFFSET_RESULT}}]);
}

オプションのエクスプレッションで制限を移動:

OPTIONAL_EXPRESSION:
testing = _inputPos;

"b" 式は pos_inputPosの上に移動testingし、failure at を追加し_inputPosます。

testing2 番目のケースでは、ブール値フラグとしてマーカーを定義できます。

if(!testing) {
  _failure(_inputPos, _code[cp + {{OFFSET_RESULT}}]);
}

この場合の "b" 式は、テスト済みであるため、失敗を追加しません (オプションの式の内部)。

何が良くて正しいと思いますか?

  1. 特定の位置として定義されたテストと、この位置より上の式 (_inputPos > testing) の場合、失敗が追加されます (オプションの式内であっても)。

  2. テストはフラグとして定義され、このフラグが設定されている場合、失敗は考慮されません。オプションの式を実行した後、以前のテスト値 (true または false) を復元します (リセットではありません!)。

また、ルールが失敗しない場合、失敗は考慮されません。解析が失敗した場合にのみ報告されました。

PS

2014 年 1 月 6 日の変更

この質問は、2 つの異なる問題に関連しているため発生しました。

最初の問題:

構文解析式文法 (PEG) は、入力の 3 つのアトミック項目のみを記述します。

  • 端子記号
  • 非終端記号
  • 空の文字列

この文法は字句前処理などの操作を提供しないため、トークンなどの要素を提供しません。

2番目の問題:

文法とは何ですか?同じ入力を受け入れても異なる結果を生成する場合、2 つの文法は等しいと見なすことができますか?

2 つの文法があるとします。

文法1

ルール <- タイプ? 識別子

文法2

ルール <- タイプ識別子 / 識別子

どちらも同じ入力を受け入れますが、(PEG で) 異なる結果を生成します。

文法 1 の結果:

  • {タイプ: タイプ、識別子: 識別子}
  • {タイプ: null、識別子: 識別子}

文法 2 の結果:

  • {タイプ: タイプ、識別子: 識別子}
  • {識別子:識別子}

質問:

  • 両方の文法は同じですか?
  • 文法の最適化を行うのは簡単ですか?

両方の質問に対する私の答えは否定的です。同等ではありません、無痛ではありません。

しかし、あなたは尋ねるかもしれません。「しかし、なぜこれが起こるのですか?」.

私はあなたに答えることができます。「これは問題ではないからです。これは機能です」。

PEG パーサーでは、式は常にこれらの部分から構成されます。

ORDERED_CHOICE => シーケンス => 式

そして、この説明は、「しかし、なぜこれが起こるのか?」という質問に対する私の答えです。

別の問題。

PEG パーサーは WHITESPACES を認識しません。これは、トークンとトークン セパレータがないためです。

この文法を見てください(要するに):

program <- WITESPACE expr EOF

expr <- ルールX

ruleX <- 'X' ホワイトスペース

ホワイトスペース < ' '?

EOF <- ! .

すべての PEG 文法は、この方法で記述されます。

最初の WHITESPACE はルールの開始時に、他の WHITESPACE は (多くの場合) ルールの最後にあります。

この場合、PEG オプションの WHITESPACE は想定どおりに想定する必要があります。

しかし、ホワイトスペースはスペースだけを意味するわけではありません。より複雑な [\t\n\r] コメントもあるかもしれません。

ただし、エラー メッセージの主なルールは次のとおりです。

期待されるすべての要素を表示できない場合 (または、期待される要素のすべてのセットから少なくとも 1 つを表示できない場合)、この場合は何も表示しないほうが正しいです。

「予期しない」エラーメッセージを表示するには、より正確に必要です。

予想される WHITESPACE を PEG でどのように表示しますか?

  • パーサー エラー: WITESPACE が必要です
  • パーサー エラー: 予期される ' '、'\t'、'\n' 、'r'

コメントの開始文字はどうですか?また、一部の文法では WHITESPACE の一部である場合もあります。

この場合、WHITESPACE は複雑すぎて表示できないため、エラー メッセージに WHITESPACE を正しく表示できないため、オプションの WHITESPACE は他のすべての潜在的な予想される要素を拒否します。

これは良いことですか、それとも悪いことですか?

これは悪いことではなく、PEG パーサーのこの性質を隠すためにいくつかのトリックが必要だったと思います。

また、私の PEG パーサーでは、オプションの (optional & zero_or_more) 式の最初の位置にある内部式を期待どおりに処理する必要があるとは想定していません。ただし、他のすべての内部 (最初の位置を除く) は、期待どおりに処理する必要があります。

例 1:

List<int list; // type? ident

Here "List<int" is a "type". But missing ">" is not at the first position in optional "type?".

この失敗を考慮して、「expected '>'」としてレポートします。これは、「type」をスキップせずに「type」に入り、実際にはオプションの「List」の後で、位置を最初から次の実際の「expected」に移動するためです (すでにテスト位置の外側) 要素。

「リスト」は「テスト」の位置にありました。

内側の式(任意の式の内側)が「制限に収まる」場合、次の位置に継続しない場合、期待される入力として想定されません。

この仮定から主な質問がされています。

PEG パーサーとそのエラー メッセージについて話していることを考慮に入れる必要があります。

4

1 に答える 1

3

あなたの文法は次のとおりです。

ここで明らかなのは、最初の入力の後に、またはaの 2 つの可能な入力があることです。エラー メッセージは、どちらかを優先するべきではありません。bc

無効な入力に対してエラーメッセージを生成するための基本的な考え方は、失敗した最も遠い場所を見つけて (文法がエラーの一部d | (a b)? a cdはない場合)、前進して言うことができるすべての可能な入力が何であるかを判断することです。"expected '...' but got '...'". パーサーを回復して強制的に続行させる方法は他にもあります。予想されるトークンが 1 つしかない場合は、一時的にトークン ストリームに挿入し、それ以来どこにでもあるかのように続行します。これにより、パーサーが最初に停止したポイントを超えてエラーを見つけることができるため、エラー検出が向上します。

于 2014-01-03T11:46:54.173 に答える