JAVA实现一个简单的代数运算语言编译器(二)--词法分析准备

上一篇文章主要介绍了这个代数运算编译器的起因,这一篇我们就来开始写这个项目。

首先我们需要先设置一些系统的基础类如系统符号类,保留字类、错误提示信息类、自定义异常、输入读取类等,下面简单地说一下这几个类。

系统符号类:

package com.liu.system;


/*
 * 系统符号集合
 * 创建于2017.3.7
 * @author lyq
 * */
public class Symbol {
	/*加号*/
	public static final char plus = '+';
	/*减号*/
	public static final char minus = '-';
	/*乘号*/
	public static final char times = '*';
	/*除号*/
	public static final char slash = '/';
	/*左括号*/
	public static final char lparen = '(';
	/*右括号*/
	public static final char rparen = ')';
	/*结束符*/
	public static final char semicolon = ';';
	/*赋值符*/
	public static final char eql = '=';
	/*小数点*/
	public static final char point ='.';
	
	//运算及赋值符号数组
	public static final char[] symbols = {
		plus,minus,times,slash,lparen,rparen,eql
	};
}

这个类主要时存储了一些系统预制符号,还用一个字符串数组存储了可用于四则运算以及赋值的符号,方便后面的词法分析。


保留字类:

package com.liu.system;

/*
 * 系统保留字类
 * 创建时间2017.3.7
 * @author lyq
 * */
public class Word {
	/*输出函数的函数名*/
	public static final String PRINT = "print";
	/*保留字数组*/
	public static final String[] WORDS = {PRINT};
}

由于作业要求里面只提到了print这一个关键字,因此这个类非常简单,但把它封装成类更方便今后程序的拓展。


错误提示类:

package com.liu.system;


/*
 * 错误提示信息类
 * 创建时间2017.3.7
 * @author lyq
 * */
public class Error {
	public static final String  END_WITH_NO_SEM = "The program ended without a semicolon.";//结尾没有结束符
	public static final String NUMBER_SPACE_NUMBER = "There is gaps between the two numbers.";//数字间有空白符
	public static final String NUMBER_SPACE_LETTER = "There are gaps between numbers and variables.";//数字和字母间有空白符
	public static final String LETTER_SPACE_LETTER = "There are graps between variables.";//字母间有空白符
	public static final String LETTER_SPACE_NUMBER = "There are gaps between numbers and variables.";//字母和数字间有空白符
	public static final String LETTER_AFTER_NUMBER = "There is a variable which is not initialized.";//数字之后紧跟字母,可能是变量名不符合规定
	public static final String POINT_AFTER_SPACE = "There is gaps before a point.";//小数点前面有空格
	public static final String POINT_AFTER_LETTER = "There is a letter before a point.";//小数点前面有字母
	public static final String POINT_AFTER_POINT = "There are too many points in a number.";//一个数字中有多个小数点
	public static final String NUMBER_END_POINT = "There is a number which ended with a point.";//一个数字以小数点结尾
	public static final String NO_THIS_TYPE =  "The system cannot recognize this symbol.";//计算表达式时找不到匹配该变量的符号类型
	public static final String NO_THIS_VARIBLE ="A varible has be used which not be initialized.";//使用了未经初始化的变量进行运算
	public static final String DIVIDED_BY_ZERO ="The divisor can not be zero.";//除数为0
	public static final String WRONG_FORMAT_OF_EXPRESSION = "There is error in expression.";//错误的表达式
	public static final String INCORRECT_ASSIGNMENT = "There is a error in assignment statement.";//赋值语句有误
	public static final String NAME_WITH_KEYWORD = "A varible named by keyword.";//使用保留字进行命名
	public static final String CONTAIN_UNKNOWN_CAHR = "There is a character which is not recognized by the system.";//输入中包含未知字符
	public static final String UNRECOGNIZED_SENTENCE = "There is a sentence which is not recognized by the system.";//包含无法识别的语句
}

这个类主要用来存储一些错误提示信息,由于首先主要是做词法分析,因此这里我们主要存储的是与词法有关的错误。


我的异常类:

package com.liu.system;

/*
 * 自定义异常类
 * 创建时间2017.3.7
 * @author lyq
 * */
public class MyException extends Exception{

	private static final long serialVersionUID = 1L;

	public MyException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public MyException(String message, Throwable cause,
			boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
		// TODO Auto-generated constructor stub
	}

	public MyException(String message, Throwable cause) {
		super(message, cause);
		// TODO Auto-generated constructor stub
	}

	public MyException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}

	public MyException(Throwable cause) {
		super(cause);
		// TODO Auto-generated constructor stub
	}
	
}

自定义异常类继承自Exception,方便报错。


输入读取类:

package com.liu.system;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

/*
 * 按分号读取输入
 * 创建于2017.3.7
 * @author lyq
 * */
public class Read {

	/*
	 * 读取系统输入的方法
	 * @param input 输入流
	 * @return 返回按结束符分割的字符串数组
	 * @exception 当输入不是以分号结尾时抛出MyException异常
	 * @exception i/o异常
	 * */
	public static String[] getInput(InputStream input) throws Exception {
		BufferedReader bf = new BufferedReader(new InputStreamReader(input));
		StringBuffer sb = new StringBuffer();
		String str = null;
		while ((str = bf.readLine()) != null) {
			sb.append(str);
		}
		String content = sb.toString();
		//如果结尾不是分号则报错
		if(!content.endsWith(Symbol.semicolon)){
			throw new MyException(Error.END_WITH_NO_SEM);
		}
		return content.split(Symbol.semicolon);
	}
}

这个类有一个静态方法getInput(),负责从输入流中读取到字符串并将其按分号进行分割,如果输入末尾不是分号则会抛出一个异常提示用户。


好了,有了上述这些类,词法分析的准备工作就算完成了,接下来我们可以开始我们的编译器词法分析了。

猜你喜欢

转载自blog.csdn.net/qq_33534383/article/details/60884924