OR 运算符内的 OR 运算符 - 正则表达式

OR operator inside OR operator - RegEX

我正在尝试在 python 中创建一个编译器,并且我正在使用 re 模块来创建标记。语言将与 Assembly.

非常相似

几乎一切正常,但我在使用令牌时遇到问题。让我举例说明这个标记是什么:

mov [eax], 4
mov [name],2
mov eax, [ebx]

Tokens: [eax], [ebx]

我可以使用此模式找到我想要的内容:\[(eax|ebx)\] 但是当与其他模式一起使用时出现错误,我相信这是因为'|'。

SCANNER = re.compile(r"""
    ;(.)*                    # comment
    |(\[-?[0-9]+\])          # memory_int
    |(\[-?0x[0-9a-fA-F]+\])      # memory_hex
    |(\[(eax|ebx)\])             # memory access with registers
    """, re.VERBOSE)

for match in re.finditer(SCANNER, lines[i]):
            comment, memory_int, memory_hex, memory_reg = match.groups()

错误:

ValueError: too many values to unpack (expected 4)

有什么方法可以用另一个字符替换 '|' 吗?

我的建议是在解包时忽略该值。

comment, memory_int, memory_hex, memory_reg, _ = match.groups()

或者:

comment, memory_int, memory_hex, memory_reg = match.groups()[:3]

您的心痛是由捕获组中的捕获组引起的,该捕获组导致每个匹配项的 groups() 调用返回一个 5 元组。不要使用捕获组,而是尝试将 非捕获组 (语法:(?:pattern))混合到您的最终捕获组中,如下所示:

(\[(?:eax|ebx)\])

示例运行:

>>> SCANNER = re.compile(r';(.)*|(\[-?[0-9]+\])|(\[-?0x[0-9a-fA-F]+\])|(\[(?:eax|ebx)\])')
>>> next(re.finditer(SCANNER, 'mov eax, [ebx]')).groups()
(None, None, None, '[ebx]')

问题不是因为 | 个字符:

    |(\[(eax|ebx)\])             # memory access with registers

这是因为表达式的那部分定义了 两个 捕获组,一个嵌套在另一个中 — 所以 match.groups() 返回的值多于可以解包的值,例如作为第一行:

(None, None, None, '[eax]', 'eax')

避免嵌套组的一种方法是改为使用:

    |(\[eax\]|\[ebx\])          # memory access with registers

这将导致返回:

(None, None, None, '[eax]')

正如@Shashank 指出的那样,您还可以使用-捕获组(?:...) 语法来定义嵌套的可能寄存器值模式:

    |(\[(?:eax|ebx)\])          # memory access with registers

实现同样的目标。当存在更多可能的子模式(并且它们更复杂)时,这种方法是有利的,因为否则你需要为每种可能性完整地拼出整个模式,而不是利用它们可能具有的一些共性.