在 Irony 中定义常量和运算符

发布于 2024-11-27 20:39:19 字数 1096 浏览 3 评论 0原文

我是 Irony 和整个语言实现 shebang 的新手,所以我一直在玩 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 行失败并显示消息:错误:变量 true 未定义。在 (5:8)。 如何将 truefalse 定义为常量?
  2. bool2 = (eval == eval2) 行失败并显示消息:错误:未为 System.Boolean 和 System.Boolean 类型定义运算符“==”。在 (6:15)。

编辑:解决了这两个问题,请参阅下面的答案。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

逆光下的微笑 2024-12-04 20:39:19

好的,解决了这两个问题。希望这对其他人有帮助。

问题 1

据我从这个讽刺讨论线程中了解到,正确false 常量应被视为预定义的全局变量,而不是直接作为语言的一部分实现。因此,我在创建 ScriptInterpreter 时将它们定义为全局变量。

人们应该意识到,通过这样做,它们可以被脚本修改,因为它们不是常量,而只是全局变量。可能有更好的方法来做到这一点,但现在就这样:

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

问题 2

首先, <> 运算符应该位于 < 和 <二元运算符规则中的 code>> 运算符:

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

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文