此次也是课题需要,才写了这么一个项目,编译原理课你懂的.
由于个人比较喜欢Java,因此写了一个Java版本简易的词法分析器.(也是因为Java对数组的使用比较随意)
注意:没有出错处理,如 9int,或是 int 23等等一系列错误是检测不出来的.
实验要求如下:
实验一 词法分析程序设计
【实验要求】
对一个简单的语言的子集编制一个一遍扫描的词法分析程序。
【实验内容】
1、待分析的简单语言词法
(1)关键字
可以自由添加。如C语言的关键字:main if else int char return void while等。
(2)标识符(ID)
ID→letter(letter|digit)* Letter→a|…|z|A|…|Z digit→0|…|9
(3)常数(可以先以整形常数为例)
NUM→digit(digit)* digit→0|…|9
(4)运算符
如C语言中的运算符= + – * / < <= > >= == !=等。
(5)界符
如C语言中的; : , { } [ ] ( )等。空格由空白、制表符和换行符组成。空格一般用来分隔关键字、ID、NUM、运算符和界符。词法分析阶段空格通常被忽略。
2、各种单词类别及对应的种别编码
关键字设置为0~99,如“main”设置为0,“if”设置为1,……;
标识符设置为100;
常数设置为101~109,如整形常数设置为101,小数常数设置为102,……;
运算符设置为110~149,如“=”设置为111,“+”设置为112,……;
界符设置为150~159,如“;”设置为150,“,”设置为151,……。
例如:对源程序int x =9; if (x>0) x=2*x+1/3; 经词法分析后输出如下序列:(3,int) (1,‘x’) (4,=) (2,9) ……
输入截图:

运行结果截图:

源代码:
package Analyzer; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.*; import java.io.*; public class LexicalAnalyzer { //将txt文件转为数组 public String txt2String(File file) throws IOException { StringBuilder result =new StringBuilder(); try { BufferedReader br= new BufferedReader(new FileReader(file)); String s=null; while((s=br.readLine())!=null){ result.append(System.lineSeparator()+s); } br.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result.toString(); } //对文本进行预处理 public char[] preTreatment(char[] sourcefile) { char []afterfile = new char[10000]; int index=0; if(sourcefile.length!=0) { for(int i=0;i
='a'&&c<='z')||(c>='A'&&c<'Z')) { return true; } else return false; } //判断是否为保留字,并返回编号 public int isReserve(String s,String []reserve) { int index=-1; for(int i=0;i
='0'&&c<='9') { return true; } else return false; } public static void main(String[] args) throws IOException { // TODO Auto-generated method stub //保留字 String []reserve={"if","else","while","throw","this","int","String","char","double","float","this", "static","public","private","default","switch","catch","void","try","return"};//0~99 //运算符 String []operator={"+","-","*","/","++","--","==","!=",">","<",">=", "<=","&&","||","!","&","|","^","~","<<",">>",">>>","+=","="};//110~149 //界符 char []divide={'<','>','(',')','{','}','[',']','\'','"',',',';','?','/','\\',':','.'};//150~无穷 LexicalAnalyzer la=new LexicalAnalyzer(); //源代码的txt文件 File file=new File("D://Source.txt"); //将txt格式的源文件放入sourcefile的字符数组中 String source=la.txt2String(file); char sourcefile[] = source.toCharArray(); //将源代码进行预处理,去掉注释和换行符 char afterfile[]=la.preTreatment(sourcefile); //index记录源代码的字符数组扫描到的数组下标 int index=0; //temp用于存储临时的字符串 String temp=""; //当未扫描到终结符则一直往下扫描 while(afterfile[index]!='\0'){ //当开头为字母时,可能为保留字或是标识符 if(la.isLetter(afterfile[index])) { temp+=afterfile[index]; //当下一个字符不为字母或数字,则停止扫描,并将扫描结果存入temp while(la.isLetter(afterfile[index+1])||la.isDigit(afterfile[index+1])) { index++; temp+=afterfile[index]; } //将temp与保留字数组匹配,匹配成功即为保留字,否则为标识符 if(la.isReserve(temp, reserve)!=-1) System.out.println("保留字:("+la.isReserve(temp, reserve)+","+temp+")"); else System.out.println("标识符:("+100+","+temp+")"); } //当开头为数字时,可能为整数或小数 else if(la.isDigit(afterfile[index])) { temp+=afterfile[index]; while(la.isDigit(afterfile[index+1])) { index++; temp+=afterfile[index]; } //若在数字后有小数点,继续判断 if(afterfile[index+1]=='.') { index++; //小数点后无数字,检测出错 if(!la.isDigit(afterfile[index+1])){ System.out.println("此处有误,小数点后无数字"); temp=""; break; } //小数点后有数字,检测为小数 else { temp+=afterfile[index]; while(la.isDigit(afterfile[index+1])) { index++; temp+=afterfile[index]; } } System.out.println("小数常数:("+102+","+temp+")"); } //无小数点,检测为整数 else { System.out.println("整数常数:("+100+","+temp+")"); } } //既不是数字也不是字母也不是空格,则为界符或运算符,跳过空格 else if(afterfile[index]!=' ') { temp+=afterfile[index]; /*由于界符只有一个字符长度,则temp放入一个字符后直接开始匹配界符数组, * 匹配成功则continue循环,匹配失败则继续扫描 */ if(la.isDivide(temp, divide)!=-1) { System.out.println("界符:("+la.isDivide(temp, divide)+","+temp+")"); temp=""; index++; continue; } //判断是否为运算符 else { //若下一个字符也是符号类型则加入temp while((la.isDivide(afterfile[index+1]+"", divide)==-1)&&(la.isDigit(afterfile[index+1])==false) &&(la.isLetter(afterfile[index+1])==false)) { index++; temp+=afterfile[index]; } //与运算符数组匹配,匹配成功,则为运算符,失败,则可能出现了检测不了的字符。 if(la.isOperator(temp, operator)!=-1) System.out.println("运算符:("+la.isOperator(temp, operator)+","+temp+")"); else System.out.println("无法识别,可能为中文字符"); } } temp=""; index++; } } }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/223193.html原文链接:https://javaforall.net
