C++ 使用BNF在Bison中实现一个循环

C++ 使用BNF在Bison中实现一个循环,c++,linux,bison,C++,Linux,Bison,所以,我得到了这个代码: calclist: /* nothing */ matches at beginning of input | calclist exp EOL { printf("= %d\n", $1); } EOL is end of an expression ; 据解释: 前两个规则定义了符号calcset,它们实现了一个循环 它读取以换行符结尾的表达式并打印其值。 calclist的定义使用了一种常见的两规则递归习惯用法 实现一个序列或列表:第一个规则为空且匹配

所以,我得到了这个代码:

calclist: /* nothing */   matches at beginning of input
 | calclist exp EOL { printf("= %d\n", $1); } EOL is end of an expression
 ;
据解释:

前两个规则定义了符号calcset,它们实现了一个循环 它读取以换行符结尾的表达式并打印其值。 calclist的定义使用了一种常见的两规则递归习惯用法 实现一个序列或列表:第一个规则为空且匹配 没有什么第二个将向列表中添加一项。第二节中的动作 规则以$2为单位打印exp的值


摘自《Flex和Bison》一书。有人能告诉我这样的语法是如何暗示循环的吗?我可以理解
exp
中的递归(稍后编写,但我不包括递归,因为它与这里无关)。然而,看看这样的语法,我只能想到第一个规则不匹配任何东西,以保持解析器不处理任何东西,从而产生无限循环,直到标准输入流给出第一个符号并启动第二个规则。然而,我不明白第二条规则。它如何到达
exp
部分?当它遇到
calclist
时,它不会保持递归吗?

如果这是一个递归下降解析器,它会保持递归,但我想关键是它不是。

如果这是一个递归下降解析器,它会保持递归,但我想关键是它不是。

第二条规则意味着一个循环,就像你有一行代码:

exp EOL exp EOL exp EOL exp EOL
每个“exp EOL”都是一个calclist,包含在另一个calclist中。 因此,规则将减少这一行:

exp EOL exp EOL exp EOL exp EOL
calclist1 exp EOL exp EOL exp EOL exp EOL < - Rule 1. calclist1 is [ ], the empty string.
calclist2 exp EOL exp EOL exp EOL < - Rule 2. calclist2 is calclist1 exp EOL
calclist3 exp EOL exp EOL < - Rule 2. calclist3 is calclist2 exp EOL
calclist4 exp EOL < - Rule 2. calclist4 is calclist3 exp EOL
calclist5 < - Rule 2. calclist5 is calclist4 exp EOL
exp下线exp下线exp下线exp下线exp下线exp下线
calclist1 exp EOL exp EOL exp EOL exp EOL<-规则1。calclist1为[],为空字符串。
calclist2 exp EOL exp EOL exp EOL<-规则2。calclist2是calclist1 exp EOL
calclist3 exp EOL exp EOL<-规则2。calclist3是calclist2 exp EOL
calclist4 exp EOL<-规则2。calclist4是calclist3 exp EOL
calclist5<-规则2。calclist5是calclist4 exp EOL
这就是它创建循环的意思。与您引用的部分一样,在定义语法以创建任意长度的表达式列表时,这是一种常见的“习惯用法”

我希望这能回答你的问题


谢谢

第二条规则意味着一个循环,就好像你有一行,比如:

exp EOL exp EOL exp EOL exp EOL
每个“exp EOL”都是一个calclist,包含在另一个calclist中。 因此,规则将减少这一行:

exp EOL exp EOL exp EOL exp EOL
calclist1 exp EOL exp EOL exp EOL exp EOL < - Rule 1. calclist1 is [ ], the empty string.
calclist2 exp EOL exp EOL exp EOL < - Rule 2. calclist2 is calclist1 exp EOL
calclist3 exp EOL exp EOL < - Rule 2. calclist3 is calclist2 exp EOL
calclist4 exp EOL < - Rule 2. calclist4 is calclist3 exp EOL
calclist5 < - Rule 2. calclist5 is calclist4 exp EOL
exp下线exp下线exp下线exp下线exp下线exp下线
calclist1 exp EOL exp EOL exp EOL exp EOL<-规则1。calclist1为[],为空字符串。
calclist2 exp EOL exp EOL exp EOL<-规则2。calclist2是calclist1 exp EOL
calclist3 exp EOL exp EOL<-规则2。calclist3是calclist2 exp EOL
calclist4 exp EOL<-规则2。calclist4是calclist3 exp EOL
calclist5<-规则2。calclist5是calclist4 exp EOL
这就是它创建循环的意思。与您引用的部分一样,在定义语法以创建任意长度的表达式列表时,这是一种常见的“习惯用法”

我希望这能回答你的问题


谢谢

啊,我明白了。calclist1 exp EOL=>calclist2。我认为Bison从左到右处理输入流,这意味着它不断进入
calclist->calclist->calclist
并且永远不会到达
exp
段。现在我想,右边的规则是让Bison匹配输入流中的模式,而不是从左到右进行处理,不是吗?因为我们可以定义:
exp:exp-exp'+'
,这显然是一种匹配模式,但不是实际的代码。通常,示例
exp
是这样写的:
exp:exp+exp
,因此我认为它是实际的实现。啊,我明白了。calclist1 exp EOL=>calclist2。我认为Bison从左到右处理输入流,这意味着它不断进入
calclist->calclist->calclist
并且永远不会到达
exp
段。现在我想,右边的规则是让Bison匹配输入流中的模式,而不是从左到右进行处理,不是吗?因为我们可以定义:
exp:exp-exp'+'
,这显然是一种匹配模式,但不是实际的代码。通常,示例
exp
是以以下形式编写的:
exp:exp+exp
,因此我认为它是实际的实现。