正则表达式是构建简易词法分析器最直接、最实用的工具,适合教学、脚本解析或轻量级语言处理;需明确词法单元类型并按优先级顺序匹配,用re.match锚定开头,关键字后处理,注意浮点数和回溯陷阱。

正则表达式是构建简易词法分析器最直接、最实用的工具。它不依赖复杂框架,几条清晰的匹配规则就能覆盖标识符、数字、运算符等基本词法单元,适合教学、脚本解析或轻量级语言处理。
明确要识别的词法单元类型
先列出目标语言中需要区分的基本记号(token),每种对应一条正则规则。常见类型包括:
-
标识符:以字母或下划线开头,后跟字母、数字或下划线,如
count、_temp1→ 正则:[a-zA-Z_][a-zA-Z0-9_]* -
整数:一串连续数字,如
42、0→ 正则:[0-9]+ -
运算符:如
+、-、*、/、=→ 正则:[+\-*/=](注意-放在字符类开头或结尾避免被误认为范围符) -
空白符:空格、制表符、换行 → 正则:
\s+,用于跳过,不生成 token -
括号与分隔符:如
(、)、;→ 可单独写为字面量,如[()]或逐个匹配
按优先级顺序逐一尝试匹配
词法分析是贪心过程:从输入字符串开头出发,用所有规则从左到右试匹配,取最长匹配且最先成功的规则(通常需按语义重要性或长度排序,比如把 == 放在 = 前面)。
- 例如,对输入
"== 42",应先尝试==(正则==),再试=,否则会错误切分为两个单等号 - 实际代码中,可将规则按列表存储,遍历执行
regex.match(input, pos),保留匹配长度最大的结果 - 匹配成功后,推进读取位置(
pos += matched_length),继续处理剩余部分
封装成可复用的 tokenizer 函数
核心逻辑简洁:维护当前位置、输入字符串、结果 token 列表;循环尝试匹配,跳过空白,遇到无法匹配的字符报错或跳过。
- Python 示例片段:
tokens = []<br>pos = 0<br>while pos matched = False<br> for pattern, token_type in rules:<br> m = re.match(pattern, text[pos:])<br> if m:<br> value = m.group(0)<br> if token_type != 'WHITESPACE':<br> tokens.append({'type': token_type, 'value': value})<br> pos += len(value)<br> matched = True<br> break<br> if not matched:<br> raise SyntaxError(f"Unexpected character at position {pos}: '{text[pos]}'") - 规则列表示例:
rules = [<br> (r'[a-zA-Z_][a-zA-Z0-9_]*', 'IDENTIFIER'),<br> (r'[0-9]+', 'NUMBER'),<br> (r'==|!=|=', 'OPERATOR'),<br> (r'[+\-*/=]', 'OPERATOR'),<br> (r'\s+', 'WHITESPACE')<br>]
注意边界与常见陷阱
看似简单,但几个细节决定是否健壮:
-
匹配必须锚定开头:使用
re.match()(而非re.search()),确保从当前读取位置开始匹配,避免跨词捕获 -
关键字需后处理:先统一匹配标识符,再查表判断是否为
if、while等保留字,避免正则穷举导致规则膨胀 -
浮点数需更严谨:
[0-9]+\.[0-9]+会漏掉.5或3.,推荐用(\d+\.\d*|\.\d+|\d+)([eE][+-]?\d+)? -
避免回溯灾难:嵌套量词如
(a+)+b在坏输入下可能指数级慢,简易 lexer 中尽量用原子结构,不写过度通用的模式











