「優先順位」レベルごとに異なる非終端記号を使用してルールを明示的に書き出す場合は、優先順位を宣言する必要はまったくなく、そうすべきではありません。
レモンは、すべてのyacc派生語と同様に、優先順位宣言を使用して、あいまいな文法からあいまいさを取り除きます。参照される特定のあいまいな文法は次のとおりです。
expression: expression '+' expression
| expression '*' expression
| '&' expression
| ... etc, etc.
その場合、すべての選択肢がシフト削減の競合につながります。パーサジェネレータに優先順位ルールがない場合、または正確にしたい場合は、それを明確な文法として記述する必要があります(これはあなたが行ったことです)。
term: ID | NUMBER | '(' expression ')' ;
postfix_expr: term | term '[' expression '] | ... ;
unary_expr: postfix_expr | '&' unary_expr | '*' unary_expr | ... ;
multiplicative_expr: unary_expr | multiplicative_expr '*' postfix_expr | ... ;
additive_expr: multiplicative_expr | additive_expr '+' multiplicative_expr | ... ;
...
assignment_expr: conditional_expr | unary_expr '=' assignment_expr | ...;
expression: assignment_expr ;
[1]
明確な文法は、左結合(上記の乗法および加法)および右結合(少し奇妙ですが、以下を参照)を示していることに注意してください。したがって、あいまいさは実際にはありません。
現在、優先順位宣言(%left
、、%right
など)は、曖昧性解消のためにのみ使用されています。あいまいさがない場合、宣言は無視されます。パーサジェネレータは、文法が反映されているかどうかさえチェックしません。(実際、多くの文法はこの種の優先関係として表現することはできません。)
したがって、文法が明確な場合は、優先順位の宣言を含めることは非常に悪い考えです。それらは完全に間違っている可能性があり、文法を読む人を誤解させる可能性があります。それらを変更しても、言語の解析方法には影響しません。これにより、文法を編集したい人を誤解させる可能性があります。
優先順位規則を使用してあいまいな文法を使用する方がよいのか、それとも明確な文法を使用する方がよいのかについて、少なくともいくつかの疑問があります。C
単純な優先順位リストでは文法を表現できないような言語の場合は、あいまいでない文法を使用する方がおそらく良いでしょう。ただし、明確な文法にはより多くの状態があり、パーサジェネレータが単位削減を最適化できない限り、構文解析がわずかに遅くなる可能性があります(上記の文法の最初の選択肢はすべて、各式のタイプが前のものである可能性があります) ASTに影響を与えない式タイプ。ほとんどの場合は操作なしであり、多くのパーサジェネレーターがコードを挿入しますが、これらの各プロダクションを減らす必要があります。)
優先関係が正確に代入演算子であるため、理由C
を単純に表現することはできません。検討:
a = 4 + b = c + 4;
assignment-expression
では、代入演算子は左側でのみ適用できるため、これは解析されませんunary-expression
。+
これは、との間の可能な数値の優先順位を反映していません=
。[2]
+
よりも優先順位が高い場合=
、式は次のように解析されます。
a = ((4 + b) = (c + 4));
+
優先順位が低い場合は、次のように解析されます
(a = 4) + (b = (c + 4));
[1] cast_expressionを省略したことに気づきましたが、キャストして元に戻すことはできません。あなたはアイデアを得る)
[2]説明が修正されました。