如何组织多个函数与PLY返回相同的标记?

时间:2017-04-16 19:55:26

标签: python ply

假设我想只有一个PLY令牌 - 'INTEGER'。但是我希望能够在不同的基础上解析典型的C风格文字,因此我希望能够有效地解析0b10(或0B10),010之类的字符串, 100x10(或0X10)。因为我并不关心“输入格式”是什么,所以我想在Python中将值设为int

然而,在单个函数中处理所有这4个案例并不是特别方便...首先或所有正则表达式都变得很长:r'0[0-7]+|0[bB][01]+|0[xX][0-9a-fA-F]+|[0-9]'。但这是一个较小的问题 - 函数的代码必须处理大量的组合才能知道使用哪个库,因为实际上以0开头的字符串只能是单个字符,所以检查更多的情况(下一个)字符xXbB)也必须考虑长度。

所以我更喜欢将它作为4个单独的函数,但都返回相同的'INTEGER'类型的令牌。我宁愿不介绍BINARY_INTEGEROCTAL_INTEGERDECIMAL_INTEGERHEXADECIMAL_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

1 个答案:

答案 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.