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(); }}
程序中未实现注释过滤功能。