编译原理实验-词法分析器(包含源码)

编译原理实验-词法分析器(包含源码)

本实验是合肥工业大学编译原理实验的百年老题目,这里只提供实验1,若有需要2、3可以去博主的GitHub上面

链接

一、实验目的

通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的理解,并能正确地、熟练地运用。

二、功能描述

1)	从文件中读入c语言源程序
2)	统计行数和列数用于错误单词的定位
3)	删除空格类字符,包括回车、制表符空格
4)	按拼写单词,并用(内码,属性)二元式表示
5)	如果发现错误则报告出错
6)	根据需要是否填写标识符表供以后各阶段使用
7)	识别注释
8)	可识别小数

三、程序结构设计

在这里插入图片描述

在这里插入图片描述

四、详细的算法描述

在这里插入图片描述

在这里插入图片描述

五、测试方法和结果

测试方法
(1). C语言源程序存放在test.txt文件里面,直接打开读取此文件。
(2).可以识别注释,不分析;可识别小数
(3).可以识别的错误有:
	标识符不规范的命名方式,如数字开头;
	连续的算数运算符连在一起,如+-
	错误的关系运算符,如<<
	一个数字里面出现两个小数点,如3.1.4
	一些非法的输入。
测试样例:
if i=0 then n++; //abc
a <=3b%);
12.3
1.3.4
<<
3+- 1
aa
测试结果

在这里插入图片描述

package bianYiYuanLi;

import java.io.*;
import java.util.*;

public class work1 {
	static ArrayList<String> k=new ArrayList<String>(Arrays.asList("do","end","for","if","printf","scanf","then","while")); //关键字
	static ArrayList<String> s=new ArrayList<String>(Arrays.asList(",",";","(",")","[","]")); //分界符
	static ArrayList<String> a=new ArrayList<String>(Arrays.asList("+","-","*","/")); //算术运算符
	static ArrayList<String> r=new ArrayList<String>(Arrays.asList("<","<=",">",">=","=","<>")); //关系运算符
	static ArrayList<String> ci=new ArrayList<>(); //常数
    static ArrayList<String> id=new ArrayList<>(); //标识符
    static int hangX=1; //行
    static int lieY=1; //列
    
    //查找识别方法
    static void searchDis(String str) {
    	int i=0; //区分String的首符,1为字母,2为数字,3为其他
    	char ch=str.charAt(0);
    	if ((ch>=65&&ch<=90)||(ch>=97&&ch<=122))
    		i=1;
    	else if(ch>=48&&ch<=57)
    		i=2;
    	else
    		i=3;
    	
    	//开始查找识别
    	if (i==1) { //首符是字母,查关键字和标识符
    		boolean find=k.contains(str);
    		if(find==true) {
    			//System.out.println(str+'\t'+'\t'+"(1,"+str+")"+'\t'+'\t'+"关键字"+'\t'+'\t'+"("+hangX+","+lieY+")");
    			System.out.printf("%-10s%-10s%-10s%-10s",str,"(1,"+str+")","关键字","("+hangX+","+lieY+")");
    			System.out.println();
    		}
    		else { //不是关键字,查询标识符
    			find=id.contains(str);
    			if(find==true) {
    				//System.out.println(str+"  (6,"+str+")  "+"标识符"+"  ("+hangX+","+lieY+")");
    				System.out.printf("%-10s%-10s%-10s%-10s",str,"(6,"+str+")","标识符","("+hangX+","+lieY+")");
        			System.out.println();
    			}
    			else { //标识符表没有时,插入
    				//System.out.println(str+"  (6,"+str+")  "+"标识符"+"  ("+hangX+","+lieY+")");
    				System.out.printf("%-10s%-10s%-10s%-10s",str,"(6,"+str+")","标识符","("+hangX+","+lieY+")");
        			System.out.println();
    				id.add(str); 
    			}
    		}
    	}
    	else if(i==2) { //首符是数字,查常数
    		boolean find=ci.contains(str);
    		if(find==true) {
    			//System.out.println(str+"  (5,"+str+")  "+"常数"+"  ("+hangX+","+lieY+")");
    			System.out.printf("%-10s%-10s%-10s%-10s",str,"(5,"+str+")","常数","("+hangX+","+lieY+")");
    			System.out.println();
    		}
    		else { //不在常数表中,插入
    			//System.out.println(str+"  (5,"+str+")  "+"常数"+"  ("+hangX+","+lieY+")");
    			System.out.printf("%-10s%-10s%-10s%-10s",str,"(5,"+str+")","常数","("+hangX+","+lieY+")");
    			System.out.println();
    			ci.add(str);
    		}
    	}
    	else { //查分界符,算术、逻辑运算符
    		if(s.contains(str)) {
    			System.out.printf("%-10s%-10s%-10s%-10s",str,"(2,"+str+")","分界符","("+hangX+","+lieY+")");
    			System.out.println();
    		}
    		else if(a.contains(str)) {
    			System.out.printf("%-10s%-10s%-10s%-10s",str,"(3,"+str+")","算术运算符","("+hangX+","+lieY+")");
    			System.out.println();
    		}
    			
    		else if(r.contains(str)) {
    			System.out.printf("%-10s%-10s%-10s%-10s",str,"(4,"+str+")","关系运算符","("+hangX+","+lieY+")");
    			System.out.println();
    		}
    			
    		else {
    			System.out.printf("%-10s%-10s%-10s%-10s",str,"Error","Error","("+hangX+","+lieY+")");
    			System.out.println();
    		}
    			
    	}
    		
    }
    
    //分析串函数
    static void analysisString(String str2) {
    	String strNow=""; //当前识别的串
    	char ch1;
    	for(int i=0;i<str2.length();i++) {
    		ch1=str2.charAt(i);
    		if(ch1==' ')
    			continue;
    		if((ch1>=65&&ch1<=90)||(ch1>=97&&ch1<=122)) { //识别字母
    			strNow+=ch1;
    			i++;
    			//超前搜索
    			do {
    				ch1=str2.charAt(i);
    				if((ch1>=65&&ch1<=90)||(ch1>=97&&ch1<=122)||(ch1>=48&&ch1<=57)) {
    					strNow+=ch1;
    					i++;
    				}
    				else
    					break;
    			}while(i<str2.length());
    			i--; //指针复位
    			searchDis(strNow);
    			strNow="";
    			lieY++;
    			continue;
    		}
    		
    		else if(ch1>=48&&ch1<=57) { //识别数字
    			strNow+=ch1;
    			i++;
    			//超前搜索
    			//将后续如果是字母或者是数字全部加进去
    			while(i<str2.length()){
    				ch1=str2.charAt(i);
    				if((ch1>=65&&ch1<=90)||(ch1>=97&&ch1<=122)||(ch1>=48&&ch1<=57)||ch1=='.') {
    					strNow+=ch1;
    					i++;
    				}
    				else
    					break;
    			}
    			i--; //指针复位
    			//判断数字中是否有字母,有输出为error
    			int j;
    			boolean errorDone=false; //标志是否做出了出错判定
    			for(j=0;j<strNow.length();j++) {
    				char ch2=strNow.charAt(j);
    				if((ch2>=65&&ch2<=90)||(ch2>=97&&ch2<=122)) {
    					System.out.printf("%-10s%-10s%-10s%-10s",strNow,"Error","Error","("+hangX+","+lieY+")");
    					System.out.println();
    					errorDone=true;
    					break;
    				}
    			}
    			//判断数字中有几个小数点,有两个及以上出error
    			int m;
    			boolean tag=false; //tag为true时,表示已经识别到一个小数点
    			for(m=0;m<strNow.length();m++) {
    				char ch2=strNow.charAt(m);
    				if(ch2=='.'&&tag) {
    					if(!errorDone) { //由于上面已经输出error,下面就不用再输出
    						System.out.printf("%-10s%-10s%-10s%-10s",strNow,"Error","Error","("+hangX+","+lieY+")");
    						System.out.println();
    					}
    					errorDone=true;
    					break;
    				}
    				else if(ch2=='.'&&!tag) {  //第一个小数点识别
    					tag=true;
    				}
    			}
    			if(!errorDone)
    				searchDis(strNow);
    			strNow="";
    			lieY++;
    			continue;
    		}
    		
    		else { //识别其他
    			strNow+=ch1;
    			if(s.contains(strNow)) { //识别为分界符
    				searchDis(strNow);
    				strNow="";
        			lieY++;
        			continue;
    			}
    			else if(a.contains(strNow)||r.contains(strNow)) { //识别为算术运算符或关系运算符
    				i++;
    				//判断运算符后面是否是关系或算术运算符,是则继续添加到strNow中
    				while(i<str2.length()) {
    					ch1=str2.charAt(i);
    					if(a.contains(ch1+"")||r.contains(ch1+"")) {
    						strNow+=ch1;
    						i++;
    					}
    					else
    						break;
    				}
    				searchDis(strNow);
    				i--; //复位
    				strNow="";
        			lieY++;
        			continue;
    			}
    			else { //识别非法字符
    				searchDis(strNow);
    				strNow="";
        			lieY++;
        			continue;
    			}
    		}
    	}
    }
    //主函数
    public static void main(String[] args) {
    	try {
    		RandomAccessFile inF=new RandomAccessFile("test.txt","r");
			String str1=null;
			while((str1=inF.readLine())!=null) { //一行一行的读取
				//删除注释
				for(int i=0;i<str1.length()-1;i++) {
					if(str1.charAt(i)=='/'&&str1.charAt(i+1)=='/') {
						str1=str1.substring(0, i);
						break;
					}
				}
				analysisString(str1); //调用分析函数
				hangX++; //行加1
				lieY=1; //列置1
			}
			
			inF.close();
		}
		catch(IOException e) {
			System.out.println(e);
		}
    }
}

  • 8
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
实验一:词法分析程序 一、实验目的     通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的类型码及单词符号的自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示) 二、实验要求 用C或C++写一个简单的词法分析程序,程序可以满足下列要求: 1、能分析如下几种简单的语言词法 (1) 标识符: ID=letter(letter|digit)* (2) 关键字(全部小写) main int float double char if then else switch case break continue while do for (3)整型常量:NUM=digit digit* (4)运算符 = + - * / < <= == != > >= ; ( )? : (5)空格由空白、制表符和换行符组成,用以分隔ID、NUM、运算符等,字符分析时被忽略。 2、单词符号和相应的类别码 假定单词符号和相应的类别码如下: 单词符号 种别码 int 1 = 17 float 2 < 20 if 3 <= 21 switch 4 == 22 while 5 != 23 Do 6 > 24 标识符 10 >= 25 整型常量 11 ; 26 + 13 ( 27 - 14 ) 28 * 15 ? 29 / 16 : 30 3、词法分析程序实现的功能 输入:单词序列(以文件形式提供),输出识别的单词的二元组序列到文件和屏幕 输出:二元组构成: (syn,token或sum) 其中: syn 为单词的种别码 token 为存放的单词自身符号串 sum 为整型常数 例: 源程序: int ab; float ef=20; ab=10+ef; 输出: (保留字--1,int) (标识符--10,ab) (分号--26,;) (保留字--2,float) (标识符--10,ef) (等号--17,=) (整数--11,20) (分号--26,;) (标识符--10,ab) (等号--17,=) (整数--11,10) (加号--13,+) (标识符--10,ef) (分号--26,;) 4、自己准备测试数据存放于TestData.txt文件中,测试数据中应覆盖有以上5种数据,测试结果要求以原数据与结果对照的形式输出并保存在Result.txt中,同时要把结果输出到屏幕。 5、提前准备 ① 实验前,先编制好程序,上机时输入并调试程序。 准备好多组测试数据(存放于文件TestData.txt中)。 6、写出实验报告 报告格式:要求有实验名称、实验目的、实验要求、实验内容、实验小结。 其中实验内容包括算法分析、程序流程图及程序代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值