• 黑豹程序员-java语法分析入门案例(模拟代码编译器解析过程)


    功能

    模拟代码编译器解析过程

    program.txt

    begin
    a:=2; b:=4;
    c:=c-1;
    area:=3.14*a*a;
    s:=2*3.1416*r*(h+r);
    end
    #
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    TestAnalyzer.java

    package voice;
    
    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * @version v1.0 创建时间:10:09
     * @author: 作者:陈子枢
     * @web CSDN:https://blog.csdn.net/nutony
     * @description 描述:
     */
    public class TestAnalyzer {
        public static List<String> llist=new ArrayList<>();
        static Map<Integer,Integer> map=new HashMap<>();
        final static String ID = "\\p{Alpha}(\\p{Alpha}|\\d)*";
        static  int countLine=1;
        /** 整形常数 NUM >> 正则表达式*/
        final static String NUM = "\\d\\d*";
    
        /** token 词法单元
         * <词符号, 种别码> */
        /** 关键字 token*/
    
        static Map<String, Integer> TOKEN_KEYWORDS;
        /** 运算符/界符 token */
        static Map<String, Integer> TOKEN_OPERATOR_BOUNDARY;
        /** 其他单词 token*/
        static Map<String, Integer> TOKEN_ID_SUM;
    
        /** 文件根目录*/
        static final String ROOT_DIRECTORY = "program.txt";
    
        /**
         * 初始化 token 单元
         */
        public static void initToken(){//种别码创建
            TOKEN_KEYWORDS = new HashMap<String, Integer>(){//关键字
                {
                    put("for循环", 100);
    
                    put("begin", 1);
                    put("if", 2);
                    put("then", 3);
                    put("while", 4);
                    put("do", 5);
                    put("end", 6);
                }
            };
    
            TOKEN_OPERATOR_BOUNDARY= new HashMap<String, Integer>(){//运算符和界符
                {
                    put("写", 300);
                    put("改成", 301);
    
                    put("+", 13);
                    put("-", 14);
                    put("*", 15);
                    put("/", 16);
                    put(":", 17);
                    put(":=", 18);
                    put("<", 20);
                    put("<>", 21);
                    put("<=", 22);
                    put(">", 23);
                    put(">=", 24);
                    put("=", 25);
                    put(";", 26);
                    put("(", 27);
                    put(")", 28);
                    put("#", 0);
    
                }
            };
    
            TOKEN_ID_SUM= new HashMap<String, Integer>(){//标识符和整型常数
                {
                    put(ID, 10);
                    put(NUM, 11);
                }
            };
        }
    
        /**
         * 读 源程序 文件
         */
        public static void ReadFile1() {
            FileInputStream fis = null;
            InputStreamReader isr = null;
            BufferedReader br = null;
            try {
                fis = new FileInputStream(ROOT_DIRECTORY);
                isr = new InputStreamReader(fis, "UTF-8"); // 转化类
                br = new BufferedReader(isr); // 装饰类
                String line;
                /** 记录 程序 行数 */
    
                while ((line = br.readLine()) != null) {  // 每次读取一行,分析一行
                    boolean answer = lexicalAnalysis(line);
                    if(answer == false){
                        System.out.printf("ERROR 编译错误=== 第 %d 行出现 词法错误 \n", countLine);
                        break;
                    }
                    countLine++;
                }
                System.out.printf("===词法分析完成===\n");
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                try {
                    br.close(); // 关闭最后一个类,会将所有的底层流都关闭
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    
        /** 判断key是否是其他单词*/
        private static boolean isIDOrSUM(String key){
            if (key.matches(ID) ) {
                llist.add(key);
                map.put(llist.size()-1,countLine);
                System.out.printf("(%d, %s)\n", TOKEN_ID_SUM.get(ID), key);
            }else if (key.matches(NUM)) {
                llist.add(key);
                map.put(llist.size()-1,countLine);
                System.out.printf("(%d, %s)\n", TOKEN_ID_SUM.get(NUM), key);
            }else {
                return false;
            }
            return true;
        }
    
        /**
         * 进行 词法分析
         * @param word 要分析的字符串
         * @return 结果
         */
        public static boolean  lexicalAnalysis(String word){
    
            word = word.trim(); // 去首尾空格
            String[] strings = word.split("\\p{Space}+"); // 分割字符串,保证处理的字符串没有空格
            for (String string : strings) {
    
                /** 3种情况:
                 *      1. 关键字 == end (关键字的后面一定是空格 )
                 *      2. 运算符/ 分界符 == continue
                 *      3. 其他单词 == continue
                 */
                String key = "";
    
                for (int i = 0; i < string.length(); i++){
                    String indexChar = String.valueOf(string.charAt(i)) ;
                    if(i+1<string.length()){
                        if((indexChar+string.charAt(i+1)).equals("//"))
                            return true;
                    }
    
    
    
                    /** 是 运算符 或者 关键字*/
                    if (TOKEN_OPERATOR_BOUNDARY.containsKey(indexChar) ||
                            TOKEN_KEYWORDS.containsKey(string.substring(i, string.length()))){
    
                        if (key.length() > 0) {
                            if (isIDOrSUM(key) == false) {
                                /** 词法错误 */
                                return false;
                            }
                            key = "";
                        }
                        if(TOKEN_OPERATOR_BOUNDARY.containsKey(indexChar)) {
    
    
    
                            /**  1. 是 运算符/分界符 */
                            key += indexChar;
                            if(i + 1 < string.length() && TOKEN_OPERATOR_BOUNDARY.containsKey(indexChar + string.charAt(i+1))){ // 运算分界符
                                key += string.charAt(++i);
                            }
                            llist.add(key);
                            map.put(llist.size()-1,countLine);
                            System.out.printf("(%d, %s)\n",TOKEN_OPERATOR_BOUNDARY.get(key),key);
                            key = "";
                        }else if(TOKEN_KEYWORDS.containsKey(key = string.substring(i, string.length()))) {
                            /** 2. 是关键字*/
                            llist.add(key);
                            map.put(llist.size()-1,countLine);
                            System.out.printf("(%d, %s)\n",TOKEN_KEYWORDS.get(key),key);
                            key = "";
                            break;
                        }
                    }else {
                        /** 是其他单词*/
                        key += indexChar;
                        /** 其他单词后面是 1. 换行,2. 运算符/界符 3. 其他单词
                         */
                        if(i+1 >= string.length()){
                            if (isIDOrSUM(key) == false) {
                                /** 词法错误 */
                                return false;
                            }
                        }
                    }
                }
    
    
            }
    
            return true;
        }
    
        public static void main(String[] args) {
    
            initToken();
            System.out.println("==词法分析程序==");
            System.out.println("从文件中读取程序");
            System.out.println("==============");
    
            ReadFile1(); for(String s:llist) System.out.println(s);
    
            System.out.println();
        }
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
  • 相关阅读:
    Python标准库之collections
    华为设备配置VRRP负载分担
    字符串函数(一)之常见用法
    ChaosBlade Java 场景性能优化,那些你不知道的事
    21、ila
    webpack前端性能优化的操作有哪些?
    如何创建自己的Spring Boot Starter并为其编写单元测试
    基于深度学习的环路滤波和残差缩放
    LeetCode —— 复写零(双指针)
    Redis高级数据类型
  • 原文地址:https://blog.csdn.net/nutony/article/details/133823038