列出 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' 项还包含数字和其他未显示的表达式。
我的理解是底部规则应该递归运行以允许列表行为,而中间规则应该允许空列表。我对自己缺少的东西感到困惑。
在这个归约函数中:
def p_lisp_list(p):
"lisp : LPAR array RPAR"
p[0] = [p[1]]
您正在将结果 p[0]
设置为 LPAR
的语义值,因为 LPAR
是 right-hand 一侧的第一个语法符号。那当然是不正确的;您想要将结果设置为 p[2]
,即 array
符号的值。 (此外,括号可能是错误的。请参阅下面的第 3 点。)
在这个归约函数中:
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。
假设以上两个问题已经解决。现在,考虑这个缩减函数
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])
我正在尝试在 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' 项还包含数字和其他未显示的表达式。
我的理解是底部规则应该递归运行以允许列表行为,而中间规则应该允许空列表。我对自己缺少的东西感到困惑。
在这个归约函数中:
def p_lisp_list(p): "lisp : LPAR array RPAR" p[0] = [p[1]]
您正在将结果
p[0]
设置为LPAR
的语义值,因为LPAR
是 right-hand 一侧的第一个语法符号。那当然是不正确的;您想要将结果设置为p[2]
,即array
符号的值。 (此外,括号可能是错误的。请参阅下面的第 3 点。)在这个归约函数中:
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。假设以上两个问题已经解决。现在,考虑这个缩减函数
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])