pyparsing 如何让 SUB 语法优先于模型名匹配?
数据小陈
结论
scanString() 会从左到右查找匹配项。modelExtract1 | modelExtract2 中的 | 是 MatchFirst,只决定同一起始位置上备选项的匹配顺序。它不会让扫描器跳过已经匹配成功的 B2 X=2,转而优先选择后面的 SUB [mname2]。
可以在第一种语法前加一个零宽负向前瞻:如果从当前扫描位置到本行末尾还能找到 SUB [,就不匹配普通模型名语法。这样,第二行会跳过 B2,再由 modelExtract2 提取 mname2。
示例
from pyparsing import (
Combine,
Literal,
OneOrMore,
Regex,
Word,
alphanums,
alphas,
nums,
)
cdl = """
A1 B1 C1 mname1 X=1 Y=2
A2 B2 X=2 SUB [mname2] C2
"""
ident = Word(alphas, alphanums)
intgr = Word(nums)
paramAssign = Combine(ident + Literal("=") + intgr)
# 从当前扫描位置开始,如果本行后面还有 SUB [,则不允许匹配普通模型名。
no_later_sub = ~Regex(r".*\bSUB\s*\[")
modelExtract1 = (
no_later_sub
+ ident("modelName")
+ OneOrMore(paramAssign)
)
modelExtract2 = (
Regex(r"\bSUB\s*\[\s*")
+ ident("modelName")
)
modelExtract = modelExtract1 | modelExtract2
for line in cdl.splitlines():
for match, start, stop in modelExtract.scanString(line):
print(match.modelName)
输出:
mname1
mname2
这里的 ~Regex(...) 是零宽负向前瞻,只检查当前位置后面的文本,不会消耗字符。扫描第二行到 B2 时,前瞻发现后面还有 SUB [,所以第一种语法匹配失败。扫描继续到 SUB 后,第二种语法匹配并提取 mname2。
适用条件
这种写法假设 SUB [ 是区分两种语法的标记,并且每次只扫描一行。如果 CDL 语法允许注释或字符串中出现 SUB [,简单的正则前瞻也可能将其识别为标记。此时应先按语言规则排除注释和字符串,或解析整行结构后再判断。示例中的标识符和参数规则也经过简化,需要根据实际 CDL 定义补全。
备注:内容仅供参考。
