文法分析与解释器模式(一)

    考虑算术表达式:(5+10)*20 他具有BNF(此处已考虑结合律问题):
exp -> exp addop term|term
addop -> +|-
term -> term mulop factor|factor
mulop -> *|/
factor -> (exp)|number
提取标记(token):  exp:"exp" "addop" "term"|
addop: "+" "-"|
term: "term" "mulop" "factor"|=>"exp" "+" "-" "*" "/" "number"
mulop: "*" "/"|
factor: "number"|
然后建立他们的类型:其中“exp”是根,所以应改建立抽象类
 1abstract class Expression 
 2
 3    public abstract double Interpret(); 
 4    public abstract override bool Equals(object obj); 
 5    public abstract override int GetHashCode(); 
 6    public abstract override string ToString(); 
 7}
 
 8class Number : Expression 
 9
10    private double value; public Number() 
11    this.value = value; } 
12    public override double Interpret() 
13    return value; } 
14    public override bool Equals(object o) 
15    
16        if (o != null && o is Number) 
17        return this.value == ((Number)o).value; } 
18        return false
19    }
 
20    public override int GetHashCode() 
21    return (this.ToString()).GetHashCode(); } 
22    public override string ToString() 
23    return value.ToString(); } 
24}
 
25class Add : Expression 
26
27    private Expression left, right; public Add(Expression left, Expression right) 
28    this.left = left; this.right = right; }    
29    public override double Interpret() 
30    return left.Interpret() + right.Interpret(); } 
31    public override bool Equals(object obj) 
32    
33        if (obj != null && obj is Add) 
34        return this.left.Equals(((Add)obj).left) && this.right.Equals(((Add)obj).right); }
35        return false
36    }
 
37    public override int GetHashCode() 
38    return (this.ToString()).GetHashCode(); } 
39    public override string ToString() 
40    return "(" + left.ToString() + "+" + right.ToString() + ")"; } 
41}
 

于此建立类似的二元运算符类:dec,mul,div 有
Expression exp= new Mul(new Add(new Number(5),new Number(10)),new number(20))这里有一个刚刚接触解释器模式的朋友(就是我^_^)最迷惑的问题:到底怎么才能动态的生成 exp 的表达式?(就是如何决定什么时候new哪种类型)呵呵,其实这并不是解释器模式所做的事!至少不是它的初衷,这是分析器所做的事,因为分析器没有固定的写法,多不同类型的需求其性能差别很大,下一章针对这种表达式建立一种简单的分析器,其中用到“后缀表达式”,再下一章讨论有“变量”存在的表达式的分析和有“一元运算符”存在的表达式。 对于一些不存在次序的问题,比如转换中文数字到阿拉伯数字,可以在其“解释函数-Interpret()"中分析(递归)这样就省略了单独的分析器”其实对于算术表达式之类的较为复杂的问题的分析,在编译原理里有建立自动机的方法,然后建立状态表,这种方法速度很快,而且对于熟练者来说更为快捷,但是对于状态表化简头痛的人(比如我当年就是),还是直接的方法好一些,还有一种方式是语法分析树,这和解释器模式有异曲同工之处,树的节点就像上面建立的类,这是编译原理的初衷。就个人使用的经验而言,状态表的最大好处就是可以很容易把错误分析集中在一起,而其他两种方式则分散的多。有时间写一下关于状态表,和语法分析树的文章来做一下横向对比。

 

posted on 2007-03-27 01:01  刘霆  阅读(207)  评论(0)    收藏  举报

导航