Python PLY解析器-将矩阵解析为列表列表

Python PLY解析器-将矩阵解析为列表列表,python,parsing,matrix,ply,Python,Parsing,Matrix,Ply,我正在使用PLY创建一个计算器,我希望能够解析如下矩阵:[[11,1];[22,4];[13,3]]到一个列表列表中,以提供给我自己的矩阵类进行进一步计算 这是到目前为止我的代码。这里的三个重要功能是p_逗号,p_分号和p_括号。其余部分纯粹用于计算和优先级 def p_操作(p): 表达方式:第六 第六:第五 第五:第四 第四:第三 第三:第二 第二:第一 第一:数字 第一:想象一下 """ p[0]=p[1] def p_逗号(p): “第六:第六”,“第五” 如果存在(p[1],请列出):

我正在使用PLY创建一个计算器,我希望能够解析如下矩阵:
[[11,1];[22,4];[13,3]]
到一个列表列表中,以提供给我自己的矩阵类进行进一步计算

这是到目前为止我的代码。这里的三个重要功能是
p_逗号
p_分号
p_括号
。其余部分纯粹用于计算和优先级

def p_操作(p):
表达方式:第六
第六:第五
第五:第四
第四:第三
第三:第二
第二:第一
第一:数字
第一:想象一下
"""
p[0]=p[1]
def p_逗号(p):
“第六:第六”,“第五”
如果存在(p[1],请列出):
p[1]。追加(p[3])
p[0]=p[1]
其他:
p[0]=[p[1],p[3]]
def p_分号(p):
“第六:第六”,“第五”
如果存在(p[1],请列出):
p[1]。追加(p[3])
p[0]=p[1]
其他:
p[0]=[p[1],p[3]]
def p_plus(p):
“第五:第五”+“第四”
p[0]=p[1]+p[3]
def p_减(p):
“第五:第五”-“第四”
p[0]=p[1]-p[3]
def p_隐式时间(p):
“第四:第四秒”
p[0]=p[1]*p[2]
def p_时间(p):
“第四:第四”*“第三”
p[0]=p[1]*p[3]
def p_除法(p):
“第四:第四”/“第三”
p[0]=p[1]/p[3]
def p_模(p):
“第四:第四“%”第三”
p[0]=p[1]%p[3]
def p_地板分割(p):
“第四层:第四层第三层”
p[0]=p[1]//p[3]
def p_一元数减(p):
“第三名:-“第三名”
p[0]=-p[2]
def p_电源(p):
“”“第二:第一个”“^”“第三个”“”
p[0]=p[1]**p[3]
定义参数(p):
“第一个:”(“表达式”)“”“
p[0]=p[2]
def p_brack(p):
“”“第一个:['表达式']'”“”
如果类型(p[2][0])==列表:
p[0]=[p[2]]
其他:
p[0]=矩阵。矩阵(p[2])
这里的问题是,我的解决方案不能很好地处理一些棘手的东西,比如:
[[1]]
,而且即使没有括号,解析也能工作,这不是我想要的

最重要的是,我坚信有一种更好的方法可以找到


有人能帮我吗?

不是所有的东西都是
表达式

特别是,在矩阵括号内的是一列用分号分隔的行,每行是一列用逗号分隔的表达式。您的语法应该反映这一简单事实,而不是将这些列表集中到
表达式中。否则,您会发现它在上下文之外接受分号和逗号分隔的列表。我想这就是你问题的基础

另外,正如我想我们已经讨论过的,如果你的动作函数需要做一个测试,它可能表明你没有利用你的语法。这里的情况确实如此

让我们从顶部开始。矩阵是用分号分隔的行列表,用方括号括起来。换言之:

matrix     : '[' row_list ']'
row_list   : row
           | row_list ';' row
行是以逗号分隔的值列表(目前为表达式),用方括号括起来:

row        : '[' value_list ']'
value_list : expression
           | value_list ',' expression
现在,我们可以编写动作函数了。这些也很简单

def p_list_first(p):
    """value_list : expression
       row_list   : row
    """
    p[0] = [ p[1] ]


def p_list_extend(p):
    """value_list : value_list ','  expression
       row_list   : row_list ';' row
    """
    p[0] = p[1]
    p[0].append(p[3])
    # Another way of writing this action:
    #     p[0] = p[1] + [ p[3] ]
    # That's cleaner, in that it doesn't modify the previous value.
    # But it's less efficient because it creates a new list every time.

def p_row(p):
    """row       : '[' value_list ']' """
    p[0] = p[2]

def p_matrix(p):
    """matrix    : '[' row_list ']' """
    p[0] = Matrix.Matrix(p[2])
这将替换逗号、分号、方括号和第六条规则。唯一剩下的就是先添加
矩阵
。(另外,
p_行
操作与您的
p_行
操作相同,因此如果您愿意,可以将它们组合在一起。)

两个外卖:

  • 如果你能用自己的母语描述语法,你就可以为它编写语法。语法只是表达同一事物的一种更正式的方式。(至少,一旦你不再被递归吓倒,这也不复杂:“列表是一个值,或者你可以通过添加逗号和值来扩展列表”应该很容易理解。)

  • 语法应该能够解析输入,而不必测试之前解析的内容


  • 第二个原则不是绝对的。例如,在这种情况下,您可能希望禁止嵌套
    矩阵
    元素中的
    中的值。你可以把它写成语法,但它会涉及大量令人讨厌的重复;实际上,
    行列表
    操作验证它们处理的
    表达式
    不是一个
    矩阵

    并不是所有的东西都是一个
    表达式
    :-)

    特别是,在矩阵括号内的是一列用分号分隔的行,每行是一列用逗号分隔的表达式。您的语法应该反映这一简单事实,而不是将这些列表集中到
    表达式中。否则,您会发现它在上下文之外接受分号和逗号分隔的列表。我想这就是你问题的基础

    另外,正如我想我们已经讨论过的,如果你的动作函数需要做一个测试,它可能表明你没有利用你的语法。这里的情况确实如此

    让我们从顶部开始。矩阵是用分号分隔的行列表,用方括号括起来。换言之:

    matrix     : '[' row_list ']'
    row_list   : row
               | row_list ';' row
    
    行是以逗号分隔的值列表(目前为表达式),用方括号括起来:

    row        : '[' value_list ']'
    value_list : expression
               | value_list ',' expression
    
    现在,我们可以编写动作函数了。这些也很简单

    def p_list_first(p):
        """value_list : expression
           row_list   : row
        """
        p[0] = [ p[1] ]
    
    
    def p_list_extend(p):
        """value_list : value_list ','  expression
           row_list   : row_list ';' row
        """
        p[0] = p[1]
        p[0].append(p[3])
        # Another way of writing this action:
        #     p[0] = p[1] + [ p[3] ]
        # That's cleaner, in that it doesn't modify the previous value.
        # But it's less efficient because it creates a new list every time.
    
    def p_row(p):
        """row       : '[' value_list ']' """
        p[0] = p[2]
    
    def p_matrix(p):
        """matrix    : '[' row_list ']' """
        p[0] = Matrix.Matrix(p[2])
    
    这将替换逗号、分号、方括号和第六条规则。唯一剩下的就是先添加
    矩阵
    。(另外,
    p_行
    操作与您的
    p_行
    操作相同,因此如果您愿意,可以将它们组合在一起。)

    两个外卖:

  • 如果你能用自己的母语描述语法,你就可以为它编写语法。语法只是表达同一事物的一种更正式的方式。(至少,一旦你不再被递归吓倒,这也不复杂:“一个列表就是一个值,或者你可以扩展一个列表