📄 text.java
字号:
/* 词法分析的主程序
* 目前为单元测试程序
*/
package accidenceAnalyse;
import java.util.*;
import java.io.*;
import java.util.regex.*;
public class Text
{
private Text(){}
public void printTokenTable() {
for (TokenTable table : tokenList)
{
System.out.println(table);
}
}
public void printError() {
for (String errorStr : errorList)
{
System.out.println(errorStr);
}
}
/* 列出所有的有待分析的源代码文件
* 要用.txt格式放在test1文件夹下! */
public int DirectryList() {
File path = new File(".");
allFiles = path.list(filter(fileNameStr));
if ( allFiles.length == 0)
{
System.out.println("不存在待分析的源代码文件!");
return 10000;
}
int fileNumber= 1;
Integer i = 0;
for (String file : allFiles)
{
System.out.print(" "+fileNumber+": "+file+" ");
if ((++i).equals(3))
{
i = 0;
System.out.println();
}
fileNumber++;
}
System.out.println("\r\n\r\n\r\n请选择要进行词法分析的文件,输入文件名前面的编号!");
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
while(true)
{
try {
String choice = read.readLine().trim();
if(choice.matches("\\d+"))
return Integer.valueOf(choice) ;
else
{
System.out.println("输入错误!重新输入!");
}
} catch(IOException e) {
//System.out.println("不存在待分析的源代码文件!");
System.out.println("出现异常!");
}
}
}
public static FilenameFilter filter(final String fileNameStr) {
return new FilenameFilter(){
private Pattern pattern = Pattern.compile(fileNameStr);
public boolean accept(File dir,String name){
return pattern.matcher(name).matches();
}
};
}
/* 词法分析阶段 */
public void BeginAnalyse(int fileNO) throws IOException {
try{
BufferedReader inputFile = new BufferedReader(new FileReader(allFiles[fileNO-1]));
try{
int ASCII;
while ((ASCII = inputFile.read())!= -1)
{
if (ASCII != 32)
{
if (ASCII == 10 || ASCII == 13) {
if(ASCII == 10) // 换行了
textLine++;
continue;
}
else
judgeWhichToAnalyse(ASCII , inputFile); // 判断要调用哪一个分析(标识符,关键字,数字....)
}
}
}finally{
inputFile.close();
}
}catch(Exception e){
System.out.println("源代码文件打开失败!");
}
}
private void judgeWhichToAnalyse(int ASCII , BufferedReader inputFile) throws IOException {
if ((""+(char)ASCII).matches("[_a-zA-Z]"))
IdentifierAnalyse(ASCII , inputFile);
else if ((""+(char)ASCII).matches("\\d"))
ConstAnalyse(ASCII , inputFile,1);
else if ((""+(char)ASCII).matches("\""))
ConstAnalyse(ASCII , inputFile,2);
else if ((""+(char)ASCII).matches("\'"))
ConstAnalyse(ASCII , inputFile,3);
else if ((""+(char)ASCII).matches("\\W"))
OperationAnalyse(ASCII , inputFile);
}
/* 标识符 以及 关键字 的分析入口*/
public void IdentifierAnalyse(int ASCII , BufferedReader inputFile) throws IOException {
ArrayList<Character> array= new ArrayList<Character>(Arrays.asList((char)ASCII));
int WordASCII;
int strLine = textLine;
boolean willOperationAnalyse = false;
while ((WordASCII = inputFile.read())!= 32) // 第一种结束情况就是遇到空格
{
if ((""+(char)WordASCII).matches("[_\\w]"))
array.add((char)WordASCII);
else if ((""+(char)WordASCII).matches(";|\\+|\\-|\\*|/|%|\\(|\\)|,|\\.|\\{|\\}|\"|\'|\\[|\\]|\\?|=|\\||&|~|^")){ //所有可能跟在标识符后面的字符 结束的第二种情况
// OperationAnalyse(WordASCII , inputFile);
willOperationAnalyse = true;
break;
}
else if (WordASCII == 10) { // 换行了 结束的第三种情况
textLine++;
break;
}
else if (WordASCII == -1)
break;
else
array.add((char)WordASCII);
}
String identify ="";
for (char c : array){
identify += c;
}
token[0].analyse(identify, tokenList , errorList , strLine);
if (willOperationAnalyse)
OperationAnalyse(WordASCII , inputFile);
}
public void ConstAnalyse(int ASCII , BufferedReader inputFile , int type) throws IOException {
int WordASCII;
int strLine = textLine;
switch (type)
{
case 1: // 分析数字常量
{
ArrayList<Character> array= new ArrayList<Character>(Arrays.asList((char)ASCII));
boolean isFloat = false , willOperationAnalyse = false;
while ((WordASCII = inputFile.read())!= 32) // 第一种结束情况就是遇到空格
{
if ((""+(char)WordASCII).matches("[xoFfUuEeLl]|\\d|\\.")){
if ((""+(char)WordASCII).matches("[Ee]"))
isFloat = true; // 如果搜索中发现了 E 或 e,表明它可能是一个浮点数
array.add((char)WordASCII);
}
else if ((""+(char)WordASCII).matches(";|\\+|\\-|\\*|/|%|\\(|\\)|,|\\{|\\}|\"|\'|\\[|\\]|\\? |=|\\||&|~|^")){ //所有可能跟在标识符后面的字符 结束的第二种情况
if ((""+(char)WordASCII).matches("\\+|\\-")){
if (isFloat){ // 如果 这个+/-紧跟在 e 或 E之后,那它就是一个浮点数
array.add((char)WordASCII);
isFloat = false;
continue;
}
else{
willOperationAnalyse = true;
break;
}
}
else{
isFloat = false;
willOperationAnalyse = true;
break;
}
}
else if (WordASCII == 10) { // 换行了 结束的第三种情况
textLine++;
break;
}
else if (WordASCII == -1)
break;
}
String identify ="";
for (char c : array){
identify += c;
}
token[1].analyse(identify, tokenList , errorList , strLine);
if (willOperationAnalyse)
OperationAnalyse(WordASCII , inputFile);
break;
}
case 2: // 分析字符串常量
{
ArrayList<Character> array= new ArrayList<Character>();
boolean isRight = true;
while ((WordASCII = inputFile.read())!= 34){ // 第一种结束情况就是遇到双引号
if (WordASCII == 10) { // 换行了 结束的第二种情况
String identify ="";
for (char c : array){
identify += c;
}
String errorStr = "第"+strLine+"行: 字符串"+identify+"没有正确结束,缺少 \"";
errorList.add(errorStr);
textLine++;
isRight = false;
break;
}
else if (WordASCII == -1){
String identify ="";
for (char c : array){
identify += c;
}
String errorStr = "第"+strLine+"行: 字符串"+identify+"没有正确结束,缺少 \"";
errorList.add(errorStr);
isRight = false;
break;
}
array.add((char)WordASCII);
}
if (isRight){
String identify ="";
for (char c : array){
identify += c;
}
tokenList.add(new TokenTable(3 , identify));
}
break;
}
case 3: // 分析字符常量
{
ArrayList<Character> array= new ArrayList<Character>();
WordASCII = inputFile.read();
if (WordASCII == 10) { // 换行了 结束的第二种情况
String errorStr = ""+strLine+"行: 字符没有正确结束,缺少\'";
errorList.add(errorStr);
textLine++;
}
else if (WordASCII == -1){
String errorStr = ""+strLine+"行: 字符没有正确结束,缺少\'";
errorList.add(errorStr);
break;
}
else{
array.add((char)WordASCII);
WordASCII = inputFile.read(); // 再读一个
if (WordASCII != 39){ // 不是单个字符了
String identify ="";
for (char c : array){
identify += c;
}
String errorStr = ""+strLine+"行: 字符串"+identify+"没有正确结束,缺少\'";
errorList.add(errorStr);
}
}
String identify ="";
for (char c : array){
identify += c;
}
tokenList.add(new TokenTable(3 , identify));
break;
}
}
}
public void OperationAnalyse(int ASCII , BufferedReader inputFile) throws IOException {
token[2].analyse(""+(char)ASCII, tokenList, errorList, textLine);
}
public void AddToFile(int fileNO) throws IOException {
String[] arrayFileName = new String[2];
arrayFileName = allFiles[fileNO-1].split("\\.") ;
String fileName = arrayFileName[0]+"Table."+arrayFileName[1];
File tableFile = new File ("accidenceAnalyse\\accidenceAnalyseTable" , ""+fileName) ;
if(tableFile.exists()){
tableFile.delete();
tableFile.createNewFile();
}
else
tableFile.createNewFile();
// DataOutputStream out = new DataOutputStream(new FileOutputStream("accidenceAnalyse\\accidenceAnalyseTable\\"+fileName));
for (TokenAnalyse t : token){
t.getArrayList(arrayFileName[0]);
}
}
public static void main(String[] args) throws IOException
{
// 目录列表模块:
int fileNO = TT.DirectryList();
if (fileNO == 10000)
return;
// 开始词法分析:
TT.BeginAnalyse(fileNO);
// 输出Token表
TT.printTokenTable();
TT.AddToFile(fileNO);
TT.printError();
}
//: 内部数据定义:
final static Text TT = new Text();
private static ArrayList<TokenTable> tokenList = new ArrayList<TokenTable>(); // token表存储在这里!
private static ArrayList<String> errorList = new ArrayList<String>(); // 错误语句数组!
private static int textLine = 1;
private String[] allFiles; // 存储搜索到的源文件
private String fileNameStr = ".+\\.txt"; // 源文件的正则表达式: 必须要以 .txt 的格式存放
private TokenAnalyse[] token = {new IdentifierAnalyse() , new ConstAnalyse() , new OperationAnalyse()};
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -