最后,从这个问题出发,问题仍然存在,这个子解析器…
private static void Factor(Scanner scanner, ref TermNode currentTree, ref Token currentToken)
{
Exponent(scanner, ref currentTree, ref currentToken);
while (currentToken is OperatorToken && ((OperatorToken)currentToken).OperatorChar == '^') // So long as the token is ^
{
TermNode node = new TermNode(currentTree, null, currentToken);
currentTree = null;
scanner.MoveNext();
currentToken = scanner.Current;
Exponent(scanner, ref currentTree, ref currentToken);
node.RightChild = currentTree;
currentTree = node;
}
}
…不能正确处理指数运算符("^")。这是因为它是右结合律。上面的代码处理它就好像它是左结合的。
例如:将文本e^x^2
解释为(e^x)^2
。然而,正确的"解释"应该是e^(x^2)
。
我已经试过这样做了:
if (/* The current token is ^ */)
{
TermNode node = new TermNode(tree, null, currentToken);
tree = null;
scanner.MoveNext();
currentToken = scanner.Current;
Exponent(ref tree);
node.RightChild = tree;
tree = node;
}
while (/* The current token is ^ */)
{
TermNode detachedExponent = tree.RightChild;
TermNode oldTree = tree;
Token token = currentToken;
tree.RightChild = null;
tree = null;
scanner.MoveNext();
currentToken = scanner.Current;
Exponent(ref tree);
oldTree.RightChild = new TermNode(distachedExponent, tree, token);
tree = oldTree;
}
只适用于两个连续的"^"表达式。不是像e^x^y^z
(这将是e^(x^(y^z))
,而不是e^((x^y)^z)
像解析器声称…我错过了什么?
当您有了a^b
,并且看到了^c
时,将其注入到顶级^
的RHS中,创建a^(b^c)
,并留下最终的完整表达式。当您看到^d
时,再次将其注入顶级^
的RHS中,创建a^((b^c)^d)
。您不应该将它注入到顶级^
的RHS中,而应该注入到最右边/最内部的^
表达式中。要实现这一点,只需在一个单独的变量中跟踪该表达式。然后,不修改顶级表达式的RightChild
属性,而是修改子表达式的。