Python 解决轮班/减少与PLY的冲突

Python 解决轮班/减少与PLY的冲突,python,parsing,compiler-construction,grammar,ply,Python,Parsing,Compiler Construction,Grammar,Ply,我的语法如下: 如何在不产生新冲突的情况下解决这些问题?我知道它们是从哪里来的,但我不知道如何修复它。任何帮助或一般建议都是值得的。我会倒着做,因为那样我们会从最容易的到最难的。事实上,对于第一次冲突,我并没有真正的解决方案 第三个冲突是语法中实际歧义的结果。您需要消除歧义: Rule 96 enclosure -> parenth_form Rule 97 enclosure -> set_display Rule 99 parenth_form -> LP

我的语法如下:


如何在不产生新冲突的情况下解决这些问题?我知道它们是从哪里来的,但我不知道如何修复它。任何帮助或一般建议都是值得的。

我会倒着做,因为那样我们会从最容易的到最难的。事实上,对于第一次冲突,我并没有真正的解决方案

第三个冲突是语法中实际歧义的结果。您需要消除歧义:

Rule 96    enclosure -> parenth_form
Rule 97    enclosure -> set_display
Rule 99    parenth_form -> LPAREN expression RPAREN
Rule 102   set_display -> LPAREN argument_list RPAREN
Rule 133   argument_list -> expression
因此,如果我们正在寻找一个
附件
,并找到一个简单的括号表达式,它可以是一个
父形式
,也可以是一个
集合显示
,其中包含一个表达式的
参数列表
。我怀疑这里的意图是,一个简单的括号表达式将是一个
parenth_形式
,但从语法上无法区分

最简单的解决方案是完全去掉
parenth\u表单
,并在为与规则102相对应的
set\u显示
构建AST节点时检查单元素
参数列表
的情况。另一种可能性是明确地表达出来;更改规则102以要求
设置_显示
至少有两个表达式:

set_display -> LPAREN expression COMMA argument_list RPAREN
但是,这仍然需要处理AST,因为在构建
set\u display
节点时,必须将
表达式
前置到
参数列表

第二次S/R冲突实际上非常相似。这是因为:

Rule 104   list_display -> LBRACKET expression COMMA expression RANGE expression RBRACKET
Rule 105   list_display -> LBRACKET argument_list RBRACKET
因此:

如果以下符号为
范围
,则需要按照规则104进行缩减;根据第105条,如果以下符号为RBRACKET;根据规则134,如果下列符号为
逗号
。(这是一个粗略的近似值,因为它假设我们已经知道第二个
表达式的结尾)尽管如此,语法需要在看到第一个
逗号时立即提交到其中一个路径,因为它需要在那一刻决定是否创建
参数列表

解决方案是延迟解析器的决策,这很容易,但很难看:

list_display -> LBRACKET expression RANGE expression RBRACKET
list_display -> LBRACKET expression COMMA expression RANGE expression RBRACKET
list_display -> LBRACKET expression RBRACKET
list_display -> LBRACKET expression COMMA argument_list RBRACKET
现在,第一个
逗号
总是被移位,关于显示什么类型的
列表
的决定被延迟到第二个
表达式
的末尾(如果有两个
表达式
的话),但是有必要对最后两个产品的AST进行调整,以更正
参数列表

出现第一个S/R冲突是因为
中的
既用作运算符,又用作
迭代器的语法部分

Rule 44    comparison -> sum IN sum
Rule 137   iterator -> target IN expression
但是,由于
目标
只是一个
表达式
,并且
表达式
可以派生
,因此(大多数情况下)解析器不可能知道它在
中查看的是哪个

前面的延迟决策技术在这里不起作用,因为您需要知道您正在查看的是
中的哪种类型的
,以便正确应用运算符优先级。假设我们在一个上下文中需要一个
迭代器,输入是:

atom1 AND atom2 IN atom3
如果这是迭代器(即,下一个符号是
逗号
RPAREN
),则实际上:

( atom1 AND atom2 ) IN atom3
但是,如果这是迭代器的左侧,则需要对其进行完全不同的解析:

( atom1 AND ( atom2 IN atom3 ) ) IN expression
此外,
atom3
可能是一个任意表达式,可能是
atom3和atom4
,导致两种解析:

( atom1 AND atom2 ) IN ( atom3 AND atom4 )
( atom1 AND ( atom2 IN atom3 ) AND atom4 ) IN expression
这就是双关语在语言设计中不好的原因

我强烈怀疑没有
LR(k)
语法能够解析语言的特定角落,尽管这只是基于直觉;我没有证据。然而,GLR解析器不会有任何问题,因为它实际上并不含糊。我不知道Python中是否有GLR解析器生成器;如果您不依赖Python,那么您当然可以使用
bison


GLR解析器还可以解决第二个冲突,这也不是歧义的结果。

我将反向执行这些操作,因为这样我们可以从最容易的到最难的。事实上,对于第一次冲突,我并没有真正的解决方案

第三个冲突是语法中实际歧义的结果。您需要消除歧义:

Rule 96    enclosure -> parenth_form
Rule 97    enclosure -> set_display
Rule 99    parenth_form -> LPAREN expression RPAREN
Rule 102   set_display -> LPAREN argument_list RPAREN
Rule 133   argument_list -> expression
因此,如果我们正在寻找一个
附件
,并找到一个简单的括号表达式,它可以是一个
父形式
,也可以是一个
集合显示
,其中包含一个表达式的
参数列表
。我怀疑这里的意图是,一个简单的括号表达式将是一个
parenth_形式
,但从语法上无法区分

最简单的解决方案是完全去掉
parenth\u表单
,并在为与规则102相对应的
set\u显示
构建AST节点时检查单元素
参数列表
的情况。另一种可能性是明确地表达出来;更改规则102以要求
设置_显示
至少有两个表达式:

set_display -> LPAREN expression COMMA argument_list RPAREN
但是,这仍然需要处理AST,因为在构建
set\u display
节点时,必须将
表达式
前置到
参数列表

第二次S/R冲突实际上非常相似。这是因为:

Rule 104   list_display -> LBRACKET expression COMMA expression RANGE expression RBRACKET
Rule 105   list_display -> LBRACKET argument_list RBRACKET
因此:

如果以下符号为
范围
,则需要按照规则104进行缩减;根据第105条,如果以下符号为
RBRACKET
;根据规则134,如果下列符号为
逗号
。(这是一个粗略的近似值,因为它假设我们已经知道第二个
表达式的结尾)