我正在尝试用jflex和杯子为javaScript-ish语言编写解析器,但是我在那些致命的转移/减少问题并减少/减少问题时遇到了一些问题。
我已经进行了彻底的搜索,并找到了很多例子,但是我无法将其推断到语法上。到目前为止,我的理解是,这些问题是因为解析器无法决定要采取哪种方式,因为它无法区分。
我的语法是以下一种: 从输入开始;
INPUT::= PROGRAM;
PROGRAM::= FUNCTION NEWLINE PROGRAM
| NEWLINE PROGRAM;
FUNCTION ::= function OPTIONAL id p_izq ARG p_der NEWLINE l_izq NEWLINE BODY l_der;
OPTIONAL ::=
| TYPE;
TYPE::= integer
| boolean
ARG ::=
| TYPE id MORE_ARGS;
MORE_ARGS ::=
| colon TYPE id MORE_ARGS;
NEWLINE ::= salto NEWLINE
| ;
BODY ::= ;
我遇到了几次冲突,但这2是一个例子:
Warning : *** Shift/Reduce conflict found in state #5
between NEWLINE ::= (*)
and NEWLINE ::= (*) salto NEWLINE
under symbol salto
Resolved in favor of shifting.
Warning : *** Shift/Reduce conflict found in state #0
between NEWLINE ::= (*)
and FUNCTION ::= (*) function OPTIONAL id p_izq ARG p_der NEWLINE l_izq NEWLINE BODY l_der
under symbol function
Resolved in favor of shifting.
ps:语法要复杂得多,但是我认为,如果我看到这些转移/减少问题的解决方法,我将能够修复其余的。
感谢您的回答。
PROGRAM
是没有用的(从技术意义上讲(。也就是说,它不能产生任何句子,因为
PROGRAM::= FUNCTION NEWLINE PROGRAM
| NEWLINE PROGRAM;
PROGRAM
的两种作品都是递归的。为了使非末端有用,它需要能够最终产生一些终端,为此,它必须至少具有一个非收集性生产。否则,递归永远无法终止。我很惊讶杯子没有向您提及。也许确实如此,您选择忽略警告。
这是一个问题 - 无用的非终端实际上永远无法匹配任何东西,因此它们最终会导致解析错误 - 但这不是您报告的解析冲突。冲突来自同一制作的另一个功能,这与您不能除以0的事实。
什么都没有的是,任何数量的毫无疑问仍然一无所有。因此,如果您有很多没有的意思,并且有人来问您确切地有多少未拨款,您会有一些问题,因为要从" 0 * lose"中获得"足够",您必须计算" 0/0",这不是定义明确的值。(如果您有很多两个人,有人问您有几个两个人,那不是问题:假设有很多两个人奏效到40;您可以轻松地计算出40/2 = 20完全因为20 * 2 = 40。(
因此,在这里我们没有算术,我们有一系列符号。不幸的是,没有包含符号的字符串确实是看不见的,就像0是针对所有这些千年的弦,直到一些阿拉伯数学家注意到一无所有的价值。
一切都在哪里,就是您有
PROGRAM::= ... something ...
| NEWLINE PROGRAM;
但是允许NEWLINE
什么都不生产。
NEWLINE ::= salto NEWLINE
| ;
因此,PROGRAM
的第二个递归生产可能一无所获。而且它可能没有很多次,因为生产是递归的。但是解析器需要确定性:它需要确切知道存在多少个漏斗,以便它可以将每种内容降低到NEWLINE
非末端,然后减少新的PROGRAM
非终端。而且它真的不知道要添加多少个漏斗。
在简短的,可选的未经事物和重复的情况下是模棱两可的。如果您要在语言中插入一无所有,则需要确保有固定的有限数量,因为这是解析器明确剖析虚无的唯一方法。
现在,由于该特定递归的唯一要点(据我所知(是允许空的newline终止语句(由于新线而可见,但什么也不做(。您可以通过更改递归以避免任何事情来做到这一点:
PROGRAM ::= ...
| salto PROGRAM;
尽管这与您当前的问题无关,但我不得不提到杯子是LALR解析器的生成器,以及您在Internet上可能已经学到或阅读过的有关递归下降的解析器无法处理左递归不应用。(我删除了对解析技术的教授方式的咆哮,因此您必须尝试从我留下的提示中恢复它。(自下而上的解析器发电机,例如杯子和Yacc/yacc/yacc/bison love 左递归。当然,他们也可以处理正确的递归,但很不情愿,因为除了左侧递归之外,他们需要浪费每个递归的堆叠空间。因此,为了应对缺陷,无需扭曲您的语法;只需自然地写语法,然后快乐即可。(因此,如果需要非终端代表"其余的"某物。(
pd:很多什么都在文化上是针对1934年歌剧 Porgy和Bess 的歌曲的。