假设我想只有一个PLY令牌 - 'INTEGER'
。但是我希望能够在不同的基础上解析典型的C风格文字,因此我希望能够有效地解析0b10
(或0B10
),010
之类的字符串, 10
和0x10
(或0X10
)。因为我并不关心“输入格式”是什么,所以我想在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
,因为这会不必要地使解析器复杂化(或者我可能会过度思考?)。
我想知道是否有更聪明的事情,而不仅仅是强迫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
答案 0 :(得分:2)
明确设置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.