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

How to organize multiple functions returning same token with PLY?

假设我只想拥有一个 PLY 代币 - 'INTEGER'。但是我希望能够在不同的基础上解析典型的 C 风格文字,所以我希望能够有效地解析像 0b10(或 0B10)、010 这样的字符串。 100x10(或 0X10)。因为我真的不在乎 "input format" 是什么,所以我只想在 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,因为这会使解析器不必要地复杂化(或者我可能想多了?)。

我想知道是否有比在四个 "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.