基于java语言的词法分析器(简)
作者用的idea2021,编码格式UTF-8(使用前调整编码格式以防看不到注释)
题目要求
<标识符>::=<字母>{<字母>|<数字>} //标识符和关键字都不区分大小写,比如if和IF均为关键字,不允许出现与关键字相同的标识符
<字母>::=_|a|...|z|A|...|Z
<数字>::=0|1|...|9
<整数>::=[+|-]<无符号整数>
<无符号整数>::=<数字>{<数字>}
<字符>::=‘<加法运算符>’|’<乘法运算符>’|’<字母>’|’<数字>’
<加法运算符>::=+|-
<乘法运算符>::=*|/
<字符串>::="{十进制编码为32,33,35-126的ASCII字符}"
//字符串中要求至少有一个字符
单词名称 | 类别码 | 单词名称 | 类别码 | 单词名称 | 类别码 | 单词名称 | 类别码 |
---|---|---|---|---|---|---|---|
标识符 | IDENFR | if | IFTK | - | MINU | = | ASSIG |
整数 | INTCON | else | ELSETK | * | MULT | ; | SEMICN |
字符 | CHARCON | do | DOTK | / | DIV | , | COMMA |
字符串 | STRCON | while | WHILETK | < | LSS | ( | LPARENT |
const | CONSTTK | for | FORTK | <= | LEQ | ) | RPARENT |
int | INTTK | scanf | SCANFTK | > | GRE | [ | LBRACK |
char | CHARTK | printf | PRINTFTK | >= | GEQ | ] | RBRACK |
void | VOIDTK | return | RETURNTK | == | EQL | { | LBRACE |
main | MAINTK | + | PLUS | != | NEQ | } | RBRACE |
(一)读文件ReadFromText.java
这里用的是相对路径,测试文件名testfile.txt,可以自行更改。
直接给源码了
package lexicalAnalysis;
import java.io.*;
public class ReadFromText {
public static File OpenFile(){
//读取文件testfile.txt
File file = new File("testfile.txt");
return file;
}
public static String readFromText(){
//对读取的文件进行内容处理
File file = OpenFile();
//用OpenFile的方法获取文件
StringBuffer getString= new StringBuffer();
// 创建StringBuffer容器,用于保存从文件读取的内容
String initString = null;
// 用initString保存取消注释后的内容(依旧包含换行符)
BufferedReader bufferedReader = null;
// 采用字符输入缓冲流读入数据:一次读取一行
try{
// 获取输入流对象
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file),"UTF-8"));
// 避免出现乱码,统一使用UTF-8编码
String line;
while ((line = bufferedReader.readLine()) != null){
// 字符输入缓冲流读取一行,不会自动加上换行
getString.append(line + "\n");
// 手动加入换行符
}
String target = getString.toString().trim();
// 对串进行去首位空格
initString =target.replaceAll("\\/\\/[^\\n]*|\\/\\*([^\\*^\\/]*|[\\*^\\/*]*|[^\\**\\/]*)*\\*+\\/", "");
//利用正则表达式去掉代码中的单行注释,多行注释
/*
* 正则表达式解读:\\/ 这样的符号在java中表示是一个斜杠字符
* 单行注释(// 注释内容) :\\/\\/[^\\n]* \\/\\/是指以//开头,[^\\n]是以换行符作为的单行注释的结束标志
* 多行注释(\\/*注释内容\\*\\/):用法跟单行注释相同,只不过是以“*\\/” 结尾
* [\\*^\\/*]*|[^\\**\\/]*)*\\*+\\/ 作特殊情况约束
*/
char[] chars = (initString+"$").toCharArray();
// 将去注释的字符串整理成一行,并且以$结尾(词法分析结束标志)
getString.replace(0,getString.length(),"");
//由于获取的代码已经成功去注释,所以将其内容清空用于存放去换行的串
for(char c : chars){
if(c != '\n'){
getString.append(c);
}else{
getString.append(" ");
// 去换行的地方用空格代替
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 完整性约束,用完文件及时关闭,以防内存浪费
if(bufferedReader != null){
try{
bufferedReader.close();
}catch (IOException e){
e