如何在PLY中将列表元素指定为Token的规格
高效定义PLY词法分析器中的Token集合
嘿,我刚好之前用PLY折腾过类似的小型英语子集解析器,太懂你这种一个个写Token规则的麻烦了!针对你提到的名词列表、不同类型动词的Token定义,这里有几个高效的实现方案:
1. 动态生成正则规则,批量匹配同类Token
不用给每个名词/动词单独写def t_XXX(t): ...,我们可以把词集合转成正则的选择分支,用一个规则就能覆盖所有同类型的词:
import ply.lex as lex # 先定义你的词集合,后续维护只需要改这里! NOUNS = ["Harry", "Ron", "Hermione", "Draco", "Snape"] INTRANSITIVE_VERBS = ["sleeps", "runs", "laughs"] TRANSITIVE_VERBS = ["sees", "likes", "hates"] DATIVE_VERBS = ["gives", "shows", "tells"] # 定义所有需要的Token类型 tokens = ( 'NOUN', 'INTRANSITIVE_VERB', 'TRANSITIVE_VERB', 'DATIVE_VERB' ) # 动态生成名词的正则匹配式 def t_NOUN(t): r'(' + '|'.join(NOUNS) + r')' return t # 不及物动词的规则 def t_INTRANSITIVE_VERB(t): r'(' + '|'.join(INTRANSITIVE_VERBS) + r')' return t # 及物动词规则 def t_TRANSITIVE_VERB(t): r'(' + '|'.join(TRANSITIVE_VERBS) + r')' return t # 与格动词规则 def t_DATIVE_VERB(t): r'(' + '|'.join(DATIVE_VERBS) + r')' return t # 别忘了定义忽略空白字符的规则 def t_ignore(t): r'\s+' pass
2. 用装饰器简化写法(可选)
PLY支持@lex.token()装饰器,结合动态正则能让代码更简洁:
@lex.token(r'(' + '|'.join(NOUNS) + r')') def t_NOUN(t): return t
3. 优先级与边界处理小技巧
- 如果你的词集合里有长短重叠的词(比如假设你有"run"和"runs"),一定要把更长的词放在正则的前面,比如
r'runs|run',避免短词被优先匹配。不过你的专有名词和动词应该不存在这个问题,放心用。 - 如果需要支持大小写不敏感的输入(比如"harry"也能被识别),可以在Token函数里统一转换大小写:
def t_NOUN(t): r'(' + '|'.join(NOUNS) + r')' t.value = t.value.lower() # 统一转成小写,方便语法分析阶段处理 return t
4. 扩展维护更轻松
以后要加新的名词或者动词,只需要修改顶部的NOUNS、INTRANSITIVE_VERBS等列表,不用动Token规则的代码,维护成本直接降下来了!
内容的提问来源于stack exchange,提问作者vball
相关产品推荐
相关产品推荐

