使用Lark解析OData过滤表达式时,comparator节点未正确显示具体操作符的问题
使用Lark解析OData过滤表达式时,comparator节点未正确显示具体操作符的问题
你遇到的问题我完全理解——用Lark解析OData过滤规则时,comparator节点在语法树打印出来是空的,没能显示eq、lt这些实际匹配到的操作符。这是因为原规则里没有正确捕获这些关键字的文本内容,咱们只需要调整comparator的规则定义就能解决。
问题根源
你原来的comparator规则只是简单匹配了一系列关键字:
comparator: "eq" | "lt" | "gt" | "le" | "ge" | "ne"
Lark处理这类纯字面量选择的规则时,默认不会把匹配到的字面量文本绑定到节点上,所以在tree.pretty()的输出里,comparator节点就显示为空,没有操作符内容。
解决方案:捕获操作符文本
我们可以用Lark的$操作符,让comparator规则把匹配到的关键字文本作为Token的值保留下来。修改后的完整代码如下:
from lark import Lark odata_grammar = """ start: expr expr: or_expr or_expr: and_expr ("or" and_expr)* and_expr: comp_expr ("and" comp_expr)* comp_expr: identifier comparator value -> comp_expr # 用$操作符捕获匹配到的关键字文本,生成带值的comparator Token comparator: $("eq" | "lt" | "gt" | "le" | "ge" | "ne") value: STRING | NUMBER identifier: CNAME STRING: /'(''|[^'])*'/ DATE: /\d{4}-\d{2}-\d{2}/ NUMBER: /-?\d+(\.\d+)?/ %import common.CNAME %import common.WS %ignore WS """ parser = Lark(odata_grammar, start='start', parser='lalr') url_filter = "Name eq 'Milk' and Price lt 2.55" tree = parser.parse(url_filter) print(tree.pretty())
运行这段代码后,你就能得到期望的语法树输出:
start expr or_expr and_expr comp_expr identifier Name comparator eq value 'Milk' comp_expr identifier Price comparator lt value 2.55
另一种可选方案(保留Tree结构)
如果你后续需要扩展comparator的规则,希望它是一个包含子节点的Tree而非单个Token,也可以把规则改成这样:
comparator: ("eq" | "lt" | "gt" | "le" | "ge" | "ne") -> comparator
此时输出的语法树结构会变成这样,操作符会作为comparator节点的子节点存在:
start expr or_expr and_expr comp_expr identifier Name comparator eq value 'Milk' comp_expr identifier Price comparator lt value 2.55
这个方案同样能保留操作符信息,你可以根据自己的需求选择。
备注:内容来源于stack exchange,提问作者francollado99
相关产品推荐
相关产品推荐

