【发布时间】:2015-09-03 22:44:51
【问题描述】:
我正在尝试为简单的语言解释器设计一个abstract syntax tree。为了避免在评估期间进行强制转换,我尝试使用泛型(此技术在here 中有更全面的描述)。
我的基本类型是Exp<T>,我使用IExpression 作为分组接口(见下文——这将是评估返回的内容)。
public interface IExpression
{
}
public abstract class Exp<T> : IExpression
{
public abstract U Accept<U>(IVisitor<U> visitor);
public IExpression Eval()
{
return this.Accept<IExpression>(new EvaluationVisitor());
}
}
public class Lit : Exp<int>
{
public int value;
public Lit(int value)
{
this.value = value;
}
public override U Accept<U>(IVisitor<U> visitor)
{
return visitor.Visit(this);
}
}
public class Plus : Exp<int>
{
public Exp<int> e1, e2;
public Plus(Exp<int> e1, Exp<int> e2)
{
this.e1 = e1;
this.e2 = e2;
}
public override U Accept<U>(IVisitor<U> visitor)
{
return visitor.Visit(this);
}
}
我曾希望我现在可以使用visitor design pattern 来评估树。然而,Plus 表达式的求值会产生丑陋的演员表。有什么办法可以避免吗?
public interface IVisitor<T>
{
T Visit(Lit exp);
T Visit(Plus exp);
}
public class EvaluationVisitor : IVisitor<IExpression>
{
public IExpression Visit(Lit exp)
{
return exp;
}
public IExpression Visit(Plus exp)
{
var v1 = (Lit)exp.e1.Accept<IExpression>(this);
var v2 = (Lit)exp.e2.Accept<IExpression>(this);
return new Lit(v1.value + v2.value);
}
}
【问题讨论】:
-
我是否认为
Exp是Expression的缩写,而Lit是Literal的缩写? -
@ClickRick 是的,您是正确的(此代码是从 Microsoft 文章链接中复制和修改的)。
标签: c# generics interpreter visitor-pattern