Java实现简易的词法分析器

原创 2018年04月16日 22:58:31

此次也是课题需要,才写了这么一个项目,编译原理课你懂的.

由于个人比较喜欢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语言中的; : , { } [ ] ( )等。空格由空白、制表符和换行符组成。空格一般用来分隔关键字、IDNUM、运算符和界符。词法分析阶段空格通常被忽略。

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; 经词法分析后输出如下序列:(3int) (1,‘x’) (4=) (29) ……


输入截图:


运行结果截图:


源代码:

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<sourcefile.length;i++)
			{
				//去掉//注释后的一整行
				if(sourcefile[i]=='/'&&sourcefile[i+1]=='/')
				{
					while(sourcefile[i]!='\n'){
					i++;
					}
				}
				//去掉/**/型注释中间的字符,若只检测到/*,未检测到*/,则提示注释有误
				if(sourcefile[i]=='/'&&sourcefile[i+1]=='*')
				{
					i=i+2;
					while(sourcefile[i]!='*'||sourcefile[i+1]!='/')
					{
						i++;
						if(i==(sourcefile.length-1))
						{
							System.out.println("注释有误,未找到注释尾");
							return afterfile;
						}
					}
					i=i+2;
				}
				if(sourcefile[i]!='\n'&&sourcefile[i]!='\r'&&sourcefile[i]!='\t')
				{
					afterfile[index]=sourcefile[i];
					index++;
				}
			}
			index++;
			afterfile[index]='\0';
		}
		return afterfile;
	}
	//判断是否为字母
	public boolean isLetter(char c)
	{
		if((c>='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<reserve.length;i++)
		{
			if(s.equals(reserve[i]))
			{
				index=i;
				break;
			}
		}
		return index;
	}
	//判断是否为运算符,并返回编号
	public int isOperator(String s,String []operator)
	{
		int index=-1;
		for(int i=0;i<operator.length;i++)
		{
			if(s.equals(operator[i]))
			{
				index=i+110;
				break;
			}
		}
		return index;
	}
	//判断是否为界符,并返回编号
	public int isDivide(String s,char []divide)
	{
		int index=-1;
		for(int i=0;i<divide.length;i++)
		{
			if(s.equals(divide[i]+""))
			{
				index=i+150;
				break;
			}
		}
		return index;
	}
	//判断是否为数字
	public  boolean isDigit(char c)
	{
		if(c>='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++;
		}
	}

}


 



应聘者轻专业 招聘者重经验

招聘会上新发现:应聘者轻专业 招聘者重经验  昨天,在国展中心的招聘会上,记者发现,今年应聘人员中,跨专业应聘者比以往有所增加。  北京一家文化传播公司的负责人告诉记者,今年在他们公司应聘的人员中,有...
  • stanely
  • stanely
  • 2001-06-04 16:34:00
  • 590

Java编写的C语言词法分析器

Java编写的C语言词法分析器                      这是java编写的C语言词法分析器,我也是参考很多代码,然后将核心代码整理起来,准备放在QQ空间和博客上,目的是互相...
  • u014427391
  • u014427391
  • 2015-05-24 16:07:34
  • 2312

一个简单词法分析器的实现代码(java实现)

http://www.cnblogs.com/xuqiang/archive/2010/09/21/1953501.html Main.java /* * 主程序 */ import j...
  • caolaosanahnu
  • caolaosanahnu
  • 2012-10-16 10:49:17
  • 6305

java正则表达式实现简单词法分析

需要识别的词 1. 关键字:if、int、for、while、do、return、break、continue;单词种别码为1。 2. 标识符;单词种别码为2。 3. 常数为无符号整形数;单词种...
  • HurryBen
  • HurryBen
  • 2017-11-28 19:39:03
  • 152

用java实现的词法分析器

  • 2010年01月29日 21:27
  • 7KB
  • 下载

(编译原理)java实现词法分析器

1、闲话最近在学编译原理,需要用语言实现一个词法分析器,其实挺简单的,主要涉及一些语言字符串操作处理,如果会正则表达式的话,感觉实现这个会很简单,但是我并不会啊,然后自己用java实现了,也算是加强了...
  • wearge
  • wearge
  • 2017-10-30 13:49:04
  • 532

<em>java</em> 实现的<em>词法分析器</em>

1.根据状态转换图直接编程 <em>编写一个词法分析</em>程序,它从左到右逐个字符的对源程序进行扫描,产生一个个的单词的二元式,形成二元式(记号)流文件输出。在此,词法...
  • 2018年04月16日 00:00

<em>java词法分析器</em>源代码

Java 实现<em>词法分析器</em>(编译原理) <em>Java编写</em>的C语言<em>词法分析器</em> <em>一个</em>简单<em>词法分析器</em>的实现代码(java实现) Java 实现<em>词法分析器</em>(编译原理) <em>一个</em>简单词法分析...
  • 2018年04月18日 00:00

用<em>JAVA写词法分析器</em>

用<em>JAVA写词法分析器</em>给出<em>一个</em>简单语言的词法规则,画出状态转换图,并依据状态转换图编制出词法分析程序,词法规则如下:单词符号 种别码 内码 break 1 char 2 ...
  • 2018年04月18日 00:00

简单词法分析器java版本

Error为错误提示类,将错误信息保存在Error中。用于输出error.txt Word为关键字定义,将关键字信息保存在Word中,用于对单词的验证 Lexer 为词法分析核心类,包含对源程序的分析...
  • jlh912008548
  • jlh912008548
  • 2016-05-31 20:35:44
  • 3517
收藏助手
不良信息举报
您举报文章:Java实现简易的词法分析器
举报原因:
原因补充:

(最多只允许输入30个字)