だから私はScalaのパーサーを使って電卓を書こうとしてきましたが、演算子の結合性が逆方向であり、文法を左再帰にしようとすると、完全に明確であるにもかかわらず、次のようになります。スタックオーバーフロー。
明確にするために、次のようなルールがある場合:def extract:Parser [Int] = num〜 "-" 〜add {x => x._1._1 --x._2}次に、7-4-3を評価すると次のようになります。 0ではなく6。
私が実際にこれを実装した方法は、演算子が非リーフノードであり、リーフノードが数値である二分木を構成しているということです。私がツリーを評価する方法は、左の子(オペレーター)の右の子です。7-4-5のツリーを構築するとき、私がそれをどのように見せたいかは次のとおりです。
-
- 5
7 4 NULL NULL
ここで、-はルート、その子は-と5、2番目の-の子は7と4です。
しかし、私が簡単に構築できる唯一のツリーは
-
7 -
NULL NULL 4 5
これは違いますが、私が望むものではありません。
基本的に、簡単な括弧は7-(4-5)ですが、私は(7-4)-5が必要です。
どうすればこれをハックできますか?演算子の優先順位に関係なく、正しい演算子の優先順位で計算機を作成できるはずだと感じています。最初にすべてをトークン化してから、トークンを逆にする必要がありますか?右の子の左の子をすべて取り、右の子の親の右の子にし、親を元の右の子の左の子にすることで、ツリーを反転させても大丈夫ですか?一見良いようですが、あまり深く考えていません。足りないケースがあるに違いない気がします。
私の印象では、LLパーサーはスカラパーサーでしか作成できません。別の方法を知っているなら、教えてください!