来自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)
之类的表达式...以及此方法和函数是否是正确的方法来实现此目的。
答案 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”,如果它在解析中途失败则抛出异常。