在数学表达式解析器中,右结合运算符

3

最后,从这个问题出发,问题仍然存在,即该子解析器...

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))。我错过了什么?


1
你有什么问题? - xxbbcc
1
我理解为:“如何使这个解析器正确处理类似于^的右结合运算符?” - Jerry Federspiel
@JerryFederspiel 是的,没错。 - HerpDerpington
这很简单。首先编写您希望接受的BNF。然后按照我建议的方式编写递归下降解析器。如果运算符是右结合的,则语法将指定为此,您的解析器将相应地工作。我在您之前的问题中向您展示了如何做到这一点;我留给您去实施。 - Ira Baxter
1个回答

1
当你有一个 a^b,并且你看到 ^c,你将其注入到顶层 ^ 的 RHS 中,创建 a^(b^c),并留下完整的表达式。当你再次看到 ^d 时,你再次将其注入到顶层 ^ 的 RHS 中,创建 a^((b^c)^d)。你不应该将其注入到顶层 ^ 的 RHS 中,而是注入到右侧/最内层的 ^ 表达式中。为了实现这一点,只需在单独的变量中跟踪该表达式即可。然后,不要修改顶层表达式的 RightChild 属性,而是修改子级的属性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接