解析缺少乘法符号的数学表达式

时间:2015-07-25 22:17:36

标签: c# parsing

来自this question,我现在想编写一个解析器的实现。

// Handles * and / 
private static void Summand(Scanner scanner, ref TermNode currentTree, ref Token currentToken)
{
    Factor(scanner, ref currentTree, ref currentToken);

    while (currentToken is OperatorToken && _multiplicationOperators.Contains(((OperatorToken)currentToken).OperatorChar)) // So long as the token is * or /
    {
        TermNode node = new TermNode(currentTree, null, currentToken);
        currentTree = null;
        scanner.MoveNext();
        currentToken = scanner.Current;
        Factor(scanner, ref currentTree, ref currentToken); // Handles ^
        node.RightChild = currentTree;
        currentTree = node;
    }
}

// I think this one might be wrong...
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;
    }
}

private static void Exponent(Scanner scanner, ref TermNode currentTree, ref Token currentToken)
{
    if (currentToken is BracketToken)
    {
        BracketToken bracketToken = (BracketToken)currentToken;
        if (bracketToken.IsOpening)
        {
            scanner.MoveNext();
            currentToken = scanner.Current;
            Term(scanner, ref currentTree, ref currentToken);
            if (currentToken is BracketToken && !((BracketToken)currentToken).IsOpening)
            {
                scanner.MoveNext();
                currentToken = scanner.Current;
            }
            else
                throw new ParseException("Unbalanced brackets!");
        }
    }
    else
    {
        node = new TermNode(null, null, currentToken);

        if (currentToken is OperatorToken)
        {
            currentTree = null;
            scanner.MoveNext();
            currentToken = scanner.Current;
            Exponent(scanner, ref currentTree, ref currentToken, false);
            node.RightChild = currentTree;
            currentTree = node;
        }
        else if (currentToken is VariableToken || currentToken is ConstantToken)
        {
            currentTree = node;
            scanner.MoveNext();
            currentToken = scanner.Current;
        }
        else if (currentToken is FunctionToken)
        {
            currentTree = null;
            scanner.MoveNext();
            currentToken = scanner.Current;
            Exponent(scanner, ref currentTree, ref currentToken, false);
            node.RightChild = currentTree;
            currentTree = node;
        }
    }

}

现在我想知道如何更改此方法以允许3(a+b)之类的表达式...以及此方法和函数是否是正确的方法来实现此目的。

1 个答案:

答案 0 :(得分:1)

这只是修改你的(未说明的)语法的案例:

Summand = Factor | Summand "*" Factor | Summand "/" Factor ;

Summand = Factor | Summand Factor | Summand "/" Factor ; 

并修改手写的递归下降parrser。

因此,您需要修改“Summand”,以便它不检查显式乘法运算符,而是继续检查除法运算符。

所以代码看起来像这样:

private static void Summand(Scanner scanner, ref TermNode currentTree, ref Token currentToken)
{
   Factor(scanner, ref currentTree, ref currentToken);
   while (true) // repeat for each implicit multiply or explicit divide
   {
     if (currentToken is OperatorToken && ((OperatorToken)currentToken).OperatorChar == '/')
     { // handle divide
       TermNode node = new TermNode(currentTree, null, currentToken);
       currentTree = null;
       scanner.MoveNext();
       currentToken = scanner.Current;
       Factor(scanner, ref currentTree, ref currentToken);
       node.RightChild = currentTree;
       currentTree = node;
     }
     else { // handle possible multiplication
            TermNode multiplicand = node ;
            Factor(scanner, ref currentTree, ref currentToken)
            if (Factor_failed) return; // no implicit product
            currentTree = new TermNode(multiplicand, currentTree,  maketoken("*"));              

          }
   } //while
} // Summand

您的解析器缺少的是来自每个子解析器的信号,表明子分析器无法找到要求解析的内容。 (你需要实现“Factor_failed”这个想法。)这与它发现的证据表明请求解析的内容不同,但它不是有效的语法。我建议你将每个返回类型更改为“bool”,如果subparser成功则返回“true”,如果找不到它应该解析的内容则返回“false”,如果它在解析中途失败则抛出异常。

查看实现这些想法的organized way to build recursive descent parsers