程序分为4个关键方法,用户输入方法,读、写文件方法以及词法分析方法。其中词法分析方法是程序的核心。
词法分析程序主要分为两个部分,第一是取词,第二是分析。
取词阶段:
依次取字符串的每一个字符,遇到空字符时停下,将取到的字符合并成一个字符串,送去进行分析阶段。
分析阶段:程序先构建有关键字数组、分隔符数组和运算符数组,通过将取词阶段送来的字符串与各数组中元素进行比较,将字符串分类到相应的类别数组中保存。
词法分析伪代码如下:
While (源码字符串没有取完){ Getchar(获取一个非空字符); If (是字母) { 拼接到目标字符串后; While (继续获取字符直到空字符出现); If (目标字符串是关键字)记录为关键字; Else 记录为标识符; } Else If (是数字){ While(循环获取直到非数字); 记录为常数; } Else if (是运算符){ 标记为运算符; } Else(是分隔符){ 标记为分隔符; } }
具体实现时,分析方法主要实现伪代码的逻辑,其中一些具体操作比如判断是否为关键字、运算符等都另写方法实现,分析方法通过调用这些方法实现具体功能。
读写文件操作:
分析方法基于缓冲区操作,用户输入的源码也是暂存缓冲区,等分析方法完成后,直接将缓冲区的源码压入文件即可。
import java.io.File;
import java.util.Scanner;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* 词法分析程序
* @author 霍淇滨
*
*/
public class Analyzer {
private String keyWords[] = { "auto", "double", "int", "struct", "break", "else",
"long", "switch", "case", "enum", "register", "typedef", "char", "extern",
"return", "union", "const", "float", "short", "unsigned", "continue",
"for", "signed", "void", "default", "goto", "sizeof", "volatile", "do", "if",
"while", "static"}; // 关键字数组
private char operators[] = { '+', '-', '*', '/', '=', '>', '<', '&' }; // 运算符数组
private char separators[] = { ',', ';', '{', '}', '(', ')', '[', ']', '_',
':', '、', '.', '"' }; // 分隔符数组
private String url;
private StringBuffer buffer = new StringBuffer(); // 缓冲区
private char ch; // 字符变量,存放最新读进的源程序字符
private static int i = 0;//下标,存放遍历到的源码位置
private String words; // 存放构成单词符号的字符串
public Analyzer(String yrl) {
this.url = url;
}
/**
* 接受用户输入
* @return
*/
public String input(){
String text = "";
System.out.println("输入源码:");
Scanner sc = new Scanner(System.in);
String n = sc.nextLine();
while(!n.equals("$")){
buffer.append(n);//加入到缓冲区
n = sc.nextLine();
}
System.out.println(text);
return text;
}
/**
* 将用户输入保存为文件
* @param text
* @throws IOException
*/
public void writeTxt() throws IOException{
File writename = new File(".\\output.txt"); // 相对路径,如果没有则要建立一个新的output.txt文件
writename.createNewFile(); // 创建新文件
BufferedWriter out = new BufferedWriter(new FileWriter(writename));
out.flush(); // 把缓存区内容压入文件
out.close(); // 最后记得关闭文件
}
/**
* 将下一个输入字符读到ch中,搜索指示器前移一个字符
*/
public void getChar() {
ch = buffer.charAt(i);
i++;
}
/**
* 检查ch中的字符是否为空白,若是则调用getChar() 直至ch中进入一个非空白字符
*/
public void getContinue() {
while (Character.isSpaceChar(ch))
getChar();
}
/**
* 将ch连接到words之后
*/
public void concat() {
words += ch;
}
/**
* 判断字符是否为字母
*/
boolean isLetter() {
return Character.isLetter(ch);
}
/**
* 判断字符是否为数字
*/
boolean isDigit() {
return Character.isDigit(ch);
}
/**
* 判断单词是否为关键字
*/
public boolean isKeyWord() {
for (int i = 0; i < keyWords.length; i++) {
if(keyWords[i].equals(words))return true;
}
return false;
}
/**
* 判断是否为运算符
*/
public boolean isOperator() {
for (int i = 0; i < operators.length; i++) {
if(ch == operators[i]) return true;
}
return false;
}
/**
* 判断是否为分隔符
*/
public boolean isSeparators() {
for (int i = 0; i < separators.length; i++) {
if (ch == separators[i]) return true;
}
return false;
}
/**
* 将源程序读入到缓冲区中
* @throws IOException
*/
public void readFile() throws IOException {
FileReader fis = new FileReader(this.url);
BufferedReader br = new BufferedReader(fis);
String temp = null;
while ((temp = br.readLine()) != null) {
buffer.append(temp);
}
}
/**
* 词法分析
*/
public void analyse() {
words = "";
while (i < buffer.length()) {
getChar();
getContinue();
if (isLetter()) { // 如果ch为字母
while (isLetter() || isDigit()) {
concat();
getChar();
}
i--;ch = ' ';
if (isKeyWord()) { // 如果是为关键字
System.out.println("(关键字,"+words+")");
} else { // 否则是标识符
System.out.println("(标识符,"+words+")");
}
words = "";
} else if (isDigit()) { //如果为数字
while (isDigit()) {
concat();
getChar();
}
i--;ch = ' ';
System.out.println("(常数,"+words+")");
words = "";
} else if (isOperator()) { // 如果是运算符
System.out.println("(运算符,"+ch+")");
} else if (isSeparators()) { // 如果是分隔符
System.out.println("(分隔符,"+ch+")");
}
}
}
/**
* 测试函数
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Analyzer ans = new Analyzer("./src/input.txt");//文件路径
//源文件测试
// ans.readFile();
// ans.analyse();
//用户输入测试
ans.input();
ans.analyse();
ans.writeTxt();
}
}
程序中未实现注释过滤功能。