有。pyparsing 和 lark 是处理这类需求的主流选择。
pyparsing 更偏向于“构建”,适合逐步定义复杂的语法规则。它的优势在于与Python代码高度集成,写起来像在搭积木,调试直观。对于搜索引擎语法这种中等复杂度的DSL很合适。
lark 更偏向于“声明”,你需要用类似EBNF的语法写好整个文法,它来生成解析器。功能更强大,能处理更复杂的语言,但学习曲线稍陡。
如果语法比较简单(比如就是“关键词 AND/OR/NOT 关键词”这种),直接用pyparsing手搓一个最快最灵活。如果语法非常复杂或需要严谨的定义,lark更合适。
示例:用 pyparsing 解析基础搜索语法
from pyparsing import Word, alphas, oneOf, Group, infixNotation, opAssoc
# 定义基础元素
keyword = Word(alphas + '_').setName('keyword')
AND, OR, NOT = map(oneOf, ['AND', 'OR', 'NOT'])
# 定义搜索表达式语法(支持括号和 NOT/AND/OR 优先级)
search_expr = infixNotation(
keyword,
[
(NOT, 1, opAssoc.RIGHT), # NOT 是右结合单目运算符
(AND, 2, opAssoc.LEFT), # AND 优先级高于 OR
(OR, 2, opAssoc.LEFT),
]
)
# 测试
query = 'python AND (fast OR simple) NOT java'
parsed = search_expr.parseString(query, parseAll=True)
print(parsed.asList())
# 输出:[[['python', 'AND', [['fast', 'OR', 'simple']]], 'NOT', 'java']]
这个解析树你可以轻松转换成SQL的WHERE子句或者Elasticsearch的bool查询。
总结:中等复杂度用 pyparsing,复杂严谨用 lark。