lex-then-parse スタイルのパーサーを実行しているように聞こえます。単項およびバイナリ マイナスの個別のトークンを取得するために、lexer に単純なステート マシンが必要になります。(PEG パーサーでは、これは気にする必要はありません。)
JavaCC では、文字が であるDEFAULT
と見なす状態があります。一次式の終わりをトークン化すると (例に基づいて、閉じ括弧または整数のいずれか)、が と見なされる状態に切り替わります。中置演算子に遭遇すると、状態に戻ります。-
UNARY_MINUS
INFIX
-
INFIX_MINUS
DEFAULT
自分で巻く場合は、それよりも少し簡単かもしれません。これを行う巧妙な方法については、このPython コードを参照してください。基本的に、 に遭遇する-
と、前のトークンが中置演算子であったかどうかを確認するだけです。この例では"-u"
、非公式のトークン化に便利な単項マイナス トークンを表す文字列を使用しています。私が知る限り、Python の例では、a-
が開き括弧の後に続く場合、または入力の先頭に来る場合を処理できません。それらも単項と見なされるべきです。
分流場アルゴリズム自体で単項マイナスを正しく処理するには、どの中置演算子よりも優先順位を高くする必要があり、右結合としてマークする必要があります。(右結合を処理することを確認してください。残りの演算子は左結合であるため、省略している可能性があります。) これは Python コードで十分に明確です (ただし、2 つの別個のマップではなく、ある種の構造体を使用します)。 .
評価するときは、単項演算子を少し異なる方法で処理する必要があります。これは、スタックから 2 つではなく 1 つの数値をポップするだけでよいためです。実装がどのように見えるかによっては、リストを調べて出現するすべての を に置き換える方が簡単な場合があり"-u"
ます[-1, "*"]
。
Python を少しでも理解できれば、リンク先の例で私が話していることをすべて理解できるはずです。コードは、他の誰かが言及した C バージョンよりも少し読みやすいと思います。また、興味がある方のために、Rubyでshunting-yard を使用することについて少し前に少し書きましたが、単項演算子は別の非終端記号として扱ったので、それらは表示されていません。