如何使用 PLY 组织返回相同标记的多个函数?
How to organize multiple functions returning same token with PLY?
假设我只想拥有一个 PLY 代币 - 'INTEGER'
。但是我希望能够在不同的基础上解析典型的 C 风格文字,所以我希望能够有效地解析像 0b10
(或 0B10
)、010
这样的字符串。 10
和 0x10
(或 0X10
)。因为我真的不在乎 "input format" 是什么,所以我只想在 Python.
中使用 int
的值
然而,在单个函数中处理所有这 4 种情况并不是特别方便...首先或所有正则表达式变得很长:r'0[0-7]+|0[bB][01]+|0[xX][0-9a-fA-F]+|[0-9]'
。但这是一个较小的问题 - 函数的代码必须处理多种组合才能知道使用哪个基数,因为实际上以 0
开头的字符串只能是单个字符,因此检查更多情况(下一个字符是 x
、X
、b
或 B
) 还必须考虑长度。
所以我更愿意将其作为 4 个独立的函数,但都返回相同的 'INTEGER'
类型的令牌。我宁愿不引入 BINARY_INTEGER
、OCTAL_INTEGER
、DECIMAL_INTEGER
和 HEXADECIMAL_INTEGER
,因为这会使解析器不必要地复杂化(或者我可能想多了?)。
我想知道是否有比在四个 "free" 函数中强制 token.type
成为 'INTEGER'
更聪明的方法?除了:
def t_BINARY_LITERAL(t):
r'0[bB][01]+'
t.value = int(t.value[2:], 2)
t.type = 'INTEGER'
return t
def t_OCTAL_LITERAL(t):
r'0[0-7]+'
t.value = int(t.value[1:], 8)
t.type = 'INTEGER'
return t
def t_DECIMAL_LITERAL(t):
r'[0-9]+'
t.value = int(t.value, 10)
t.type = 'INTEGER'
return t
def t_HEXADECIMAL_LITERAL(t):
r'0[xX][0-9a-fA-F]+'
t.value = int(t.value[2:], 16)
t.type = 'INTEGER'
return t
明确设置t.type
是正确的解决方案。如果觉得多余,可以重构为转换函数:
def send_int(t, offset, base):
t.value = int(t.value[offset:], base)
t.type = 'INTEGER'
return t
def t_HEXADECIMAL_LITERAL(t):
r'0[xX][0-9a-fA-F]+'
return send_int(t, 2, 16)
# etc.
假设我只想拥有一个 PLY 代币 - 'INTEGER'
。但是我希望能够在不同的基础上解析典型的 C 风格文字,所以我希望能够有效地解析像 0b10
(或 0B10
)、010
这样的字符串。 10
和 0x10
(或 0X10
)。因为我真的不在乎 "input format" 是什么,所以我只想在 Python.
int
的值
然而,在单个函数中处理所有这 4 种情况并不是特别方便...首先或所有正则表达式变得很长:r'0[0-7]+|0[bB][01]+|0[xX][0-9a-fA-F]+|[0-9]'
。但这是一个较小的问题 - 函数的代码必须处理多种组合才能知道使用哪个基数,因为实际上以 0
开头的字符串只能是单个字符,因此检查更多情况(下一个字符是 x
、X
、b
或 B
) 还必须考虑长度。
所以我更愿意将其作为 4 个独立的函数,但都返回相同的 'INTEGER'
类型的令牌。我宁愿不引入 BINARY_INTEGER
、OCTAL_INTEGER
、DECIMAL_INTEGER
和 HEXADECIMAL_INTEGER
,因为这会使解析器不必要地复杂化(或者我可能想多了?)。
我想知道是否有比在四个 "free" 函数中强制 token.type
成为 'INTEGER'
更聪明的方法?除了:
def t_BINARY_LITERAL(t):
r'0[bB][01]+'
t.value = int(t.value[2:], 2)
t.type = 'INTEGER'
return t
def t_OCTAL_LITERAL(t):
r'0[0-7]+'
t.value = int(t.value[1:], 8)
t.type = 'INTEGER'
return t
def t_DECIMAL_LITERAL(t):
r'[0-9]+'
t.value = int(t.value, 10)
t.type = 'INTEGER'
return t
def t_HEXADECIMAL_LITERAL(t):
r'0[xX][0-9a-fA-F]+'
t.value = int(t.value[2:], 16)
t.type = 'INTEGER'
return t
明确设置t.type
是正确的解决方案。如果觉得多余,可以重构为转换函数:
def send_int(t, offset, base):
t.value = int(t.value[offset:], base)
t.type = 'INTEGER'
return t
def t_HEXADECIMAL_LITERAL(t):
r'0[xX][0-9a-fA-F]+'
return send_int(t, 2, 16)
# etc.