想了解更多内容,移步至编译原理专栏
==========================2021.12.22 更新===================================
整理了一下代码,同步到了gitee
https://gitee.com/godelgnis/lrparserhttps://gitee.com/godelgnis/lrparser
--------------------------------------------------分割线---------------------------------------------------------------------
终于做完了这学期最后的综合实验,不想再动了,参考附录C4.5做的,主要是能够识别和分析多条赋值语句,循环语句,和判断语句。参照书本上的C代码(书上的代码有几个地方是错的,估计是排版的时候没检查出来)改写 成java版本的,主要修改的还是IrParser.java这个类,毕竟改动的是语法规则,词法分析器还是跟之前的差不多,修改一下种别码就可以了。
其实我这个分析器主要的一个思想就是,先分析处理源程序(识别单词,处理换行注释等),把单词先抽取出来放到一个表里面。然后再进行语法和语义的处理,语法分析时,先从main()这个固定的入口进行分析,然后再进入语句块分析,语句块里面再进行语句串的分析,只能识别三种语法规则,即赋值语句,判断语句,循环语句。
判读语句和循环语句需要进行条件判断,一旦进入了条件判断,就意味着之后的程序运行会出现分支,即跳转,所以需要记录好条件为真的入口和条件为假的入口,因为,当分析器分析这个地方时,已经生成了相应的四元式,当分析器继续分析时才可以将出口位置回填到入口位置(我是这么理解的,可能有误。。)在我的程序,我主要是用了statement()方法中用一个tempFalse来记录条件为假的入口的位置,程序的递归返回时,才能将正确的出口位置回填到入口位置,如果不记录的话就会出错。至于条件为真的入口位置可以很快就回填,因为条件判断完之后从condition()中返回就能立刻把出口回填。
可以这样子理解,进入条件判断时,
记录条件为真的入口位置trueConditon=当前四元式下标,
生成条件为真的四元式(goto 关系运算符,参数1,参数2,0)
条件为假的四元式下标falseCondition = 等于当前四元式下标
生成条件为假的四元式(goto , , ,0),四元式中的0就是待回填的,
生成四元式之后,列表下标是自动往后移动的。
然后从方法中返回之后,就可以将当前的四元式下标回填给条件为真的入口,成为它的跳转位置
然后后面基本就是,记录位置——递归——返回位置——回填,基本上就是这样了,知道程序出错或者正常结束运行。
C语言里的递归真的很有毒,不出错的情况下没什么感觉,一旦出错能把人烦死。。。。。。
各位读者如果如果有兴趣的话可以参考一下我的代码,建议在我的基础之上进行修改,完成属于自己的一个小型语言分析器
由于我做的这个分析器知识一个简单的分析器,所以只能识别部分错误,在某些测试代码下会出现死循环,抛出异常等等
所以最后,强烈建议读者能够自行修改并完成自己的分析器。以下是测试说明
测试数据:
main()
{
//A处缺赋值号,D处缺逗号错误
A 2 + 2; B=4; C=10; D=100
A= q +(q*j+ 0)* 2-V*c;
while (a<0){
while(C>0){
a=1;
}
//缺左括号和左花括号
if k=j)
C = p;
}
//缺右括号
while(c<d {
a = 0;
}
}
}
#
程序运行效果如下:
代码清单
public class Word {
private int typenum; //种别码
private String word; //扫描得到的词
public int getTypenum() {
return typenum;
}
public void setTypenum(int typenum) {
this.typenum = typenum;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
}
package codescanner;
public class CodeScanner {
private static String _KEY_WORD_END = "end string of string";
private int charNum = 0;
private Word word;
private char[] input = new char[255];
private char[] token = new char[255];
private int p_input=0;
private int p_token=0;
private char ch;
private String[] rwtab &