如何确保pyparsing中某元素拥有比其他元素更高的解析优先级?
解决pyparsing标记语法解析的两个问题
问题1:配对标签被优先匹配为独立标签
pyparsing的MatchFirst虽按顺序尝试解析,但如果独立标签的语法(比如{standalone})能匹配配对标签的起始部分({tag}),就会提前截取匹配,导致后续闭合标签无法被识别。
解决思路:
- 明确区分配对标签与独立标签的语法:配对标签是
{tag}开头、{/tag}结尾的完整结构,独立标签是无闭合的{standalone}。 - 用
Forward递归定义配对内容,确保解析器先尝试匹配完整的配对标签结构,再匹配独立标签和纯文本。
示例代码:
from pyparsing import ( Word, alphas, Forward, Literal, Group, ZeroOrMore ) # 定义标签名称规则 tag_name = Word(alphas) # 闭合标签规则 closing_tag = Literal("{/") + tag_name + Literal("}") # 递归定义配对内容 tagged_content = Forward() # 内容可包含纯文本、独立标签或嵌套配对标签 content = ZeroOrMore(tagged_content | Word(alphas + " ") | Literal("{standalone}")) # 完整配对标签结构 tagged_content << Group(Literal("{") + tag_name + Literal("}") + content + closing_tag) # 顶层解析规则 top_level = ZeroOrMore(tagged_content | Literal("{standalone}") | Word(alphas + " ")) # 测试解析 test_str = "{tag}Tagged content{/tag} plain text {standalone}{tag}Tagged again!{/tag}" result = top_level.parseString(test_str) print(result.dump())
问题2:可选属性被识别为纯文本
要支持{tag}Tagged text.|attribute|{/tag}的可选属性,必须在配对标签内部明确属性的语法结构,将属性从纯文本规则中分离,避免被当成普通文本匹配。
解决思路:
- 在配对标签的内容末尾,用
Optional包裹属性规则:Literal("|") + 属性内容 + Literal("|")。 - 调整内容结构,让解析器优先匹配属性部分,再匹配纯文本内容。
示例代码:
from pyparsing import ( Word, alphas, Forward, Literal, Group, Optional, ZeroOrMore ) tag_name = Word(alphas) closing_tag = Literal("{/") + tag_name + Literal("}") # 定义可选属性规则 attribute = Optional(Literal("|") + Word(alphas) + Literal("|")) tagged_content = Forward() # 内容 = 纯文本/嵌套标签 + 可选属性 content = ZeroOrMore(tagged_content | Word(alphas + " ")) + attribute tagged_content << Group(Literal("{") + tag_name + Literal("}") + content + closing_tag) top_level = ZeroOrMore(tagged_content | Literal("{standalone}") | Word(alphas + " ")) # 测试带属性的情况 test_str = "{tag}Tagged text.|attribute|{/tag}" result = top_level.parseString(test_str) print(result.dump())
关键优化点
- 避免直接用
MatchFirst混合配对标签与独立标签,通过递归结构让解析器优先识别完整的配对标签。 - 对于可选属性,必须在配对标签内部明确其语法位置,不能让纯文本规则覆盖属性规则。
内容的提问来源于stack exchange,提问作者Virgileo
相关产品推荐
相关产品推荐

