Newbie Question: Reuse ExpressionEvaluatorGrammar

Aug 1, 2013 at 11:11 AM
Hi there,

I would like to use Irony to parse and evaluate boolean expression. Since the ExpressionEvaluatorGrammar from the samples is pretty much able to cover all my requirements, I'd like to re-use it.

The only thing I'd like to change for a start is to introduce new operators "AND" and "OR" to replace the operators "&&" and "||".

How would this be done?
Aug 2, 2013 at 11:18 AM
Edited Aug 2, 2013 at 11:18 AM
Hi there,

I think I've got a solution now.

First of all, I created a new Grammar and derived it from ExpressionEvaluatorGrammer. This way I am able to re-use the ExpressionEvaluator given in the samples. Further, I had to adjust the Grammar itself. I started with the ExpressionEvaluatorGrammer and removed those terminals, non-terminals, rules and operators that I do not need, and replaced the "&&" and "||" operators with the operators "AND" and "OR" respectively. And voila! That seems to do the job! Thankfully, the operators "AND" and "OR" are already supported, so I did not have to adjust anything more.

Last thing, that I wanted to adjust was to allow identifiers that start with a number. I did not manage to solve this problem yet. However, I can workaround this pretty well.

Any comments on my approach would be appreciated. Especially, if I'm doing something fundamentally wrong...
Coordinator
Aug 2, 2013 at 4:26 PM
looks ok. Except why inherit from expr ev grammar? you rebuild grammar rules from scartch as far as I understand, so you could inherit from interpreter grammar directly.
Aug 7, 2013 at 12:16 PM
Hi rivantsov!
Thank you for your comment!

The reason why I inherited from ExpressionEvaluatorGrammer is, because thus I can re-use the ExpressionEvaluator. The ExpressionEvaluator does only take an ExpressionEvaluatorGrammer as Grammar.

Might there be another evaluation framework in Irony.Net, thus I do not have to inherit from ExpressionEvaluatorGrammer?
Coordinator
Aug 8, 2013 at 1:42 AM
you can use evaluator/interpreter engine if you use interpreter AST nodes, just like ExpressionEvaluatorGrammar does. If you are inheriting from ExprEvGrammar, you still have to redefine all terms/nonterms and set some new root - no nodes in base constructor are available to you. So you can just copy ExprEvGrammar to a new file, rename it, and modify some operators to your liking
Roman
Aug 8, 2013 at 6:54 AM
Hi Roman,

thanks for your advice. I've now implemented it exactly that way. Seems to work just fine! :)
Aug 9, 2013 at 5:46 PM
Hi Roman,

I've encountered another problem. I use the IdentifierTerminal to identify variables in my boolean expressions. I'm abled to parse expressions like "A AND B" now where the values of the identifiers "A" and "B" are usually set in the ScriptApps.Globals dictionary.

This works just fine. However, I also need to parse expression like "2220 AND 2221", i.e. I need an IdentifierTerminal that can also start with a number. Is there an easy way to achieve such a behaviour? I also have to be able to assign these identifiers boolean values (true, false) in the ScriptApps.Globals.

As for now, I really don't know how to solve this problem. Is is possible to create a user defined terminal that works that way? Or should I use RegexBasedTerminal or StringLiterals. Which option would you recommend? Or is there still another (better) way?
Coordinator
Aug 11, 2013 at 5:31 AM
Edited Aug 15, 2013 at 4:42 PM
that's a strange language you have there. Do you still have 'normal' numbers? If not, you can try to add digits as StartChars to your identifier terminal definition, then I guess everything, including ints will be parsed as identifiers. More refined control is available through ValidateToken event of a Terminal - you can inspect the token right after it is scanned, and validate/change or even replace it with a different token. So you can catch Number token, and replace it with Identifier token.
Finally, there is OutputTerminal property of a terminal. It allows to replace the output terminal in scanned token - you can set 'numberTerm.OutputTerminal = identTerminal;', and then all 'numbers' would produce identifier terminals
Did not test this all, just out of my head, try these, there might some extra tweaks you have to make
Roman
Aug 11, 2013 at 9:52 AM
Hi Roman,

I do not have any normal numbers, only boolean values ("true", "false") and identifiers. Thus, adding digits to the AllStartChars property of the IdentifierTerminal already did the trick. Thanks a lot for your advice... I should have seen this earlier. :/