列出 PLY 中的实现?

List implementation in PLY?

我正在尝试在 PLY python 库的解析器中实现一个列表。这是我到目前为止的代码-

def p_lisp_list(p):
    "lisp : LPAR array RPAR"
    p[0] = [p[1]]


def p_array_1(p):
    "array : "
    p[0] = [p[1]]


def p_array_2(p):
    "array : lisp array"
    p[0] = [p[1], p[2]]

'lisp' 项还包含数字和其他未显示的表达式。

我的理解是底部规则应该递归运行以允许列表行为,而中间规则应该允许空列表。我对自己缺少的东西感到困惑。

  1. 在这个归约函数中:

    def p_lisp_list(p):
        "lisp : LPAR array RPAR"
        p[0] = [p[1]]
    

    您正在将结果 p[0] 设置为 LPAR 的语义值,因为 LPAR 是 right-hand 一侧的第一个语法符号。那当然是不正确的;您想要将结果设置为 p[2],即 array 符号的值。 (此外,括号可能是错误的。请参阅下面的第 3 点。)

  2. 在这个归约函数中:

    def p_array_1(p):
        "array : "
        p[0] = [p[1]]
    

    没有p[1]。参数p“是包含相应规则中每个文法符号值的序列”(来自the Ply manual, section 6.1。在这种情况下,相应的规则是array : ,它没有文法符号在right-hand这边。所以只有p[0]是有效的,它指的是减少的结果。空规则的常见操作是p[0] = [],但当然还有许多其他可能性。正如我们将看到的,这条规则的结果基本上就是您将用来表示 LISP 的 NIL(如果您要创建 LISP-like 列表)和 [] 是个不错的选择。但实际上你最好使用单个可区分的不可变对象,也许是空元组 (),这样就不可能修改 NIL。

  3. 假设以上两个问题已经解决。现在,考虑这个缩减函数

    def p_array_2(p):
        "array : lisp array"
        p[0] = [p[1], p[2]]
    

    您尝试用另一个元素扩展数组的位置。由于您正在使用 right-recursion(有时有用,但不是很频繁),因此正在构建数组 right-to-left:

    [  lisp1 lisp2 lisp3 lisp4       ]
    
                                ----- => []                  (from p_array_1)
                          lisp  array
                         ------------ => [lisp4, []]         (from p_array_2)
                   lisp  array
                   ----------- => [lisp3, [lisp4, []]]       (from p_array_2)
             lisp  array
             ----------- => [lisp2, [lisp3, [lisp4, []]]]    (from p_array_2)
       lisp  array
       ----------- => [lisp1, [lisp2, [lisp3, [lisp4, []]]]] (from p_array_2) 
    [  array                         ]
    -------- => [[lisp1, [lisp2, [lisp3, [lisp4, []]]]]]     (from p_lisp_list) 
    

如果你试图模拟 LISP 的 cons 节点,那几乎是正确的,除了被 [=27= 嵌入到一个额外的 single-element 列表中] 规则(应该只是复制值而不是将其包含在 one-element 列表中)。

但是,如果您尝试创建一个 Python-like 数组,您可能需要 [lisp1, lisp2, lisp3, lisp4]。您当然可以使用此语法实现这一点,但最简单的解决方案是使用 left-recursion 并按逻辑顺序构建数组:

def p_lisp_list:
    ''' lisp : '[' list ']' '''
    p[0] = p[2]

def p_list_empty:
    ''' list : '''
    p[0] = []

def p_list_append:
    ''' list : list lisp '''
    p[0] = p[1]
    p[0].append(p[2])