Parsing 寻找关于使此BNF语法适合LL(1)解析(左因子分解)的建议

Parsing 寻找关于使此BNF语法适合LL(1)解析(左因子分解)的建议,parsing,compiler-construction,bnf,Parsing,Compiler Construction,Bnf,我正在从事一个解析项目,该项目将此语法的改编用于Perl的正则表达式。为了我自己的目的,我简化了这个语法,如下所示(注意,因为“|”是一个标记,所以我改为使用逗号“,”以便将给定非终结符的结果分开): :=, := | := , := := , , := * := + := ? := , , := () := [] := , := , 我想写一个LL(1)解析器来处理这个语法,对于LL(1)解析器,的结果有一些歧义。为了解决这个问题,我可以添加一个新的非终结符,这样做: <

我正在从事一个解析项目,该项目将此语法的改编用于Perl的正则表达式。为了我自己的目的,我简化了这个语法,如下所示(注意,因为“|”是一个标记,所以我改为使用逗号“,”以便将给定非终结符的结果分开):

:=,
:=  | 
:= , 
:= 
:= , , 
:= *
:= +
:= ?
:= , , 
:= ()
:= []
:= , 
:= , 
我想写一个LL(1)解析器来处理这个语法,对于LL(1)解析器,
的结果有一些歧义。为了解决这个问题,我可以添加一个新的非终结符
,这样做:

<items>   :=  <item><X>
<X>       :=  <items>, epsilon
:=
:=,ε
但我想知道的是,我能不能在
中翻转第二个产品的顺序,像这样:

<items>   := <item>, <items><item>
def items():
  list = [ item() ]
  while couldStart(item, lookahead):
    list.append(item())
  return list
:=,

并避免添加新的非终结符?它看起来并没有破坏任何东西,毕竟这个产品的全部要点是允许任何数量的顺序符号,如果我们颠倒顺序,我们仍然可以得到它。在这种情况下,是我遗漏了什么,还是仅仅颠倒顺序就达到了与左分解相同的目标?

您试图解决的问题是

items → item
items → item items
不考虑因素;两个产品都以
项开始

你提议的解决方案

items → item
items → items item
实际上没有帮助(任何启动
item
的东西仍然可以启动
items
的生产),但更重要的是,它是左递归的,这对于LL语法来说是多余的

原则上,“新的非终端”是正确的解决方案,但在递归下降解析器中,您可能会执行以下操作:

<items>   := <item>, <items><item>
def items():
  list = [ item() ]
  while couldStart(item, lookahead):
    list.append(item())
  return list

啊哈,左递归。我可能需要掸掉红龙书上的灰尘。。。。我忘了很多这些东西。谢谢你。你是说,在递归下降的实际实现中,这个问题可以在不考虑语法左因子的情况下解决吗?我看不出你用那段python代码提出的解决方案。@ErikNyquist:也许伪python代码没有多大帮助。关键是一个实用的RD解析器使用循环而不是递归,并且可以将
X+
实现为循环:首先识别
X
,然后重复,只要下一个标记可以启动
X
。在C语言中,我会把它写成一个
do。。。而
循环;也许这会更清楚<代码>X*
也可以通过循环识别;唯一的区别是考试是在开头而不是结尾。好的,我明白了。我确实会避免递归,所以我很快就会达到我必须实现它的地步,我很感谢你的建议。我还没有找到任何与编译器设计相关的IRC室,或者更小的子区域(即LL解析器、BNF语法)。你知道有什么好的论坛可以讨论这些事情吗。。。。除了stackoverflow之外?@ErikNyquist:再也没有了,对不起。这并不意味着它们不存在:)