jdc*_*589 6 java lambda parsing list-comprehension
我在今年的假日季节感到无聊,并随机决定为Java编写一个简单的列表理解/过滤库(我知道那里有一些很棒的,我只是想把它自己写得很糟糕).
对于此列表:
LinkedList<Person> list = new LinkedList<Person>();
list.add(new Person("Jack", 20));
list.add(new Person("Liz", 58));
list.add(new Person("Bob", 33));
Run Code Online (Sandbox Code Playgroud)
语法是:
Iterable<Person> filtered = Query.from(list).where(
Condition.ensure("Age", Op.GreaterEqual, 21)
.and(Condition.ensure("Age", Op.LessEqual, 50));
Run Code Online (Sandbox Code Playgroud)
我知道它的丑陋,但如果我使用静态导入并使用更短的方法名称,它变得非常简洁.
以下语法是最终目标:
Iterable<Person> list2 = Query.from(list).where("x=> x.Age >= 21 & x.Age <= 50");
Run Code Online (Sandbox Code Playgroud)
显然,表达式解析不是我最强的区域,我在解析嵌套/多个条件时遇到了麻烦.有人知道我可能会发现有用的一些资源/文献吗?
我现在只有从String lambda语法中成功解析出单个条件表达式:"x=> x.Name == Jack".我的底层Expression结构非常可靠,可以轻松处理任何数量的嵌套,问题只是从字符串解析表达式.
谢谢
只是为了解决问题,这里有一点了解幕后的表达结构是如何工作的(显然我可以在下面的例子中指定'op.GreaterEqual'等...但我想证明它是如何灵活的到任何数量的嵌套):
Condition minAge1 = Condition.ensure("Age", Op.Equal, 20);
Condition minAge2 = Condition.ensure("Age", Op.Greater, 20);
Expression minAge = new Expression(minAge1, Express.Or, minAge2);
Expression maxAge = Condition.ensure("Age", Op.Equal, 50).or(Condition.ensure("Age", Op.Less, 50));
Expression ageExpression = new Expression(minAge, Express.And, maxAge);
Condition randomException = Condition.ensure("Name", Op.Equal, "Liz");
Expression expressionFinal = new Expression(ageExpression, Express.Or, randomException);
Run Code Online (Sandbox Code Playgroud)
基本上你想要的是表达式的递归下降解析器.这是编译器理论中的一个主题,所以任何关于编译器的书都将涵盖这个主题.在正式的语法术语中,它看起来像这样:
condition : orAtom ('||' orAtom)+ ;
orAtom : atom ('&&' atom)+ ;
atom : '(' condition ')'
| expression ;
expression : value OPER value ;
value : VARIABLE | LITERAL '
VARIABLE : (LETTER | '_') (LETTER | DIGIT | '_')* ;
LITERAL : NUMBER
| STRING ;
NUMBER : '-'? DIGIT+ ('.' DIGIT+)? ;
STRING : '"' . CHAR* . '"' '
CHAR : ('\\' | '\"' | .) + ;
LETTER : 'a'..'z' | 'A'..'Z' ;
DIGIT : '0'..'9' ;
OPER : '>' | '>=' | '<' | '<=' | '=' | '!=' ;
Run Code Online (Sandbox Code Playgroud)
上面的语法(大部分)是ANTLR形式,就像我最熟悉的那样.
在处理解析时,解析布尔或算术表达式是一个经典的介绍性主题,因此您应该能够找到大量有关它的文献.如果你想追求ANTLR(因为你正在使用Java),我强烈建议你阅读The Definitive ANTLR Reference:Building Domain-Specific Languages.
如果所有这些看起来有点过分而且有点太多可以接受,那么你可能是对的.入门是一个艰难的话题.
你有一个替代方案是不创建一个任意的字符串表达式,而是使用一个流畅的接口(就像你正在做的那样):
List results = from(source)
.where(var("x").greaterThan(25), var("x").lessThan(50))
.select("field1", "field2");
Run Code Online (Sandbox Code Playgroud)
因为这是在代码中声明表达式树并且应该更容易实现.
| 归档时间: |
|
| 查看次数: |
2422 次 |
| 最近记录: |