带状态转换图的词法分析器

编译原理词法分析器java带状态转换图

内容

输入:根据教学要求和学生具体情况,从具有代表性的高级程序设计语言中,选取一个适当大小的子集,例如可以选取一类典型单词,也可以尽可能使各种类型的单词都能兼顾到。
输出:单词串的输出形式,所输出的每一单词均按形如(CLASS,VALUE)的二元式编码。对于变量和常数,CLASS字段为相应的类别码,VALUE字段则是该标识符、常数的具体值或在其符号表中登记项的序号(要求在变量名表登记项中存放该标识符的字符串;常数表登记项中则存放该常数的二进制形式)。对于关键字和分隔符,采用一词一类的编码形式。由于采用一词一类的编码方式,所以仅需在二元式的CLASS字段上放置相应的单词的类别码,VALUE字段则为“空”。不过,为便于查看由词法分析程序所输出的单词串,要求在CLASS字段上直接放置单词符号串本身。

语言文法描述

<数字>→<数字><.><数字>|<数字>
<字母>→<标识符>|<保留字>
<保留字>→if|else|while|throw|this|int|String|char|double|float|this|
static|public|private|default|switch|catch|void|try|return
<运算符>→+|-|*|/|++|–|==|>|<|&&| || |!|&| | |^|~|=
<界符>→<|>|(|)|{|}|[|]|’|”|,|;|?|/|\|:|.

状态转换图

在这里插入图片描述

全部代码

package d;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.io.*;
public class Gf{
	//将txt文件转为数组
	public  String txttoString(File file) throws IOException//IOException是读写异常,通常发生在流,文件的读写过程中
	{
		StringBuilder result =new StringBuilder();//有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串生成器中
		try {
			BufferedReader br= new BufferedReader(new FileReader(file));
			String s=null;
			while((s=br.readLine())!=null){//readLine()读取流读数据时使用,每次读取一行
				result.append(System.lineSeparator()+s);//append 方法始终将这些字符添加到生成器的末端  
				//System.lineSeparator()换行的意思
			}
			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~无穷
		Gf la=new Gf();
		//源代码的txt文件路径
		File file=new File("C:\\Users\\Administrator\\Desktop\\a.txt");
		//将txt格式的源文件放入sourcefile的字符数组中
		String source=la.txttoString(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+")");//100为标识符
			}
			//当为#时
			else if(afterfile[index]=='#'){
				temp+=afterfile[index];
				System.out.println("("+103+","+temp+")");//103为#
				
			}
			//当开头为数字时,可能为整数或小数
			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+")");//102为小数
				}
				//无小数点,检测为整数
				else
				{
					System.out.println("("+101+","+temp+")");//101为整数
				}
			}
			//既不是数字也不是字母也不是空格,则为界符或运算符,跳过空格
			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++;
		}
	}
 
}
**注:此程序为硬编程,需要分析的代码段需要写在txt文档里**
  • 10
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值