1 つの解決策は、分流場アルゴリズムを使用して式を RPN に変換し、それを RPN として評価することです (RPN は infix よりも評価がはるかに簡単であるため)。最初の部分、RPN への変換 (疑似コード):
while (tokens left) {
t = read_token();
if (t is number) {
output(t);
} else if (t is unary operator) {
push(t);
} else if (t is binary operator) {
r = pop();
if (r is operator and precedence(t)<=precedence(r)) {
output(r);
} else {
push(r);
}
push(t);
} else if (t is left parenthesis) {
push(t);
} else if (r is right parenthesis) {
while ((r = pop()) is not left parenthesis) {
output(r);
if (stack is empty) {
mismatched parenthesis!
}
}
if (top() is unary operator) {
output(pop());
}
}
}
while (stack is not empty) {
if (top() is parenthesis) {
mismatched parenthesis!
}
output(pop());
}
read_token
入力キューからトークンを読み取ります
output
出力キューに値を挿入します
push
値をスタックにプッシュします (必要なのは 1 つだけです)。
pop
スタックから値をポップします
top
ポップせずにスタックの一番上にある値をピークします
RPN 評価はより単純です。
while (tokens left) {
t = read_token();
if (t is number) {
push(t);
} else if (t is unary operator) {
push(eval(t, pop()));
} else if (t is binary operator) {
val1 = pop();
val2 = pop();
push(eval(t, val1, val2));
}
}
result = pop();
read_token()
前のステップで生成された RPN キューから値を読み取ります
eval(t, val)
t
オペランドで単項演算子を評価しますval
eval(t, val1, val2)
t
オペランドを持つ二項演算子を評価しval1
、val2
result
式の最終値です
この単純化されたアルゴリズムは、すべての演算子が左結合で、関数が使用されていない場合に機能するはずです。独自のスタック実装を使用しているため、再帰は必要ありません。例と詳細については、Shunting-yardの Rosetta Code およびRPNの Rosetta Code を参照してください。