c++ - 如何手动遵循计算器的 C++ 语法?
问题描述
我正在关注 Bjarne Stroustrup 使用 C++ 编写的 PPP,但我很难理解他的计算器介绍性语法(第 189-192 页),如下所示:
// a simple expression grammar
Expression:
Term
Expression "+" Term // addition
Expression "-" Term // subtraction
Term:
Primary
Term "*" Primary // multiplication
Term "/" Primary // division
Term "%" Primary // remainder (modulo)
Primary:
Number
"(" Expression ")"
Number:
floating-point-literal
首先我们解析 2,它是一个浮点文字,它是一个 Number,它是 Primary,它是一个 Term,它是一个 Expression。
2 是一个浮点字面量,它是一个 Number,它是 Primary,它是一个 Term,它是一个 Expression
- 直接跳到表达式(这是我开始迷路的地方)
3 是一个浮点文字,它是一个 Number,它是一个 Primary,它是一个 Term。为什么这本书在这里停止解析,“3”目前符合所有条件成为表达式?
当我尝试手动执行此操作时,我只能在忽略“+”并将 3 解析为 Term 以匹配需求表达式“+” Term 时得出与给定图表匹配的结论。
此外,如果我尝试进一步外推以解析 9 + 3 * 2,而不是向前看 *,我将无法完成语法,因为 9+3 (显然)是一个有效的表达式,没有要相乘的语法。 .
解决方案
我想您遇到的主要问题与您从下到上阅读它的事实有关。书中的箭头表示信息流,而不是解析顺序。
下面是我们感兴趣的语法(供参考):
Expression:
Term
Expression "+" Term
Expression "-" Term
Term:
Primary
Term "*" Primary
Term "/" Primary
Term "%" Primary
Primary:
Number
"(" Expression ")"
Number:
floating-point-literal
以下段落试图概述在这种语法的情况下以及更一般的设置中的解析过程。
解析表达式:一个简单的例子
上面的语法给出了解析Expression
. Expression
被称为语法公理。这意味着为了解析任何给定的表达式,我们必须从Expression
规则开始。
让我们考虑表达式2 + 3
。解析过程如下:
- 我们匹配
2 + 3
的规则Expression
。它必须是 aTerm
, 形式Expression "+" Term
的表达式或形式的表达式Expression "-" Term
。原来它是一个Expression "+" Term
. 2 + 3
我们匹配with的左侧Expression
。- 唯一可能的规则
2
是Term
。 2
然后我们根据 的规则进行匹配Term
。2
不包含"*"
, 也不"/"
, 也不"%"
。因此它必须是一个Primary
.- 我们继续执行 的规则
Primary
。由于它不包含任何括号,2
因此必须是Number
. - 最后,我们有
2
一个floating-point-literal
.
- 唯一可能的规则
2 + 3
我们匹配with的右侧Term
。- 至于
2
,3
必须是Primary
。 - 同样,遵循与上述相同的路径,
3
推导出为 aNumber
,然后是 afloating-point-literal
。
- 至于
最后,2 + 3
是形式的表达floating-point-literal "+" floating-point-literal
。
解析表达式:复杂表达式
我们现在知道如何解析一个简单的表达式。但是更复杂的呢,比如(2 - 1) + 9 * 3
?上述技术也适用于这种情况。这是解析过程的展开版本:
(2 - 1) + 9 * 3
是形式Expression "+" Term
。- 我们将左侧与 的规则相匹配
Expression
。(2 - 1)
是 aTerm
(因为它不包含"+"
也不"-"
)。- 同样,
(2 - 1)
是一个Primary
。 (2 - 1)
是形式"(" Expression ")"
。通过使用与 for 完全相同的过程2 + 3
,我们最终得到"(" floating-point-literal "-" floating-point-literal ")"
.
- 我们将右侧与 的规则相匹配
Term
。9 * 3
是形式Term "*" Primary
。9
我们根据规则匹配Term
并继续,直到我们得到一个floating-point-literal
.- 我们匹配
3
的规则,Primary
也得到了floating-point-literal
一些细化。 - 最后,
9 * 3
是Term
的形式floating-point-literal "*" floating-point-literal
。
- 最后,
(2 - 1) + 9 * 3
减少到"(" fp - fp ")" "+" fp "*" fp
。
推荐阅读
- c# - 在子测试类中隐藏测试方法
- javascript - Office 加载项 Javascript - 如何模拟选项卡或输入键以选择范围内的单元格
- sumo - SUMO 内部边缘
- reactjs - 如何从父反应钩子调用子函数
- jenkins - 使用 Jenkins 管道作业,是否可以在实际结帐之前在 Jenkinsfile 旁边提供其他文件?
- node.js - 如何在 node.js api 中创建用户并发送邀请
- java - 使用 MS Graph 获取 Sharepoint 站点的 Java 调用返回 500 错误
- jquery - 使用jquery动态添加下拉列表值(选项)
- node.js - (节点:1184)UnhandledPromiseRejectionWarning:错误:连接 ECONNREFUSED 127.0.0.1:5432
- c++ - 是否有使用朋友类隐藏私有函数的习惯用法的名称?