专栏首页云霄雨霁词法分析程序

词法分析程序

程序分为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();
	}
}

程序中未实现注释过滤功能。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 加权有向图----一般性单源最短路径问题(Bellman-Ford算法)

    SuperHeroes
  • 数据结构----背包

    SuperHeroes
  • Dijkstra双栈表达式求值算法

    SuperHeroes
  • Android中封装RecyclerView实现添加头部和底部示例代码

    我们大家都知道ListView具有添加头部和添加底部的方法,但是RecyclerView并没有这样子的方法。所以RecyclerView是不能添加底部和头部的,...

    砸漏
  • 跨服夺矿战——java游戏服务器功能

    以前开发的游戏活动,在普通的游戏活动上添加了跨服玩法,需要用到世界服务器中转,提供思路给大家参考

    深雾
  • 【初识Go】| Day13 并发编程

    “Concurrency is about dealing with lots of things at once. Parallelism is about ...

    yussuy
  • 聊聊flink jdbc的ParameterValuesProvider

    本文主要研究一下flink jdbc的ParameterValuesProvider

    codecraft
  • 【要什么自行车】ASP.NET MVC4笔记03:调用编辑器 kindeditor

    阿炬
  • 聊聊flink jdbc的ParameterValuesProvider

    本文主要研究一下flink jdbc的ParameterValuesProvider

    codecraft
  • Spring boot+Spring security+JJWT 实现restful风格的权限验证

    https://github.com/MarkGao11520/spring-boot-security-restful

    Meet相识

扫码关注云+社区

领取腾讯云代金券