【编译原理】作业:简单的词法分析器(Java)

课堂上留的作业,简单的词法分析器,花了一天时间做完,写个小笔记

程序思路来自 四季写爱 ,感兴趣的可以去看看

以下是我的代码:

import java.io.File;
import java.io.FileReader;
import java.util.Scanner;

public class Lexer {
    public static void main(String[] args) throws Exception {
        char[] chars = readFile();
        analyze(chars);
    }

    public static void analyze(char[] opt){
        int variableCounter = 0;        //标识符计数器
        String temp;        //当前字符串
        char current;       //当前字符
        for (int i = 0; i < opt.length; i++){
            temp = "";
            current = opt[i];
            if (current == ' ' || current == '\t' || current =='\r'){       //空格处理
            }else if (isLetter(current) || current == '_'){     //读取到字母或者_
                while (isLetter(current) || isDigit(current) || current == '_'){        //字母或_开头可能出现的情况
                    temp+=current;      //拼接到当前字符串
                    current = opt[++i];
                }
                i--;        //不匹配while条件时的回退
                if (isKeyWord(temp)){       //关键字匹配
                    System.out.println(temp + "是关键字");
                }else if (isVariableName(temp)){        //标识符匹配
                    variableCounter++;
                    System.out.println("<id(" + temp + ")," + variableCounter + ">");
                }
            }else if (isDigit(current)){
                while (isDigit(current) || current == '.' || current == 'E' || current == 'e' ||current == '-' || current == '+'){      //数字开头可能出现的情况
                    temp+=current;
                    current = opt[++i];
                }
                i--;
                if (isUnsignedNumber(temp)){
                    System.out.println("<" + temp + ">");
                }
            }else if (isOperator(temp+=current)){       //操作符情况
                System.out.println("<" + temp + ">");
            }
        }
    }

    /**
     * 获取文件字符流
     * @return  返回给定文件的字符流
     * @throws Exception
     */
    public static char[] readFile() throws Exception {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter the src of your file:");
        String src = sc.nextLine();
        File file = new File(src);
        FileReader fileReader = new FileReader(file);
        int length = (int) file.length();
        char buf[] =new char[length+1];
        fileReader.read(buf);
        fileReader.close();
        sc.close();
        return buf;
    }

    /**
     * 判定变量名
     * @param opt 判定对象
     * @return true是合法变量名,false非法变量名
     */
    public static boolean isVariableName(String opt){
        char[] chars = opt.toCharArray();
        boolean flag = true;
        if (!isLetter(chars[0]) && chars[0] != '_'){
            flag = false;
            return flag;
        }
        for (int i = 1; i < chars.length; i++){
            if (!isLetter(chars[i]) && chars[i] != '_' && !isDigit(chars[i])){
                flag = false;
                return flag;
            }
        }
        return flag;
    }

    /**
     * 判定无符号数
     * @param opt 判定对象字符串
     * @return true是无符号数,false不是无符号数
     */
    public static boolean isUnsignedNumber(String opt){
        char[] chars = opt.toCharArray();
        boolean flag = true;
        boolean dot = false;
        boolean exponent = false;
        if (!isDigit(chars[0])){        //第一个字符不是数字
            flag = false;
            return flag;
        }
        for (int i = 1; i < chars.length; i++){
            //非数字,小数点,Ee的字符判定
            if (!isDigit(chars[i]) && chars[i] != 'e' && chars[i] != 'E' && chars[i] != '.' ){
                flag = false;
                return flag;
            }
            //.的判定
            if (chars[i] == '.' && !dot){       //第一次出现小数点
                dot = true;     //包含小数点
            }else if(chars[i] == '.' && dot){       //第二次出现小数点
                flag = false;
                return flag;
            }
            //Ee的判定
            if ((chars[i] == 'e' || chars[i] == 'E') && !exponent) {    //第一次出现指数e
                exponent = true;        //指数e
                i++;
                //Ee后的符号判定及处理
                if(i == chars.length){  //数组越界处理,说明字符串以e结尾
                    flag = false;
                    return flag;
                }
                if (chars[i] != '-' && chars[i] != '+') {       //指数后面的符号
                    i--;        //回溯
                }
            }else if((chars[i] == 'e' || chars[i] == 'E') && exponent){     //第二次出现指数e
                flag =false;
                return flag;
            }
        }
        return flag;
    }

    /**
     * 判断关键字
     * @param opt 被判断的字符串
     * @return true是关键字,false不是关键字
     */
    public static boolean isKeyWord(String opt){
        //保留字集
        String[] keyWordSet = {"if", "while", "else", "switch"};
        boolean flag = false;
        for (int i = 0; i < keyWordSet.length; i++) {
            if (opt.equals(keyWordSet[i])){
                flag = true;
                return flag;
            }
        }
        return flag;
    }

    /**
     * 判别无符号数
     * @param opt 被判别的字符
     * @return true是数字,false不是数字
     */
    public static boolean isDigit(char opt){
        if (opt >= '0' && opt <= '9'){
            return true;
        }
        return false;
    }

    /**
     * 判别字母
     * @param opt 被判别的字符
     * @return true是字母,false不是字母
     */
    public static boolean isLetter(char opt){
        if ((opt >= 'a' && opt <= 'z')||(opt >= 'A' && opt <= 'Z')) {
            return true;
        }
        return false;
    }

    /**
     * 判断操作符
     * @param opt 被判断的字符
     * @return true是操作符,false非操作符
     */
    public static boolean isOperator(String opt){
        boolean flag = false;
        String[] operators = {"+", "-", "*", "/", "="};
        for (int i = 0; i < operators.length; i++){
            if (opt.equals(operators[i])){
                flag = true;
                return flag;
            }
        }
        return flag;
    }
}

提供的文件:

提供的文件

运行结果:

运行结果

posted @ 2020-10-25 16:48  夕風吹雨  阅读(129)  评论(0)    收藏  举报