At 05:17 PM 1/27/2005, Scott Deboy wrote:
If we are going to provide a separate parser and lexer, we need to use tools that generate the lexer and parser from definition files - we shouldn't write this code by hand, even if it is trivial.
While it's simple to write a lexer and parser, it's simpler to add new tokens to a lexer definition file and actions to a parser definition file.
As a side benefit, as I mentioned previously, sister projects could take the lexer and parser input files and change the parser actions to generate a syntactically and semantically identical expression language - where folks would have to write this themselves.
Even if it's trivial, writing this by hand is error prone compared to the parser-generator alternative.
You are assuming that parser-generators are easy to work with, which is not necessarily the case. We now have code that works and that can be customized with ease. Honest! Once the basic parser was in place, It took me just a few hours to add support for expressions involving event message, level and logger name. This morning the code could only handle expressions containing 'true' and 'false'. See also accompanying test cases.
On re-using rules:
Each rule has two static getRule methods - one that takes a stack and one that takes the expected number of params - we can definitely reuse the Rule classes.
Here's a bit of clarification on my use of postfix to create rules.
The postfix output is used to create the context stack that's passed in to rules. ExpressionRule's PostFixExpressionCompiler.compileExpression returns a single rule that is evaluated - this rule could be an AndRule, orRule, notRule, or just an equalsRule, etc.
In your example the OrRule would short-circuit after the first rule evaluation.
Here's the contents of OrRule's evaluate method.
public boolean evaluate(LoggingEvent event) { return (rule1.evaluate(event) || rule2.evaluate(event)); }
To summarize my usually long-winded email:
- I STRONGLY suggest we implement this expression language using a lexer and parser generator.
Unless I am missing something, it should only take a few minutes to migrate the code which currently references Rule to reference LBELEvaluator instead. The usage format is quite simple.
LBELEventEvaluator evaluator = new LBELEventEvaluator(some expression); evaluator.evaluate(a LoggingEvent);
For example.
LBELEventEvaluator evaluator = new LBELEventEvaluator("level < INFO AND message = 'hello');
An evaluator can be used to successively evaluate one or more events.
I think the only missing part for chainsaw is that LBELEventEvaluator is not currently serializable. I'll fix that tomorrow. From chainsaw's point of view, is there anything else missing ?
- There's nothing preventing us from reusing the Rule classes - they provide static getRule methods with the needed parameters
The LBEL parser generates Node objects which as the name indicates are nodes in a syntax tree. The syntax tree is binary. Thus, Node object have references to their children. Moreover, leaf nodes always contain Comparator instances.
As a side note, we should not create yet another acronym as a package name - could we move what you've just committed to o.a.l.expression?
I don't mind at all. Note that the classes in the lbel package will probably will not be directly reference by the end-user. (She will deal mostly with expression strings.)
Scott
-- Ceki G�lc�
The complete log4j manual: http://www.qos.ch/log4j/
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
