我是Irony的新手和整个语言实现shebang,所以我一直在玩ExpressionEvaluator附带的Irony source样本,这似乎(几乎)适合我正在进行的项目的需要。
但是,我希望它也支持布尔值,所以我将比较运算符添加到二元运算符列表中,如下:
BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**"
| "==" | "<=" | ">=" | "<" | ">" | "!=" | "<>"; // added comparison operators
以下是我想要实现的一个例子:
x = 1
y = 2
eval = x < 2
eval2 = y < x
bool = true
bool2 = (eval == eval2)
由于添加了二元运算符,它成功解析了上述内容。但是,在编译和运行代码时,它在最后两行失败。
bool = true
行失败并显示以下消息:错误:变量true未定义。在(5:8)。如何将 true 和 false 定义为常量?bool2 = (eval == eval2)
行失败,并显示以下消息:错误:未对类型System.Boolean和System.Boolean定义运算符'=='。在(6:15)。 修改:解决了这两个问题,请参阅下面的答案。
答案 0 :(得分:9)
好的,解决了这两个问题。希望这对其他人有帮助。
据我所知this Irony discussion thread, true 和 false 常量应视为预定义的全局变量,而不是直接作为语言。因此,我在创建 ScriptInterpreter 时将它们定义为全局变量。
应该意识到,通过这种方式,它们可以被脚本修改,因为它们不是常量,而只是全局变量。可能有更好的方法可以做到这一点,但现在这样做:
var interpreter = new Irony.Interpreter.ScriptInterpreter(
new ExpressionEvaluatorGrammar());
interpreter.Globals["true"] = true;
interpreter.Globals["false"] = false;
interpreter.Evaluate(parsedSample);
首先,<>
运算符应位于二元运算符规则中的<
和>
运算符之前:
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);
}