学习DP--3.状态模式
我们编译实验课要做编译器,第一步要先完成词法分析器。
题目大概如下:
PL/0语言建立一个词法分程序GETSYM(函数),把关键字、算符、界符称为语言固有的单词,标识符、常量称为用户自定义的单词。为此设置三个全程量:SYM,ID,NUM 。
SYM:存放每个单词的类别,为内部编码的表示形式。
ID:存放用户所定义的标识符的值,即标识符字符串的机内表示。
NUM:存放用户定义的数。
GETSYM要完成的任务:
1。滤掉单词间的空格。
2。识别关键字,用查关键字表的方法识别。当单词是关键字时,将对应的类别放在SYM中。如IF的类别为IFSYM,THEN的类别为THENSYM。
3。识别标识符,标识符的类别为IDENT,IDENT放在SYM中,标识符本身的值放在ID中。关键字或标识符的最大长度是10。
4。拼数,将数的类别NUMBER放在SYM中,数本身的值放在NUM中。
拼由两个字符组成的运算符,如:>=、<=等等,识别后将类别存放在SYM中。
5。打印源程序,边读入字符边打印。
我本来想用过程式的方法来解决这个问题的,结果发现条件分支太多,难以编写,难以理解。后来想到用自动机的方法来解决这个问题。自动机的话,大概就是状态的转换是吧,编译课没有听太懂。于是,想到用状态模式来诠释这个自动机。
首先是:State这样的抽象类,表示自动机的状态。如图:
他有很多的代理方法,这里忽略了。最最总要的是他有一个抽象方法handle(char,Controler),这个方法可以处理一个字符,即处理参数char。另外一个参数Controler则是State的上下文。
State有一些子类,代表了自动机的各种状态,并实现了相应的handle方法。如图:
其中CharacterState的代码如下,override了handle方法。
/** * 2012 2012-10-29 下午9:01:54 * Compiler getsym.state */package getsym.state;import getsym.Controler;/** * @author zhenzxie.iteye.com * @version 1.0 * @since 1.0 */public class CharacterState extends State {@Override public void handle(char c, Controler controler) {if (isCharacter(c)||(isNumber(c)&&isCurrentWordNotEmpty())) {this.append2CurrentWord(c);} else {this.dealCurrentWord();this.clearCurrentWord();State targetState = null;if (isOperator(c)) {targetState = Controler.operatState;} else if (isSeperator(c)) {targetState = Controler.separatorState;}targetState.handle(c, controler);controler.changeState(targetState);}}private void dealCurrentWord() {String word = this.getCurrentWord();if (isKeyWord(word))this.addAKeyWord(word);// 关键字elsethis.addAId(word);// 标识符}}/** * 2012 2012-10-29 上午11:16:57 * Compiler getsym */package getsym;import getsym.state.CharacterState;import getsym.state.NumberState;import getsym.state.OperatorState;import getsym.state.SeparatorState;import getsym.state.StartState;import getsym.state.State;/** * @author zhenzxie.iteye.com * @version 1.0 * @since 1.0 */public class Controler {public static State startState = new StartState();public static State characterState = new CharacterState();public static State numberState = new NumberState();public static State operatState = new OperatorState();public static State separatorState = new SeparatorState();public void deal(char c){currentState.handle(c, this);}public void changeState(State state) {Controler.currentState = state;}private static State currentState = startState;}