【发布时间】:2011-09-04 19:42:03
【问题描述】:
我正在构建一个表达式分析器,我想从中生成数据库查询代码,我已经走了很远,但我无法准确地解析 BinaryExpressions。将它们分成左右很容易,但我需要检测括号并相应地生成我的代码,我不知道如何做到这一点。
一个例子[请忽略有缺陷的逻辑:)]:
a => a.Line2 != "1" && (a.Line2 == "a" || a.Line2 != "b") && !a.Line1.EndsWith("a")
我需要检测中间的“集合”并保留它们的分组,但在解析过程中我看不到表达式与普通 BinaryExpression 的任何差异(我不想检查括号中的字符串表示)
任何帮助将不胜感激。
(我可能应该提到我正在使用 C#)
--编辑-- 我没有提到我正在使用标准的 .Net Expression 类来构建表达式(System.Linq.Expressions 命名空间)
--编辑2-- 好的,我不是将文本解析为代码,而是将代码解析为文本。所以我的 Parser 类有一个这样的方法:
void FilterWith<T>(Expression<Func<T, bool>> filterExpression);
它允许你编写这样的代码:
FilterWith<Customer>(c => c.Name =="asd" && c.Surname == "qwe");
使用标准的 .Net 类很容易解析,我的挑战是解析这个表达式:
FilterWith<Customer>(c => c.Name == "asd" && (c.Surname == "qwe" && c.Status == 1) && !c.Disabled)
我的挑战是将括号之间的表达式保持为一个集合。 .Net 类正确地将括号部分与其他部分分开,但由于括号而没有表明它是一个集合。
【问题讨论】:
-
我只是观察到这比人们想象的要难(已经做了几次),并且是许多“玩具”解析示例方便地没有解决的问题。
-
递归体面的解析器很容易上手,任何关于编译器构造的大学水平的介绍性文本都会谈论它。括号由产生式 expr = "(" + expr + ")" 处理。不过,几乎不需要重新发明这种代码。甚至 .NET 也有一个:DataTable.Compute()。
-
愿意分享您针对此问题所做的工作吗?我同意,这些例子是这个主题的基础......
-
Expression 类为您处理上述所有问题。它检索完整的、已实现的 AST。你能详细说明你的括号问题吗?或者你是用 Expression 类构建你的 AST 并且仍然手工编写词法分析器/解析器?
标签: c# .net expression-trees parentheses