在Irony中定义常量和操作符

本文关键字:操作符 常量 定义 Irony | 更新日期: 2023-09-27 18:04:09

我对Irony和整个语言实现都不熟悉,所以我一直在使用Irony源代码附带的ExpressionEvaluator示例,它似乎(几乎)适合我正在进行的项目的需要。

但是,我希望它也支持布尔值,所以我在二进制操作符列表中添加了比较操作符,如下所示:

BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**"
  | "==" | "<=" | ">=" | "<" | ">" | "!=" | "<>"; // added comparison operators

下面是我想要实现的一个例子:

x = 1
y = 2
eval = x < 2
eval2 = y < x
bool = true
bool2 = (eval == eval2)

由于添加了二进制操作符,因此可以成功解析上述内容。但是,在编译和运行代码时,它在最后两行失败。

  1. bool = true行失败,提示信息:Error: Variable true not defined。(8)。如何定义truefalse作为常量?
  2. bool2 = (eval == eval2)行失败,出现以下消息:错误:Operator '=='未为System类型定义。Boolean和System.Boolean。(15)。

编辑:两个问题都解决了,见下面的答案

在Irony中定义常量和操作符

好了,两个问题都解决了。希望能对别人有所帮助。

一号

据我所知,从这个Irony讨论线程中,truefalse常量应该被视为预定义的全局变量,而不是直接作为语言的一部分实现。因此,我在创建ScriptInterpreter时将它们定义为全局变量。

应该注意,通过这种方式,它们可以被脚本修改,因为它们不是常量,而是简单的全局变量。可能有更好的方法来做这件事,但现在就这样做:

var interpreter = new Irony.Interpreter.ScriptInterpreter(
  new ExpressionEvaluatorGrammar());
interpreter.Globals["true"] = true;
interpreter.Globals["false"] = false;
interpreter.Evaluate(parsedSample);
2

问题

首先,在二进制运算符规则中,<>运算符应该位于<>运算符之前:

BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**"
  | "<>" | "==" | "<=" | ">=" | "<" | ">" | "!="; // added comparison operators
接下来,我创建了一个LanguageRuntime类的自定义实现,它实现了必要的操作符。
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);
  }
}

ExpressionEvaluatorGrammar中,重写CreateRuntime方法以返回CustomLanguageRuntime:

public override LanguageRuntime CreateRuntime(LanguageData data)
{
  return new CustomLanguageRuntime(data);
}