编译原理课程实验语义分析.doc
编译原理课程实验报告班 级:软件51学 号:05161005姓 名:曹建兵提交日期:2009年3月17日联系方式:13488101375一、实验内容:实现一个程序设计语言子集的编译系统。包括:词法分析,语法分析,语义分析,符号表,出错处理等语言成分:(1) 数据类型:整型,布尔型;(2) 简单变量;(3) 算术表达式(+,×);(4) 布尔表达式(,);(5) 语句:(6) 赋值语句;(7) 分支语句(if-then, if-then-else);(8) 循环语句(while);(9) 定义语句等。输入方式:文本文件(如: .txt);二、实验过程:1. 程序设计语言的形式化描述语法分析:S->V; | If B then V; | If B then V else V; | while B do V; | int i;| bool i;(不考虑直接表达式形式)B->(B)F | i F(由于要求只有布尔型常量或变量)F-> B | B;V->i := E(赋值语句,这里i 只能是变量)E->iT | (E)(表达式语句)T->*E | +E | (表达式中间状态)2. 单词种别定义单词符号种别编号Program1True2false3bool4int5If6Then7Else8Do9While10标识符11常量12+13-14(15)16=17>18<19;20:21:=22,23*2425262728293. 语法分析程序:package compiler;import java.util.ArrayList;import java.util.HashMap;public class GrammarAnalysis private String SYM ;private ArrayList<Word> result ;private HashMap<Integer,String> reverse ;private int current = 0 ;private int row = 1 ;private int number = 1 ;private boolean flag = true ;private int count=0;private int NXQ=1;private ArrayList<SiYuanShi> output;private int totalVar=0;private HashMap<String,String> var; private boolean t=true;public GrammarAnalysis(ArrayList<Word> al)result = new ArrayList<Word>();reverse = new HashMap<Integer,String>();int i;for(i=0;i<al.size();i+)if(al.get(i).getType()=0) break;if(i=al.size()result=al;else result=null;var=new HashMap<String,String>();output=new ArrayList<SiYuanShi>();output.add(new SiYuanShi(0,"-","-","-","0");/reverse.put("1","program");/reverse.put("2","begin");/reverse.put("3","end");/reverse.put("4","var");reverse.put(2,"true");reverse.put(3,"false");reverse.put(4,"bool");reverse.put(5,"int");reverse.put(6,"if");reverse.put(7,"then");reverse.put(8,"else");reverse.put(9,"do");reverse.put(10,"while");reverse.put(11, "identifier"); /标识符reverse.put(12, "constants"); /常量reverse.put(13,"+");/reverse.put("14","-");reverse.put(15,"(");reverse.put(16,")");reverse.put(17,"=");reverse.put(18,">");reverse.put(19,"<");reverse.put(20,"");reverse.put(21,":");reverse.put(22,":=");reverse.put(23,",");/reverse.put("24", "/");reverse.put(24, "*");reverse.put(25, "");reverse.put(26, "");reverse.put(27,"");reverse.put(28,"");reverse.put(29,"");if(result!=null)ADVANCE();public void run()if(result!=null)while(current<result.size()if(flag)P();else break;if(t)System.out.println("生成四元式如下:");for(int i=1;i<output.size();i+)System.out.println(output.get(i).toString();System.out.println("符号表如下:");System.out.println(var.toString();/*结果输出*/else System.out.println("请先除去未定义符号");private int newTemp()count+;return count;private int entry(String i)return 0;private void gen(String op,String arg1 ,String arg2 ,String result)SiYuanShi a=new SiYuanShi(NXQ,op,arg1,arg2,result);/System.out.println(a.toString();output.add(a);NXQ+;private void ADVANCE()if(current<result.size()SYM = reverse.get(result.get(current).getType();current + ;number + ;private int merge(int p1,int p2)tryint i=p2;if(p1!=0&&p2!=0)while(Integer.parseInt(output.get(i).getResult()!=0)i=Integer.parseInt(output.get(i).getResult();output.get(i).setResult(Integer.toString(p1);return p2;catch(Exception e)System.out.println("Error1");return p2;private void backpatch(int p,int m)tryint i=p;int t=0;if(p!=0)while(Integer.parseInt(output.get(i).getResult()!=0)t=Integer.parseInt(output.get(i).getResult();output.get(i).setResult(Integer.toString(m);i=t;output.get(i).setResult(Integer.toString(m);catch(Exception e)System.out.println("Error2");private void ERROR(int i)t&=false;flag = flag & false ;System.out.println("判断句子以分号为标准。");System.out.print("错误位于第"+row+"句,第"+number+"个单词上。");switch(i)case 0 : System.out.println("语法错:缺少分号");break;case 1 : System.out.println("语法错:else关键字错误。");break;case 2 : System.out.println("语法错:then关键字缺失。");break;case 3 : System.out.println("语法错:限定非符号之后只能跟随左括号。");break;/case 3 : System.out.println("语法错:While-do 循环语句未结束。");break;case 4 : System.out.println("语法错:do关键字缺失。");break;case 5 : System.out.println("语法错:非法定义非变量");break;case 6 : System.out.println("语法错:非正常语句开头。");break;case 7 : System.out.println("语法错:赋值符号缺失。");break;case 8 : System.out.println("语法错:格式错误。");break;case 9 : System.out.println("语法错:丢失右括号。");break;case 10 : System.out.println("语法错:表达式格式错误。");break;case 11 : System.out.println("语法错:丢失右大括号。");break;case 12 : System.out.println("语义错:变量"+result.get(current-1).getValue()+"未定义。");break;case 13 : System.out.println("语义错:变量"+result.get(current-1).getValue()+"重定义。");break;case 14 : System.out.println("语义错:变量"+result.get(current-1).getValue()+"类型错误。");break;if(!"".equals(SYM)while( current<result.size() && !"".equals(reverse.get(result.get(current).getType()current + ;current + ;/*if("".equals(reverse.get(result.get(current).getType()current+;*/current=result.size()-1;number = 1 ;row + ;ADVANCE();/*报错处理,若出错则寻找下个句子,以分后做标记*/private int P()int truelist=0;int falselist=0;int nextlist=0;if(flag)if("if".equals(SYM)ADVANCE();Word r=B();truelist=r.getType();falselist=Integer.parseInt(r.getValue();if(flag)if("then".equals(SYM)ADVANCE();backpatch(truelist,NXQ);falselist=truelist+1;int pnext=0;if("".equals(SYM)ADVANCE();pnext=P();if("".equals(SYM) ADVANCE();number = 1 ;else ERROR(11);elseQ();if(flag)if("".equals(SYM)if(pnext!=0)nextlist=merge(falselist,pnext);else nextlist=falselist;ADVANCE();row + ;number = 1 ;/*无else的*/else if(flag)if("else".equals(SYM)int N=NXQ;gen("j","-","-","0");nextlist=merge(pnext,N);ADVANCE();backpatch(falselist,NXQ);if("".equals(SYM)ADVANCE();int a=P();if(a!=0)nextlist=merge(N,a);else nextlist=N;if("".equals(SYM) ADVANCE();number = 1 ;else ERROR(11);elseQ();if(flag)if("".equals(SYM)ADVANCE();row + ;number = 1 ;elseERROR(0);elseERROR(0);/*有else的*/elseERROR(2);/*分支语句*/else if("while".equals(SYM)int back=NXQ;ADVANCE();Word r=B();truelist=r.getType();falselist=Integer.parseInt(r.getValue();if(flag)if("do".equals(SYM)ADVANCE();backpatch(truelist,NXQ);if("".equals(SYM)ADVANCE();backpatch(P(),back);if("".equals(SYM) ADVANCE();number = 1 ;else ERROR(11);else Q();if(flag)if("".equals(SYM)ADVANCE();nextlist=falselist;gen("j","-","-",Integer.toString(back);row + ;number = 1 ;elseERROR(0);/*丢失分号*/elseERROR(4);/*循环语句*/elseif("identifier".equals(SYM)Q();if(flag)if("".equals(SYM)ADVANCE();row + ;number = 1 ;elseERROR(0);else if("bool".equals(SYM)|"int".equals(SYM)String t=SYM;ADVANCE();if("identifier".equals(SYM)if(var.get(result.get(current-1).getValue()=null)totalVar+;var.put( result.get(current-1).getValue(),t);ADVANCE();if("".equals(SYM)ADVANCE();row + ;number = 1 ;else ERROR(0);/*缺少分号*/else ERROR(13);/*变量未定义*/else ERROR(5);/*格式错误:非法定义非变量*/elseERROR(6);/*非正常语句开头*/*若已经出错则不做这部分判断*/return nextlist;private Word and(int t,int f)int m=NXQ;Word r=B();int tl=r.getType();int fl=Integer.parseInt(r.getValue();backpatch(t,m);t=tl;f=merge(f,fl);return new Word(t,Integer.toString(f);private Word or(int t,int f)int m=NXQ;Word r=B();int tl=r.getType();int fl=Integer.parseInt(r.getValue();backpatch(f,m);t=merge(t,tl);f=fl;return new Word(t,Integer.toString(f);private Word B()int truelist=0;int falselist=0;if("identifier".equals(SYM)if(var.get(result.get(current-1).getValue()!=null)String arg1=result.get(current-1).getValue();ADVANCE();if(var.get(arg1)="bool")truelist=NXQ;gen("j=",arg1,"true","0");falselist=NXQ;gen("j","-","-","0");if("".equals(SYM)ADVANCE();Word r=and(truelist,falselist);truelist=r.getType();falselist=Integer.parseInt(r.getValue();/*B->BB*/else if("".equals(SYM)ADVANCE();Word r=or(truelist,falselist);truelist=r.getType();falselist=Integer.parseInt(r.getValue();/*B->BB*/else if(">".equals(SYM)|"<".equals(SYM)if(var.get(arg1)!="int") ERROR(14);String o=SYM;ADVANCE();if("identifier".equals(SYM)|"constants".equals(SYM)if("identifier".equals(SYM)String arg2=result.get(current-1).getValue();if(var.get(arg2)=null)ERROR(12);else if(var.get(arg2)!="int") ERROR(14);truelist=NXQ;gen("j"+o,arg1,result.get(current-1).getValue(),"0");falselist=NXQ;gen("j","-","-","0");ADVANCE();/*B->iRi*/if("".equals(SYM)ADVANCE();Word r=and(truelist,falselist);truelist=r.getType();falselist=Integer.parseInt(r.getValue();/*B->BB*/else if("".equals(SYM)ADVANCE();Word r=or(truelist,falselist);truelist=r.getType();falselist=Integer.parseInt(r.getValue();/*B->BB*/else ERROR(8);/*比较符号后跟随非变量或常量*/else ERROR(14);else ERROR(12);return new Word(truelist,Integer.toString(falselist);else if("constants".equals(SYM)String arg1=result.get(current-1).getValue();ADVANCE();if(">".equals(SYM)|"<".equals(SYM)String o=SYM;ADVANCE();if("identifier".equals(SYM)|"constants".equals(SYM)if("identifier".equals(SYM)if(var.get(result.get(current-1).getValue()=null)ERROR(12);truelist=NXQ;gen("j"+o,arg1,result.get(current-1).getValue(),"0");falselist=NXQ;gen("j","-","-","0");ADVANCE();if("".equals(SYM)ADVANCE();Word r=and(truelist,falselist);truelist=r.getType();falselist=Integer.parseInt(r.getValue();/*B->BB*/else if("".equals(SYM)ADVANCE();Word r=or(truelist,falselist);truelist=r.getType();falselist=Integer.parseInt(r.getValue();/*B->BB*/return new Word(truelist,Integer.toString(falselist);else ERROR(8);else if("".equals(SYM)ADVANCE();/*非之后必须用括号将求非部分括起来*/if("(".equals(SYM)ADVANCE();Word r=B();truelist=Integer.parseInt(r.getValue();falselist=r.getType();if(")".equals(SYM)ADVANCE();if("".equals(SYM)ADVANCE();Word r2=and(truelist,falselist);truelist=r2.getType();falselist=Integer.parseInt(r2.getValue();/*B->BB*/else if("".equals(SYM)ADVANCE();Word r2=or(truelist,falselist);truelist=r2.getType();falselist=Integer.parseInt(r2.getValue();/*B->BB*/return new Word(truelist,Integer.toString(falselist);else ERROR(9);else ERROR(3);/*限定非符号之后只能跟随左括号*/else if("true".equals(SYM)|"false".equals(SYM) ADVANCE();elseERROR(6);return new Word(0,"0");private int Q()if(flag)if("identifier".equals(SYM)if(var.get(result.get(current-1).getValue()!=null)if(var.get(result.get(current-1).getValue()!="int") ERROR(14);String v=result.get(current-1).getValue();ADVANCE();if(":=".equals(SYM)ADVANCE();gen(":=",E(),"-",v);return NXQ;elseERROR(7);elseERROR(12);else ERROR(8);return 0;/*赋值语句判断*/private String E()String value=""if("identifier".equals(SYM)if(var.get(result.get(current-1).getValue()!=null)if(var.get(result.get(current-1).getValue()!="int") ERROR(14);value=result.get(current-1).getValue();ADVANCE();value=T(value);else ERROR(12);else if("constants".equals(SYM)value=result.get(current-1).getValue();ADVANCE();value=T(value);elseif("(".equals(SYM)ADVANCE();E();if(")".equals(SYM)ADVANCE();else ERROR(9);else ERROR(10);return value;private String T(String value)String n="T"+newTemp();if("+".equals(SYM)|"*".equals(SYM)String o=SYM;ADVANCE();String v2=E();gen(o,value,v2,n);else n=value;count-;return n;注:此程序由原先的语法分析程序改写,由于用递归向下的算法且实验要求的语言成分较为简单,可以直接判断句型,故可以直接编写相应的语义分析。测试类如下:package compiler;import java.util.ArrayList;public class test public static void main(String args)ArrayList<Word> m ;WordAnalysis w=new WordAnalysis();w.analysis("d:/input.txt");w.output("d:/output.txt");m=w.getResult();GrammarAnalysis g=new GrammarAnalysis(m);g.run();4. 关键算法解释:依据之前的语法分析结果,对各个语句类别做判断。首先可以得到赋值语句的FIRST只有i,分支语句 FIRST 为 if,循环语句 FIRST 为 while。由此可以得到各个语句的入口。由于赋值语句的FOLLOW 等同于表达式的 FOLLOW 为 else及分号,故此可以作为返回判断语句正确与否的标准。布尔语句的 FOLLOW 为 then及do。而其余语句的FOLLOW 均为分号。至此,可以准确的将各个语句区别开来,并分析语句是否正确。用一个ArrayList来存储将要产生的四元式序列,NXQ是将要产生的下个四元式的编号。Gen()函数依据传入的参数生成对应