I'm new to Irony and the whole language implementation shebang, so I've been playing around with the ExpressionEvaluator sample that comes with the Irony source, which seems to (almost) suit my needs for a project I'm working on.
However, I would like it to support booleans as well, so I've added comparison operators to the list of binary operators, as such:
BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**"
| "==" | "<=" | ">=" | "<" | ">" | "!=" | "<>"; // added comparison operators
Here's an example of what I'm trying to achieve:
x = 1
y = 2
eval = x < 2
eval2 = y < x
bool = true
bool2 = (eval == eval2)
Because of the added binary operators, it succeeds in parsing the above. However, when compiling and running the code, it fails on the last two lines.
bool = true
line fails with the message: Error: Variable true not defined. At (5:8). How do I define true and false as constants?bool2 = (eval == eval2)
line fails with the message: Error: Operator '==' is not defined for types System.Boolean and System.Boolean. At (6:15). Edit: Solved both issues, see answer below.
Ok, solved both issues. Hopefully this can be of help to others.
As far as I can understand from this Irony discussion thread, true and false constants should be treated as predefined global variables, rather than be implemented directly as part of the language. As such, I define these as globals when creating the ScriptInterpreter.
One should be aware that by doing it this way, they can be modified by the script as they are not constants, but simply global variables. There might be a better way to do this, but this will do for now:
var interpreter = new Irony.Interpreter.ScriptInterpreter(
new ExpressionEvaluatorGrammar());
interpreter.Globals["true"] = true;
interpreter.Globals["false"] = false;
interpreter.Evaluate(parsedSample);
First off, the <>
operator should come before the <
and >
operators in the binary operator rule:
BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**"
| "<>" | "==" | "<=" | ">=" | "<" | ">" | "!="; // added comparison operators
Next, I created a custom implementation of the LanguageRuntime class which implements the necessary operators.
public class CustomLanguageRuntime : LanguageRuntime
{
public CustomLanguageRuntime(LanguageData data)
: base(data)
{
}
public override void InitOperatorImplementations()
{
base.InitOperatorImplementations();
AddImplementation("<>", typeof(bool), (x, y) => (bool)x != (bool)y);
AddImplementation("!=", typeof(bool), (x, y) => (bool)x != (bool)y);
AddImplementation("==", typeof(bool), (x, y) => (bool)x == (bool)y);
}
}
In the ExpressionEvaluatorGrammar, override the CreateRuntime method to return an instance of CustomLanguageRuntime:
public override LanguageRuntime CreateRuntime(LanguageData data)
{
return new CustomLanguageRuntime(data);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With