1、词法分析器说明文档指数 E|e 都可,考虑过/的注释词法规则 关键字: 本程序识别的关键字为 int real if then else while,仅当单独出现以上标识符时识别为关键字,对于 inta,ifb 等识别为标识符。 标识符: 一个标识符必须以字母开头,后面接上字母和数字,否则产生报错信息,程 序停止词法分析,输出相关错误信息如: 正确:abc, abc123, 等错误:123abc 操作符: 本程序识别的操作符为: + - / * = = = !=当 !后跟其它字符时产生出错信息。 分隔符: 本程序识别的分隔符为: ( ) ; 数字: 识别的数字遵循以下文法规则:digit 0
2、| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9intnumber digit+ exponent (E|e) ( + | - | ) digit+ fraction . digit+realnumber digit+ exponent | digit+ fraction ( exponent | )例如:正确: 123, 123E2, 123.3123.3E4 错误: 123A,123E, 123.A . 123.3A, 123.3E 注释符: 注释部分以 / 本程序对其不进行识别. 引入文件 为 #include形式,其他做出错处理设计思路本程序采用字符流形式读入文件
3、,识别其中的关键字,标识符,分隔符,注释符,引入文件声明等.设计了一个灵活的读取字符的自动机为如下图所显示读入文件的第一个字符回车空格操作符+ - * 直接识别为操作符. 操作符号 ! = 进行跳转看是否是=; !=; = = ;操作符/ 进行跳转看是否是/ ( ); 直接识别为分隔符根据 isletter()函数判断是否读到字符,若是,进行跳转,以此识别出标识符串和关键字 根据 isdigit()函数判断是否读到数字,若是,进行跳转,以此识别出整个数字状态 0 判断读入字符类型,进行状态跳转,并对行号和列号做相应调整转入相应状态,进行相关操作根据 install()函数按格式将符号表输出。根
4、据 nextChar()函数读取下一个将要读取的字符。根据 iskey()函数判断是否读到规定的关键字。据 analyzer()函数判断各个字符各属各家。词法分析部分的 Lexical 类如下:public class Lexical private int rnum;/行号private int rpos;/列号private static ArrayList symbolTable;private StreamReader br;private char c;private char bC;private int state;private String str;public Lexica
5、l(StreamReader br)symbolTable = new ArrayList();this.br=br;c= ;bC= ;state = 0;rnum=1;rpos=0;str=“;public ArrayList getSymbolTable()c = nextChar();state = 0;analyzer();return symbolTable;private void analyzer()bool isRunning=true;while(isRunning)switch (state)case 0:if(c= ) /空格else if(c=t) /tabrpos+=
6、3;else if(int)c=13) /空格else if(int)c=10) /回车rpos = 0;rnum+;else if(c=) /结束符return;else if(c=+) /操作符+install(“操作符“,“+“,rpos,rnum); else if(c=-) /操作符-install(“操作符“,“-“,rpos,rnum);else if(c=/) /操作符/state = 1;else if(c=*) /操作符*install(“操作符“,“*“,rpos,rnum);else if(c=) /操作符= state = 2;else if(c=) /操作符stat
7、e = 4;else if(c=!) /操作符!state = 5;else if(c=) /分隔符install(“分隔符“,“,rpos,rnum);else if(c=) /分隔符install(“分隔符“,“,rpos,rnum);else if(c=() /分隔符(install(“分隔符“,“(“,rpos,rnum);else if(c=) /分隔符)install(“分隔符“,“)“,rpos,rnum);else if(c=;) /分隔符;install(“分隔符“,“;“,rpos,rnum);else if(int)c=65535)isRunning=false;else
8、 if(isLetter(c) /读到了字符bC = c;state = 6;else if(isDigit(c) /读到了数字符bC = c;str=“;state = 7;else if(c=#)state=13;else state=0;isRunning=false;fail(0);c = nextChar();break;case 1:if(c=/) /表示注释后面的东西,不读它while(int)c!=10)c = nextChar();rpos=0; /从下一行开始rnum+;c = nextChar();state = 0;else state = 0; / 下一个不是/, 后
9、退一步到state=0install(“操作符“,“/“,rpos-1,rnum);break;case 2:if(c=) /表示操作符=state = 0;install(“操作符“,“=“,rpos-1,rnum);c = nextChar();else state = 0;install(“操作符“,“=“,rpos-1,rnum);break;case 3:if(c=) /表示操作符=state = 0;install(“操作符“,“=“,rpos-1,rnum);c = nextChar();else state = 0;install(“操作符“,“,rpos-1,rnum);br
10、eak;case 5:if(c=) / 表示操作符!=state = 0;install(“操作符“,“!=“,rpos-1,rnum);c = nextChar();else state = 0;isRunning=false;fail(2);break;/*/读入标识符,后面是 数字符和字母才是对的/*case 6: String id = “+bC;while(isLetter(c)|isDigit(c)id+=c;c = nextChar();if(isKey(id)install(“关键字“,id,rpos-id.Length,rnum);elseinstall(“标识符“,id,r
11、pos-id.Length,rnum);state = 0;break;/*/读入数字符,后面是 数字符(循环); .(转状态);E(转状态)/*case 7: str+=bC; while(isDigit(c) str+=c;c=nextChar();if(c=.) state=8;c=nextChar(); else if(c=E) state=10;c=nextChar();/需要判断是否是 11w等else if(isLetter(c)state = 0;isRunning=false;fail(1);else state = 0;install(“数字符“,str,rpos-str.
12、Length,rnum);break;/*/ “ .“ 后面跟的字符,除了数字符其它都出错/*case 8: str+=.;if(isDigit(c)state = 9;str+=c;c=nextChar();elsestate = 0;isRunning=false;fail(1);break;/*/ “.数字符“ 后面字符,可以是数字符或者是E(需要加错误提示,当不是空格而是其他字母时候)/*case 9:while(isDigit(c)str+=c;c=nextChar();if(c=E)state = 10;c=nextChar();/需要判断是否是 11w 等else if(isLe
13、tter(c)state = 0;isRunning=false;fail(1);elsestate = 0;install(“数字符“,str,rpos-str.Length,rnum);break;/*/ “E“ 后面字符, “+“;“-“;“数字符“ 都是对的,其他都是错的/*case 10:str+=E;if(c=+|c=-)state=11;str+=c;c=nextChar();else if(isDigit(c)state=12;str+=c;c=nextChar();elsestate=0;isRunning=false;fail(1);break;/*/ “+“ “-“ 后面
14、字符, 数字符是对的.其他都是错的/*case 11:if(isDigit(c)state=12;str+=c;c=nextChar();elsestate = 0;isRunning=false;fail(1);break;/*/ “E数字符“ 后面字符,只有数字符是对的/*case 12:while(isDigit(c)str+=c;c=nextChar();if(isLetter(c)state = 0;isRunning=false;fail(1);install(“数字符“,str,rpos-str.Length,rnum);state=0;break;case 13: /声明部分i
15、d =“#“;while(isLetter(c)id+=c;c = nextChar();if(id=“#include“install(“文件引入“,id,rpos-id.Length,rnum);c = nextChar();elsefail(3);elsefail(0);state = 0;break; private void fail(int i) string typeerror=“;switch(i)case 0:typeerror=“输入非法字符错误“;break;case 1:typeerror=“操作符错误“;break;case 2:typeerror=“数字符错误“;b
16、reak;case 3:typeerror=“声明错误“;break;Console.WriteLine(typeerror+“,位置“);private char nextChar()char t;rpos+;if(br.Peek() = -1)br.Close();return ;t= (char) br.Read();return t;private void install(String tType,String aValue,int rpos,int rnum)ArrayList tokenArray = new ArrayList();tokenArray.Add(tType);t
17、okenArray.Add(aValue);tokenArray.Add(“);symbolTable.Add(tokenArray);str=“;private bool isLetter(char checkChar)int checkInt = (int)checkChar;if(checkInt=97)|(checkInt=65return false;private bool isKey(String checkKey)if(checkKey.Equals(“if“)|checkKey.Equals(“then“)|checkKey.Equals(“else“)|checkKey.E
18、quals(“int“)|checkKey.Equals(“real“)|checkKey.Equals(“while“)return true;return false;程序输入输出举例:输出格式为 : 记号 字符 1:#include#includemain() a=1;if(a=1)then a=2.3;else a=3;2:main() string 1a=aa;if(a=1)then a=2.3;else a=3;由词法规则可得 ”1a” 以数字开头,为错误的标识符,应产生报错信息,所以输出如下3:main() int a=123Ea;if(a=1)then a=2.3;else a=3;由词法规则可得 ”123Ea” 为错误的数字表示形式,应产生报错信息,所以输出如下4:main() int a=123Ea;if(a!1)then a=2.3;else a=3;由词法规则可得 ”a!1” 为错误的操作符使用形式,应为”a!=1” , 所以应产生报错信息,输出如下