无需手动遍历检查,如何实现自定义编程语言的词法分析器?
自定义词法分析器的优化方案(避免大量if/else)
用正则表达式是替代手动遍历+大量if/else的绝佳方案,你可以把所有Token的匹配规则集中定义成一个列表,每个规则包含正则模式和对应的Token类型,然后通过正则引擎一次性匹配所有可能的token,彻底消除分支嵌套问题。
下面是修改后的实现代码:
import re class Token: def __init__(self, type, value): self.type = type self.value = value def __str__(self): return f'Token({self.type}, {self.value})' def __repr__(self): return self.__str__() # 定义所有Token规则,注意顺序:优先匹配更长/更特殊的规则(比如关键词要在标识符前面) TOKEN_RULES = [ # 关键词 (r'if', 'KEYWORD_IF'), (r'else', 'KEYWORD_ELSE'), (r'while', 'KEYWORD_WHILE'), (r'return', 'KEYWORD_RETURN'), # 标识符(字母开头,字母数字下划线) (r'[a-zA-Z_][a-zA-Z0-9_]*', 'IDENTIFIER'), # 数字(整数和浮点数) (r'\d+\.\d+', 'FLOAT'), (r'\d+', 'INTEGER'), # 运算符和分隔符 (r'\+', 'OP_ADD'), (r'-', 'OP_SUB'), (r'\*', 'OP_MUL'), (r'/', 'OP_DIV'), (r'=', 'OP_ASSIGN'), (r'\(', 'PAREN_OPEN'), (r'\)', 'PAREN_CLOSE'), (r'{', 'BRACE_OPEN'), (r'}', 'BRACE_CLOSE'), (r';', 'SEMICOLON'), # 空白字符(忽略) (r'\s+', None), ] # 编译正则表达式,用|连接所有模式,添加命名分组便于识别Token类型 pattern = re.compile('|'.join(f'(?P<{token_type}>{regex})' for regex, token_type in TOKEN_RULES if token_type is not None)) def lex(code): tokens = [] # 遍历所有匹配结果,自动处理位置偏移 for match in pattern.finditer(code): token_type = match.lastgroup token_value = match.group() tokens.append(Token(token_type, token_value)) return tokens
关键说明:
- 规则顺序优先级:比如
if这类关键词必须放在IDENTIFIER规则前面,否则正则会把if识别成普通标识符。 - 忽略无关Token:像空格这类不需要保留的Token,可将类型设为
None,编译时自动跳过。 - 预编译提升性能:提前编译正则表达式能避免重复解析,大幅提升多次调用
lex函数时的效率。 - 自动位置管理:
finditer会自动从上次匹配结束的位置继续扫描,不需要手动维护索引变量,彻底替代手动遍历逻辑。
你可以根据自定义语言的语法需求,随时扩展或修改TOKEN_RULES,比如添加字符串、注释的匹配规则,这种方式比手写大量if/else更易维护,性能也更稳定。
内容的提问来源于stack exchange,提问作者BrandonDev
相关产品推荐
相关产品推荐

