我想模拟编译器的扫描程序和解析器阶段。我设法使用
拆分 re.findall(r"[\w,.,\"]+",file)
如果文件包含:
INT x;
READ x;
x := (x+1)*x;
WRITE x
结果是:
['INT', 'x', 'READ', 'x', 'x', 'x', '1', 'x', 'WRITE', 'x']
然而我需要;和+和()等...我如何分割单词但保留字符?谢谢
这应该是输出:
['INT', 'x', ';', 'READ', 'x', ';', 'x', ':=', '(','x', '+', '1', ')', '*', 'x', ';', 'WRITE', 'x']
答案 0 :(得分:1)
最简单(几乎正确)的代码应该是:
import re
source = """
INT x;
READ x;
x := (x+1)*x;
WRITE x
"""
print(re.findall(r'\w+|[^\s\w]+', source)
输出:
['INT', 'x', ';', 'READ', 'x', ';', 'x', ':=', '(', 'x', '+', '1', ')*', 'x', ';', 'WRITE', 'x']
但是,只要您没有明确定义您的语言的所有运算符,就没有解决方案来区分正确的多字符运算符(例如:=
)与单字符运算符的连接序列(例如)*
。因此,使用真正的解析器对任务来说会更容易。
正则表达式基本上搜索两种类型的序列:一个或多个连续的字母数字字符(由\w+
表示)或一个或多个非字母数字和非空格的连续字符(表示由[^\w\s]+
)。
答案 1 :(得分:0)
这是我能想到的最好的:
import re
test_str = "INT x; READ x; x := (x+1)*x; WRITE x"
test_reg_pat = "([A-Z]+)|([x])|([^ ])"
test_list = re.findall(test_reg_pat,test_str)
ret_list = []
for sub_list in test_list:
for elem in sub_list:
if elem != '':
ret_list.append(elem)
print(ret_list)
ret_list
的输出为:
['INT', 'x', ';', 'READ', 'x', ';', 'x', ':', '=', '(', 'x', '+', '1', ')', '*', 'x', ';', 'WRITE', 'x']
可能有一种方法可以完全使用正则表达式执行此操作,而无需将test_list
处理为ret_list
我是如何做到的。最大的问题是将re.findall()
与组(我在我的模式中使用的)一起使用的是它将返回一个子列表,其中包含与该组匹配的任何内容,如下所示:
[('INT', '', ''), ('', 'x', ''), ('', '', ';'), ('READ', '', ''), ('', 'x', ''), ('', '', ';'), ('', 'x', ''), ('', '', ':'), ('', '', '='), ('', '', '('), ('', 'x', ''), ('', '', '+'), ('', '', '1'), ('', '', ')'), ('', '', '*'), ('', 'x', ''), ('', '', ';'), ('WRITE', '', ''), ('', 'x', '')]
希望它有所帮助 - 如果您需要纯正的正则表达式让我知道,我可以看看我是否可以解决问题!
答案 2 :(得分:0)
您可以尝试非常明确地说明您想要匹配的内容,其中input
是您的输入字符串:
re.findall(r"\w+|:=|[\w()*+;]", input)
这应该提供您正在寻找的确切输出:
['INT', 'x', ';', 'READ', 'x', ';', 'x', ':=', '(', 'x', '+', '1', ')', '*', 'x', ';', 'WRITE', 'x']