编译原理2 词法分析器设计

设计一个词法分析器,用 C 语言或者其他的高级语言实现。从预处理过的源代码文本 文件(实验一的输出文件)中读取源代码字符串,词法分析输出的二元式写入另外一个文本文件中。

 定义Type类:

type:词的类型(保留字、运算符、分界符、标识符、整型、浮点型等)

value:词的值

typeValue:词在类型中的对应下标(标识符、整型、浮点型为-1)

//定义type类
class StrType{
    String type;
    String value;
    int typeValue = -1;
    StrType(String type,String value,int typeValue){
        this.type = type;
        this.value = value;
        this.typeValue = typeValue;
    }
    StrType(String type,String value){
        this.type = type;
        this.value = value;
    }

    @Override
    public String toString() {
        return "( "+type+" , "+typeValue+" , "+value+" )";
    }//重写toString方法
}

定义WordCut类:

参数:

String [ ] reserve 用于存储保留字。

String [ ] operator 用于存储运算符。

char [ ] divide 用于存储分界符。

方法:

char[ ] textTreatment(char[ ] firstText) 文件预处理

boolean isLetter(char ch) 判断是否为字母

boolean isNum(char ch) 判断是否为数字

int isReserve(String str) 判断是否为保留字(返回对应编号)

int isOperator(String str) 判断是否为运算符(返回对应编号)

int isDivide(String str) 判断是否为分界符(返回对应编号)

String textToString(File file) 使用io流,将文件转换为字符串

List start() 初始方法

public class WordCut {
    //保留字
    public String []reserve={"if","else","while","throw","this","int","String","char","double","float","this",
            "static","public","private","default","switch","catch","void","try","return"};
    //运算符
    public String []operator={"+","-","*","/","++","--","==","!=",">","<",">=",
            "<=","&&","||","!","&","|","^","~","<<",">>",">>>","+=","="};
    //分界符
    public char[]divide={'<','>','(',')','{','}','[',']','\'','"',',',';','?','/','\\',':','.'};

    //文本预处理 1)去掉单行注释 2)去掉多行注释 3)去掉空格换行
    public char[] textTreatment(char[] firstText){
        char []nextText = new char[9999];
        int flag = 0;//标识当前处理字符位置
        if (firstText.length!=0){//如果字符数组长度为0,则文件为空文件,不需要处理
            for (int i = 0; i < firstText.length; i++) {//从字符数组第一位开始遍历
                //去掉单行注释
                if (firstText[i] == '/' && firstText[i+1] == '/'){
                    //寻找单行注释
                    while(firstText[i]!='\n'){//寻找换行符号,表示单行注释结束
                        i++;//省略注释中的内容,故i++ flag保持不变
                    }
                }
                //去除多行注释
                if (firstText[i] == '/' && firstText[i+1] == '*'){
                    //寻找多行注释开头位置
                    i = i + 2;//开头“/*”占两个字符,要去掉
                    while(firstText[i] == '/' && firstText[i+1] == '*'){//寻找注释结束位置
                        i++;//省略注释中的内容,故i++ flag保持不变
                        if(i == (firstText.length-1)){
                            //如果找到字符数组最后一位,还没有找到结束位置,则有错误
                            System.out.println("未找到注释终止符号!");
                            System.exit(0);
                        }
                    }
                    i = i + 2;//结束“*/”占两个字符,要去掉
                }
                //去除空格换行
                if (firstText[i] != '\n' && firstText[i] != '\r' && firstText[i] != '\t'){
                    nextText[flag] = firstText[i];//将字符存入nextText数组
                    flag++;
                }
            }
            flag++;
            nextText[flag] = '\0';//终结字符串
        }
        return nextText;
    }

    //判断是否为字母
    public boolean isLetter(char ch){
        if((ch>='a'&&ch<='z')||(ch>='A'&&ch<'Z'))
        //判断是否为大写或小写字母
        {
            return true;
        }
        else
            return false;
    }

    //判断是否为数字
    public boolean isNum(char ch){
        if(ch>='0'&&ch<='9')
        {
            return true;
        }
        else
            return false;
    }

    //判断是否为保留字(返回对应编号)
    public int isReserve(String str){
        int flag = -1;
        //设置flag,如果是保留字,则返回对应下标,否则返回-1
        for (int i = 0; i < reserve.length; i++) {
            //遍历reserve
            if (str.equals(reserve[i])){
                flag = i;
                break;//已经查找到位置停止遍历
            }
        }
        return flag;
    }

    //判断是否为运算符(返回对应编号)
    public int isOperator(String str){
        int flag = -1;
        for (int i = 0; i < operator.length; i++) {
            if (str.equals(operator[i])){
                flag = i;
                break;
            }
        }
        return flag;
    }

    //判断是否为分界符(返回对应编号)
    public int isDivide(String str){
        int flag = -1;
        for (int i = 0; i < divide.length; i++) {
            if (str.equals(divide[i]+"")){
                flag = i;
                break;
            }
        }
        return flag;
    }

    //使用io流,将文件转换为字符串
    public String textToString(File file){
        StringBuilder strs = new StringBuilder();//使用StringBuilder存储文件内容
        try{//io异常处理
            BufferedReader br = new BufferedReader(new FileReader(file));
            String s = null;
            while ((s=br.readLine())!=null){
                strs.append(System.lineSeparator()+s);//strs追加内容
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return strs.toString();
    }

    //初始方法
    public List start(){
        List<StrType> textList = new LinkedList<StrType>();//使用列表存储类型和值
        //源文件
        File newFile = new File("D://a.txt");
        //将源文件转String
        String fileString = textToString(newFile);
        //String转字符数组
        char[] fileFirstChar = fileString.toCharArray();
        //对内容进行预处理,去除注释,换行
        char[] fileChar = textTreatment(fileFirstChar);
        int flag = 0;//当前扫描位置
        String strFlag = "";//临时存储字符串

        while (fileChar[flag]!='\0'){
            //判断是不是字母 可能为保留字或者为标识符
            if (isLetter(fileChar[flag])){
                strFlag+=fileChar[flag];
                //当不为字符或数组时停止扫描
                while(isLetter(fileChar[flag+1]) || isNum(fileChar[flag+1])){
                    flag++;
                    strFlag += fileChar[flag];
                }
                //判断是否为保留字
                if(isReserve(strFlag)!=-1){
                    textList.add(new StrType("保留字",strFlag,isReserve(strFlag)));
                }else{
                    textList.add(new StrType("标识符",strFlag));
                }
            }

            //当开头为数字时,可能为整数或浮点数
            else if(isNum(fileChar[flag])){
                strFlag+=fileChar[flag];
                while(isNum(fileChar[flag+1])){
                    flag++;
                    strFlag+=fileChar[flag];
                }
                //如果有小数点,则为浮点数
                if (fileChar[flag+1]=='.'){
                    flag++;
                    //如果小数点后无数字
                    if (!isNum(fileChar[flag+1])){
                        System.out.println("小数点后无数字");
                        strFlag="";
                        break;
                    }else{
                        strFlag+=fileChar[flag];
                        while(isNum(fileChar[flag+1])){
                            flag++;
                            strFlag+=fileChar[flag];
                        }
                    }
                    textList.add(new StrType("浮点数",strFlag));
                }else {
                    textList.add(new StrType("整数",strFlag));
                }
            }else if(fileChar[flag]!=' '){//既不是数字也不是字母,为分节符或字母
                strFlag+=fileChar[flag];
                if (isDivide(strFlag)!=-1){
                    textList.add(new StrType("分界符",strFlag,isDivide(strFlag)));
                    strFlag="";
                    flag++;
                    continue;
                }else {
                    while((isDivide(fileChar[flag+1]+"")==-1) && (isNum(fileChar[flag+1])==false)
                            && (isLetter(fileChar[flag+1])==false)){
                        flag++;
                        strFlag+=fileChar[flag];
                    }
                    if (isOperator(strFlag)!=-1){
                        textList.add(new StrType("运算符",strFlag,isOperator(strFlag)));
                    }else {
                        textList.add(new StrType("非法字符",strFlag));
                    }
                }
            }
            strFlag="";
            flag++;
        }

        return textList;
    }
}

主类main类:

public class Main {
    public static void main(String[] args) {
        WordCut wdc = new WordCut();
        List<StrType> fileList = wdc.start();
        for (StrType styp:fileList) {
            System.out.println(styp.toString());
        }
    }
}

源文件处理前:

处理结果:

猜你喜欢

转载自blog.csdn.net/yubo_830/article/details/102896350