修改 PLY 解析器的堆栈
Modify the stack of a PLY parser
正在尝试修改已推送到 PLY/Yacc 解析器堆栈的值。我在 python 上使用 ply
3.
基本上我想在使用令牌 SWAP
时反转前两个值。
假设我们有这个堆栈:
1
、2
、3
、4
、SWAP
我需要将它减少到:
1
、2
、4
、3
你写到p[0]
的值会被压入栈中,但是我怎样才能压入一个以上的值呢?
# this fails because it consume two values and pushes only one
# results into: `1`, `2`, `4`
def p_swap(p):
'value : value value SWAP'
p[0] = p[2]
# this was just a try... fails as well
def p_swap(p):
'value : value value SWAP'
p[0] = p[2]
p[1] = p[1]
# this locked as a good idea since consumes only only value and modify the second in place
# it fails because the stack (negative indexes) are immutable:
# https://github.com/dabeaz/ply/blob/master/ply/yacc.py#L234
# results into: `1`, `2`, `3`, `3`
def p_swap(p):
'value : value SWAP'
p[0] = p[-1]
p[-1] = p[1] # this is a NOP
p
is an instance of this class
我想它被设计成不可变的,以强制以某种方式(正确的方式)完成解析,但我想念它:修改堆栈或设计解析器的正确方法是什么?
听起来您正在尝试创建一个像 Forth 或 Joy 这样的 stack-based language。如果是这样,您就不需要 bottom-up 解析器,并且您不应该对 bottom-up parser-generator 无法按您希望的方式工作感到惊讶。
Stack-based 语言大多只是标记流。每个令牌都有某种叠加效应,它们只是按顺序应用;除此之外通常很少或没有句法结构。因此,这些语言实际上并没有被解析;充其量,它们被标记化了。
大多数 stack-based 语言包含某种不严格符合上述要求的嵌套控制结构(但不是全部;例如,参见 Postscript)。但即使是这些也非常简单,不需要真正的解析器。
当然,没有什么能阻止您使用生成的解析器来解析普通语言。但是如果你这样做了,你当然不应该期望能够访问解析器的内部数据结构。解析器使用解析器堆栈的方式可能并不十分明显,但肯定不能受到干扰。如果你想实现一个stack-based语言解释器,你需要使用你自己的值栈。 (或堆栈;许多 stack-based 语言有几个不同的堆栈,每个堆栈都有自己的语义。)
正在尝试修改已推送到 PLY/Yacc 解析器堆栈的值。我在 python 上使用 ply
3.
基本上我想在使用令牌 SWAP
时反转前两个值。
假设我们有这个堆栈:
1
、2
、3
、4
、SWAP
我需要将它减少到:
1
、2
、4
、3
你写到p[0]
的值会被压入栈中,但是我怎样才能压入一个以上的值呢?
# this fails because it consume two values and pushes only one
# results into: `1`, `2`, `4`
def p_swap(p):
'value : value value SWAP'
p[0] = p[2]
# this was just a try... fails as well
def p_swap(p):
'value : value value SWAP'
p[0] = p[2]
p[1] = p[1]
# this locked as a good idea since consumes only only value and modify the second in place
# it fails because the stack (negative indexes) are immutable:
# https://github.com/dabeaz/ply/blob/master/ply/yacc.py#L234
# results into: `1`, `2`, `3`, `3`
def p_swap(p):
'value : value SWAP'
p[0] = p[-1]
p[-1] = p[1] # this is a NOP
p
is an instance of this class
我想它被设计成不可变的,以强制以某种方式(正确的方式)完成解析,但我想念它:修改堆栈或设计解析器的正确方法是什么?
听起来您正在尝试创建一个像 Forth 或 Joy 这样的 stack-based language。如果是这样,您就不需要 bottom-up 解析器,并且您不应该对 bottom-up parser-generator 无法按您希望的方式工作感到惊讶。
Stack-based 语言大多只是标记流。每个令牌都有某种叠加效应,它们只是按顺序应用;除此之外通常很少或没有句法结构。因此,这些语言实际上并没有被解析;充其量,它们被标记化了。
大多数 stack-based 语言包含某种不严格符合上述要求的嵌套控制结构(但不是全部;例如,参见 Postscript)。但即使是这些也非常简单,不需要真正的解析器。
当然,没有什么能阻止您使用生成的解析器来解析普通语言。但是如果你这样做了,你当然不应该期望能够访问解析器的内部数据结构。解析器使用解析器堆栈的方式可能并不十分明显,但肯定不能受到干扰。如果你想实现一个stack-based语言解释器,你需要使用你自己的值栈。 (或堆栈;许多 stack-based 语言有几个不同的堆栈,每个堆栈都有自己的语义。)