我尝试在python中创建编译器,并且我使用re
模块创建令牌。该语言与Assembly
非常相似。
几乎所有东西都在工作,但我在使用令牌方面遇到了麻烦。让我举一个例子来说明这个标记:
mov [eax], 4
mov [name],2
mov eax, [ebx]
代币:[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)
有没有办法用另一个角色替换'|'
?
答案 0 :(得分:2)
您的心痛是由捕获组内的捕获组引起的,该捕获组导致每个匹配的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]')
答案 1 :(得分:1)
我的建议是在解包时忽略该值。
comment, memory_int, memory_hex, memory_reg, _ = match.groups()
或者:
comment, memory_int, memory_hex, memory_reg = match.groups()[:3]
答案 2 :(得分:1)
问题不在于:
中的|
个字符
|(\[(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
实现同样的目标。当存在大量可能的子模式(并且它们更复杂)时,这种方法是有利的,因为否则你需要为每种可能性完整地拼出整个模式而不是利用一些他们可能具有的共性。