编译原理:词法分析程序

前言

  又到了做实验的时候了,而且是编译原理的实验,课程内容还没怎么听懂呢,但是也只能硬着头皮上了。

实现

  我们先来看看实验要求吧:

  1. 允许用户自己输入程序并保存为文件

  2. 系统能够输出经过预处理后的源程序(去掉注释、换行、空格等)

  3. 能够将该源程序中所有的单词根据其所属类型(整数、保留字、运算符、标识符等。定义的类C 语言中的标识符只能以字母或下划线开头)进行归类显示,例如:识别保留字:if、int、for、while、do、return、break、continue 等,其他的都识别为标识符;常数为无符号整形数;运算符包括:+、-、*、/=、>、<、>=、<=、!=等;分隔符包括:,、;、{、}、(、)等。

  4. 实现文件的读取操作,而不是将文本以字符串形式预存于程序中。文本内容为待分析的类 C 语言程序。
      我们先来看一看从控制台输入的程序和最后的结果。


      运行结果如下:

直接上源码了:

MyMain.java

package java_project;

import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class MyMain{
    Set<String> keyWordsSet = new HashSet<String>();
    Set<String> operatorSet = new HashSet<String>();
    Set<String> separatorSet= new HashSet<String>();
    String fileStr = "",currentStr="";
    int index = -1;

    public static void main(String[] args){
        MyMain my = new MyMain();
        MyUtil.readProgram();
        my.initSets();
        my.readFile();
        my.start();

    }

    private void start(){
        for(int i=0;i<fileStr.length();i++){
            currentStr = "";
            String s = fileStr.charAt(i)+"";
            index = i;
            if(Character.isLetter(fileStr.charAt(i))||s.equals("_")){
                dealLetter();
            }else if(Character.isDigit(fileStr.charAt(i))){
                dealDigit();
            }else if(separatorSet.contains(s)){
                dealSeparator();
            }else if(operatorSet.contains(s)||s.equals("!")){
                dealOperator();
            }
            i = index;
        }
    }

    /**
     * 初始化集合
     */
    private void initSets(){
        String keyWords[] = {"if","int","for","while","do","return","break","continue"};
        keyWordsSet.addAll(Arrays.asList(keyWords));
        String operators[] = {"+","-","*","/","=",">","<",">=","<=","!="};
        operatorSet.addAll(Arrays.asList(operators));
        String separators[] = {",",";","{","}",")","("};
        separatorSet.addAll(Arrays.asList(separators));
    }

    /**
     * 初始化需要读取的程序文件
     */
    private void readFile(){
        try {
            InputStreamReader reader = new InputStreamReader(new FileInputStream("jc.c"));
            int temp;
            while((temp=reader.read())!=-1)
                fileStr+=((char)temp);
        } catch (Exception e){}
    }

    private void dealLetter(){
        currentStr+=fileStr.charAt(index);
        for(int i=index+1;i<fileStr.length();i++){
            String s = fileStr.charAt(i)+"";
            index = i;
            if(s.equals("_")||Character.isLetterOrDigit(fileStr.charAt(i))){
                currentStr+=fileStr.charAt(i);
            }else{
                break;
            }
        }
        index--;
        if(keyWordsSet.contains(currentStr)){
            System.out.println("(1,"+"\""+currentStr+"\")");
        }else{
            System.out.println("(2,"+"\""+currentStr+"\")");
        }

    }

    private void dealDigit(){
        currentStr+=fileStr.charAt(index);
        for(int i=index+1;i<fileStr.length();i++){
            index = i;
            if(Character.isDigit(fileStr.charAt(i))){
                currentStr+=fileStr.charAt(i);
            }else{
                break;
            }
        }
        index--;
        System.out.println("(3,"+"\""+currentStr+"\")");
    }

    private void dealSeparator() {
        currentStr+=fileStr.charAt(index);
        System.out.println("(5,"+"\""+currentStr+"\")");
    }

    private void dealOperator(){
        currentStr = fileStr.charAt(index)+"";
        if(index+1<fileStr.length()){
            String s1 = fileStr.charAt(index)+"";
            s1 += fileStr.charAt(index+1)+"";
            if(operatorSet.contains(s1)){
                System.out.println("(4,"+"\""+s1+"\")");
                index++;
            }else{
                System.out.println("(4,"+"\""+currentStr+"\")");
            }
        }else{
            System.out.println("(4,"+"\""+currentStr+"\")");
        }
    }
}

MyUtil.java

package java_project;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

public class MyUtil {

    public static String readProgram(){
        String str = "";
        Scanner reader = new Scanner(System.in);
        System.out.println("请输入源程序(以#end#作为输入结束的标志):");
        while(true){
            String _S = reader.nextLine();
            str+=_S+"\n";
            if(_S.endsWith("#end#")){
                str = str.replace("#end#", "");
                break;
            }
        }
        writeStrToFile(str);
        return str;
    }

    private static void writeStrToFile(String str){
        String s = dealString(str);
        try {
            FileWriter writer = new FileWriter("jc.c");
            writer.write(s);
            writer.flush();
            writer.close();
        } catch (IOException e){}
    }

    private static String dealString(String str){
        str = str.replaceAll("//.{0,}\n",""); //处理类型为 //的注释/
        str = str.replaceAll("\\s{1,}", " ");  //处理空格和回车,把几个空格合并成一个
        str = str.replaceAll("/[*].{0,}[*]/", "");  //处理类型为 /**/ 的注释
        return str;
    }
}

分析
  实现的思路比较简单,因为需要从控制台输入程序,所以 我先得到输入的字符串,然后对字符串进行预处理,去除注释,回车,以及把连续的空格换成一个空格,就可以把处理之后的字符串写入文件里。接着所有的字符从文件里读取出来放在字符串中,然后从第一个字符串开始判断,如果该字符是字母或下划线,那么就有可能是标识符或者是关键字,如果是数字那么就是整数型,如果是分隔符或者运算符,这些都是比较好考虑的,然后继续判断下一个字符,直到遇到的字符不是与前面字符不是同一类的字符,那么字符读取完毕,接下来判断该单词到底是哪一个类型并将单词输出。然后从刚才停止的位置开始,继续读取单词进行判断,直到读取完毕。

源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值