[英]What was Tim Sweeney thinking? (How does this C++ parser work?)
[英]How does this C++ parser work?
我目前正在阅读Bjarne Stroustrup撰写的“编程:使用C ++的原理和实践”,并且在理解如何实现这种特定语法方面遇到问题。
这是语法及其规则:
Expression:
Term
Expression "+" Term
Expression "-" Term
Term:
Primary
Term "*" Primary
Term "/" Primary
Term "%" Primary
Primary:
Number
"(" Expression ")"
Number:
floating-point literal
但是,这是Term的实现方式:
double term()
{
double left = primary();
Token t = ts.get(); // get the next token from token stream
while(true) {
switch (t.kind) {
case '*':
left *= primary();
t = ts.get();
break;
case '/':
{
double d = primary();
if (d == 0) error("divide by zero");
left /= d;
t = ts.get();
break;
}
default:
ts.putback(t); // put t back into the token stream
return left;
}
}
}
为什么我们在switch语句中调用left *= primary();
如果令牌等于“ *”,而不是left *= term()
?
我试图替换left *= primary();
left *= term()
(除法是否相同),程序仍然可以正常工作。 但是,我不理解Bjarne想到的设计决策,这就是为什么他以自己的方式实现功能。 也许我在这里缺少什么?
提前致谢!
为什么我们在switch语句中调用
left *= primary();
如果令牌等于"*"
,而不是left *= term()?
因为语法说:
Term:
Primary
Term "*" Primary
Term "/" Primary
Term "%" Primary
请注意,如果C ++(和C)具有幂运算符,或者他的示例语法具有一元运算符,那么您将看到的是更常见的:
Expression:
Term
Expression "+" Term
Expression "-" Term
Term:
Factor
Term "*" Factor
Term "/" Factor
Term "%" Factor
Factor:
Primary
Primary "**" Factor /* note right-associativity */
Primary:
"+" Primary
"-" Primary
Number
"(" Expression ")"
Number:
floating-point literal
因为生产不是Term "*" Term
。
这是Term "*" Primary
。
在语法本身中这样做的原因是,如果您在表达式中有任何嵌套的Term
,则从解析的角度来看,它们被迫“出现”在左侧。 有效地说服了右侧仅包含主表达式(不包含其他运算符)。 当将此方法应用于递归解析“程序”时,结果是运算符是左关联的,结果是((a*b)*c)
,而不是(a*(b*c))
。
这样的语法只会“向下”传播,而不会“向上”传播,否则您将陷入一团糟的歧义,或者至少会出现一种不自然的联想,从而使试图用您的语言编写算术的人们感到困惑。
当然,对于乘法,算术结果在理论上是相同的。 但是,当您开始使用其他运算符时,问题变得很明显: ((a*b)/c)
与(a/(b*c))
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.