Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining constants and operators in Irony

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.

  1. The bool = true line fails with the message: Error: Variable true not defined. At (5:8). How do I define true and false as constants?
  2. The 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.

like image 975
bernhof Avatar asked Jan 19 '23 02:01

bernhof


1 Answers

Ok, solved both issues. Hopefully this can be of help to others.

Issue 1

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);

Issue 2

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);
}
like image 134
bernhof Avatar answered Jan 28 '23 10:01

bernhof