私の脳は、生産ルールからいくつかの左再帰を排除しようとして揚げられています。JavaCCを使用してコンパイラを構築しており、次の2つのプロダクションルールを使用する必要があります。
expression := fragment ( ( + | - | * | / ) fragment )*
fragment := identifier | number | ( + | - ) fragment | expression
しかし、問題は、フラグメントがフラグメントに関連する式に関連していることです。つまり、間接的な左再帰です。
私はインターネットを見回しましたが、誰もがここにあるこのアルゴリズムを使用しているようです。そのサイトでは、ここで見つけることができる直接左再帰の除去については説明していません
私は次のようなルールになります:
void expression(): {}
{
fragment()
(
(< PLUS >|< MINUS >|< DIVIDE >|< ASTERISKS >)
fragment()
)*
}
void k(): {}
{
(
((< PLUS >|< MINUS >|< DIVIDE >|< ASTERISKS >)fragment())*k()
| fragment()
)
}
void fragment(): {}
{
(
< ID >k()
| number()k()
| (< PLUS >|< MINUS >)fragment()k()
)
}
それらはJavaCCで使用されるコードで書かれているので、うまくいけば理解できます。基本的に、再帰を処理するためのルールKを導入しましたが、問題はまだ存在します。ただし、Kの最初の部分は*(0回以上)であるため、K-> k()が残り、残りが少なくなるため、ゼロに減らすことができます。再帰!!
ここからどこへ行けばいいのかわからず、髪の毛がたくさん抜けてしまいました。任意の洞察をいただければ幸いです!