1 算法思想
程序分为4个关键方法,用户输入方法,读、写文件方法以及词法分析方法。其中词法分析方法是程序的核心。
词法分析程序主要分为两个部分,第一是取词,第二是分析。
1.1 取词阶段
依次取字符串的每一个字符,遇到空字符时停下,将取到的字符合并成一个字符串,送去进行分析阶段。
1.2 分析阶段
程序先构建有关键字数组、分隔符数组和运算符数组,通过将取词阶段送来的字符串与各数组中元素进行比较,将字符串分类到相应的类别数组中保存。
1.3 伪代码
While (源码字符串没有取完){Getchar(获取一个非空字符);If (是字母) {拼接到目标字符串后;While (继续获取字符直到空字符出现);If (目标字符串是关键字) 记录为关键字;Else 记录为标识符;}Else If (是数字){While(循环获取直到非数字);记录为常数;}Else if (是运算符){标记为运算符;}Else(是分隔符){标记为分隔符;}}
2 算法实现
具体实现时,分析方法主要实现伪代码的逻辑,其中一些具体操作比如判断是否为关键字、运算符等都另写方法实现,分析方法通过调用这些方法实现具体功能。
读写文件操作:分析方法基于缓冲区操作,用户输入的源码也是暂存缓冲区,等分析方法完成后,直接将缓冲区的源码压入文件即可。
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();}
}
程序中未实现注释过滤功能。