zoukankan      html  css  js  c++  java
  • 软件构造——制作词法分析器

    实验内容:

    编制一个读单词过程,源程序为一个文件,读取该文件,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、界符五大类。并依次输出各个单词的内部编码及单词符号自身值。

    单词的内部编码如下:

    1、保留字:if、int、for、while、do、return、break、continue;单词种别码为1;

    2、标识符:除保留字外的以字母开头,后跟字母、数字的字符序列;单词种别码为2;

    3、常数为无符号整形数;单词种别码为3;

    4、运算符包括:+、-、*、/、=;单词种别码为4;

    5、分隔符包括:,;{}(); 单词种别码为5

    代码实现:

    //mainpage.java

    /**
     * 高泽伟 19.11.15
     */
    package rjgz_CiFaFenXiQi;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.Reader;
    import java.util.Arrays;
    import java.util.List;
    
    public class mainpage {
        //利用List存放五大单词类
        
        
        //保存关键字
        private static List<String> KeyWords;
        //保存运算符
        private static List<String> Operators;
        //保存界符
        private static List<String> Boundarys;
        //空格字符
        private static List<String> Spaces;
        
        //剩下的就是标识符
        
        //初始化单词
        static {
            // 关键字数组 --> 关键字列表
            String[] keywordArr = { "public", "private", "protected", "short",
                    "int", "long", "char", "float", "double", "boolean", "static",
                    "void", "for","while" ,"return","continue"};
            KeyWords = Arrays.asList(keywordArr);//Arrays.asList(keywordArr)返回指定数组支持的固定大小列表
     
            // 操作符数组 --> 操作符列表
            String[] operatorArr = { "+", "-", "*", "/", "%", "=", ">", "<", "&" };
            Operators = Arrays.asList(operatorArr);
     
            // 界符数组 --> 界符列表
            String[] boundaryArr = { "" + '{', "" + '}', "" + '[', "" + ']',
                    "" + '(', "" + ')', "" + ';' , "" + '.' };
            Boundarys = Arrays.asList(boundaryArr);
     
            // 空格字符数组 --> 空格字符列表
            String[] SpaceArr = { " ", "	", "
    " };
            Spaces = Arrays.asList(SpaceArr);
        }
        
        
        static String str="";//存储文件内容的字符串
        static StringBuffer strb = new StringBuffer();//字符串缓冲
        static boolean isDelimiter = false;//判断是否有分隔符
        
        
        
        //主函数
        public static void main(String[] args) {
            String inStr =  readFileByChars("E:/课程学习资料/软件构造 刘丹/软件构造/源程序代码test.txt");
            //System.out.println("+++"+inStr);
            System.out.println("---------------------词法分析器---------------------");
            for (char ch : inStr.toCharArray()) {//toCharArray() 方法将字符串转换为字符数组。
    //            System.out.println(ch);
                match(ch);
            }
        }
        
        
        
        /*
         * 将文件里的源码以String格式存入str字符串,并且排除了‘~’符(为啥?)
         */
        public static String  readFileByChars(String fileName) {
            Reader reader = null;
          
            try {
                //System.out.println("以字符为单位读取文件内容,一次读多个字符:");
                // 一次读多个字符
                char[] tempchars = new char[300];//char[] 字符数组
                int charread = 0;
                reader = new InputStreamReader(new FileInputStream("E:/课程学习资料/软件构造 刘丹/软件构造/源程序代码test.txt"));
                // 读入多个字符到字符数组中,charread为一次读取字符数
               
                /*
                 * read()会返回一个布尔值,有数据则为true,没有数据就是false
                 * reader.read(char[])返回字符的个数(
    占两个字符)
                 */
                while ((charread = reader.read(tempchars)) != -1) {
                    //这一步运行了charread = reader.read(tempchars)
                    System.out.println("-------读取过程:-------");
                    System.out.println("charread="+charread);
                    
                    //排除'~'符
                    if ((charread == tempchars.length)
                            && (tempchars[tempchars.length - 1] != '~')) {
                        System.out.print(tempchars+"1");
                    } else {
                        for (int i = 0; i < charread; i++) {
                            if (tempchars[i] == '~') {
                                continue;
                            } else {
                                str+=tempchars[i];
                                System.out.println(tempchars[i]);
                               
                            }
                        }
                        System.out.println("-------源程序str:-------");
                        System.out.println(str);
                    }
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e1) {
                    }
                }
            }
            return str;
        }
        
        
        
        
        /*
         * 识别单词并分类
         */
        static void match(char ch) {
            // 分割符缓冲
            StringBuffer bouStrb = new StringBuffer();
            // 1. 判断字符类型
            /**
             * 以(界符、空格符、运算符)作为(关键字和一般标识符)的划分
             * 即,(关键字和一般标识符)两边一定是(界符、空格符、运算符)
             */
            // 1.0 空格,返回空格
            if (Spaces.indexOf(ch + "") >= 0) {
                /*
                 * indexOF(String)
                 * 返回字符中indexof(string)中字串string在父串中首次出现的位置,
                 * 从0开始!没有返回-1;方便判断和截取字符串!
                 */
                isDelimiter = true;
                
            }
            // 1.1. 操作符, 返回"operator"
            if (Operators.indexOf(ch + "") >= 0) {
                isDelimiter = true;
                bouStrb = new StringBuffer(ch + " 是操作符  单词种别码为4");
            }
            // 1.2 界符, 返回"boundary"
            if (Boundarys.indexOf(ch + "") >= 0) {
                isDelimiter = true;
                bouStrb = new StringBuffer(ch + " 是界符 单词种别码为5");
            }
            
            
            
            
            /**
             * 如果是分隔符,则判断已经存入strb内的内容是常数、关键字还是标识符
             */
            if (isDelimiter) {
                if (strb.length() > 0) {
                    //charAt() 方法可返回指定位置的字符。
                    if (strb.charAt(0) >= '0' && strb.charAt(0) <= '9') {
                        System.out.println(strb + " 是常数 单词种别码为3");
     
                    } else if (KeyWords.indexOf(strb.toString()) >= 0) {    //toString()方法返回反映这个对象的字符串
                        System.out.println(strb + " 是关键字  单词种别码为1");
                    } else {
                        System.out.println(strb + "是标识符  单词种别码为2");
                    }
                }
                if (bouStrb.length() > 0)
                    System.out.println(bouStrb);
                strb.setLength(0);
                isDelimiter = false;
                return;
            }
            
            
            
     
            /**
             * 如果不是分隔符,则将该字符存入strb内,直到出现分隔符
             */
            strb.append(ch);
     
        }
        
        
    }

    源程序文件内容:

    //源程序代码test.txt
    if i>j then ~i=0
    else j=1

    实验结果截图:

       发现自己好多java基础的东西都不会,借这次实验把一些不会的东西从网上找到答案,用注释写在代码里了,以后还要多加学习,补习java。

  • 相关阅读:
    Apache Pig的前世今生
    openssl之EVP系列之6---EVP_Encrypt系列函数编程架构及样例
    P3388 【模板】割点(割顶)
    让priority_queue支持小根堆的几种方法
    2017.11.7解题报告
    一个例子教你如何与出题人斗智斗勇
    debug
    树上倍增求LCA及例题
    素数的筛法
    Catalan卡特兰数入门
  • 原文地址:https://www.cnblogs.com/jmdd/p/11868430.html
Copyright © 2011-2022 走看看