在Irony中定义常量和运算符

ber*_*hof 4 c# irony boolean-expression expression-evaluation

我是Irony和整个语言实现shebang的新手,所以我一直在玩Irony源附带的ExpressionEvaluator示例,这似乎(几乎)适合我正在进行的项目的需求.

但是,我希望它也支持布尔值,所以我将比较运算符添加到二元运算符列表中,如下所示:

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

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

x = 1
y = 2
eval = x < 2
eval2 = y < x
bool = true
bool2 = (eval == eval2)
Run Code Online (Sandbox Code Playgroud)

由于添加了二元运算符,它成功解析了上述内容.但是,在编译和运行代码时,它在最后两行失败.

  1. bool = true行失败并显示以下消息:错误:变量true未定义.在(5:8).如何将truefalse定义为常量?
  2. bool2 = (eval == eval2)行失败并显示以下消息:错误:未为类型System.Boolean和System.Boolean定义Operator'=='.在(6:15).

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

ber*_*hof 9

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

问题1

至于我可以理解这种反讽的讨论话题,常量应被视为预定义的全局变量,而不是直接实现为语言的一部分.因此,我在创建ScriptInterpreter时将它们定义为全局变量.

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

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

问题2

首先,<>运算符应该在二元运算符规则中的<and >运算符之前:

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

接下来,我创建了一个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);
  }
}
Run Code Online (Sandbox Code Playgroud)

ExpressionEvaluatorGrammar,覆盖CreateRuntime方法返回的实例CustomLanguageRuntime:

public override LanguageRuntime CreateRuntime(LanguageData data)
{
  return new CustomLanguageRuntime(data);
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这为我节省了很多时间.如果有其他人遇到此问题,则AddImplementation()不再存在.相反,我使用了AddBinary(),例如:AddBinary(ExpressionType.NotEqual,typeof(DateTime),(x,y)=>(DateTime)x!=(DateTime)y); (2认同)