Python 解析隐式与显式时间运算符

Python 解析隐式与显式时间运算符,python,parsing,ply,lalr,Python,Parsing,Ply,Lalr,我一直在使用ply编写LALR解析器,在尝试解析乘法时遇到了不一致的情况 由于完整的解析器有几千行长,我将不在这里介绍它,但我创建了一个简单的演示: import ply.lex as lex import ply.yacc as yacc tokens = ( 'int', 'times', 'plus', ) precedence = ( ('left', 'plus'), ('left', 'times'), ) t_ignore = ' \t

我一直在使用ply编写LALR解析器,在尝试解析乘法时遇到了不一致的情况

由于完整的解析器有几千行长,我将不在这里介绍它,但我创建了一个简单的演示:

import ply.lex as lex
import ply.yacc as yacc

tokens = (
    'int',
    'times',
    'plus',
)

precedence = (
    ('left', 'plus'),
    ('left', 'times'),
)

t_ignore = ' \t\n '
t_int = r' \d+ '
t_plus = r' \+ '
t_times = ' \* '

def p_int(args):
    'expr : int'
    args[0] = int(args[1])

def p_times(args):
    '''expr : expr times expr
            | expr expr %prec times'''
    if len(args) == 3:
        args[0] = args[1] * args[2]
    elif len(args) == 4:
        args[0] = args[1] * args[3]

def p_plus(args):
    'expr : expr plus expr'
    args[0] = args[1] + args[3]

lex.lex()
parser = yacc.yacc()

while True:
    s = raw_input('>> ')
    print " = ", parser.parse(s)
PLY没有报告移位/减少冲突或减少/减少冲突,但我发现以下不一致:

    >>  1 + 2 3
     =  9
    >>  1 + 2 * 3
     =  7
这对我来说似乎很奇怪,因为显式时间规则和隐式时间规则具有相同的优先级。 但我认为这可能是因为PLY为“times”标记分配了一个优先级,从而将其转移到堆栈上,以利于使用p_plus规则减少表达式。我怎样才能解决这个问题


编辑:更简单的演示。

快速破解:将
int
标记添加到优先级规范中(具有时间优先级)。
int
标记随后将被适当地转移到符号堆栈上。即(根据原问题),

这是可行的,但在处理可能大量的代币时会很混乱(开放括号, 符号、浮点数等)


我还是想知道是否有更优雅的解决方案

快速破解:将
int
标记添加到优先级规范(具有时间优先级)。
int
标记随后将被适当地转移到符号堆栈上。即(根据原问题),

这是可行的,但在处理可能大量的代币时会很混乱(开放括号, 符号、浮点数等)


我还是想知道是否有更优雅的解决方案

有一个更合适的解决方案:取消运算符优先级,并以通常的方式定义非终端符号
expr
术语
、和
因子。原因是什么?隐含乘法没有作为优先决策基础的特征标记,并且您不希望手动恢复第一组非终结符。此外,随着语法的发展,第一套语法也会随之发展

在BNF中,考虑类似于:

expr -> term | expr + term | expr - term
term -> factor | term * factor | term factor | term / factor
factor -> number | variable | ( expr )
顺便说一句,你可能想做一个额外的非终结层来表示这样一个事实,即通过邻接进行的隐式乘法通常被认为比除法具有更高的优先级,而显式乘法通常被解释为具有相同的优先级


这并不特定于任何特定的解析器生成器框架。

有一个更合适的解决方案:放弃运算符优先级,并以通常的方式定义非终端符号
expr
术语和
因子。原因是什么?隐含乘法没有作为优先决策基础的特征标记,并且您不希望手动恢复第一组非终结符。此外,随着语法的发展,第一套语法也会随之发展

在BNF中,考虑类似于:

expr -> term | expr + term | expr - term
term -> factor | term * factor | term factor | term / factor
factor -> number | variable | ( expr )
顺便说一句,你可能想做一个额外的非终结层来表示这样一个事实,即通过邻接进行的隐式乘法通常被认为比除法具有更高的优先级,而显式乘法通常被解释为具有相同的优先级


这并不特定于任何特定的解析器生成器框架。

您可以将
open
添加到优先级关联中吗?我还没有在这种情况下完成语法,但是还有其他的情况需要考虑。例如“1+2 3”=>9对“1+2*3”=>7。@JoranBeasley我已经编辑了这个问题,以使示例更简单。您能将expr添加到您的先例中吗。。。不确定那会不会破坏其他东西是的,那也不行。我认为,因为expr是一个非终端,PLY只允许您为终端指定优先级。编辑:类似的方法也能起作用-将int添加到优先级中,因为这是移位的标记。您能将
open
添加到优先级关联中吗?我还没有在这种情况下完成语法,但是还有其他的情况需要考虑。例如“1+2 3”=>9对“1+2*3”=>7。@JoranBeasley我已经编辑了这个问题,以使示例更简单。您能将expr添加到您的先例中吗。。。不确定那会不会破坏其他东西是的,那也不行。我认为,因为expr是一个非终端,PLY只允许您为终端指定优先级。编辑:类似的东西也可以工作-将int添加到优先级,因为这是移位的标记。
expr -> term | expr + term | expr - term
term -> factor | term * factor | term factor | term / factor
factor -> number | variable | ( expr )