├── .gitignore ├── README.md ├── docs ├── 01_var_defn.txt ├── 02_var_defn.txt ├── 03_var_defn.txt ├── 04_var_defn.txt ├── 05_var_defn.txt ├── grammar.txt └── 大作业.pdf ├── input ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── code.txt ├── grammar.txt └── grammar_test.txt ├── output ├── First集合.tsv ├── Follow集合.tsv ├── 分析表.tsv ├── 文法.tsv ├── 终结符.tsv ├── 词法分析产生的中间结果.tsv └── 非终结符.tsv ├── result ├── gra.tsv └── lex.tsv └── src ├── Config.java ├── FirstTable.java ├── FollowTable.java ├── Main.java ├── MainLexicon.java ├── MainParse.java ├── PredictMap.java ├── TextLexicon.java ├── TextLexiconInput.java ├── TextParse.java └── TextParseInput.java /.gitignore: -------------------------------------------------------------------------------- 1 | /out 2 | /.idea 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 天津大学编译原理大作业 2 | 3 | * 完成词法分析 4 | * 完成语法分析 5 | 6 | ## 代码结构 7 | 8 | ```bash 9 | compiler 10 | |- input 11 | |- grammer.txt 12 | |- 测试文件 13 | |- ... 14 | |- output 15 | |- First集合.txt 16 | |- Follow集合.txt 17 | |- 分析表.txt 18 | |- 文法.txt 19 | |- 终结符.txt 20 | |- 词法分析产生的中间结果.txt 21 | |- 非终结符.txt 22 | |- result 23 | |- gra.tsv 24 | |- lex.tsv 25 | |- src 26 | |- Config.java 27 | |- TextLexicon.java 28 | |- TextLexiconInput.java 29 | |- MainLexicon.java 30 | |- FirstTable.java 31 | |- FollowTable.java 32 | |- PredictMap.java 33 | |- TextParse.java 34 | |- TextParseInput.java 35 | |- MainParse.java 36 | |- Main.java 37 | |- README.md 38 | ``` 39 | 40 | Config: 一些配置 41 | 42 | TextLexicon: 词法分析的主类 43 | 44 | MainLexicon: 词法分析的入口类 45 | 46 | TextLexiconInput: 词法分析的输入类 47 | 48 | TextParseInput: 语法分析的输入类 49 | 50 | TextParse: 语法分析中负责解析文法,生成First表,Follow表,预测表的类 51 | 52 | MainParse: 利用语法分析的输入和预测表进行语法分析的类 53 | 54 | FirstTable: 生成First表的类 55 | 56 | FollowTable: 生成Follow表的类 57 | 58 | PredictMap: 生成预测表的类 59 | 60 | Formula: 表示文法的类 61 | 62 | ## 源程序编译步骤 63 | 64 | Main.java 为入口文件,从 Main.java 进行编译。 65 | 66 | ## 一、词法分析器设计 67 | 68 | ### 1. 实现路径 69 | 70 | #### 1.1 实现思路 71 | 72 | 读取c--文件,存放为字符串类型。遍历整个字符串,将结果存放于三元组数组中,将中间结果也存放于数组中,输出后作为语法分析的输入 73 | 74 | #### 1.2 需要实现的单词符号 75 | 76 | 1. 关键字(KW,不区分大小写)包括: (1) int (2) void (3) return (4) const (5) main 77 | 2. 运算符(OP)包括:(6) + (7) - (8) * (9) / (10) % (11) = (12) > (13) < (14) == (15) <= (16) >= (17) != (18) && (19) || 78 | 3. 界符(SE)包括:(20)( (21) ) (22) { (23) } (24); (25) , 79 | 4. 标识符(IDN)定义与 C 语言保持相同,为字母、数字和下划线(_)组成的不以数字开头的串 80 | 5. 整数(INT)的定义与 C 语言类似,整数由数字串表示 81 | 82 | ### 2. 算法描述 83 | 84 | 运用面向对象的编程思想,创建TextLexicon类和MainLexicon类。 85 | 由简到繁,先将类的定义规划好,再逐渐扩充完善细节。 86 | 87 | #### 2.1 TextLexicon类定义与实现 88 | 89 | 设置threeElements,lex\_result\_stack,lex\_error\_stack,text\_length,row\_numberKey 六个属性,分别代表要输出的三元组,得出的文本的值,可能出现的错误,输入文本的长度,输入文本行号,关键字。使用面向对象的编程方式来进行词法分析器的编写。 90 | 91 | **类中的方法:** 92 | 93 | - isAlpha方法 94 | 95 | 用于判断当前字符是否为字母或下划线。 96 | 97 | ```java 98 | public int isAlpha(char c){ 99 | if(((c<='z')&&(c>='a')) || ((c<='Z')&&(c>='A')) || (c=='_')) 100 | return 1; 101 | else 102 | return 0; 103 | } 104 | ``` 105 | 106 | - isNumber方法 107 | 108 | 用于判断当前字符是否为数字。。 109 | 110 | ```java 111 | public int isNumber(char c) { 112 | if ((c >= '0') && (c <= '9')) 113 | return 1; 114 | else 115 | return 0; 116 | } 117 | ``` 118 | 119 | - isKey方法 120 | 121 | 用于判断当前字符串是否为关键字。 122 | 123 | ```java 124 | public int isKey(String t) { 125 | for (int i = 0; i < Key.length; i++) { 126 | if (t.equals(Key[i])) { 127 | return 1; 128 | } 129 | } 130 | return 0; 131 | } 132 | ``` 133 | 134 | - scannerAll方法 135 | 136 | 用于遍历读取的整个c--文本字符串。 137 | 138 | ```java 139 | public void scannerAll() { 140 | int i = 0; 141 | char c; 142 | text = text + '\0'; 143 | while (i < text_length) { 144 | c = text.charAt(i); 145 | if (c == ' ' || c == '\t') 146 | i++; 147 | else if (c == '\r' || c == '\n') { 148 | row_number++; 149 | i++; 150 | } else 151 | i = scannerPart(i); 152 | } 153 | } 154 | ``` 155 | 156 | - scannerPart方法 157 | 158 | 用于扫描字符串单元。 159 | 160 | ```java 161 | public int scannerPart(int arg0) { 162 | int i = arg0; 163 | char ch = text.charAt(i); 164 | String s = ""; 165 | // 第一个输入的字符是字母 166 | if (isAlpha(ch) == 1) { 167 | s = "" + ch; 168 | return handleFirstAlpha(i, s); 169 | } 170 | // 第一个是数字的话 171 | else if (isNumber(ch) == 1) { 172 | s = "" + ch; 173 | return handleFirstNum(i, s); 174 | 175 | } 176 | // 既不是既不是数字也不是字母 177 | else { 178 | s = "" + ch; 179 | switch (ch) { 180 | case ' ': 181 | case '\n': 182 | case '\r': 183 | case '\t': 184 | return ++i; 185 | case '[': 186 | case ']': 187 | case '(': 188 | case ')': 189 | case '{': 190 | case '}': 191 | printResult(s, "双界符"); 192 | return ++i; 193 | case ':': 194 | if (text.charAt(i + 1) == '=') { 195 | s = s + "="; 196 | printResult(s, "界符"); 197 | return i + 2; 198 | } else { 199 | printError(row_number, s, "不能识别"); 200 | return i + 1; 201 | } 202 | case ',': 203 | case '.': 204 | case ';': 205 | printResult(s, "单界符"); 206 | return ++i; 207 | case '\\': 208 | if (text.charAt(i + 1) == 'n' || text.charAt(i + 1) == 't' || text.charAt(i + 1) == 'r') { 209 | printResult(s + text.charAt(i + 1), "转义"); 210 | return i + 2; 211 | } 212 | case '\'': 213 | // 判断是否为单字符,否则报错 214 | return handleChar(i, s); 215 | case '\"': 216 | // 判定字符串 217 | return handleString(i, s); 218 | case '+': 219 | return handlePlus(i, s); 220 | case '-': 221 | return handleMinus(i, s); 222 | case '*': 223 | case '/': 224 | if (text.charAt(i + 1) == '*') { 225 | return handleNote(i, s); 226 | } else if (text.charAt(i + 1) == '/') { 227 | return handleSingleLineNote(i, s); 228 | } 229 | case '!': 230 | case '=': 231 | ch = text.charAt(++i); 232 | if (ch == '=') { 233 | // 输出运算符 234 | s = s + ch; 235 | printResult(s, "运算符"); 236 | return ++i; 237 | } else { 238 | // 输出运算符 239 | printResult(s, "运算符"); 240 | return i; 241 | } 242 | case '>': 243 | return handleMore(i, s); 244 | case '<': 245 | return handleLess(i, s); 246 | case '%': 247 | ch = text.charAt(++i); 248 | if (ch == '=') { 249 | // 输出运算符 250 | s = s + ch; 251 | printResult(s, "运算符"); 252 | return ++i; 253 | } else if (ch == 's' || ch == 'c' || ch == 'd' || ch == 'f' || ch == 'l') { 254 | // 输出类型标识符 255 | s = s + ch; 256 | printResult(s, "输出类型标识符"); 257 | return ++i; 258 | } else { 259 | // 输出求余标识符 260 | printResult(s, "求余标识符"); 261 | return i; 262 | } 263 | default: 264 | // 输出暂时无法识别的字符,制表符也被当成了有问题的字符 265 | printError(row_number, s, "暂时无法识别的标识符"); 266 | return ++i; 267 | } 268 | } 269 | } 270 | ``` 271 | 272 | - handleFirstAlpha方法 273 | 274 | 用于处理字符串单元的第一个输入为字母或下划线的情况 275 | 276 | ```java 277 | public int handleFirstAlpha(int arg, String arg0) { 278 | int i = arg; 279 | String s = arg0; 280 | char ch = text.charAt(++i); 281 | while (isAlpha(ch) == 1 || isNumber(ch) == 1) { 282 | s = s + ch; 283 | ch = text.charAt(++i); 284 | } 285 | // if(s.length()==1){ 286 | // printResult(s, "字符常数"); 287 | // return i; 288 | // } 289 | // 到了结尾 290 | if (isKey(s) == 1) { 291 | // 输出key 292 | printResult(s, "关键字"); 293 | return i; 294 | 295 | } else { 296 | // 输出普通的标识符 297 | printResult(s, "标识符"); 298 | return i; 299 | } 300 | } 301 | ``` 302 | 303 | - handleFirstNum方法 304 | 305 | 用于处理字符串单元的第一个输入为数字的情况 306 | 307 | ```java 308 | public int handleFirstNum(int arg, String arg0) { 309 | int i = arg; 310 | char ch = text.charAt(++i); 311 | String s = arg0; 312 | while (isNumber(ch) == 1) { 313 | s = s + ch; 314 | ch = text.charAt(++i); 315 | } 316 | if ((text.charAt(i) == ' ') || (text.charAt(i) == '\t') || (text.charAt(i) == '\n') || (text.charAt(i) == '\r') 317 | || (text.charAt(i) == '\0') || ch == ';' || ch == ',' || ch == ')' || ch == ']' || ch == '[' 318 | || ch == '(') { 319 | // 到了结尾,输出数字 320 | printResult(s, "整数"); 321 | return i; 322 | } else if (ch == 'E') { 323 | if (text.charAt(i + 1) == '+') { 324 | s = s + ch; 325 | ch = text.charAt(++i); 326 | s = s + ch; 327 | ch = text.charAt(++i); 328 | while (isNumber(ch) == 1) { 329 | s = s + ch; 330 | ch = text.charAt(++i); 331 | } 332 | if (ch == '\r' || ch == '\n' || ch == ';' || ch == '\t') { 333 | printResult(s, "科学计数"); 334 | return ++i; 335 | } else { 336 | printError(i, s, "浮点数错误"); 337 | return i; 338 | } 339 | } else if (isNumber(text.charAt(i + 1)) == 1) { 340 | s = s + ch; 341 | ch = text.charAt(++i); 342 | while (isNumber(ch) == 1) { 343 | s = s + ch; 344 | ch = text.charAt(++i); 345 | } 346 | if (ch == '\r' || ch == '\n' || ch == ';' || ch == '\t') { 347 | printResult(s, "科学计数"); 348 | return ++i; 349 | } else { 350 | printError(row_number, s, "浮点数错误"); 351 | return i; 352 | } 353 | } else { 354 | printError(row_number, s, "科学计数法错误"); 355 | return ++i; 356 | } 357 | } 358 | 359 | // 浮点数判断 360 | else if (text.charAt(i) == '.' && (isNumber(text.charAt(i + 1)) == 1)) { 361 | s = s + '.'; 362 | ch = text.charAt(++i); 363 | while (isNumber(ch) == 1) { 364 | s = s + ch; 365 | ch = text.charAt(++i); 366 | } 367 | if (ch == 'E') { 368 | if (text.charAt(i + 1) == '+') { 369 | s = s + ch; 370 | ch = text.charAt(++i); 371 | s = s + ch; 372 | ch = text.charAt(++i); 373 | while (isNumber(ch) == 1) { 374 | s = s + ch; 375 | ch = text.charAt(++i); 376 | } 377 | if (ch == '\r' || ch == '\n' || ch == ';' || ch == '\t') { 378 | printResult(s, "科学计数"); 379 | return ++i; 380 | } else { 381 | printError(i, s, "浮点数错误"); 382 | return i; 383 | } 384 | } else if (isNumber(text.charAt(i + 1)) == 1) { 385 | s = s + ch; 386 | ch = text.charAt(++i); 387 | while (isNumber(ch) == 1) { 388 | s = s + ch; 389 | ch = text.charAt(++i); 390 | } 391 | if (ch == '\r' || ch == '\n' || ch == ';' || ch == '\t') { 392 | printResult(s, "科学计数"); 393 | return ++i; 394 | } else { 395 | printError(row_number, s, "浮点数错误"); 396 | return i; 397 | } 398 | } else { 399 | printError(row_number, s, "科学计数法错误"); 400 | return ++i; 401 | } 402 | } else if (ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ' || ch == '\0' || ch != ',' || ch != ';') { 403 | printResult(s, "浮点数"); 404 | return i; 405 | } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '\0') { 406 | printResult(s, "浮点数"); 407 | return i; 408 | } else { 409 | while (ch != '\n' && ch != '\t' && ch != ' ' && ch != '\r' && ch != '\0' && ch != ';' && ch != '.' 410 | && ch != ',') { 411 | s = s + ch; 412 | ch = text.charAt(++i); 413 | } 414 | printError(row_number, s, "不合法的字符"); 415 | return i; 416 | } 417 | } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '\0') { 418 | printResult(s, "整数"); 419 | return i; 420 | } else { 421 | do { 422 | ch = text.charAt(i++); 423 | s = s + ch; 424 | } while ((text.charAt(i) != ' ') && (text.charAt(i) != '\t') && (text.charAt(i) != '\n') 425 | && (text.charAt(i) != '\r') && (text.charAt(i) != '\0')); 426 | printError(row_number, s, "错误的标识符"); 427 | return i; 428 | } 429 | } 430 | ``` 431 | 432 | - printResult方法 433 | 434 | 用于将中间结果和最终结果添加到lex_result_stack数组和threeElements数组中。 435 | 436 | ```java 437 | public void printResult(String rs_value, String rs_name) { 438 | if (rs_name.equals("标识符")) { 439 | lex_result_stack.add("Ident"); 440 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "IDN", rs_value))); 441 | } else if (rs_name.equals("整数")) { 442 | lex_result_stack.add("INT"); 443 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "INT", rs_value))); 444 | } else if (rs_name.equals("科学计数") || rs_name.equals("浮点数")) { 445 | lex_result_stack.add("float"); 446 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "FLOAT", rs_value))); 447 | } else if (rs_name.equals("单字符")) { 448 | lex_result_stack.add("char"); 449 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "CHAR", rs_value))); 450 | } else if (rs_name.equals("字符串")) { 451 | lex_result_stack.add("str"); 452 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "STR", rs_value))); 453 | } else if (rs_name.equals("运算符")) { 454 | lex_result_stack.add(rs_value); 455 | if (rs_value.equals("+")) { 456 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "6"))); 457 | } else if (rs_value.equals("-")) { 458 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "7"))); 459 | } else if (rs_value.equals("*")) { 460 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "8"))); 461 | } else if (rs_value.equals("/")) { 462 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "9"))); 463 | } else if (rs_value.equals("%")) { 464 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "10"))); 465 | } else if (rs_value.equals("=")) { 466 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "11"))); 467 | } else if (rs_value.equals(">")) { 468 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "12"))); 469 | } else if (rs_value.equals("<")) { 470 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "13"))); 471 | } else if (rs_value.equals("==")) { 472 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "14"))); 473 | } else if (rs_value.equals("<=")) { 474 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "15"))); 475 | } else if (rs_value.equals(">=")) { 476 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "16"))); 477 | } else if (rs_value.equals("!=")) { 478 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "17"))); 479 | } else if (rs_value.equals("&&")) { 480 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "18"))); 481 | } else if (rs_value.equals("||")) { 482 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "19"))); 483 | } 484 | } else if (rs_name.equals("单界符") || rs_name.equals("双界符")) { 485 | lex_result_stack.add(rs_value); 486 | if (rs_value.equals("(")) { 487 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "20"))); 488 | } else if (rs_value.equals(")")) { 489 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "21"))); 490 | } else if (rs_value.equals("{")) { 491 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "22"))); 492 | } else if (rs_value.equals("}")) { 493 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "23"))); 494 | } else if (rs_value.equals(";")) { 495 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "24"))); 496 | } else if (rs_value.equals(",")) { 497 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "25"))); 498 | } 499 | } else if (rs_name.equals("关键字")) { 500 | lex_result_stack.add(rs_value); 501 | if (rs_value.equals("int")) { 502 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", "1"))); 503 | } else if (rs_value.equals("void")) { 504 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", "2"))); 505 | } else if (rs_value.equals("return")) { 506 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", "3"))); 507 | } else if (rs_value.equals("const")) { 508 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", "4"))); 509 | } else if (rs_value.equals("main")) { 510 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", "5"))); 511 | } else { 512 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", rs_value))); 513 | } 514 | } 515 | } 516 | ``` 517 | 518 | - printError方法 519 | 520 | 用于打印错误信息。 521 | 522 | ```java 523 | public void printError(int row_num, String rs_value, String rs_name) { 524 | HashMap hashMap = new HashMap(); 525 | hashMap.put("行号:", row_num + ""); 526 | hashMap.put("输入:", rs_value); 527 | hashMap.put("错误类型: ", rs_name); 528 | lex_error_stack.add(hashMap); 529 | // tbModel_lex_result.addRow(new String[]{"ERROR,"+rs_name, rs_value}); 530 | } 531 | ``` 532 | 533 | #### 2.2MainLexicon类的定义与实现 534 | 535 | 此类主要定义了词法分析的入口函数,用于打印词法分析结果及将结果输出到文件中。 536 | 537 | ```java 538 | public static void DoLex() { 539 | String content = TextLexiconInput.input(); // 得到文本内容 540 | TextLexicon textLexicon = new TextLexicon(content); // 将文本内容给词法编译器 541 | textLexicon.scannerAll(); // 入口函数 542 | ArrayList> lex_error_stack = textLexicon.get_Lex_Error(); 543 | if (lex_error_stack.size() != 0) { // 错误信息不为空 544 | System.out.println("词法分析阶段出现错误!"); 545 | for (HashMap stringStringHashMap : lex_error_stack) { // 输出错误信息 546 | System.out.println(stringStringHashMap); 547 | } 548 | return; // 词法分析中断 549 | } 550 | ArrayList> threeElements = textLexicon.getThreeElements(); // 得到要输出的三元组 551 | // 打印 552 | System.out.println("开始输出词法分析结果: ---------------------"); 553 | for (ArrayList threeElement : threeElements) { 554 | System.out.println(threeElement.get(0) + " <" 555 | + threeElement.get(1) + "," 556 | + threeElement.get(2) + ">" 557 | ); 558 | } 559 | // 输出到文件中 560 | try { 561 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.lexiconResultPath)); 562 | for (ArrayList threeElement : threeElements) { 563 | out.write(threeElement.get(0) + " <" 564 | + threeElement.get(1) + "," 565 | + threeElement.get(2) + ">" 566 | + "\n" 567 | ); 568 | } 569 | out.close(); 570 | } catch(IOException e) { 571 | throw new RuntimeException(e); 572 | } 573 | lex_result_stack = textLexicon.get_Lex_Result(); 574 | } 575 | ``` 576 | 577 | ## 二、语法分析器设计 578 | 579 | 1. 解析文法,找到终结符和非终结符 580 | 581 | 2. 构造First集合 582 | 583 | 3. 构造Follow集合 584 | 585 | 4. 根据First集合和Follow集合构造预测表 586 | 587 | 5. 根据预测表和词法分析的结果进行语法分析 588 | 589 | 590 | ### 1. 解析文法 591 | 592 | Formula 是表示文法的类,其中的left字段表示文法的左值,right表示文法的右值。有一个初始化方法,和两个gettr方法。 593 | 594 | ```java 595 | class Formula { 596 | String left; 597 | String[] right; 598 | public Formula(String left, String[] right){ 599 | this.left = left; 600 | this.right = right; 601 | } 602 | 603 | public String[] returnRights(){ 604 | return right; 605 | } 606 | 607 | public String returnLeft(){ 608 | return left; 609 | } 610 | } 611 | ``` 612 | 613 | TextParse 类是语法分析类,主要的工作就是根据语法规则来解析出语法分析需要的各种资源,包括文法,终结符,非终结符,First表,Follow表,预测表。 614 | 615 | setFormulas() 这个方法用于从文法文件中解析出文法规则。解析的规则如下 left -> []right。具体代码如下: 616 | 617 | ```java 618 | public static void setFormulas() { 619 | try { 620 | File file = new File(Config.grammarPath); 621 | RandomAccessFile randomfile = new RandomAccessFile(file, "r"); 622 | String line; 623 | String left; 624 | String right; 625 | Formula formula; 626 | while ((line=randomfile.readLine())!=null) { 627 | // System.out.println(line); 628 | // System.out.println("split: " + Arrays.toString(line.split("->"))); 629 | left = line.split("->")[0].trim(); 630 | right = line.split("->")[1].trim(); // 将右侧所有的值都算进去 631 | formula = new Formula(left, right.split(" ")); // 根据空格分离右侧的值 632 | formulas.add(formula); 633 | } 634 | randomfile.close(); 635 | } catch (Exception e) { 636 | // TODO: handle exception 637 | e.printStackTrace(); 638 | } 639 | } 640 | ``` 641 | 642 | 解析文法中的非终结符,并将其存储到 ArrayList< String > 中。因为文法中的非终结符就是文法左侧的全部符号,只需要统计左侧就可以了。 643 | 644 | ```java 645 | // 解析文法中的非终结符,并设置 646 | // 非终结符在文法中就是所有的left 647 | static void setNonTerminals() { 648 | for (Formula formula : formulas) { 649 | if (nonTerminals.contains(formula.left)) { 650 | continue; 651 | } else { 652 | nonTerminals.add(formula.left); 653 | } 654 | } 655 | } 656 | ``` 657 | 658 | 解析文法中的终结符,并将其存储到 ArrayList < String > 中。文法中的终结符是文法中全部的符号去掉终结符。 659 | 660 | ```java 661 | // 生成终结符 662 | static void setTerminals() { 663 | for (Formula formula : formulas) { 664 | String[] rights = formula.returnRights(); 665 | // 从右侧去掉非终结符,剩下的就是终结符 666 | for (String s : rights) { 667 | // 去掉非终结符和空 668 | if (nonTerminals.contains(s) || s.equals("$")) { 669 | continue; 670 | } else { // 剩下的就是终结符 671 | terminals.add(s); 672 | } 673 | } 674 | } 675 | } 676 | ``` 677 | 678 | ### 2. 构造 First 集合 679 | 680 | 根据解析出的文法,终结符,非终结符来推导出 First 集合。根据以下算法来构造 First 集合。 681 | 682 | ```java 683 | // 生成 First 集合 684 | static void setFirsts() { 685 | FirstTable.setFirst(formulas,terminals,nonTerminals,firsts); 686 | } 687 | ``` 688 | 689 | - 使用 HashMap 来存储 First 集合,Key 值是符号,Value 值是ArrayList< String> ,存储着 Key 的 First 集合中所有元素。 690 | 691 | - 全部终结符号的 First 集合就是终结符本身。 692 | 693 | - 将全部非终结符都注册一个 Map,方便后序代码。 694 | 695 | - 遍历文法右侧的每一个符号的First集合,然后将该符号的First集合去掉空加入到左侧文法的First集合中。因为 Java 是按照引用来传递的,这个过程就可以看作一个递归过程。 696 | 697 | 698 | ```java 699 | public class FirstTable { 700 | static ArrayList formulas; 701 | static ArrayList terminals; 702 | static ArrayList nonTerminals; 703 | static HashMap> firsts; 704 | 705 | static void setFirst(ArrayList _formulas, ArrayList _terminals, 706 | ArrayList _nonTerminals, HashMap> _firsts) { 707 | formulas = _formulas; 708 | terminals = _terminals; 709 | nonTerminals = _nonTerminals; 710 | firsts = _firsts; 711 | 712 | // 终结符全部求出first集 713 | ArrayList first; 714 | for (String terminal : terminals) { 715 | first = new ArrayList(); 716 | first.add(terminal); 717 | firsts.put(terminal, first); 718 | } 719 | // 给所有非终结符注册一下 720 | for (String nonterminal : nonTerminals) { 721 | first = new ArrayList(); 722 | firsts.put(nonterminal, first); 723 | } 724 | 725 | boolean flag; 726 | while (true) { 727 | flag = true; 728 | String left; 729 | String right; 730 | String[] rights; 731 | // 遍历所有文法 732 | for (Formula formula : formulas) { 733 | left = formula.returnLeft(); 734 | rights = formula.returnRights(); 735 | // 每个文法的右侧 736 | for (String s : rights) { 737 | right = s; 738 | // oneOfRight是否存在,遇到空怎么办 739 | if (!right.equals("$")) { // 右侧的字符串不为空(任意一个都不为空) 740 | // 遍历每一个右侧字符串的First集合,即 First(右侧字符串) 741 | // 这个就类似于一个递归 742 | for (int l = 0; l < firsts.get(right).size(); l++) { 743 | // First(left) 包括了 First(oneOfRights) 744 | if (firsts.get(left).contains(firsts.get(right).get(l))) { 745 | continue; 746 | } else { 747 | // 不包括, 就加入 748 | firsts.get(left).add(firsts.get(right).get(l)); 749 | flag = false; 750 | } 751 | } 752 | } 753 | // OneOfRights -> $ 754 | if (isCanBeNull(formulas, right)) { 755 | continue; 756 | } else { 757 | break; 758 | } 759 | } 760 | } 761 | if (flag) { 762 | break; 763 | } 764 | } 765 | 766 | // 判断是否产生$ 767 | static boolean isCanBeNull(ArrayList formulas, String symbol){ 768 | String[] rights; 769 | // 遍历每一个文法 770 | for (Formula formula : formulas) { 771 | // 找到产生式 772 | if (formula.returnLeft().equals(symbol)) { 773 | // symbol -> [rights] 774 | rights = formula.returnRights(); 775 | // symbol -> $ 776 | if (rights[0].equals("$")) { // 第一个就是$, 即类似于 E -> $ 777 | return true; 778 | } 779 | } 780 | } 781 | return false; 782 | } 783 | } 784 | ``` 785 | 786 | ### 3. 构造 Follow 集合 787 | 788 | 根据解析出的文法,终结符,非终结符。通过以下算法来推导出 Follow 集合。 789 | 790 | ```java 791 | // 生成 Follow 集合 792 | static void setFollows() { 793 | FollowTable.setFollow(formulas,terminals,nonTerminals,firsts,follows); 794 | } 795 | ``` 796 | 797 | - 将文法开始符号 program 置于 Follow(program)。 798 | 799 | - 将最后一个元素的 First 集合去掉空之后加入到文法右侧前一个元素的 Follow 集合中。 800 | 801 | - 将文法左侧的 Follow 集合加入到文法右侧最后一个 First 集合中没有空的符号的 Follow 集合中。 802 | 803 | 804 | ```java 805 | public class FollowTable { 806 | static void setFollow(ArrayList formulas, ArrayList terminals, 807 | ArrayList nonTerminals, HashMap> firsts, 808 | HashMap> follows) { 809 | // 所有非终结符的follow集初始化一下 810 | ArrayList follow; 811 | for (String nonTerminal : nonTerminals) { 812 | follow = new ArrayList(); 813 | follows.put(nonTerminal, follow); 814 | } 815 | // 将#加入到follow(S)中 816 | // follows.get("S").add("#"); // 开始文法的入口必须是S 817 | follows.get(Config.initSymbol).add("#"); 818 | 819 | boolean flag; 820 | boolean fab; 821 | while (true) { 822 | flag = true; 823 | // 循环 824 | for (Formula formula : formulas) { 825 | String left; 826 | String right; 827 | String[] rights; 828 | rights = formula.returnRights(); 829 | for (int j = 0; j < rights.length; j++) { 830 | right = rights[j]; 831 | 832 | // 非终结符 833 | if (nonTerminals.contains(right)) { 834 | fab = true; 835 | for (int k = j + 1; k < rights.length; k++) { 836 | 837 | // 查找first集 838 | for (int v = 0; v < firsts.get(rights[k]).size(); v++) { 839 | // 将后一个元素的first集加入到前一个元素的follow集中 840 | if (follows.get(right).contains(firsts.get(rights[k]).get(v))) { 841 | continue; 842 | } else { 843 | follows.get(right).add(firsts.get(rights[k]).get(v)); 844 | flag = false; 845 | } 846 | } 847 | if (isCanBeNull(formulas, rights[k])) { 848 | continue; 849 | } else { 850 | fab = false; 851 | break; 852 | } 853 | } 854 | if (fab) { 855 | left = formula.returnLeft(); 856 | for (int p = 0; p < follows.get(left).size(); p++) { 857 | if (follows.get(right).contains(follows.get(left).get(p))) { 858 | continue; 859 | } else { 860 | follows.get(right).add(follows.get(left).get(p)); 861 | flag = false; 862 | } 863 | } 864 | } 865 | } 866 | 867 | } 868 | } 869 | if(flag){ 870 | break; 871 | } 872 | } 873 | 874 | // 清除follow集中的# 875 | String left; 876 | for (String nonterminal : nonTerminals) { 877 | left = nonterminal; 878 | for (int v = 0; v < follows.get(left).size(); v++) { 879 | if (follows.get(left).get(v).equals("#")) 880 | follows.get(left).remove(v); 881 | } 882 | } 883 | 884 | // ------------------- 885 | // 为Follow加上# 886 | for (String notTerminal : nonTerminals) { 887 | follows.get(notTerminal).add("#"); 888 | } 889 | // ------------------- 890 | } 891 | 892 | // 判断是否产生$ 893 | static boolean isCanBeNull(ArrayList formulas, String symbol){ 894 | String[] rights; 895 | for (Formula formula : formulas) { 896 | // 找到产生式 897 | if (formula.returnLeft().equals(symbol)) { 898 | rights = formula.returnRights(); 899 | if (rights[0].equals("$")) { 900 | return true; 901 | } 902 | } 903 | } 904 | return false; 905 | } 906 | } 907 | ``` 908 | 909 | ### 4. 构造预测表 910 | 911 | ```java 912 | static void setPrediction() { 913 | PredictMap.setPrediction(formulas,terminals,nonTerminals,firsts,follows,predictions); 914 | } 915 | ``` 916 | 917 | - 遍历每一个文法 918 | 919 | - 将文法左侧符号的 First 集合中的每一个终结符作为横坐标,左侧符号作为纵坐标,填上这个文法。 920 | 921 | - 如果左侧文法符号的 First 集合中包含空,则将文法左侧的 Follow 集合的每一个终结符作为横坐标,左侧符号作为纵坐标,填上这个文法。 922 | 923 | 924 | ```java 925 | public class PredictMap { 926 | static void setPrediction(ArrayList formulas, ArrayList terminals, 927 | ArrayList nonTerminals, HashMap> firsts, 928 | HashMap> follows, 929 | HashMap predictions) { 930 | // (2) 931 | for (Formula formula : formulas) { 932 | // First(formula.right[0]) 933 | try { 934 | if (formula.right[0].equals("$")) { // 类似于 value' -> $ 这种文法 935 | // First集合中First($)是不存在的 936 | // 遇到这种文法,直接跳过就行 937 | continue; 938 | } 939 | for (String terminalInFirsts : firsts.get(formula.right[0])) { 940 | // 空 941 | if (terminalInFirsts.equals("$")) { 942 | // Follow(formula.left) 943 | for (String terminalInFollows : follows.get(formula.left)) { 944 | predictions.put(getMapKey(terminalInFollows, formula.left), 945 | new Formula(formula.left, new String[]{"$"})); 946 | } 947 | } 948 | // 不空 949 | // [Terminal, notTerminal] : formula 950 | predictions.put(getMapKey(terminalInFirsts, formula.left), formula); 951 | } 952 | } catch (Exception e) { 953 | System.out.println("first结合中没有 key: " + formula.right[0]); 954 | e.printStackTrace(); 955 | } 956 | } 957 | 958 | // (3) 959 | // E -> $ 960 | for (Formula formula : formulas) { 961 | if (formula.returnRights()[0].equals("$")) { // E -> $ 962 | for (String followElement : follows.get(formula.returnLeft())) { // Follow(E) 963 | // [FollowElement(E), E] : E - > $ 964 | predictions.put(getMapKey(followElement, formula.returnLeft()), formula); 965 | } 966 | } 967 | } 968 | } 969 | 970 | // 以固定的格式产生分析表的 Key 971 | static String getMapKey(String terminal, String nonTerminal) { 972 | // i 为终结符,横坐标 973 | // j 为非终结符,纵坐标 974 | return "{横坐标: " + terminal + " , " + "纵坐标: " + nonTerminal + "}"; 975 | } 976 | } 977 | ``` 978 | 979 | ### 5. 语法分析 980 | 981 | - 根据上图来进行语法分析,不断的来进行移进规约。 982 | 983 | - 首先要在压栈一个#,然后在输入串的末尾压入一个# 984 | 985 | - 然后严格依照图中的遍历规则,来进行移进规约,直到 # 遇到 # 就结束。 986 | 987 | 988 | ```java 989 | public class MainParse { 990 | static HashMap predictMap; // 预测表 991 | static ArrayList input_str; // 输入串, 词法分析的结果 992 | static ArrayList symbol_stack; // 符号栈 993 | // static ArrayList parse_error_stack; // 语法分析输出可能的错误结果 994 | static ArrayList parse_result_stack; // 语法分析输出展示的结果 995 | static int parse_result_counter; // 语法分析输出结果的计数器 996 | 997 | // 入口函数 998 | static void DoParse() { 999 | input_str = TextParseInput.getLex_result_stack(); // 词法分析的输入 1000 | symbol_stack = new ArrayList<>(); 1001 | parse_result_stack = new ArrayList<>(); 1002 | parse_result_counter = 0; 1003 | 1004 | TextParse.Do(); // 生成各种表,First,Follow,预测表 1005 | predictMap = TextParse.predictions; // 预测表 1006 | 1007 | TextParse.writeAllIntoFile(); // 将语法分析开始前生成的所有表打印出来 1008 | writeLexiconMiddleResultIntoFile(); // 将词法分析的中间结果打印出来 1009 | 1010 | parse(); // 开始语法分析 1011 | 1012 | printParseResult(); // 打印语法分析结果 1013 | } 1014 | 1015 | // 将词法分析传递给语法分析的中间结果打印出来 1016 | static void writeLexiconMiddleResultIntoFile() { 1017 | try { 1018 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.lexiconMiddleResult)); 1019 | out.write("词法分析的中间结果结果如下: --------------------\n"); 1020 | out.write("总共有 " + input_str.size() + " 条数据\n"); 1021 | out.write("\n"); 1022 | for (String s : input_str) { 1023 | out.write(s + "\n"); 1024 | } 1025 | out.close(); 1026 | } catch (IOException e) { 1027 | throw new RuntimeException(e); 1028 | } 1029 | } 1030 | 1031 | // 利用预测表和词法分析的输入来解析 1032 | // 语法分析 1033 | static void parse() { 1034 | // ------ 1035 | // 将 # 压入栈 1036 | symbol_stack.add("#"); 1037 | input_str.add("#"); //输入串在最后也需要放 # 1038 | // ------ 1039 | 1040 | // 初始符号压入栈 1041 | // symbol_stack.add("S"); 1042 | symbol_stack.add(Config.initSymbol); 1043 | 1044 | String predictMapKey; // PredictMap-Key 1045 | // String process=""; 1046 | 1047 | 1048 | // 符号栈和输入串如果同时为0,那么语法分析结束 1049 | // while (symbol_stack.size()>0 && input_str.size()>0 ) { 1050 | while (true) { 1051 | parse_result_counter++; // 语法分析结果的计数器加一 1052 | if (symbol_stack.get(symbol_stack.size()-1).equals("#") && input_str.get(0).equals("#")) { 1053 | parse_result_stack.add(parse_result_counter + " " 1054 | + "EOF" + "#" 1055 | + "EOF" + " " + "accept"); 1056 | break; 1057 | } 1058 | // 输入缓冲区与推导符号串第一个字符相等的话,删掉 1059 | try { 1060 | if(input_str.get(0).equals(symbol_stack.get(symbol_stack.size()-1))){ 1061 | // 语法分析的结果写入栈中 1062 | parse_result_stack.add(parse_result_counter + " " 1063 | + symbol_stack.get(symbol_stack.size()-1) + "#" 1064 | + input_str.get(0) + " " + "move"); 1065 | input_str.remove(0); // 输入字符移除第一个,类似于指针向后遍历 1066 | symbol_stack.remove(symbol_stack.size()-1); // 符号栈移除栈顶 1067 | continue; 1068 | } 1069 | } catch (Exception e) { 1070 | // TODO: handle exception 1071 | e.printStackTrace(); 1072 | } 1073 | 1074 | // 匹配字符 1075 | predictMapKey = PredictMap.getMapKey(input_str.get(0), symbol_stack.get(symbol_stack.size()-1)); 1076 | 1077 | // 能够找到匹配的 1078 | Formula formula = predictMap.get(predictMapKey); // 找到文法 1079 | if (formula != null) { // 文法不为空,为空报错 1080 | // 语法分析的结果写入栈中 1081 | parse_result_stack.add(parse_result_counter + " " 1082 | + symbol_stack.get(symbol_stack.size()-1) + "#" 1083 | + input_str.get(0) + " " + "reduction"); 1084 | // 符号栈的最后一个元素如果是 #, 就不能删除了 1085 | if (symbol_stack.get(symbol_stack.size()-1).equals("#")) { 1086 | } else { 1087 | symbol_stack.remove(symbol_stack.size()-1); // 删除符号栈中最后一个元素 1088 | } 1089 | String[] rights = formula.returnRights(); // 文法的右侧 1090 | if (rights[0].equals("$")) { // E->$,不能压入空 1091 | continue; 1092 | } 1093 | for (int i = rights.length-1; i >= 0; i--) { 1094 | // 将文法右侧的非终结符反向压入栈中 1095 | symbol_stack.add(rights[i]); 1096 | } 1097 | } 1098 | 1099 | else { 1100 | // 语法分析的结果写入栈中 1101 | parse_result_stack.add(parse_result_counter + " " 1102 | + symbol_stack.get(symbol_stack.size()-1) + "#" 1103 | + input_str.get(0) + " " + "error"); 1104 | return; // 遇到error直接返回 1105 | } 1106 | } 1107 | } 1108 | 1109 | // 输出语法分析结果 1110 | static void printParseResult() { 1111 | System.out.println("开始输出语法分析结果: --------------------"); 1112 | for (String s : parse_result_stack) { 1113 | System.out.println(s); 1114 | } 1115 | try { 1116 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.parseResultPath)); 1117 | for (String s : parse_result_stack) { 1118 | out.write(s + "\n"); 1119 | } 1120 | out.close(); 1121 | } catch (Exception e) { 1122 | e.printStackTrace(); 1123 | } 1124 | } 1125 | } 1126 | ``` 1127 | 1128 | ## 三、输出的一些表 1129 | 1130 | ### 1. 文法 1131 | 1132 | ``` 1133 | 文法解析结果如下: -------------------- 1134 | 总共有 77 条数据 1135 | 1136 | 文法左侧: program 文法右侧: [compUnit] 1137 | 文法左侧: compUnit 文法右侧: [decl, compUnit] 1138 | 文法左侧: compUnit 文法右侧: [funcDef, compUnit] 1139 | 文法左侧: compUnit 文法右侧: [$] 1140 | 文法左侧: decl 文法右侧: [constDecl] 1141 | 文法左侧: decl 文法右侧: [varDecl] 1142 | 文法左侧: constDecl 文法右侧: [const, bType, constDef, argConst, ;] 1143 | 文法左侧: argConst 文法右侧: [,, constDef, argConst] 1144 | 文法左侧: argConst 文法右侧: [$] 1145 | 文法左侧: constDef 文法右侧: [Ident, =, constInitVal] 1146 | 文法左侧: constInitVal 文法右侧: [constExp] 1147 | 文法左侧: varDecl 文法右侧: [bType, varDef, argVarDecl, ;] 1148 | 文法左侧: argVarDecl 文法右侧: [,, varDef, argVarDecl] 1149 | 文法左侧: argVarDecl 文法右侧: [$] 1150 | 文法左侧: varDef 文法右侧: [Ident, argVarDef] 1151 | 文法左侧: argVarDef 文法右侧: [=, initVal] 1152 | 文法左侧: argVarDef 文法右侧: [$] 1153 | 文法左侧: initVal 文法右侧: [exp] 1154 | 文法左侧: bType 文法右侧: [int] 1155 | 文法左侧: funcDef 文法右侧: [funcType, Ident, (, funcFParams, ), block] 1156 | 文法左侧: funcType 文法右侧: [void] 1157 | 文法左侧: funcFParams 文法右侧: [funcFParam, argFunctionF] 1158 | 文法左侧: funcFParams 文法右侧: [$] 1159 | 文法左侧: argFunctionF 文法右侧: [,, funcFParam, argFunctionF] 1160 | 文法左侧: argFunctionF 文法右侧: [$] 1161 | 文法左侧: funcFParam 文法右侧: [bType, Ident] 1162 | 文法左侧: block 文法右侧: [{, blockItem, }] 1163 | 文法左侧: blockItem 文法右侧: [decl, blockItem] 1164 | 文法左侧: blockItem 文法右侧: [stmt, blockItem] 1165 | 文法左侧: blockItem 文法右侧: [$] 1166 | 文法左侧: stmt 文法右侧: [exp, ;] 1167 | 文法左侧: stmt 文法右侧: [;] 1168 | 文法左侧: stmt 文法右侧: [block] 1169 | 文法左侧: stmt 文法右侧: [return, argExp, ;] 1170 | 文法左侧: argExp 文法右侧: [$] 1171 | 文法左侧: argExp 文法右侧: [exp] 1172 | 文法左侧: exp 文法右侧: [assignExp] 1173 | 文法左侧: lVal 文法右侧: [Ident] 1174 | 文法左侧: primaryExp 文法右侧: [(, exp, )] 1175 | 文法左侧: primaryExp 文法右侧: [number] 1176 | 文法左侧: number 文法右侧: [INT] 1177 | 文法左侧: unaryOp 文法右侧: [+] 1178 | 文法左侧: unaryOp 文法右侧: [-] 1179 | 文法左侧: unaryOp 文法右侧: [!] 1180 | 文法左侧: unaryExp 文法右侧: [unaryOp, unaryExp] 1181 | 文法左侧: unaryExp 文法右侧: [Ident, callFunc] 1182 | 文法左侧: callFunc 文法右侧: [(, funcRParams, )] 1183 | 文法左侧: callFunc 文法右侧: [$] 1184 | 文法左侧: unaryExp 文法右侧: [primaryExp] 1185 | 文法左侧: funcRParams 文法右侧: [funcRParam, argFunctionR] 1186 | 文法左侧: funcRParams 文法右侧: [$] 1187 | 文法左侧: argFunctionR 文法右侧: [,, funcRParam, argFunctionR] 1188 | 文法左侧: argFunctionR 文法右侧: [$] 1189 | 文法左侧: funcRParam 文法右侧: [exp] 1190 | 文法左侧: mulExp 文法右侧: [unaryExp, mulExpAtom] 1191 | 文法左侧: mulExpAtom 文法右侧: [*, unaryExp, mulExpAtom] 1192 | 文法左侧: mulExpAtom 文法右侧: [/, unaryExp, mulExpAtom] 1193 | 文法左侧: mulExpAtom 文法右侧: [%, unaryExp, mulExpAtom] 1194 | 文法左侧: mulExpAtom 文法右侧: [$] 1195 | 文法左侧: addExp 文法右侧: [mulExp, addExpAtom] 1196 | 文法左侧: addExpAtom 文法右侧: [+, mulExp, addExpAtom] 1197 | 文法左侧: addExpAtom 文法右侧: [-, mulExp, addExpAtom] 1198 | 文法左侧: addExpAtom 文法右侧: [$] 1199 | 文法左侧: relExp 文法右侧: [addExp, relExpAtom] 1200 | 文法左侧: relExpAtom 文法右侧: [<, addExp, relExpAtom] 1201 | 文法左侧: relExpAtom 文法右侧: [>, addExp, relExpAtom] 1202 | 文法左侧: relExpAtom 文法右侧: [<=, addExp, relExpAtom] 1203 | 文法左侧: relExpAtom 文法右侧: [>=, addExp, relExpAtom] 1204 | 文法左侧: relExpAtom 文法右侧: [$] 1205 | 文法左侧: eqExp 文法右侧: [relExp, eqExpAtom] 1206 | 文法左侧: eqExpAtom 文法右侧: [==, relExp, eqExpAtom] 1207 | 文法左侧: eqExpAtom 文法右侧: [!=, relExp, eqExpAtom] 1208 | 文法左侧: eqExpAtom 文法右侧: [$] 1209 | 文法左侧: assignExp 文法右侧: [eqExp, assignExpAtom] 1210 | 文法左侧: assignExpAtom 文法右侧: [=, eqExp, assignExpAtom] 1211 | 文法左侧: assignExpAtom 文法右侧: [$] 1212 | 文法左侧: constExp 文法右侧: [assignExp] 1213 | ``` 1214 | 1215 | ### 2. 终结符 1216 | 1217 | ``` 1218 | 从文法中解析的终结符结果如下: -------------------- 1219 | 总共有 45 条数据 1220 | 1221 | const 1222 | ; 1223 | , 1224 | Ident 1225 | = 1226 | ; 1227 | , 1228 | Ident 1229 | = 1230 | int 1231 | Ident 1232 | ( 1233 | ) 1234 | void 1235 | , 1236 | Ident 1237 | { 1238 | } 1239 | ; 1240 | ; 1241 | return 1242 | ; 1243 | Ident 1244 | ( 1245 | ) 1246 | INT 1247 | + 1248 | - 1249 | ! 1250 | Ident 1251 | ( 1252 | ) 1253 | , 1254 | * 1255 | / 1256 | % 1257 | + 1258 | - 1259 | < 1260 | > 1261 | <= 1262 | >= 1263 | == 1264 | != 1265 | = 1266 | ``` 1267 | 1268 | ### 3. 非终结符 1269 | 1270 | ``` 1271 | 从文法中解析的非终结符结果如下: -------------------- 1272 | 总共有 43 条数据 1273 | 1274 | program 1275 | compUnit 1276 | decl 1277 | constDecl 1278 | argConst 1279 | constDef 1280 | constInitVal 1281 | varDecl 1282 | argVarDecl 1283 | varDef 1284 | argVarDef 1285 | initVal 1286 | bType 1287 | funcDef 1288 | funcType 1289 | funcFParams 1290 | argFunctionF 1291 | funcFParam 1292 | block 1293 | blockItem 1294 | stmt 1295 | argExp 1296 | exp 1297 | lVal 1298 | primaryExp 1299 | number 1300 | unaryOp 1301 | unaryExp 1302 | callFunc 1303 | funcRParams 1304 | argFunctionR 1305 | funcRParam 1306 | mulExp 1307 | mulExpAtom 1308 | addExp 1309 | addExpAtom 1310 | relExp 1311 | relExpAtom 1312 | eqExp 1313 | eqExpAtom 1314 | assignExp 1315 | assignExpAtom 1316 | constExp 1317 | ``` 1318 | 1319 | ### 4. First 集合 1320 | 1321 | ``` 1322 | First列表结果如下: -------------------- 1323 | 总共有 68 条数据 1324 | 1325 | argFunctionR [,] 1326 | <= [<=] 1327 | decl [const, int] 1328 | constInitVal [+, -, !, Ident, (, INT] 1329 | constDef [Ident] 1330 | compUnit [const, void, int] 1331 | addExp [+, -, !, Ident, (, INT] 1332 | unaryOp [+, -, !] 1333 | program [const, void, int] 1334 | addExpAtom [+, -] 1335 | mulExpAtom [*, /, %] 1336 | relExp [+, -, !, Ident, (, INT] 1337 | argVarDecl [,] 1338 | number [INT] 1339 | eqExp [+, -, !, Ident, (, INT] 1340 | funcFParams [int] 1341 | block [{] 1342 | mulExp [+, -, !, Ident, (, INT] 1343 | argExp [+, -, !, Ident, (, INT] 1344 | exp [+, -, !, Ident, (, INT] 1345 | constExp [+, -, !, Ident, (, INT] 1346 | == [==] 1347 | ! [!] 1348 | void [void] 1349 | assignExp [+, -, !, Ident, (, INT] 1350 | % [%] 1351 | lVal [Ident] 1352 | ( [(] 1353 | ) [)] 1354 | * [*] 1355 | assignExpAtom [=] 1356 | + [+] 1357 | , [,] 1358 | - [-] 1359 | / [/] 1360 | bType [int] 1361 | unaryExp [+, -, !, Ident, (, INT] 1362 | varDef [Ident] 1363 | primaryExp [(, INT] 1364 | ; [;] 1365 | blockItem [const, ;, {, return, int, +, -, !, Ident, (, INT] 1366 | < [<] 1367 | != [!=] 1368 | = [=] 1369 | > [>] 1370 | >= [>=] 1371 | funcDef [void] 1372 | eqExpAtom [==, !=] 1373 | const [const] 1374 | funcRParam [+, -, !, Ident, (, INT] 1375 | INT [INT] 1376 | funcRParams [+, -, !, Ident, (, INT] 1377 | initVal [+, -, !, Ident, (, INT] 1378 | argConst [,] 1379 | funcType [void] 1380 | Ident [Ident] 1381 | relExpAtom [<, >, <=, >=] 1382 | constDecl [const] 1383 | callFunc [(] 1384 | int [int] 1385 | argVarDef [=] 1386 | funcFParam [int] 1387 | { [{] 1388 | argFunctionF [,] 1389 | } [}] 1390 | varDecl [int] 1391 | return [return] 1392 | stmt [;, {, return, +, -, !, Ident, (, INT] 1393 | ``` 1394 | 1395 | ### 5. Follow 集合 1396 | 1397 | ``` 1398 | Follow列表结果如下: -------------------- 1399 | 总共有 43 条数据 1400 | 1401 | argFunctionR [), #] 1402 | eqExpAtom [=, ,, ;, ), #] 1403 | decl [const, void, int, ;, {, return, +, -, !, Ident, (, INT, }, #] 1404 | constInitVal [,, ;, #] 1405 | constDef [,, ;, #] 1406 | compUnit [#] 1407 | funcRParam [,, ), #] 1408 | addExp [<, >, <=, >=, ==, !=, =, ,, ;, ), #] 1409 | unaryOp [+, -, !, Ident, (, INT, #] 1410 | program [#] 1411 | addExpAtom [<, >, <=, >=, ==, !=, =, ,, ;, ), #] 1412 | mulExpAtom [+, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 1413 | relExp [==, !=, =, ,, ;, ), #] 1414 | funcRParams [), #] 1415 | argVarDecl [;, #] 1416 | initVal [,, ;, #] 1417 | number [*, /, %, +, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 1418 | argConst [;, #] 1419 | eqExp [=, ,, ;, ), #] 1420 | funcFParams [), #] 1421 | block [const, void, int, ;, {, return, +, -, !, Ident, (, INT, }, #] 1422 | mulExp [+, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 1423 | argExp [;, #] 1424 | exp [,, ;, ), #] 1425 | constExp [,, ;, #] 1426 | funcType [Ident, #] 1427 | assignExp [,, ;, ), #] 1428 | relExpAtom [==, !=, =, ,, ;, ), #] 1429 | lVal [#] 1430 | constDecl [const, void, int, ;, {, return, +, -, !, Ident, (, INT, }, #] 1431 | assignExpAtom [,, ;, ), #] 1432 | callFunc [*, /, %, +, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 1433 | bType [Ident, #] 1434 | unaryExp [*, /, %, +, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 1435 | argVarDef [,, ;, #] 1436 | funcFParam [,, ), #] 1437 | varDef [,, ;, #] 1438 | primaryExp [*, /, %, +, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 1439 | blockItem [}, #] 1440 | argFunctionF [), #] 1441 | varDecl [const, void, int, ;, {, return, +, -, !, Ident, (, INT, }, #] 1442 | stmt [const, ;, {, return, int, +, -, !, Ident, (, INT, }, #] 1443 | funcDef [const, void, int, #] 1444 | ``` 1445 | 1446 | ### 6. 分析表 1447 | 1448 | ``` 1449 | 预测表结果如下: -------------------- 1450 | 总共有 217 条数据 1451 | 1452 | {横坐标: Ident 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 1453 | {横坐标: ! 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 1454 | {横坐标: # 纵坐标: funcFParams} 文法: funcFParams->[$] 1455 | {横坐标: void 纵坐标: funcType} 文法: funcType->[void] 1456 | {横坐标: const 纵坐标: constDecl} 文法: constDecl->[const, bType, constDef, argConst, ;] 1457 | {横坐标: < 纵坐标: addExpAtom} 文法: addExpAtom->[$] 1458 | {横坐标: const 纵坐标: compUnit} 文法: compUnit->[decl, compUnit] 1459 | {横坐标: + 纵坐标: unaryExp} 文法: unaryExp->[unaryOp, unaryExp] 1460 | {横坐标: ) 纵坐标: addExpAtom} 文法: addExpAtom->[$] 1461 | {横坐标: ) 纵坐标: callFunc} 文法: callFunc->[$] 1462 | {横坐标: >= 纵坐标: addExpAtom} 文法: addExpAtom->[$] 1463 | {横坐标: - 纵坐标: stmt} 文法: stmt->[exp, ;] 1464 | {横坐标: ( 纵坐标: constInitVal} 文法: constInitVal->[constExp] 1465 | {横坐标: + 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 1466 | {横坐标: ! 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 1467 | {横坐标: , 纵坐标: addExpAtom} 文法: addExpAtom->[$] 1468 | {横坐标: Ident 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 1469 | {横坐标: + 纵坐标: constExp} 文法: constExp->[assignExp] 1470 | {横坐标: Ident 纵坐标: lVal} 文法: lVal->[Ident] 1471 | {横坐标: ; 纵坐标: callFunc} 文法: callFunc->[$] 1472 | {横坐标: , 纵坐标: argFunctionF} 文法: argFunctionF->[,, funcFParam, argFunctionF] 1473 | {横坐标: != 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1474 | {横坐标: # 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1475 | {横坐标: + 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1476 | {横坐标: > 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1477 | {横坐标: + 纵坐标: unaryOp} 文法: unaryOp->[+] 1478 | {横坐标: } 纵坐标: blockItem} 文法: blockItem->[$] 1479 | {横坐标: != 纵坐标: addExpAtom} 文法: addExpAtom->[$] 1480 | {横坐标: ! 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 1481 | {横坐标: Ident 纵坐标: varDef} 文法: varDef->[Ident, argVarDef] 1482 | {横坐标: - 纵坐标: argExp} 文法: argExp->[exp] 1483 | {横坐标: ( 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 1484 | {横坐标: ( 纵坐标: primaryExp} 文法: primaryExp->[(, exp, )] 1485 | {横坐标: INT 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 1486 | {横坐标: ) 纵坐标: relExpAtom} 文法: relExpAtom->[$] 1487 | {横坐标: const 纵坐标: program} 文法: program->[compUnit] 1488 | {横坐标: ! 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 1489 | {横坐标: int 纵坐标: decl} 文法: decl->[varDecl] 1490 | {横坐标: void 纵坐标: compUnit} 文法: compUnit->[funcDef, compUnit] 1491 | {横坐标: # 纵坐标: relExpAtom} 文法: relExpAtom->[$] 1492 | {横坐标: % 纵坐标: callFunc} 文法: callFunc->[$] 1493 | {横坐标: , 纵坐标: argConst} 文法: argConst->[,, constDef, argConst] 1494 | {横坐标: INT 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 1495 | {横坐标: ( 纵坐标: funcRParam} 文法: funcRParam->[exp] 1496 | {横坐标: ( 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 1497 | {横坐标: INT 纵坐标: unaryExp} 文法: unaryExp->[primaryExp] 1498 | {横坐标: ; 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 1499 | {横坐标: # 纵坐标: eqExpAtom} 文法: eqExpAtom->[$] 1500 | {横坐标: ; 纵坐标: eqExpAtom} 文法: eqExpAtom->[$] 1501 | {横坐标: < 纵坐标: relExpAtom} 文法: relExpAtom->[<, addExp, relExpAtom] 1502 | {横坐标: ; 纵坐标: relExpAtom} 文法: relExpAtom->[$] 1503 | {横坐标: - 纵坐标: funcRParam} 文法: funcRParam->[exp] 1504 | {横坐标: ( 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 1505 | {横坐标: + 纵坐标: funcRParam} 文法: funcRParam->[exp] 1506 | {横坐标: > 纵坐标: relExpAtom} 文法: relExpAtom->[>, addExp, relExpAtom] 1507 | {横坐标: # 纵坐标: blockItem} 文法: blockItem->[$] 1508 | {横坐标: >= 纵坐标: callFunc} 文法: callFunc->[$] 1509 | {横坐标: + 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 1510 | {横坐标: Ident 纵坐标: initVal} 文法: initVal->[exp] 1511 | {横坐标: ) 纵坐标: funcFParams} 文法: funcFParams->[$] 1512 | {横坐标: # 纵坐标: addExpAtom} 文法: addExpAtom->[$] 1513 | {横坐标: * 纵坐标: callFunc} 文法: callFunc->[$] 1514 | {横坐标: , 纵坐标: assignExpAtom} 文法: assignExpAtom->[$] 1515 | {横坐标: Ident 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 1516 | {横坐标: > 纵坐标: addExpAtom} 文法: addExpAtom->[$] 1517 | {横坐标: ( 纵坐标: unaryExp} 文法: unaryExp->[primaryExp] 1518 | {横坐标: { 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 1519 | {横坐标: INT 纵坐标: argExp} 文法: argExp->[exp] 1520 | {横坐标: # 纵坐标: argVarDef} 文法: argVarDef->[$] 1521 | {横坐标: { 纵坐标: block} 文法: block->[{, blockItem, }] 1522 | {横坐标: ! 纵坐标: constExp} 文法: constExp->[assignExp] 1523 | {横坐标: > 纵坐标: callFunc} 文法: callFunc->[$] 1524 | {横坐标: - 纵坐标: constInitVal} 文法: constInitVal->[constExp] 1525 | {横坐标: ; 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1526 | {横坐标: - 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 1527 | {横坐标: % 纵坐标: mulExpAtom} 文法: mulExpAtom->[%, unaryExp, mulExpAtom] 1528 | {横坐标: < 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1529 | {横坐标: + 纵坐标: addExpAtom} 文法: addExpAtom->[+, mulExp, addExpAtom] 1530 | {横坐标: + 纵坐标: argExp} 文法: argExp->[exp] 1531 | {横坐标: ; 纵坐标: argVarDef} 文法: argVarDef->[$] 1532 | {横坐标: INT 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 1533 | {横坐标: - 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 1534 | {横坐标: const 纵坐标: decl} 文法: decl->[constDecl] 1535 | {横坐标: + 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 1536 | {横坐标: int 纵坐标: varDecl} 文法: varDecl->[bType, varDef, argVarDecl, ;] 1537 | {横坐标: , 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1538 | {横坐标: ) 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1539 | {横坐标: int 纵坐标: blockItem} 文法: blockItem->[decl, blockItem] 1540 | {横坐标: , 纵坐标: argFunctionR} 文法: argFunctionR->[,, funcRParam, argFunctionR] 1541 | {横坐标: Ident 纵坐标: funcRParam} 文法: funcRParam->[exp] 1542 | {横坐标: INT 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 1543 | {横坐标: - 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1544 | {横坐标: { 纵坐标: stmt} 文法: stmt->[block] 1545 | {横坐标: ) 纵坐标: assignExpAtom} 文法: assignExpAtom->[$] 1546 | {横坐标: ( 纵坐标: exp} 文法: exp->[assignExp] 1547 | {横坐标: - 纵坐标: constExp} 文法: constExp->[assignExp] 1548 | {横坐标: - 纵坐标: callFunc} 文法: callFunc->[$] 1549 | {横坐标: Ident 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 1550 | {横坐标: INT 纵坐标: initVal} 文法: initVal->[exp] 1551 | {横坐标: = 纵坐标: addExpAtom} 文法: addExpAtom->[$] 1552 | {横坐标: ; 纵坐标: addExpAtom} 文法: addExpAtom->[$] 1553 | {横坐标: ; 纵坐标: assignExpAtom} 文法: assignExpAtom->[$] 1554 | {横坐标: # 纵坐标: argExp} 文法: argExp->[$] 1555 | {横坐标: INT 纵坐标: stmt} 文法: stmt->[exp, ;] 1556 | {横坐标: ; 纵坐标: argConst} 文法: argConst->[$] 1557 | {横坐标: INT 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 1558 | {横坐标: + 纵坐标: constInitVal} 文法: constInitVal->[constExp] 1559 | {横坐标: ( 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 1560 | {横坐标: + 纵坐标: initVal} 文法: initVal->[exp] 1561 | {横坐标: ( 纵坐标: initVal} 文法: initVal->[exp] 1562 | {横坐标: ! 纵坐标: stmt} 文法: stmt->[exp, ;] 1563 | {横坐标: # 纵坐标: funcRParams} 文法: funcRParams->[$] 1564 | {横坐标: # 纵坐标: argFunctionR} 文法: argFunctionR->[$] 1565 | {横坐标: != 纵坐标: relExpAtom} 文法: relExpAtom->[$] 1566 | {横坐标: Ident 纵坐标: exp} 文法: exp->[assignExp] 1567 | {横坐标: ! 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 1568 | {横坐标: - 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 1569 | {横坐标: int 纵坐标: program} 文法: program->[compUnit] 1570 | {横坐标: - 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 1571 | {横坐标: # 纵坐标: compUnit} 文法: compUnit->[$] 1572 | {横坐标: = 纵坐标: callFunc} 文法: callFunc->[$] 1573 | {横坐标: ) 纵坐标: argFunctionR} 文法: argFunctionR->[$] 1574 | {横坐标: ( 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 1575 | {横坐标: + 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 1576 | {横坐标: != 纵坐标: callFunc} 文法: callFunc->[$] 1577 | {横坐标: int 纵坐标: compUnit} 文法: compUnit->[decl, compUnit] 1578 | {横坐标: - 纵坐标: unaryOp} 文法: unaryOp->[-] 1579 | {横坐标: INT 纵坐标: number} 文法: number->[INT] 1580 | {横坐标: Ident 纵坐标: constExp} 文法: constExp->[assignExp] 1581 | {横坐标: - 纵坐标: addExpAtom} 文法: addExpAtom->[-, mulExp, addExpAtom] 1582 | {横坐标: == 纵坐标: addExpAtom} 文法: addExpAtom->[$] 1583 | {横坐标: ! 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 1584 | {横坐标: = 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1585 | {横坐标: - 纵坐标: unaryExp} 文法: unaryExp->[unaryOp, unaryExp] 1586 | {横坐标: INT 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 1587 | {横坐标: + 纵坐标: callFunc} 文法: callFunc->[$] 1588 | {横坐标: Ident 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 1589 | {横坐标: + 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 1590 | {横坐标: * 纵坐标: mulExpAtom} 文法: mulExpAtom->[*, unaryExp, mulExpAtom] 1591 | {横坐标: - 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 1592 | {横坐标: INT 纵坐标: funcRParam} 文法: funcRParam->[exp] 1593 | {横坐标: , 纵坐标: eqExpAtom} 文法: eqExpAtom->[$] 1594 | {横坐标: / 纵坐标: mulExpAtom} 文法: mulExpAtom->[/, unaryExp, mulExpAtom] 1595 | {横坐标: ( 纵坐标: argExp} 文法: argExp->[exp] 1596 | {横坐标: / 纵坐标: callFunc} 文法: callFunc->[$] 1597 | {横坐标: INT 纵坐标: constInitVal} 文法: constInitVal->[constExp] 1598 | {横坐标: ! 纵坐标: constInitVal} 文法: constInitVal->[constExp] 1599 | {横坐标: Ident 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 1600 | {横坐标: return 纵坐标: stmt} 文法: stmt->[return, argExp, ;] 1601 | {横坐标: , 纵坐标: argVarDef} 文法: argVarDef->[$] 1602 | {横坐标: <= 纵坐标: callFunc} 文法: callFunc->[$] 1603 | {横坐标: ! 纵坐标: unaryOp} 文法: unaryOp->[!] 1604 | {横坐标: ! 纵坐标: initVal} 文法: initVal->[exp] 1605 | {横坐标: void 纵坐标: funcDef} 文法: funcDef->[funcType, Ident, (, funcFParams, ), block] 1606 | {横坐标: ) 纵坐标: funcRParams} 文法: funcRParams->[$] 1607 | {横坐标: , 纵坐标: callFunc} 文法: callFunc->[$] 1608 | {横坐标: # 纵坐标: assignExpAtom} 文法: assignExpAtom->[$] 1609 | {横坐标: Ident 纵坐标: constInitVal} 文法: constInitVal->[constExp] 1610 | {横坐标: ( 纵坐标: stmt} 文法: stmt->[exp, ;] 1611 | {横坐标: ( 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 1612 | {横坐标: Ident 纵坐标: argExp} 文法: argExp->[exp] 1613 | {横坐标: < 纵坐标: callFunc} 文法: callFunc->[$] 1614 | {横坐标: = 纵坐标: relExpAtom} 文法: relExpAtom->[$] 1615 | {横坐标: = 纵坐标: argVarDef} 文法: argVarDef->[=, initVal] 1616 | {横坐标: INT 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 1617 | {横坐标: # 纵坐标: argFunctionF} 文法: argFunctionF->[$] 1618 | {横坐标: Ident 纵坐标: unaryExp} 文法: unaryExp->[Ident, callFunc] 1619 | {横坐标: ! 纵坐标: unaryExp} 文法: unaryExp->[unaryOp, unaryExp] 1620 | {横坐标: ! 纵坐标: funcRParam} 文法: funcRParam->[exp] 1621 | {横坐标: const 纵坐标: blockItem} 文法: blockItem->[decl, blockItem] 1622 | {横坐标: Ident 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 1623 | {横坐标: - 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 1624 | {横坐标: + 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 1625 | {横坐标: == 纵坐标: relExpAtom} 文法: relExpAtom->[$] 1626 | {横坐标: INT 纵坐标: exp} 文法: exp->[assignExp] 1627 | {横坐标: = 纵坐标: assignExpAtom} 文法: assignExpAtom->[=, eqExp, assignExpAtom] 1628 | {横坐标: ( 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 1629 | {横坐标: , 纵坐标: relExpAtom} 文法: relExpAtom->[$] 1630 | {横坐标: return 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 1631 | {横坐标: INT 纵坐标: primaryExp} 文法: primaryExp->[number] 1632 | {横坐标: # 纵坐标: argVarDecl} 文法: argVarDecl->[$] 1633 | {横坐标: # 纵坐标: argConst} 文法: argConst->[$] 1634 | {横坐标: ) 纵坐标: argFunctionF} 文法: argFunctionF->[$] 1635 | {横坐标: == 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1636 | {横坐标: = 纵坐标: eqExpAtom} 文法: eqExpAtom->[$] 1637 | {横坐标: ! 纵坐标: argExp} 文法: argExp->[exp] 1638 | {横坐标: - 纵坐标: initVal} 文法: initVal->[exp] 1639 | {横坐标: - 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 1640 | {横坐标: int 纵坐标: funcFParam} 文法: funcFParam->[bType, Ident] 1641 | {横坐标: void 纵坐标: program} 文法: program->[compUnit] 1642 | {横坐标: ! 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 1643 | {横坐标: ( 纵坐标: callFunc} 文法: callFunc->[(, funcRParams, )] 1644 | {横坐标: ( 纵坐标: constExp} 文法: constExp->[assignExp] 1645 | {横坐标: ; 纵坐标: stmt} 文法: stmt->[;] 1646 | {横坐标: ; 纵坐标: argExp} 文法: argExp->[$] 1647 | {横坐标: int 纵坐标: funcFParams} 文法: funcFParams->[funcFParam, argFunctionF] 1648 | {横坐标: ; 纵坐标: argVarDecl} 文法: argVarDecl->[$] 1649 | {横坐标: # 纵坐标: callFunc} 文法: callFunc->[$] 1650 | {横坐标: >= 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1651 | {横坐标: <= 纵坐标: relExpAtom} 文法: relExpAtom->[<=, addExp, relExpAtom] 1652 | {横坐标: - 纵坐标: exp} 文法: exp->[assignExp] 1653 | {横坐标: <= 纵坐标: addExpAtom} 文法: addExpAtom->[$] 1654 | {横坐标: == 纵坐标: eqExpAtom} 文法: eqExpAtom->[==, relExp, eqExpAtom] 1655 | {横坐标: + 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 1656 | {横坐标: , 纵坐标: argVarDecl} 文法: argVarDecl->[,, varDef, argVarDecl] 1657 | {横坐标: Ident 纵坐标: stmt} 文法: stmt->[exp, ;] 1658 | {横坐标: + 纵坐标: exp} 文法: exp->[assignExp] 1659 | {横坐标: <= 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 1660 | {横坐标: >= 纵坐标: relExpAtom} 文法: relExpAtom->[>=, addExp, relExpAtom] 1661 | {横坐标: + 纵坐标: stmt} 文法: stmt->[exp, ;] 1662 | {横坐标: != 纵坐标: eqExpAtom} 文法: eqExpAtom->[!=, relExp, eqExpAtom] 1663 | {横坐标: ! 纵坐标: exp} 文法: exp->[assignExp] 1664 | {横坐标: INT 纵坐标: constExp} 文法: constExp->[assignExp] 1665 | {横坐标: int 纵坐标: bType} 文法: bType->[int] 1666 | {横坐标: == 纵坐标: callFunc} 文法: callFunc->[$] 1667 | {横坐标: Ident 纵坐标: constDef} 文法: constDef->[Ident, =, constInitVal] 1668 | {横坐标: ) 纵坐标: eqExpAtom} 文法: eqExpAtom->[$] 1669 | ``` -------------------------------------------------------------------------------- /docs/01_var_defn.txt: -------------------------------------------------------------------------------- 1 | int 2 | a 3 | ; 4 | void 5 | func 6 | ( 7 | ) 8 | { 9 | a 10 | = 11 | 10 12 | ; 13 | return 14 | 0 15 | ; 16 | } 17 | 18 | 1 program#int reduction 19 | 2 compUnit#int reduction 20 | 3 decl#int reduction 21 | 4 valDecl#int reduction 22 | 5 btype#int reduction 23 | 6 int#int move 24 | 7 varDef#Ident reduction 25 | 8 Ident#Ident move 26 | 27 | 9 argVarDef#; reduction 28 | 10 argVarDecl#; reduction 29 | 30 | 11 ;#; move 31 | 32 | 12 compUnit#void reduction 33 | 34 | 13 funcDef#void reduction 35 | 14 funcType#void reduction 36 | 15 void#void move 37 | 16 Ident#Ident move 38 | 17 (#( move 39 | 40 | 18 funcFParams#) reduction 41 | 42 | 19 )#) move 43 | 20 block#{ reduction 44 | 21 {#{ move 45 | 22 blockItem#Ident reduction 46 | 23 stmt#Ident reduction 47 | 48 | 24 exp#Ident reduction 49 | 25 assignExp#Ident reduction 50 | 26 lOrExp#Ident reduction 51 | 27 lAndExp#Ident reduction 52 | 28 eqExp#Ident reduction 53 | 29 relExp#Ident reduction 54 | 30 addExp#Ident reduction 55 | 31 mulExp#Ident reduction 56 | 32 unaryExp#Ident reduction 57 | 58 | 33 Ident#Ident move 59 | 60 | 34 callFunc#= reduction 61 | 35 mulExpAtom#= reduction 62 | 36 addExpAtom#= reduction 63 | 37 relExpAtom#= reduction 64 | 38 eqExpAtom#= reduction 65 | 39 lAndExpAtom#= reduction 66 | 40 lOrExpAtom#= reduction 67 | 41 assignExpAtom#= reduction 68 | 69 | 42 =#= move 70 | 71 | 43 lOrExp#INT reduction 72 | 44 lAndExp#INT reduction 73 | 45 eqExp#INT reduction 74 | 46 relExp#INT reduction 75 | 47 addExp#INT reduction 76 | 48 mulExp#INT reduction 77 | 49 unaryExp#INT reduction 78 | 50 primaryExp#INT reduction 79 | 51 number#INT reduction 80 | 81 | 82 | 52 INT#INT move 83 | 84 | 53 mulExpAtom#; reduction 85 | 54 addExpAtom#; reduction 86 | 55 relExpAtom#; reduction 87 | 56 eqExpAtom#; reduction 88 | 57 lAndExpAtom#; reduction 89 | 58 lOrExpAtom#; reduction 90 | 59 assignExpAtom#; reduction 91 | 92 | 60 ;#; move 93 | 61 blockItem#return reduction 94 | 62 stmt#return reduction 95 | 63 return#return move 96 | 64 exp#INT reduction 97 | 98 | 65 assignExp#INT reduction 99 | 66 lOrExp#INT reduction 100 | 67 lAndExp#INT reduction 101 | 68 eqExp#INT reduction 102 | 69 relExp#INT reduction 103 | 104 | 70 addExp#INT reduction 105 | 71 mulExp#INT reduction 106 | 72 unaryExp#INT reduction 107 | 73 primaryExp#INT reduction 108 | 74 number#INT reduction 109 | 75 INT#INT move 110 | 111 | 76 mulExpAtom#; reduction 112 | 77 addExpAtom#; reduction 113 | 78 relExpAtom#; reduction 114 | 79 eqExpAtom#; reduction 115 | 80 lAndExpAtom#; reduction 116 | 81 lOrExpAtom#; reduction 117 | 82 assignExpAtom#; reduction 118 | 83 ;#; move 119 | 84 blockItem#} reduction 120 | 121 | 85 }#} move 122 | 86 EOF#EOF accept -------------------------------------------------------------------------------- /docs/02_var_defn.txt: -------------------------------------------------------------------------------- 1 | int 2 | a 3 | = 4 | 3 5 | ; 6 | int 7 | b 8 | = 9 | 5 10 | ; 11 | void 12 | func 13 | ( 14 | ) 15 | { 16 | return 17 | a 18 | + 19 | b 20 | ; 21 | } 22 | 23 | 1 program#int reduction 24 | 2 compUnit#int reduction 25 | 26 | 3 decl#int reduction 27 | 4 valDecl#int reduction 28 | 5 btype#int reduction 29 | 6 int#int move 30 | 7 varDef#Ident reduction 31 | 8 Ident#Ident move 32 | 33 | 9 argVarDef#= reduction 34 | 35 | 10 =#= move 36 | 11 initVal#INT reduction 37 | 12 exp#INT reduction 38 | 39 | 13 assignExp#INT reduction 40 | 14 OrExp#INT reduction 41 | 15 AndExp#INT reduction 42 | 16 eqExp#INT reduction 43 | 17 relExp#INT reduction 44 | 45 | 18 addExp#INT reduction 46 | 19 mulExp#INT reduction 47 | 20 unaryExp#INT reduction 48 | 21 primaryExp#INT reduction 49 | 22 number#INT reduction 50 | 23 INT#INT move 51 | 52 | 24 mulExpAtom#; reduction 53 | 25 addExpAtom#; reduction 54 | 26 relExpAtom#; reduction 55 | 27 eqExpAtom#; reduction 56 | 28 lAndExpAtom#; reduction 57 | 29 lOrExpAtom#; reduction 58 | 30 assignExpAtom#; reduction 59 | 31 argVarDecl#; reduction 60 | 61 | 32 ;#; move 62 | 63 | 33 compUnit#int reduction 64 | 65 | 34 decl#int reduction 66 | 35 valDecl#int reduction 67 | 36 btype#int reduction 68 | 37 int#int move 69 | 38 varDef#Ident reduction 70 | 39 Ident#Ident move 71 | 72 | 40 argVarDef#= reduction 73 | 74 | 41 =#= move 75 | 42 initVal#INT reduction 76 | 43 exp#INT reduction 77 | 78 | 44 assignExp#INT reduction 79 | 45 lOrExp#INT reduction 80 | 46 lAndExp#INT reduction 81 | 47 eqExp#INT reduction 82 | 48 relExp#INT reduction 83 | 84 | 49 addExp#INT reduction 85 | 50 mulExp#INT reduction 86 | 51 unaryExp#INT reduction 87 | 52 primaryExp#INT reduction 88 | 53 number#INT reduction 89 | 54 INT#INT move 90 | 91 | 55 mulExpAtom#; reduction 92 | 56 addExpAtom#; reduction 93 | 57 relExpAtom#; reduction 94 | 58 eqExpAtom#; reduction 95 | 59 lAndExpAtom#; reduction 96 | 60 lOrExpAtom#; reduction 97 | 61 assignExpAtom#; reduction 98 | 62 argVarDecl#; reduction 99 | 100 | 63 ;#; move 101 | 102 | 64 compUnit#void reduction 103 | 104 | 65 funcDef#void reduction 105 | 66 funcType#void reduction 106 | 67 void#void move 107 | 68 Ident#Ident move 108 | 69 (#( move 109 | 110 | 70 funcFParams#) reduction 111 | 112 | 71 )#) move 113 | 72 block#{ reduction 114 | 73 {#{ move 115 | 116 | 74 blockItem#return reduction 117 | 75 stmt#return reduction 118 | 76 return#return move 119 | 77 exp#Ident reduction 120 | 121 | 78 assignExp#Ident reduction 122 | 79 lOrExp#Ident reduction 123 | 80 lAndExp#Ident reduction 124 | 81 eqExp#Ident reduction 125 | 82 Exp#Ident reduction 126 | 127 | 128 | 83 addExp#Ident reduction 129 | 84 mulExp#Ident reduction 130 | 85 unaryExp#Ident reduction 131 | 86 Ident#Ident move 132 | 133 | 87 callFunc#+ reduction 134 | 88 mulExpAtom#+ reduction 135 | 89 addExpAtom#+ reduction 136 | 137 | 90 +#+ move 138 | 91 mulExp#Ident reduction 139 | 92 unaryExp#Ident reduction 140 | 93 Ident#Ident move 141 | 142 | 94 mulExpAtom#; reduction 143 | 95 addExpAtom#; reduction 144 | 96 relExpAtom#; reduction 145 | 97 eqExpAtom#; reduction 146 | 98 lAndExpAtom#; reduction 147 | 99 lOrExpAtom#; reduction 148 | 100 assignExpAtom#; reduction 149 | 150 | 101 ;#; move 151 | 152 | 102 blockItem#} reduction 153 | 154 | 103 }#} move 155 | 104 EOF#EOF accept -------------------------------------------------------------------------------- /docs/03_var_defn.txt: -------------------------------------------------------------------------------- 1 | int 2 | a 3 | = 4 | 3 5 | ; 6 | int 7 | b 8 | = 9 | 5 10 | ; 11 | void 12 | func 13 | ( 14 | ) 15 | { 16 | int 17 | a 18 | = 19 | 5 20 | ; 21 | return 22 | a 23 | + 24 | b 25 | ; 26 | } 27 | 28 | 1 program#int reduction 29 | 2 compUnit#int reduction 30 | 31 | 3 decl#int reduction 32 | 4 valDecl#int reduction 33 | 5 btype#int reduction 34 | 6 int#int move 35 | 7 varDef#Ident reduction 36 | 8 Ident#Ident move 37 | 38 | 9 argVarDef#= reduction 39 | 40 | 10 =#= move 41 | 11 initVal#INT reduction 42 | 12 exp#INT reduction 43 | 44 | 13 assignExp#INT reduction 45 | 14 eqExp#INT reduction 46 | 15 relExp#INT reduction 47 | 48 | 49 | 16 addExp#INT reduction 50 | 17 mulExp#INT reduction 51 | 18 unaryExp#INT reduction 52 | 19 primaryExp#INT reduction 53 | 20 number#INT reduction 54 | 21 INT#INT move 55 | 56 | 22 mulExpAtom#; reduction 57 | 23 addExpAtom#; reduction 58 | 24 relExpAtom#; reduction 59 | 25 eqExpAtom#; reduction 60 | 26 assignExpAtom#; reduction 61 | 27 argVarDecl#; reduction 62 | 63 | 28 ;#; move 64 | 65 | 29 compUnit#int reduction 66 | 67 | 30 decl#int reduction 68 | 31 valDecl#int reduction 69 | 32 btype#int reduction 70 | 33 int#int move 71 | 34 varDef#Ident reduction 72 | 35 Ident#Ident move 73 | 74 | 36 argVarDef#= reduction 75 | 76 | 37 =#= move 77 | 38 initVal#INT reduction 78 | 39 exp#INT reduction 79 | 80 | 40 assignExp#INT reduction 81 | 41 eqExp#INT reduction 82 | 42 relExp#INT reduction 83 | 84 | 43 addExp#INT reduction 85 | 44 mulExp#INT reduction 86 | 45 unaryExp#INT reduction 87 | 46 primaryExp#INT reduction 88 | 47 number#INT reduction 89 | 48 INT#INT move 90 | 91 | 49 mulExpAtom#; reduction 92 | 50 addExpAtom#; reduction 93 | 51 relExpAtom#; reduction 94 | 52 eqExpAtom#; reduction 95 | 53 assignExpAtom#; reduction 96 | 54 argVarDecl#; reduction 97 | 98 | 55 ;#; move 99 | 100 | 56 compUnit#void reduction 101 | 102 | 57 funcDef#void reduction 103 | 58 funcType#void reduction 104 | 59 void#void move 105 | 60 Ident#Ident move 106 | 61 (#( move 107 | 108 | 62 funcFParams#) reduction 109 | 110 | 63 )#) move 111 | 64 block#{ reduction 112 | 65 {#{ move 113 | 114 | 66 blockItem#int reduction 115 | 67 decl#int reduction 116 | 68 valDecl#int reduction 117 | 69 btype#int reduction 118 | 70 int#int move 119 | 71 varDef#Ident reduction 120 | 72 Ident#Ident move 121 | 122 | 73 argVarDef#= reduction 123 | 124 | 74 =#= move 125 | 75 initVal#INT reduction 126 | 76 exp#INT reduction 127 | 128 | 77 assignExp#INT reduction 129 | 78 eqExp#INT reduction 130 | 79 relExp#INT reduction 131 | 132 | 80 addExp#INT reduction 133 | 81 mulExp#INT reduction 134 | 82 unaryExp#INT reduction 135 | 83 primaryExp#INT reduction 136 | 84 number#INT reduction 137 | 85 INT#INT move 138 | 139 | 86 mulExpAtom#; reduction 140 | 87 addExpAtom#; reduction 141 | 88 relExpAtom#; reduction 142 | 89 eqExpAtom#; reduction 143 | 90 assignExpAtom#; reduction 144 | 91 argVarDecl#; reduction 145 | 146 | 92 ;#; move 147 | 148 | 93 blockItem#return reduction 149 | 94 stmt#return reduction 150 | 95 return#return move 151 | 152 | 96 argExp#Ident reduction 153 | 97 exp#Ident reduction 154 | 98 assignExp#Ident reduction 155 | 99 eqExp#Ident reduction 156 | 100 relExp#Ident reduction 157 | 158 | 101 addExp#Ident reduction 159 | 102 mulExp#Ident reduction 160 | 103 unaryExp#Ident reduction 161 | 104 Ident#Ident move 162 | 163 | 105 callFunc#+ reduction 164 | 106 mulExpAtom#+ reduction 165 | 107 addExpAtom#+ reduction 166 | 167 | 108 +#+ move 168 | 109 mulExp#Ident reduction 169 | 110 unaryExp#Ident reduction 170 | 111 Ident#Ident move 171 | 172 | 112 callFunc#; reduction 173 | 113 mulExpAtom#; reduction 174 | 114 addExpAtom#; reduction 175 | 115 relExpAtom#; reduction 176 | 116 eqExpAtom#; reduction 177 | 117 assignExpAtom#; reduction 178 | 179 | 118 ;#; move 180 | 181 | 119 blockItem#} reduction 182 | 183 | 120 }#} move 184 | 121 EOF#EOF accept -------------------------------------------------------------------------------- /docs/04_var_defn.txt: -------------------------------------------------------------------------------- 1 | int 2 | a 3 | = 4 | 3 5 | , 6 | b 7 | = 8 | 1 9 | , 10 | c 11 | = 12 | 3 13 | ; 14 | void 15 | func 16 | ( 17 | ) 18 | { 19 | int 20 | a 21 | = 22 | 5 23 | ; 24 | return 25 | a 26 | + 27 | b 28 | ; 29 | } 30 | 31 | 1 program#int reduction 32 | 2 compUnit#int reduction 33 | 34 | 3 decl#int reduction 35 | 4 valDecl#int reduction 36 | 5 btype#int reduction 37 | 6 int#int move 38 | 7 varDef#Ident reduction 39 | 8 Ident#Ident move 40 | 41 | 9argVarDef#= 42 | 43 | 44 | 10 =#= move 45 | 11 initVal#INT reduction 46 | 12 exp#INT reduction 47 | 48 | 13 assignExp#INT reduction 49 | 14 eqExp#INT reduction 50 | 15 relExp#INT reduction 51 | 52 | 53 | 16 addExp#INT reduction 54 | 17 mulExp#INT reduction 55 | 18 unaryExp#INT reduction 56 | 19 primaryExp#INT reduction 57 | 20 number#INT reduction 58 | 21 INT#INT move 59 | 60 | 22 mulExpAtom#, reduction 61 | 23 addExpAtom#, reduction 62 | 24 relExpAtom#, reduction 63 | 25 eqExpAtom#, reduction 64 | 26 assignExpAtom#, reduction 65 | 27 argVarDecl#, reduction 66 | 67 | 28 ,#, move 68 | 69 | 29 varDef#Ident reduction 70 | 30 Ident#Ident move 71 | 72 | 31argVarDef#= 73 | 74 | 32 =#= move 75 | 33 initVal#INT reduction 76 | 34 exp#INT reduction 77 | 78 | 35 assignExp#INT reduction 79 | 36 eqExp#INT reduction 80 | 37 relExp#INT reduction 81 | 82 | 38 addExp#INT reduction 83 | 39 mulExp#INT reduction 84 | 40 unaryExp#INT reduction 85 | 41 primaryExp#INT reduction 86 | 42 number#INT reduction 87 | 43 INT#INT move 88 | 89 | 44 mulExpAtom#, reduction 90 | 45 addExpAtom#, reduction 91 | 46 relExpAtom#, reduction 92 | 47 eqExpAtom#, reduction 93 | 48 assignExpAtom#, reduction 94 | 49 argVarDecl#, reduction 95 | 96 | 50 ,#, move 97 | 98 | 51 varDef#Ident reduction 99 | 52 Ident#Ident move 100 | 101 | 53 argVarDef#= reduction 102 | 103 | 54 =#= move 104 | 55 initVal#INT reduction 105 | 56 exp#INT reduction 106 | 107 | 57 assignExp#INT reduction 108 | 58 eqExp#INT reduction 109 | 59 relExp#INT reduction 110 | 111 | 60 addExp#INT reduction 112 | 61 mulExp#INT reduction 113 | 62 unaryExp#INT reduction 114 | 63 primaryExp#INT reduction 115 | 64 number#INT reduction 116 | 65 INT#INT move 117 | 118 | 66 mulExpAtom#; reduction 119 | 67 addExpAtom#; reduction 120 | 68 relExpAtom#; reduction 121 | 69 eqExpAtom#; reduction 122 | 70 assignExpAtom#; reduction 123 | 71 argVarDecl#; reduction 124 | 125 | 72 ;#; move 126 | 127 | 73 compUnit#void reduction 128 | 129 | 74 funcDef#void reduction 130 | 75 funcType#void reduction 131 | 76 void#void move 132 | 77 Ident#Ident move 133 | 78 (#( move 134 | 135 | 79 funcFParams#) reduction 136 | 137 | 80 )#) move 138 | 81 block#{ reduction 139 | 82 {#{ move 140 | 141 | 83 blockItem#int reduction 142 | 84 decl#int reduction 143 | 85 valDecl#int reduction 144 | 86 btype#int reduction 145 | 87 int#int move 146 | 88 varDef#Ident reduction 147 | 89 Ident#Ident move 148 | 149 | 90 argVarDef#= reduction 150 | 151 | 91 =#= move 152 | 92 initVal#INT reduction 153 | 93 exp#INT reduction 154 | 155 | 94 assignExp#INT reduction 156 | 95 eqExp#INT reduction 157 | 96 relExp#INT reduction 158 | 159 | 97 addExp#INT reduction 160 | 98 mulExp#INT reduction 161 | 99 unaryExp#INT reduction 162 | 100 primaryExp#INT reduction 163 | 101 number#INT reduction 164 | 102 INT#INT move 165 | 166 | 103 mulExpAtom#; reduction 167 | 104 addExpAtom#; reduction 168 | 105 relExpAtom#; reduction 169 | 106 eqExpAtom#; reduction 170 | 107 assignExpAtom#; reduction 171 | 108 argVarDecl#; reduction 172 | 173 | 109 ;#; move 174 | 175 | 110 blockItem#return reduction 176 | 111 stmt#return reduction 177 | 112 return#return move 178 | 179 | 113 argExp#Ident reduction 180 | 114 exp#Ident reduction 181 | 115 assignExp#Ident reduction 182 | 116 eqExp#Ident reduction 183 | 117 relExp#Ident reduction 184 | 185 | 118 addExp#Ident reduction 186 | 119 mulExp#Ident reduction 187 | 120 unaryExp#Ident reduction 188 | 121 Ident#Ident move 189 | 190 | 122 callFunc#+ reduction 191 | 123 mulExpAtom#+ reduction 192 | 124 addExpAtom#+ reduction 193 | 194 | 125 +#+ move 195 | 126 mulExp#Ident reduction 196 | 127 unaryExp#Ident reduction 197 | 128 Ident#Ident move 198 | 199 | 129 callFunc#; reduction 200 | 130 mulExpAtom#; reduction 201 | 131 addExpAtom#; reduction 202 | 132 relExpAtom#; reduction 203 | 133 eqExpAtom#; reduction 204 | 134 assignExpAtom#; reduction 205 | 206 | 135 ;#; move 207 | 208 | 136 blockItem#} reduction 209 | 210 | 137 }#} move 211 | 138 EOF#EOF accept -------------------------------------------------------------------------------- /docs/05_var_defn.txt: -------------------------------------------------------------------------------- 1 | int 2 | a 3 | = 4 | 3 5 | ; 6 | int 7 | b 8 | = 9 | 1 10 | ; 11 | int 12 | c 13 | = 14 | 3 15 | ; 16 | int 17 | e 18 | = 19 | 0 20 | , 21 | f 22 | = 23 | 10 24 | ; 25 | void 26 | func 27 | ( 28 | ) 29 | { 30 | int 31 | a 32 | = 33 | 5 34 | ; 35 | int 36 | c 37 | = 38 | 2 39 | ; 40 | int 41 | temp1 42 | = 43 | f 44 | + 45 | e 46 | ; 47 | int 48 | temp2 49 | = 50 | f 51 | + 52 | 2 53 | ; 54 | int 55 | temp3 56 | = 57 | c 58 | ; 59 | return 60 | a 61 | + 62 | b 63 | ; 64 | } 65 | 66 | 1 program#int reduction 67 | 2 compUnit#int reduction 68 | 69 | 3 decl#int reduction 70 | 4 valDecl#int reduction 71 | 5 btype#int reduction 72 | 6 int#int move 73 | 7 varDef#Ident reduction 74 | 8 Ident#Ident move 75 | 76 | argVarDef#= 77 | 78 | 9 =#= move 79 | 10 initVal#INT reduction 80 | 11 exp#INT reduction 81 | 82 | 12 assignExp#INT reduction 83 | 13 eqExp#INT reduction 84 | 14 relExp#INT reduction 85 | 86 | 15 addExp#INT reduction 87 | 16 mulExp#INT reduction 88 | 17 unaryExp#INT reduction 89 | 18 primaryExp#INT reduction 90 | 19 number#INT reduction 91 | 20 INT#INT move 92 | 93 | 21 mulExpAtom#; reduction 94 | 22 addExpAtom#; reduction 95 | 23 relExpAtom#; reduction 96 | 24 eqExpAtom#; reduction 97 | 25 assignExpAtom#; reduction 98 | 26 argVarDecl#; reduction 99 | 100 | 27 ;#; move 101 | 102 | 28 compUnit#int reduction 103 | 104 | 29 decl#int reduction 105 | 30 valDecl#int reduction 106 | 31 btype#int reduction 107 | 32 int#int move 108 | 33 varDef#Ident reduction 109 | 34 Ident#Ident move 110 | 35 =#= move 111 | 112 | 36 argVarDef#= reduction 113 | 114 | 37 initVal#INT reduction 115 | 38 exp#INT reduction 116 | 117 | 39 assignExp#INT reduction 118 | 40 eqExp#INT reduction 119 | 41 relExp#INT reduction 120 | 121 | 42 addExp#INT reduction 122 | 43 mulExp#INT reduction 123 | 44 unaryExp#INT reduction 124 | 45 primaryExp#INT reduction 125 | 46 number#INT reduction 126 | 47 INT#INT move 127 | 128 | 48 mulExpAtom#; reduction 129 | 49 addExpAtom#; reduction 130 | 50 relExpAtom#; reduction 131 | 51 eqExpAtom#; reduction 132 | 52 assignExpAtom#; reduction 133 | 53 argVarDecl#; reduction 134 | 135 | 54 ;#; move 136 | 137 | 55 compUnit#int reduction 138 | 139 | 56 decl#int reduction 140 | 57 valDecl#int reduction 141 | 58 btype#int reduction 142 | 59 int#int move 143 | 60 varDef#Ident reduction 144 | 61 Ident#Ident move 145 | 62 =#= move 146 | 147 | 63 argVarDef#= reduction 148 | 149 | 64 initVal#INT reduction 150 | 65 exp#INT reduction 151 | 152 | 66 assignExp#INT reduction 153 | 67 eqExp#INT reduction 154 | 68 relExp#INT reduction 155 | 156 | 69 addExp#INT reduction 157 | 70 mulExp#INT reduction 158 | 71 unaryExp#INT reduction 159 | 72 primaryExp#INT reduction 160 | 73 number#INT reduction 161 | 74 INT#INT move 162 | 163 | 75 mulExpAtom#; reduction 164 | 76 addExpAtom#; reduction 165 | 77 relExpAtom#; reduction 166 | 78 eqExpAtom#; reduction 167 | 79 assignExpAtom#; reduction 168 | 80 argVarDecl#; reduction 169 | 170 | 81 ;#; move 171 | 172 | 173 | 82 program#int reduction 174 | 83 compUnit#int reduction 175 | 176 | 84 decl#int reduction 177 | 85 valDecl#int reduction 178 | 86 btype#int reduction 179 | 87 int#int move 180 | 88 varDef#Ident reduction 181 | 89 Ident#Ident move 182 | 183 | 90 argVarDef#= reduction 184 | 185 | 186 | 91 =#= move 187 | 92 initVal#INT reduction 188 | 93 exp#INT reduction 189 | 190 | 94 assignExp#INT reduction 191 | 95 eqExp#INT reduction 192 | 96 relExp#INT reduction 193 | 194 | 195 | 97 addExp#INT reduction 196 | 98 mulExp#INT reduction 197 | 99 unaryExp#INT reduction 198 | 100 primaryExp#INT reduction 199 | 101 number#INT reduction 200 | 102 INT#INT move 201 | 202 | 103 mulExpAtom#, reduction 203 | 104 addExpAtom#, reduction 204 | 105 relExpAtom#, reduction 205 | 106 eqExpAtom#, reduction 206 | 107 assignExpAtom#, reduction 207 | 108 argVarDecl#, reduction 208 | 209 | 109 ,#, move 210 | 211 | 110 varDef#Ident reduction 212 | 111 Ident#Ident move 213 | 214 | 112 argVarDef#= reduction 215 | 216 | 113 =#= move 217 | 114 initVal#INT reduction 218 | 115 exp#INT reduction 219 | 220 | 116 assignExp#INT reduction 221 | 117 eqExp#INT reduction 222 | 118 relExp#INT reduction 223 | 224 | 119 addExp#INT reduction 225 | 120 mulExp#INT reduction 226 | 121 unaryExp#INT reduction 227 | 122 primaryExp#INT reduction 228 | 123 number#INT reduction 229 | 124 INT#INT move 230 | 231 | 125 mulExpAtom#; reduction 232 | 126 addExpAtom#; reduction 233 | 127 relExpAtom#; reduction 234 | 128 eqExpAtom#; reduction 235 | 129 assignExpAtom#; reduction 236 | 130 argVarDecl#; 237 | 238 | 131 ;#; move 239 | 240 | 132 compUnit#void reduction 241 | 242 | 133 funcDef#void reduction 243 | 134 funcType#void reduction 244 | 135 void#void move 245 | 136 Ident#Ident move 246 | 137 (#( move 247 | 248 | 138 funcFParams#) reduction 249 | 250 | 139 )#) move 251 | 140 block#{ reduction 252 | 141 {#{ move 253 | 254 | 142 blockItem#int reduction 255 | 143 decl#int reduction 256 | 144 valDecl#int reduction 257 | 145 btype#int reduction 258 | 146 int#int move 259 | 147 varDef#Ident reduction 260 | 148 Ident#Ident move 261 | 262 | 149 argVarDef#= reduction 263 | 264 | 150 =#= move 265 | 151 initVal#INT reduction 266 | 152 exp#INT reduction 267 | 268 | 153 assignExp#INT reduction 269 | 154 eqExp#INT reduction 270 | 155 relExp#INT reduction 271 | 272 | 156 addExp#INT reduction 273 | 157 mulExp#INT reduction 274 | 158 unaryExp#INT reduction 275 | 159 primaryExp#INT reduction 276 | 160 number#INT reduction 277 | 161 INT#INT move 278 | 279 | 162 mulExpAtom#; reduction 280 | 163 addExpAtom#; reduction 281 | 164 relExpAtom#; reduction 282 | 165 eqExpAtom#; reduction 283 | 166 assignExpAtom#; reduction 284 | 167 argVarDecl#; reduction 285 | 286 | 168 ;#; move 287 | 288 | 169 blockItem#int reduction 289 | 170 decl#int reduction 290 | 171 valDecl#int reduction 291 | 172 btype#int reduction 292 | 173 int#int move 293 | 174 varDef#Ident reduction 294 | 175 Ident#Ident move 295 | 296 | 176 argVarDef#= reduction 297 | 298 | 177 =#= move 299 | 178 initVal#INT reduction 300 | 179 exp#INT reduction 301 | 302 | 180 assignExp#INT reduction 303 | 181 eqExp#INT reduction 304 | 182 relExp#INT reduction 305 | 306 | 183 addExp#INT reduction 307 | 184 mulExp#INT reduction 308 | 185 unaryExp#INT reduction 309 | 186 primaryExp#INT reduction 310 | 187 number#INT reduction 311 | 188 INT#INT move 312 | 313 | 189 mulExpAtom#; reduction 314 | 190 addExpAtom#; reduction 315 | 191 relExpAtom#; reduction 316 | 192 eqExpAtom#; reduction 317 | 193 assignExpAtom#; reduction 318 | 194 argVarDecl#; reduction 319 | 320 | 195 ;#; move 321 | 322 | 196 blockItem#int reduction 323 | 197 decl#int reduction 324 | 198 valDecl#int reduction 325 | 199 btype#int reduction 326 | 200 int#int move 327 | 201 varDef#Ident reduction 328 | 202 Ident#Ident move 329 | 330 | 203 argVarDef#= reduction 331 | 332 | 204 =#= move 333 | 205 initVal#Ident reduction 334 | 206 exp#Ident reduction 335 | 336 | 207 assignExp#Ident reduction 337 | 208 eqExp#Ident reduction 338 | 209 relExp#Ident reduction 339 | 340 | 210 addExp#Ident reduction 341 | 211 mulExp#Ident reduction 342 | 212 unaryExp#Ident reduction 343 | 344 | 213 Ident#Ident move 345 | 346 | 214 callFunc#+ reduction 347 | 215 mulExpAtom#+ reduction 348 | 216 addExpAtom#+ reduction 349 | 350 | 217 +#+ move 351 | 218 mulExp#Ident reduction 352 | 219 unaryExp#Ident reduction 353 | 220 Ident#Ident move 354 | 355 | 221 mulExpAtom#; reduction 356 | 222 addExpAtom#; reduction 357 | 223 relExpAtom#; reduction 358 | 224 eqExpAtom#; reduction 359 | 225 assignExpAtom#; reduction 360 | 226 argVarDecl#; reduction 361 | 362 | 227 ;#; move 363 | 364 | 228 blockItem#int reduction 365 | 229 decl#int reduction 366 | 230 valDecl#int reduction 367 | 231 btype#int reduction 368 | 232 int#int move 369 | 233 varDef#Ident reduction 370 | 234 Ident#Ident move 371 | 372 | 235 argVarDef#= reduction 373 | 374 | 236 =#= move 375 | 237 initVal#Ident reduction 376 | 238 exp#Ident reduction 377 | 378 | 239 assignExp#Ident reduction 379 | 240 eqExp#Ident reduction 380 | 241 relExp#Ident reduction 381 | 382 | 242 addExp#Ident reduction 383 | 243 mulExp#Ident reduction 384 | 244 unaryExp#Ident reduction 385 | 386 | 245 Ident#Ident move 387 | 388 | 246 callFunc#+ reduction 389 | 247 mulExpAtom#+ reduction 390 | 248 addExpAtom#+ reduction 391 | 392 | 249 +#+ move 393 | 250 mulExp#INT reduction 394 | 251 unaryExp#INT reduction 395 | 396 | 252 primaryExp#INT reduction 397 | 253 number#INT reduction 398 | 399 | 254 INT#INT move 400 | 401 | 255 mulExpAtom#; reduction 402 | 256 addExpAtom#; reduction 403 | 257 relExpAtom#; reduction 404 | 258 eqExpAtom#; reduction 405 | 259 assignExpAtom#; reduction 406 | 260 argVarDecl#; reduction 407 | 408 | 261 ;#; move 409 | 410 | 262 blockItem#int reduction 411 | 263 decl#int reduction 412 | 264 valDecl#int reduction 413 | 265 btype#int reduction 414 | 266 int#int move 415 | 267 varDef#Ident reduction 416 | 268 Ident#Ident move 417 | 418 | 269 argVarDef#= reduction 419 | 420 | 270 =#= move 421 | 271 initVal#Ident reduction 422 | 272 exp#Ident reduction 423 | 424 | 273 assignExp#Ident reduction 425 | 274 eqExp#Ident reduction 426 | 275 relExp#Ident reduction 427 | 428 | 276 addExp#Ident reduction 429 | 277 mulExp#Ident reduction 430 | 278 unaryExp#Ident reduction 431 | 279 Ident#Ident move 432 | 433 | 280 mulExpAtom#; reduction 434 | 281 addExpAtom#; reduction 435 | 282 relExpAtom#; reduction 436 | 283 eqExpAtom#; reduction 437 | 284 assignExpAtom#; reduction 438 | 285 argVarDecl#; reduction 439 | 440 | 286 ;#; move 441 | 442 | 287 blockItem#return reduction 443 | 288 stmt#return reduction 444 | 289 return#return move 445 | 446 | 290 argExp#Ident reduction 447 | 291 exp#Ident reduction 448 | 292 assignExp#Ident reduction 449 | 293 eqExp#Ident reduction 450 | 294 relExp#Ident reduction 451 | 452 | 295 addExp#Ident reduction 453 | 296 mulExp#Ident reduction 454 | 297 unaryExp#Ident reduction 455 | 298 Ident#Ident move 456 | 457 | 299 callFunc#+ reduction 458 | 300 mulExpAtom#+ reduction 459 | 301 addExpAtom#+ reduction 460 | 461 | 302 +#+ move 462 | 303 mulExp#Ident reduction 463 | 304 unaryExp#Ident reduction 464 | 305 Ident#Ident move 465 | 466 | 306 callFunc#; reduction 467 | 307 mulExpAtom#; reduction 468 | 308 addExpAtom#; reduction 469 | 309 relExpAtom#; reduction 470 | 310 eqExpAtom#; reduction 471 | 311 assignExpAtom#; reduction 472 | 473 | 312 ;#; move 474 | 475 | 313 blockItem#} reduction 476 | 477 | 314 }#} move 478 | 315 EOF#EOF accept -------------------------------------------------------------------------------- /docs/grammar.txt: -------------------------------------------------------------------------------- 1 | program -> compUnit 2 | compUnit -> decl compUnit 3 | compUnit -> funcDef compUnit 4 | compUnit -> $ 5 | decl -> constDecl 6 | decl -> varDecl 7 | constDecl -> const bType constDef argConst ; 8 | argConst -> , constDef argConst 9 | argConst -> $ 10 | constDef -> Ident = constInitVal 11 | constInitVal -> constExp 12 | varDecl -> bType varDef argVarDecl ; 13 | argVarDecl -> , varDef argVarDecl 14 | argVarDecl -> $ 15 | varDef -> Ident argVarDef 16 | argVarDef -> = initVal 17 | argVarDef -> $ 18 | initVal -> exp 19 | bType -> int 20 | funcDef -> funcType Ident ( funcFParams ) block 21 | funcType -> void 22 | funcFParams -> funcFParam argFunctionF 23 | funcFParams -> $ 24 | argFunctionF -> , funcFParam argFunctionF 25 | argFunctionF -> $ 26 | funcFParam -> bType Ident 27 | block -> { blockItem } 28 | blockItem -> decl blockItem 29 | blockItem -> stmt blockItem 30 | blockItem -> $ 31 | stmt -> exp ; 32 | stmt -> ; 33 | stmt -> block 34 | stmt -> return argExp ; 35 | argExp -> $ 36 | argExp -> exp 37 | exp -> assignExp 38 | lVal -> Ident 39 | primaryExp -> ( exp ) 40 | primaryExp -> number 41 | number -> INT 42 | unaryOp -> + 43 | unaryOp -> - 44 | unaryOp -> ! 45 | unaryExp -> unaryOp unaryExp 46 | unaryExp -> Ident callFunc 47 | callFunc -> ( funcRParams ) 48 | callFunc -> $ 49 | unaryExp -> primaryExp 50 | funcRParams -> funcRParam argFunctionR 51 | funcRParams -> $ 52 | argFunctionR -> , funcRParam argFunctionR 53 | argFunctionR -> $ 54 | funcRParam -> exp 55 | mulExp -> unaryExp mulExpAtom 56 | mulExpAtom -> * unaryExp mulExpAtom 57 | mulExpAtom -> / unaryExp mulExpAtom 58 | mulExpAtom -> % unaryExp mulExpAtom 59 | mulExpAtom -> $ 60 | addExp -> mulExp addExpAtom 61 | addExpAtom -> + mulExp addExpAtom 62 | addExpAtom -> - mulExp addExpAtom 63 | addExpAtom -> $ 64 | relExp -> addExp relExpAtom 65 | relExpAtom -> < addExp relExpAtom 66 | relExpAtom -> > addExp relExpAtom 67 | relExpAtom -> <= addExp relExpAtom 68 | relExpAtom -> >= addExp relExpAtom 69 | relExpAtom -> $ 70 | eqExp -> relExp eqExpAtom 71 | eqExpAtom -> == relExp eqExpAtom 72 | eqExpAtom -> != relExp eqExpAtom 73 | eqExpAtom -> $ 74 | assignExp -> eqExp assignExpAtom 75 | assignExpAtom -> = eqExp assignExpAtom 76 | assignExpAtom -> $ 77 | constExp -> assignExp -------------------------------------------------------------------------------- /docs/大作业.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geraldkohn/compiler/1d9c81c338e77ac515215f77c7ce6e8b82e96d3d/docs/大作业.pdf -------------------------------------------------------------------------------- /input/1.txt: -------------------------------------------------------------------------------- 1 | int a; 2 | void func () { 3 | a = 10; 4 | return 0; 5 | } -------------------------------------------------------------------------------- /input/2.txt: -------------------------------------------------------------------------------- 1 | int a = 3; 2 | int b = 5; 3 | void func () { 4 | return a + b; 5 | } -------------------------------------------------------------------------------- /input/3.txt: -------------------------------------------------------------------------------- 1 | int a = 3; 2 | int b = 5; 3 | void func () { 4 | a = 5; 5 | return a + b; 6 | } -------------------------------------------------------------------------------- /input/4.txt: -------------------------------------------------------------------------------- 1 | int a = 3, b = 1, c = 3; 2 | void func () { 3 | int a = 5; 4 | return a + b; 5 | } -------------------------------------------------------------------------------- /input/5.txt: -------------------------------------------------------------------------------- 1 | int a = 3; 2 | int b = 1; 3 | int c = 3; 4 | int e = 0, f = 10; 5 | void func () { 6 | int a = 5; 7 | int c = 2; 8 | int temp2 = f + 2; 9 | int temp3 = c; 10 | return a + b; 11 | } -------------------------------------------------------------------------------- /input/code.txt: -------------------------------------------------------------------------------- 1 | int a = 3; 2 | int b = 1; 3 | int c = 3; 4 | int e = 0, f = 10; 5 | void func () { 6 | int a = 5; 7 | int c = 2; 8 | int temp2 = f + 2; 9 | int temp3 = c; 10 | return a + b; 11 | } -------------------------------------------------------------------------------- /input/grammar.txt: -------------------------------------------------------------------------------- 1 | program -> compUnit 2 | compUnit -> decl compUnit 3 | compUnit -> funcDef compUnit 4 | compUnit -> $ 5 | decl -> constDecl 6 | decl -> varDecl 7 | constDecl -> const bType constDef argConst ; 8 | argConst -> , constDef argConst 9 | argConst -> $ 10 | constDef -> Ident = constInitVal 11 | constInitVal -> constExp 12 | varDecl -> bType varDef argVarDecl ; 13 | argVarDecl -> , varDef argVarDecl 14 | argVarDecl -> $ 15 | varDef -> Ident argVarDef 16 | argVarDef -> = initVal 17 | argVarDef -> $ 18 | initVal -> exp 19 | bType -> int 20 | funcDef -> funcType Ident ( funcFParams ) block 21 | funcType -> void 22 | funcFParams -> funcFParam argFunctionF 23 | funcFParams -> $ 24 | argFunctionF -> , funcFParam argFunctionF 25 | argFunctionF -> $ 26 | funcFParam -> bType Ident 27 | block -> { blockItem } 28 | blockItem -> decl blockItem 29 | blockItem -> stmt blockItem 30 | blockItem -> $ 31 | stmt -> exp ; 32 | stmt -> ; 33 | stmt -> block 34 | stmt -> return argExp ; 35 | argExp -> $ 36 | argExp -> exp 37 | exp -> assignExp 38 | lVal -> Ident 39 | primaryExp -> ( exp ) 40 | primaryExp -> number 41 | number -> INT 42 | unaryOp -> + 43 | unaryOp -> - 44 | unaryOp -> ! 45 | unaryExp -> unaryOp unaryExp 46 | unaryExp -> Ident callFunc 47 | callFunc -> ( funcRParams ) 48 | callFunc -> $ 49 | unaryExp -> primaryExp 50 | funcRParams -> funcRParam argFunctionR 51 | funcRParams -> $ 52 | argFunctionR -> , funcRParam argFunctionR 53 | argFunctionR -> $ 54 | funcRParam -> exp 55 | mulExp -> unaryExp mulExpAtom 56 | mulExpAtom -> * unaryExp mulExpAtom 57 | mulExpAtom -> / unaryExp mulExpAtom 58 | mulExpAtom -> % unaryExp mulExpAtom 59 | mulExpAtom -> $ 60 | addExp -> mulExp addExpAtom 61 | addExpAtom -> + mulExp addExpAtom 62 | addExpAtom -> - mulExp addExpAtom 63 | addExpAtom -> $ 64 | relExp -> addExp relExpAtom 65 | relExpAtom -> < addExp relExpAtom 66 | relExpAtom -> > addExp relExpAtom 67 | relExpAtom -> <= addExp relExpAtom 68 | relExpAtom -> >= addExp relExpAtom 69 | relExpAtom -> $ 70 | eqExp -> relExp eqExpAtom 71 | eqExpAtom -> == relExp eqExpAtom 72 | eqExpAtom -> != relExp eqExpAtom 73 | eqExpAtom -> $ 74 | assignExp -> eqExp assignExpAtom 75 | assignExpAtom -> = eqExp assignExpAtom 76 | assignExpAtom -> $ 77 | constExp -> assignExp -------------------------------------------------------------------------------- /input/grammar_test.txt: -------------------------------------------------------------------------------- 1 | S -> T E' 2 | E'-> + T E' 3 | E' -> $ 4 | T -> F T' 5 | T' -> * F T' 6 | T' -> $ 7 | F -> ( S ) 8 | F -> i -------------------------------------------------------------------------------- /output/First集合.tsv: -------------------------------------------------------------------------------- 1 | argFunctionR [,] 2 | <= [<=] 3 | decl [const, int] 4 | constInitVal [+, -, !, Ident, (, INT] 5 | constDef [Ident] 6 | compUnit [const, void, int] 7 | addExp [+, -, !, Ident, (, INT] 8 | unaryOp [+, -, !] 9 | program [const, void, int] 10 | addExpAtom [+, -] 11 | mulExpAtom [*, /, %] 12 | relExp [+, -, !, Ident, (, INT] 13 | argVarDecl [,] 14 | number [INT] 15 | eqExp [+, -, !, Ident, (, INT] 16 | funcFParams [int] 17 | block [{] 18 | mulExp [+, -, !, Ident, (, INT] 19 | argExp [+, -, !, Ident, (, INT] 20 | exp [+, -, !, Ident, (, INT] 21 | constExp [+, -, !, Ident, (, INT] 22 | == [==] 23 | ! [!] 24 | void [void] 25 | assignExp [+, -, !, Ident, (, INT] 26 | % [%] 27 | lVal [Ident] 28 | ( [(] 29 | ) [)] 30 | * [*] 31 | assignExpAtom [=] 32 | + [+] 33 | , [,] 34 | - [-] 35 | / [/] 36 | bType [int] 37 | unaryExp [+, -, !, Ident, (, INT] 38 | varDef [Ident] 39 | primaryExp [(, INT] 40 | ; [;] 41 | blockItem [const, ;, {, return, int, +, -, !, Ident, (, INT] 42 | < [<] 43 | != [!=] 44 | = [=] 45 | > [>] 46 | >= [>=] 47 | funcDef [void] 48 | eqExpAtom [==, !=] 49 | const [const] 50 | funcRParam [+, -, !, Ident, (, INT] 51 | INT [INT] 52 | funcRParams [+, -, !, Ident, (, INT] 53 | initVal [+, -, !, Ident, (, INT] 54 | argConst [,] 55 | funcType [void] 56 | Ident [Ident] 57 | relExpAtom [<, >, <=, >=] 58 | constDecl [const] 59 | callFunc [(] 60 | int [int] 61 | argVarDef [=] 62 | funcFParam [int] 63 | { [{] 64 | argFunctionF [,] 65 | } [}] 66 | varDecl [int] 67 | return [return] 68 | stmt [;, {, return, +, -, !, Ident, (, INT] 69 | -------------------------------------------------------------------------------- /output/Follow集合.tsv: -------------------------------------------------------------------------------- 1 | argFunctionR [), #] 2 | eqExpAtom [=, ,, ;, ), #] 3 | decl [const, void, int, ;, {, return, +, -, !, Ident, (, INT, }, #] 4 | constInitVal [,, ;, #] 5 | constDef [,, ;, #] 6 | compUnit [#] 7 | funcRParam [,, ), #] 8 | addExp [<, >, <=, >=, ==, !=, =, ,, ;, ), #] 9 | unaryOp [+, -, !, Ident, (, INT, #] 10 | program [#] 11 | addExpAtom [<, >, <=, >=, ==, !=, =, ,, ;, ), #] 12 | mulExpAtom [+, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 13 | relExp [==, !=, =, ,, ;, ), #] 14 | funcRParams [), #] 15 | argVarDecl [;, #] 16 | initVal [,, ;, #] 17 | number [*, /, %, +, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 18 | argConst [;, #] 19 | eqExp [=, ,, ;, ), #] 20 | funcFParams [), #] 21 | block [const, void, int, ;, {, return, +, -, !, Ident, (, INT, }, #] 22 | mulExp [+, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 23 | argExp [;, #] 24 | exp [,, ;, ), #] 25 | constExp [,, ;, #] 26 | funcType [Ident, #] 27 | assignExp [,, ;, ), #] 28 | relExpAtom [==, !=, =, ,, ;, ), #] 29 | lVal [#] 30 | constDecl [const, void, int, ;, {, return, +, -, !, Ident, (, INT, }, #] 31 | assignExpAtom [,, ;, ), #] 32 | callFunc [*, /, %, +, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 33 | bType [Ident, #] 34 | unaryExp [*, /, %, +, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 35 | argVarDef [,, ;, #] 36 | funcFParam [,, ), #] 37 | varDef [,, ;, #] 38 | primaryExp [*, /, %, +, -, <, >, <=, >=, ==, !=, =, ,, ;, ), #] 39 | blockItem [}, #] 40 | argFunctionF [), #] 41 | varDecl [const, void, int, ;, {, return, +, -, !, Ident, (, INT, }, #] 42 | stmt [const, ;, {, return, int, +, -, !, Ident, (, INT, }, #] 43 | funcDef [const, void, int, #] 44 | -------------------------------------------------------------------------------- /output/分析表.tsv: -------------------------------------------------------------------------------- 1 | {横坐标: ( 纵坐标: constInitVal} 文法: constInitVal->[constExp] 2 | {横坐标: >= 纵坐标: addExpAtom} 文法: addExpAtom->[$] 3 | {横坐标: < 纵坐标: addExpAtom} 文法: addExpAtom->[$] 4 | {横坐标: ; 纵坐标: eqExpAtom} 文法: eqExpAtom->[$] 5 | {横坐标: INT 纵坐标: number} 文法: number->[INT] 6 | {横坐标: ; 纵坐标: assignExpAtom} 文法: assignExpAtom->[$] 7 | {横坐标: + 纵坐标: unaryExp} 文法: unaryExp->[unaryOp, unaryExp] 8 | {横坐标: ) 纵坐标: argFunctionR} 文法: argFunctionR->[$] 9 | {横坐标: int 纵坐标: bType} 文法: bType->[int] 10 | {横坐标: ( 纵坐标: unaryExp} 文法: unaryExp->[primaryExp] 11 | {横坐标: = 纵坐标: assignExpAtom} 文法: assignExpAtom->[=, eqExp, assignExpAtom] 12 | {横坐标: Ident 纵坐标: constExp} 文法: constExp->[assignExp] 13 | {横坐标: ( 纵坐标: initVal} 文法: initVal->[exp] 14 | {横坐标: + 纵坐标: constExp} 文法: constExp->[assignExp] 15 | {横坐标: # 纵坐标: argVarDecl} 文法: argVarDecl->[$] 16 | {横坐标: ! 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 17 | {横坐标: # 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 18 | {横坐标: ! 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 19 | {横坐标: ) 纵坐标: funcFParams} 文法: funcFParams->[$] 20 | {横坐标: } 纵坐标: blockItem} 文法: blockItem->[$] 21 | {横坐标: > 纵坐标: addExpAtom} 文法: addExpAtom->[$] 22 | {横坐标: ( 纵坐标: constExp} 文法: constExp->[assignExp] 23 | {横坐标: = 纵坐标: addExpAtom} 文法: addExpAtom->[$] 24 | {横坐标: ; 纵坐标: argVarDecl} 文法: argVarDecl->[$] 25 | {横坐标: { 纵坐标: block} 文法: block->[{, blockItem, }] 26 | {横坐标: ) 纵坐标: eqExpAtom} 文法: eqExpAtom->[$] 27 | {横坐标: ) 纵坐标: assignExpAtom} 文法: assignExpAtom->[$] 28 | {横坐标: int 纵坐标: compUnit} 文法: compUnit->[decl, compUnit] 29 | {横坐标: INT 纵坐标: argExp} 文法: argExp->[exp] 30 | {横坐标: ! 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 31 | {横坐标: ; 纵坐标: argConst} 文法: argConst->[$] 32 | {横坐标: + 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 33 | {横坐标: Ident 纵坐标: exp} 文法: exp->[assignExp] 34 | {横坐标: ; 纵坐标: argVarDef} 文法: argVarDef->[$] 35 | {横坐标: ; 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 36 | {横坐标: Ident 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 37 | {横坐标: # 纵坐标: blockItem} 文法: blockItem->[$] 38 | {横坐标: ; 纵坐标: argExp} 文法: argExp->[$] 39 | {横坐标: # 纵坐标: addExpAtom} 文法: addExpAtom->[$] 40 | {横坐标: int 纵坐标: funcFParams} 文法: funcFParams->[funcFParam, argFunctionF] 41 | {横坐标: # 纵坐标: callFunc} 文法: callFunc->[$] 42 | {横坐标: ) 纵坐标: callFunc} 文法: callFunc->[$] 43 | {横坐标: == 纵坐标: eqExpAtom} 文法: eqExpAtom->[==, relExp, eqExpAtom] 44 | {横坐标: ; 纵坐标: addExpAtom} 文法: addExpAtom->[$] 45 | {横坐标: < 纵坐标: relExpAtom} 文法: relExpAtom->[<, addExp, relExpAtom] 46 | {横坐标: INT 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 47 | {横坐标: ! 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 48 | {横坐标: , 纵坐标: argConst} 文法: argConst->[,, constDef, argConst] 49 | {横坐标: # 纵坐标: argConst} 文法: argConst->[$] 50 | {横坐标: == 纵坐标: callFunc} 文法: callFunc->[$] 51 | {横坐标: + 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 52 | {横坐标: ! 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 53 | {横坐标: ! 纵坐标: constInitVal} 文法: constInitVal->[constExp] 54 | {横坐标: - 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 55 | {横坐标: INT 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 56 | {横坐标: ( 纵坐标: argExp} 文法: argExp->[exp] 57 | {横坐标: ! 纵坐标: stmt} 文法: stmt->[exp, ;] 58 | {横坐标: + 纵坐标: addExpAtom} 文法: addExpAtom->[+, mulExp, addExpAtom] 59 | {横坐标: INT 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 60 | {横坐标: ! 纵坐标: argExp} 文法: argExp->[exp] 61 | {横坐标: > 纵坐标: relExpAtom} 文法: relExpAtom->[>, addExp, relExpAtom] 62 | {横坐标: - 纵坐标: constInitVal} 文法: constInitVal->[constExp] 63 | {横坐标: - 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 64 | {横坐标: + 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 65 | {横坐标: # 纵坐标: assignExpAtom} 文法: assignExpAtom->[$] 66 | {横坐标: INT 纵坐标: initVal} 文法: initVal->[exp] 67 | {横坐标: + 纵坐标: stmt} 文法: stmt->[exp, ;] 68 | {横坐标: - 纵坐标: stmt} 文法: stmt->[exp, ;] 69 | {横坐标: int 纵坐标: decl} 文法: decl->[varDecl] 70 | {横坐标: INT 纵坐标: primaryExp} 文法: primaryExp->[number] 71 | {横坐标: ! 纵坐标: unaryExp} 文法: unaryExp->[unaryOp, unaryExp] 72 | {横坐标: Ident 纵坐标: initVal} 文法: initVal->[exp] 73 | {横坐标: INT 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 74 | {横坐标: INT 纵坐标: unaryExp} 文法: unaryExp->[primaryExp] 75 | {横坐标: + 纵坐标: unaryOp} 文法: unaryOp->[+] 76 | {横坐标: INT 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 77 | {横坐标: - 纵坐标: funcRParam} 文法: funcRParam->[exp] 78 | {横坐标: < 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 79 | {横坐标: # 纵坐标: argFunctionR} 文法: argFunctionR->[$] 80 | {横坐标: # 纵坐标: funcFParams} 文法: funcFParams->[$] 81 | {横坐标: ! 纵坐标: initVal} 文法: initVal->[exp] 82 | {横坐标: + 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 83 | {横坐标: - 纵坐标: callFunc} 文法: callFunc->[$] 84 | {横坐标: ; 纵坐标: relExpAtom} 文法: relExpAtom->[$] 85 | {横坐标: ( 纵坐标: exp} 文法: exp->[assignExp] 86 | {横坐标: # 纵坐标: argExp} 文法: argExp->[$] 87 | {横坐标: * 纵坐标: callFunc} 文法: callFunc->[$] 88 | {横坐标: , 纵坐标: eqExpAtom} 文法: eqExpAtom->[$] 89 | {横坐标: * 纵坐标: mulExpAtom} 文法: mulExpAtom->[*, unaryExp, mulExpAtom] 90 | {横坐标: <= 纵坐标: callFunc} 文法: callFunc->[$] 91 | {横坐标: ! 纵坐标: constExp} 文法: constExp->[assignExp] 92 | {横坐标: ; 纵坐标: stmt} 文法: stmt->[;] 93 | {横坐标: - 纵坐标: constExp} 文法: constExp->[assignExp] 94 | {横坐标: ! 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 95 | {横坐标: int 纵坐标: program} 文法: program->[compUnit] 96 | {横坐标: INT 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 97 | {横坐标: Ident 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 98 | {横坐标: Ident 纵坐标: unaryExp} 文法: unaryExp->[Ident, callFunc] 99 | {横坐标: < 纵坐标: callFunc} 文法: callFunc->[$] 100 | {横坐标: # 纵坐标: relExpAtom} 文法: relExpAtom->[$] 101 | {横坐标: INT 纵坐标: stmt} 文法: stmt->[exp, ;] 102 | {横坐标: int 纵坐标: blockItem} 文法: blockItem->[decl, blockItem] 103 | {横坐标: ( 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 104 | {横坐标: void 纵坐标: funcDef} 文法: funcDef->[funcType, Ident, (, funcFParams, ), block] 105 | {横坐标: const 纵坐标: constDecl} 文法: constDecl->[const, bType, constDef, argConst, ;] 106 | {横坐标: INT 纵坐标: funcRParam} 文法: funcRParam->[exp] 107 | {横坐标: ( 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 108 | {横坐标: INT 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 109 | {横坐标: , 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 110 | {横坐标: # 纵坐标: argFunctionF} 文法: argFunctionF->[$] 111 | {横坐标: , 纵坐标: argVarDef} 文法: argVarDef->[$] 112 | {横坐标: Ident 纵坐标: constDef} 文法: constDef->[Ident, =, constInitVal] 113 | {横坐标: Ident 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 114 | {横坐标: != 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 115 | {横坐标: + 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 116 | {横坐标: <= 纵坐标: relExpAtom} 文法: relExpAtom->[<=, addExp, relExpAtom] 117 | {横坐标: != 纵坐标: eqExpAtom} 文法: eqExpAtom->[!=, relExp, eqExpAtom] 118 | {横坐标: void 纵坐标: compUnit} 文法: compUnit->[funcDef, compUnit] 119 | {横坐标: - 纵坐标: exp} 文法: exp->[assignExp] 120 | {横坐标: ( 纵坐标: funcRParam} 文法: funcRParam->[exp] 121 | {横坐标: - 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 122 | {横坐标: , 纵坐标: argFunctionF} 文法: argFunctionF->[,, funcFParam, argFunctionF] 123 | {横坐标: ( 纵坐标: callFunc} 文法: callFunc->[(, funcRParams, )] 124 | {横坐标: # 纵坐标: argVarDef} 文法: argVarDef->[$] 125 | {横坐标: , 纵坐标: relExpAtom} 文法: relExpAtom->[$] 126 | {横坐标: - 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 127 | {横坐标: Ident 纵坐标: argExp} 文法: argExp->[exp] 128 | {横坐标: + 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 129 | {横坐标: Ident 纵坐标: funcRParam} 文法: funcRParam->[exp] 130 | {横坐标: return 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 131 | {横坐标: ! 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 132 | {横坐标: ( 纵坐标: addExp} 文法: addExp->[mulExp, addExpAtom] 133 | {横坐标: ( 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 134 | {横坐标: % 纵坐标: callFunc} 文法: callFunc->[$] 135 | {横坐标: Ident 纵坐标: stmt} 文法: stmt->[exp, ;] 136 | {横坐标: + 纵坐标: callFunc} 文法: callFunc->[$] 137 | {横坐标: = 纵坐标: callFunc} 文法: callFunc->[$] 138 | {横坐标: / 纵坐标: mulExpAtom} 文法: mulExpAtom->[/, unaryExp, mulExpAtom] 139 | {横坐标: + 纵坐标: initVal} 文法: initVal->[exp] 140 | {横坐标: ( 纵坐标: primaryExp} 文法: primaryExp->[(, exp, )] 141 | {横坐标: const 纵坐标: program} 文法: program->[compUnit] 142 | {横坐标: - 纵坐标: unaryExp} 文法: unaryExp->[unaryOp, unaryExp] 143 | {横坐标: ! 纵坐标: unaryOp} 文法: unaryOp->[!] 144 | {横坐标: - 纵坐标: unaryOp} 文法: unaryOp->[-] 145 | {横坐标: { 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 146 | {横坐标: # 纵坐标: eqExpAtom} 文法: eqExpAtom->[$] 147 | {横坐标: + 纵坐标: funcRParam} 文法: funcRParam->[exp] 148 | {横坐标: - 纵坐标: addExpAtom} 文法: addExpAtom->[-, mulExp, addExpAtom] 149 | {横坐标: = 纵坐标: eqExpAtom} 文法: eqExpAtom->[$] 150 | {横坐标: - 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 151 | {横坐标: # 纵坐标: compUnit} 文法: compUnit->[$] 152 | {横坐标: != 纵坐标: relExpAtom} 文法: relExpAtom->[$] 153 | {横坐标: return 纵坐标: stmt} 文法: stmt->[return, argExp, ;] 154 | {横坐标: Ident 纵坐标: constInitVal} 文法: constInitVal->[constExp] 155 | {横坐标: ) 纵坐标: relExpAtom} 文法: relExpAtom->[$] 156 | {横坐标: Ident 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 157 | {横坐标: - 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 158 | {横坐标: , 纵坐标: argVarDecl} 文法: argVarDecl->[,, varDef, argVarDecl] 159 | {横坐标: ! 纵坐标: exp} 文法: exp->[assignExp] 160 | {横坐标: + 纵坐标: constInitVal} 文法: constInitVal->[constExp] 161 | {横坐标: ( 纵坐标: mulExp} 文法: mulExp->[unaryExp, mulExpAtom] 162 | {横坐标: = 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 163 | {横坐标: ) 纵坐标: argFunctionF} 文法: argFunctionF->[$] 164 | {横坐标: const 纵坐标: decl} 文法: decl->[constDecl] 165 | {横坐标: ; 纵坐标: callFunc} 文法: callFunc->[$] 166 | {横坐标: > 纵坐标: callFunc} 文法: callFunc->[$] 167 | {横坐标: <= 纵坐标: addExpAtom} 文法: addExpAtom->[$] 168 | {横坐标: , 纵坐标: assignExpAtom} 文法: assignExpAtom->[$] 169 | {横坐标: / 纵坐标: callFunc} 文法: callFunc->[$] 170 | {横坐标: Ident 纵坐标: lVal} 文法: lVal->[Ident] 171 | {横坐标: ( 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 172 | {横坐标: = 纵坐标: relExpAtom} 文法: relExpAtom->[$] 173 | {横坐标: void 纵坐标: program} 文法: program->[compUnit] 174 | {横坐标: + 纵坐标: argExp} 文法: argExp->[exp] 175 | {横坐标: > 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 176 | {横坐标: INT 纵坐标: constExp} 文法: constExp->[assignExp] 177 | {横坐标: , 纵坐标: callFunc} 文法: callFunc->[$] 178 | {横坐标: , 纵坐标: addExpAtom} 文法: addExpAtom->[$] 179 | {横坐标: Ident 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 180 | {横坐标: - 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 181 | {横坐标: - 纵坐标: initVal} 文法: initVal->[exp] 182 | {横坐标: ( 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 183 | {横坐标: , 纵坐标: argFunctionR} 文法: argFunctionR->[,, funcRParam, argFunctionR] 184 | {横坐标: == 纵坐标: relExpAtom} 文法: relExpAtom->[$] 185 | {横坐标: >= 纵坐标: relExpAtom} 文法: relExpAtom->[>=, addExp, relExpAtom] 186 | {横坐标: const 纵坐标: compUnit} 文法: compUnit->[decl, compUnit] 187 | {横坐标: = 纵坐标: argVarDef} 文法: argVarDef->[=, initVal] 188 | {横坐标: ( 纵坐标: stmt} 文法: stmt->[exp, ;] 189 | {横坐标: Ident 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 190 | {横坐标: ; 纵坐标: blockItem} 文法: blockItem->[stmt, blockItem] 191 | {横坐标: + 纵坐标: eqExp} 文法: eqExp->[relExp, eqExpAtom] 192 | {横坐标: != 纵坐标: callFunc} 文法: callFunc->[$] 193 | {横坐标: - 纵坐标: funcRParams} 文法: funcRParams->[funcRParam, argFunctionR] 194 | {横坐标: ) 纵坐标: funcRParams} 文法: funcRParams->[$] 195 | {横坐标: ) 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 196 | {横坐标: ! 纵坐标: funcRParam} 文法: funcRParam->[exp] 197 | {横坐标: >= 纵坐标: callFunc} 文法: callFunc->[$] 198 | {横坐标: # 纵坐标: funcRParams} 文法: funcRParams->[$] 199 | {横坐标: + 纵坐标: exp} 文法: exp->[assignExp] 200 | {横坐标: int 纵坐标: varDecl} 文法: varDecl->[bType, varDef, argVarDecl, ;] 201 | {横坐标: Ident 纵坐标: varDef} 文法: varDef->[Ident, argVarDef] 202 | {横坐标: - 纵坐标: argExp} 文法: argExp->[exp] 203 | {横坐标: == 纵坐标: addExpAtom} 文法: addExpAtom->[$] 204 | {横坐标: const 纵坐标: blockItem} 文法: blockItem->[decl, blockItem] 205 | {横坐标: INT 纵坐标: constInitVal} 文法: constInitVal->[constExp] 206 | {横坐标: ) 纵坐标: addExpAtom} 文法: addExpAtom->[$] 207 | {横坐标: Ident 纵坐标: assignExp} 文法: assignExp->[eqExp, assignExpAtom] 208 | {横坐标: { 纵坐标: stmt} 文法: stmt->[block] 209 | {横坐标: INT 纵坐标: exp} 文法: exp->[assignExp] 210 | {横坐标: % 纵坐标: mulExpAtom} 文法: mulExpAtom->[%, unaryExp, mulExpAtom] 211 | {横坐标: == 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 212 | {横坐标: >= 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 213 | {横坐标: <= 纵坐标: mulExpAtom} 文法: mulExpAtom->[$] 214 | {横坐标: void 纵坐标: funcType} 文法: funcType->[void] 215 | {横坐标: != 纵坐标: addExpAtom} 文法: addExpAtom->[$] 216 | {横坐标: + 纵坐标: relExp} 文法: relExp->[addExp, relExpAtom] 217 | {横坐标: int 纵坐标: funcFParam} 文法: funcFParam->[bType, Ident] 218 | -------------------------------------------------------------------------------- /output/文法.tsv: -------------------------------------------------------------------------------- 1 | 文法左侧: program 文法右侧: [compUnit] 2 | 文法左侧: compUnit 文法右侧: [decl, compUnit] 3 | 文法左侧: compUnit 文法右侧: [funcDef, compUnit] 4 | 文法左侧: compUnit 文法右侧: [$] 5 | 文法左侧: decl 文法右侧: [constDecl] 6 | 文法左侧: decl 文法右侧: [varDecl] 7 | 文法左侧: constDecl 文法右侧: [const, bType, constDef, argConst, ;] 8 | 文法左侧: argConst 文法右侧: [,, constDef, argConst] 9 | 文法左侧: argConst 文法右侧: [$] 10 | 文法左侧: constDef 文法右侧: [Ident, =, constInitVal] 11 | 文法左侧: constInitVal 文法右侧: [constExp] 12 | 文法左侧: varDecl 文法右侧: [bType, varDef, argVarDecl, ;] 13 | 文法左侧: argVarDecl 文法右侧: [,, varDef, argVarDecl] 14 | 文法左侧: argVarDecl 文法右侧: [$] 15 | 文法左侧: varDef 文法右侧: [Ident, argVarDef] 16 | 文法左侧: argVarDef 文法右侧: [=, initVal] 17 | 文法左侧: argVarDef 文法右侧: [$] 18 | 文法左侧: initVal 文法右侧: [exp] 19 | 文法左侧: bType 文法右侧: [int] 20 | 文法左侧: funcDef 文法右侧: [funcType, Ident, (, funcFParams, ), block] 21 | 文法左侧: funcType 文法右侧: [void] 22 | 文法左侧: funcFParams 文法右侧: [funcFParam, argFunctionF] 23 | 文法左侧: funcFParams 文法右侧: [$] 24 | 文法左侧: argFunctionF 文法右侧: [,, funcFParam, argFunctionF] 25 | 文法左侧: argFunctionF 文法右侧: [$] 26 | 文法左侧: funcFParam 文法右侧: [bType, Ident] 27 | 文法左侧: block 文法右侧: [{, blockItem, }] 28 | 文法左侧: blockItem 文法右侧: [decl, blockItem] 29 | 文法左侧: blockItem 文法右侧: [stmt, blockItem] 30 | 文法左侧: blockItem 文法右侧: [$] 31 | 文法左侧: stmt 文法右侧: [exp, ;] 32 | 文法左侧: stmt 文法右侧: [;] 33 | 文法左侧: stmt 文法右侧: [block] 34 | 文法左侧: stmt 文法右侧: [return, argExp, ;] 35 | 文法左侧: argExp 文法右侧: [$] 36 | 文法左侧: argExp 文法右侧: [exp] 37 | 文法左侧: exp 文法右侧: [assignExp] 38 | 文法左侧: lVal 文法右侧: [Ident] 39 | 文法左侧: primaryExp 文法右侧: [(, exp, )] 40 | 文法左侧: primaryExp 文法右侧: [number] 41 | 文法左侧: number 文法右侧: [INT] 42 | 文法左侧: unaryOp 文法右侧: [+] 43 | 文法左侧: unaryOp 文法右侧: [-] 44 | 文法左侧: unaryOp 文法右侧: [!] 45 | 文法左侧: unaryExp 文法右侧: [unaryOp, unaryExp] 46 | 文法左侧: unaryExp 文法右侧: [Ident, callFunc] 47 | 文法左侧: callFunc 文法右侧: [(, funcRParams, )] 48 | 文法左侧: callFunc 文法右侧: [$] 49 | 文法左侧: unaryExp 文法右侧: [primaryExp] 50 | 文法左侧: funcRParams 文法右侧: [funcRParam, argFunctionR] 51 | 文法左侧: funcRParams 文法右侧: [$] 52 | 文法左侧: argFunctionR 文法右侧: [,, funcRParam, argFunctionR] 53 | 文法左侧: argFunctionR 文法右侧: [$] 54 | 文法左侧: funcRParam 文法右侧: [exp] 55 | 文法左侧: mulExp 文法右侧: [unaryExp, mulExpAtom] 56 | 文法左侧: mulExpAtom 文法右侧: [*, unaryExp, mulExpAtom] 57 | 文法左侧: mulExpAtom 文法右侧: [/, unaryExp, mulExpAtom] 58 | 文法左侧: mulExpAtom 文法右侧: [%, unaryExp, mulExpAtom] 59 | 文法左侧: mulExpAtom 文法右侧: [$] 60 | 文法左侧: addExp 文法右侧: [mulExp, addExpAtom] 61 | 文法左侧: addExpAtom 文法右侧: [+, mulExp, addExpAtom] 62 | 文法左侧: addExpAtom 文法右侧: [-, mulExp, addExpAtom] 63 | 文法左侧: addExpAtom 文法右侧: [$] 64 | 文法左侧: relExp 文法右侧: [addExp, relExpAtom] 65 | 文法左侧: relExpAtom 文法右侧: [<, addExp, relExpAtom] 66 | 文法左侧: relExpAtom 文法右侧: [>, addExp, relExpAtom] 67 | 文法左侧: relExpAtom 文法右侧: [<=, addExp, relExpAtom] 68 | 文法左侧: relExpAtom 文法右侧: [>=, addExp, relExpAtom] 69 | 文法左侧: relExpAtom 文法右侧: [$] 70 | 文法左侧: eqExp 文法右侧: [relExp, eqExpAtom] 71 | 文法左侧: eqExpAtom 文法右侧: [==, relExp, eqExpAtom] 72 | 文法左侧: eqExpAtom 文法右侧: [!=, relExp, eqExpAtom] 73 | 文法左侧: eqExpAtom 文法右侧: [$] 74 | 文法左侧: assignExp 文法右侧: [eqExp, assignExpAtom] 75 | 文法左侧: assignExpAtom 文法右侧: [=, eqExp, assignExpAtom] 76 | 文法左侧: assignExpAtom 文法右侧: [$] 77 | 文法左侧: constExp 文法右侧: [assignExp] 78 | -------------------------------------------------------------------------------- /output/终结符.tsv: -------------------------------------------------------------------------------- 1 | const 2 | ; 3 | , 4 | Ident 5 | = 6 | ; 7 | , 8 | Ident 9 | = 10 | int 11 | Ident 12 | ( 13 | ) 14 | void 15 | , 16 | Ident 17 | { 18 | } 19 | ; 20 | ; 21 | return 22 | ; 23 | Ident 24 | ( 25 | ) 26 | INT 27 | + 28 | - 29 | ! 30 | Ident 31 | ( 32 | ) 33 | , 34 | * 35 | / 36 | % 37 | + 38 | - 39 | < 40 | > 41 | <= 42 | >= 43 | == 44 | != 45 | = 46 | -------------------------------------------------------------------------------- /output/词法分析产生的中间结果.tsv: -------------------------------------------------------------------------------- 1 | int 2 | Ident 3 | = 4 | INT 5 | ; 6 | int 7 | Ident 8 | = 9 | INT 10 | ; 11 | int 12 | Ident 13 | = 14 | INT 15 | ; 16 | int 17 | Ident 18 | = 19 | INT 20 | , 21 | Ident 22 | = 23 | INT 24 | ; 25 | void 26 | Ident 27 | ( 28 | ) 29 | { 30 | int 31 | Ident 32 | = 33 | INT 34 | ; 35 | int 36 | Ident 37 | = 38 | INT 39 | ; 40 | int 41 | Ident 42 | = 43 | Ident 44 | + 45 | INT 46 | ; 47 | int 48 | Ident 49 | = 50 | Ident 51 | ; 52 | return 53 | Ident 54 | + 55 | Ident 56 | ; 57 | } 58 | -------------------------------------------------------------------------------- /output/非终结符.tsv: -------------------------------------------------------------------------------- 1 | program 2 | compUnit 3 | decl 4 | constDecl 5 | argConst 6 | constDef 7 | constInitVal 8 | varDecl 9 | argVarDecl 10 | varDef 11 | argVarDef 12 | initVal 13 | bType 14 | funcDef 15 | funcType 16 | funcFParams 17 | argFunctionF 18 | funcFParam 19 | block 20 | blockItem 21 | stmt 22 | argExp 23 | exp 24 | lVal 25 | primaryExp 26 | number 27 | unaryOp 28 | unaryExp 29 | callFunc 30 | funcRParams 31 | argFunctionR 32 | funcRParam 33 | mulExp 34 | mulExpAtom 35 | addExp 36 | addExpAtom 37 | relExp 38 | relExpAtom 39 | eqExp 40 | eqExpAtom 41 | assignExp 42 | assignExpAtom 43 | constExp 44 | -------------------------------------------------------------------------------- /result/gra.tsv: -------------------------------------------------------------------------------- 1 | 1 program#int reduction 2 | 2 compUnit#int reduction 3 | 3 decl#int reduction 4 | 4 varDecl#int reduction 5 | 5 bType#int reduction 6 | 6 int#int move 7 | 7 varDef#Ident reduction 8 | 8 Ident#Ident move 9 | 9 argVarDef#= reduction 10 | 10 =#= move 11 | 11 initVal#INT reduction 12 | 12 exp#INT reduction 13 | 13 assignExp#INT reduction 14 | 14 eqExp#INT reduction 15 | 15 relExp#INT reduction 16 | 16 addExp#INT reduction 17 | 17 mulExp#INT reduction 18 | 18 unaryExp#INT reduction 19 | 19 primaryExp#INT reduction 20 | 20 number#INT reduction 21 | 21 INT#INT move 22 | 22 mulExpAtom#; reduction 23 | 23 addExpAtom#; reduction 24 | 24 relExpAtom#; reduction 25 | 25 eqExpAtom#; reduction 26 | 26 assignExpAtom#; reduction 27 | 27 argVarDecl#; reduction 28 | 28 ;#; move 29 | 29 compUnit#int reduction 30 | 30 decl#int reduction 31 | 31 varDecl#int reduction 32 | 32 bType#int reduction 33 | 33 int#int move 34 | 34 varDef#Ident reduction 35 | 35 Ident#Ident move 36 | 36 argVarDef#= reduction 37 | 37 =#= move 38 | 38 initVal#INT reduction 39 | 39 exp#INT reduction 40 | 40 assignExp#INT reduction 41 | 41 eqExp#INT reduction 42 | 42 relExp#INT reduction 43 | 43 addExp#INT reduction 44 | 44 mulExp#INT reduction 45 | 45 unaryExp#INT reduction 46 | 46 primaryExp#INT reduction 47 | 47 number#INT reduction 48 | 48 INT#INT move 49 | 49 mulExpAtom#; reduction 50 | 50 addExpAtom#; reduction 51 | 51 relExpAtom#; reduction 52 | 52 eqExpAtom#; reduction 53 | 53 assignExpAtom#; reduction 54 | 54 argVarDecl#; reduction 55 | 55 ;#; move 56 | 56 compUnit#int reduction 57 | 57 decl#int reduction 58 | 58 varDecl#int reduction 59 | 59 bType#int reduction 60 | 60 int#int move 61 | 61 varDef#Ident reduction 62 | 62 Ident#Ident move 63 | 63 argVarDef#= reduction 64 | 64 =#= move 65 | 65 initVal#INT reduction 66 | 66 exp#INT reduction 67 | 67 assignExp#INT reduction 68 | 68 eqExp#INT reduction 69 | 69 relExp#INT reduction 70 | 70 addExp#INT reduction 71 | 71 mulExp#INT reduction 72 | 72 unaryExp#INT reduction 73 | 73 primaryExp#INT reduction 74 | 74 number#INT reduction 75 | 75 INT#INT move 76 | 76 mulExpAtom#; reduction 77 | 77 addExpAtom#; reduction 78 | 78 relExpAtom#; reduction 79 | 79 eqExpAtom#; reduction 80 | 80 assignExpAtom#; reduction 81 | 81 argVarDecl#; reduction 82 | 82 ;#; move 83 | 83 compUnit#int reduction 84 | 84 decl#int reduction 85 | 85 varDecl#int reduction 86 | 86 bType#int reduction 87 | 87 int#int move 88 | 88 varDef#Ident reduction 89 | 89 Ident#Ident move 90 | 90 argVarDef#= reduction 91 | 91 =#= move 92 | 92 initVal#INT reduction 93 | 93 exp#INT reduction 94 | 94 assignExp#INT reduction 95 | 95 eqExp#INT reduction 96 | 96 relExp#INT reduction 97 | 97 addExp#INT reduction 98 | 98 mulExp#INT reduction 99 | 99 unaryExp#INT reduction 100 | 100 primaryExp#INT reduction 101 | 101 number#INT reduction 102 | 102 INT#INT move 103 | 103 mulExpAtom#, reduction 104 | 104 addExpAtom#, reduction 105 | 105 relExpAtom#, reduction 106 | 106 eqExpAtom#, reduction 107 | 107 assignExpAtom#, reduction 108 | 108 argVarDecl#, reduction 109 | 109 ,#, move 110 | 110 varDef#Ident reduction 111 | 111 Ident#Ident move 112 | 112 argVarDef#= reduction 113 | 113 =#= move 114 | 114 initVal#INT reduction 115 | 115 exp#INT reduction 116 | 116 assignExp#INT reduction 117 | 117 eqExp#INT reduction 118 | 118 relExp#INT reduction 119 | 119 addExp#INT reduction 120 | 120 mulExp#INT reduction 121 | 121 unaryExp#INT reduction 122 | 122 primaryExp#INT reduction 123 | 123 number#INT reduction 124 | 124 INT#INT move 125 | 125 mulExpAtom#; reduction 126 | 126 addExpAtom#; reduction 127 | 127 relExpAtom#; reduction 128 | 128 eqExpAtom#; reduction 129 | 129 assignExpAtom#; reduction 130 | 130 argVarDecl#; reduction 131 | 131 ;#; move 132 | 132 compUnit#void reduction 133 | 133 funcDef#void reduction 134 | 134 funcType#void reduction 135 | 135 void#void move 136 | 136 Ident#Ident move 137 | 137 (#( move 138 | 138 funcFParams#) reduction 139 | 139 )#) move 140 | 140 block#{ reduction 141 | 141 {#{ move 142 | 142 blockItem#int reduction 143 | 143 decl#int reduction 144 | 144 varDecl#int reduction 145 | 145 bType#int reduction 146 | 146 int#int move 147 | 147 varDef#Ident reduction 148 | 148 Ident#Ident move 149 | 149 argVarDef#= reduction 150 | 150 =#= move 151 | 151 initVal#INT reduction 152 | 152 exp#INT reduction 153 | 153 assignExp#INT reduction 154 | 154 eqExp#INT reduction 155 | 155 relExp#INT reduction 156 | 156 addExp#INT reduction 157 | 157 mulExp#INT reduction 158 | 158 unaryExp#INT reduction 159 | 159 primaryExp#INT reduction 160 | 160 number#INT reduction 161 | 161 INT#INT move 162 | 162 mulExpAtom#; reduction 163 | 163 addExpAtom#; reduction 164 | 164 relExpAtom#; reduction 165 | 165 eqExpAtom#; reduction 166 | 166 assignExpAtom#; reduction 167 | 167 argVarDecl#; reduction 168 | 168 ;#; move 169 | 169 blockItem#int reduction 170 | 170 decl#int reduction 171 | 171 varDecl#int reduction 172 | 172 bType#int reduction 173 | 173 int#int move 174 | 174 varDef#Ident reduction 175 | 175 Ident#Ident move 176 | 176 argVarDef#= reduction 177 | 177 =#= move 178 | 178 initVal#INT reduction 179 | 179 exp#INT reduction 180 | 180 assignExp#INT reduction 181 | 181 eqExp#INT reduction 182 | 182 relExp#INT reduction 183 | 183 addExp#INT reduction 184 | 184 mulExp#INT reduction 185 | 185 unaryExp#INT reduction 186 | 186 primaryExp#INT reduction 187 | 187 number#INT reduction 188 | 188 INT#INT move 189 | 189 mulExpAtom#; reduction 190 | 190 addExpAtom#; reduction 191 | 191 relExpAtom#; reduction 192 | 192 eqExpAtom#; reduction 193 | 193 assignExpAtom#; reduction 194 | 194 argVarDecl#; reduction 195 | 195 ;#; move 196 | 196 blockItem#int reduction 197 | 197 decl#int reduction 198 | 198 varDecl#int reduction 199 | 199 bType#int reduction 200 | 200 int#int move 201 | 201 varDef#Ident reduction 202 | 202 Ident#Ident move 203 | 203 argVarDef#= reduction 204 | 204 =#= move 205 | 205 initVal#Ident reduction 206 | 206 exp#Ident reduction 207 | 207 assignExp#Ident reduction 208 | 208 eqExp#Ident reduction 209 | 209 relExp#Ident reduction 210 | 210 addExp#Ident reduction 211 | 211 mulExp#Ident reduction 212 | 212 unaryExp#Ident reduction 213 | 213 Ident#Ident move 214 | 214 callFunc#+ reduction 215 | 215 mulExpAtom#+ reduction 216 | 216 addExpAtom#+ reduction 217 | 217 +#+ move 218 | 218 mulExp#INT reduction 219 | 219 unaryExp#INT reduction 220 | 220 primaryExp#INT reduction 221 | 221 number#INT reduction 222 | 222 INT#INT move 223 | 223 mulExpAtom#; reduction 224 | 224 addExpAtom#; reduction 225 | 225 relExpAtom#; reduction 226 | 226 eqExpAtom#; reduction 227 | 227 assignExpAtom#; reduction 228 | 228 argVarDecl#; reduction 229 | 229 ;#; move 230 | 230 blockItem#int reduction 231 | 231 decl#int reduction 232 | 232 varDecl#int reduction 233 | 233 bType#int reduction 234 | 234 int#int move 235 | 235 varDef#Ident reduction 236 | 236 Ident#Ident move 237 | 237 argVarDef#= reduction 238 | 238 =#= move 239 | 239 initVal#Ident reduction 240 | 240 exp#Ident reduction 241 | 241 assignExp#Ident reduction 242 | 242 eqExp#Ident reduction 243 | 243 relExp#Ident reduction 244 | 244 addExp#Ident reduction 245 | 245 mulExp#Ident reduction 246 | 246 unaryExp#Ident reduction 247 | 247 Ident#Ident move 248 | 248 callFunc#; reduction 249 | 249 mulExpAtom#; reduction 250 | 250 addExpAtom#; reduction 251 | 251 relExpAtom#; reduction 252 | 252 eqExpAtom#; reduction 253 | 253 assignExpAtom#; reduction 254 | 254 argVarDecl#; reduction 255 | 255 ;#; move 256 | 256 blockItem#return reduction 257 | 257 stmt#return reduction 258 | 258 return#return move 259 | 259 argExp#Ident reduction 260 | 260 exp#Ident reduction 261 | 261 assignExp#Ident reduction 262 | 262 eqExp#Ident reduction 263 | 263 relExp#Ident reduction 264 | 264 addExp#Ident reduction 265 | 265 mulExp#Ident reduction 266 | 266 unaryExp#Ident reduction 267 | 267 Ident#Ident move 268 | 268 callFunc#+ reduction 269 | 269 mulExpAtom#+ reduction 270 | 270 addExpAtom#+ reduction 271 | 271 +#+ move 272 | 272 mulExp#Ident reduction 273 | 273 unaryExp#Ident reduction 274 | 274 Ident#Ident move 275 | 275 callFunc#; reduction 276 | 276 mulExpAtom#; reduction 277 | 277 addExpAtom#; reduction 278 | 278 relExpAtom#; reduction 279 | 279 eqExpAtom#; reduction 280 | 280 assignExpAtom#; reduction 281 | 281 ;#; move 282 | 282 blockItem#} reduction 283 | 283 }#} move 284 | 284 compUnit## reduction 285 | 285 EOF#EOF accept 286 | -------------------------------------------------------------------------------- /result/lex.tsv: -------------------------------------------------------------------------------- 1 | int 2 | a 3 | = 4 | 3 5 | ; 6 | int 7 | b 8 | = 9 | 1 10 | ; 11 | int 12 | c 13 | = 14 | 3 15 | ; 16 | int 17 | e 18 | = 19 | 0 20 | , 21 | f 22 | = 23 | 10 24 | ; 25 | void 26 | func 27 | ( 28 | ) 29 | { 30 | int 31 | a 32 | = 33 | 5 34 | ; 35 | int 36 | c 37 | = 38 | 2 39 | ; 40 | int 41 | temp2 42 | = 43 | f 44 | + 45 | 2 46 | ; 47 | int 48 | temp3 49 | = 50 | c 51 | ; 52 | return 53 | a 54 | + 55 | b 56 | ; 57 | } 58 | -------------------------------------------------------------------------------- /src/Config.java: -------------------------------------------------------------------------------- 1 | public class Config { 2 | static String grammarPath = ".\\input\\grammar.txt"; 3 | // static String grammarPath = ".\\input\\grammar_test.txt"; 4 | 5 | // static String lexInputPath = ".\\input\\1.txt"; 6 | // static String lexInputPath = ".\\input\\2.txt"; 7 | // static String lexInputPath = ".\\input\\3.txt"; 8 | // static String lexInputPath = ".\\input\\4.txt"; 9 | // static String lexInputPath = ".\\input\\5.txt"; 10 | static String lexInputPath = ".\\input\\code.txt"; 11 | 12 | static String formulaPath = ".\\output\\文法.tsv"; 13 | static String firstTablePath = ".\\output\\First集合.tsv"; 14 | static String followTablePath = ".\\output\\Follow集合.tsv"; 15 | static String predictMapPath = ".\\output\\分析表.tsv"; 16 | static String terminalPath = ".\\output\\终结符.tsv"; 17 | static String nonTerminalPath = ".\\output\\非终结符.tsv"; 18 | static String lexiconMiddleResult = ".\\output\\词法分析产生的中间结果.tsv"; 19 | static String parseResultPath = ".\\result\\gra.tsv"; 20 | static String lexiconResultPath = ".\\result\\lex.tsv"; 21 | 22 | static String initSymbol = "program"; // 入口文法! 23 | } 24 | -------------------------------------------------------------------------------- /src/FirstTable.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.HashMap; 3 | 4 | public class FirstTable { 5 | static ArrayList formulas; 6 | static ArrayList terminals; 7 | static ArrayList nonTerminals; 8 | static HashMap> firsts; 9 | 10 | static void setFirst(ArrayList _formulas, ArrayList _terminals, 11 | ArrayList _nonTerminals, HashMap> _firsts) { 12 | formulas = _formulas; 13 | terminals = _terminals; 14 | nonTerminals = _nonTerminals; 15 | firsts = _firsts; 16 | 17 | // 终结符全部求出first集 18 | ArrayList first; 19 | for (String terminal : terminals) { 20 | first = new ArrayList(); 21 | first.add(terminal); 22 | firsts.put(terminal, first); 23 | } 24 | // 给所有非终结符注册一下 25 | for (String nonterminal : nonTerminals) { 26 | first = new ArrayList(); 27 | firsts.put(nonterminal, first); 28 | } 29 | 30 | boolean flag; 31 | while (true) { 32 | flag = true; 33 | String left; 34 | String right; 35 | String[] rights; 36 | // 遍历所有文法 37 | for (Formula formula : formulas) { 38 | left = formula.returnLeft(); 39 | rights = formula.returnRights(); 40 | // 每个文法的右侧 41 | for (String s : rights) { 42 | right = s; 43 | // oneOfRight是否存在,遇到空怎么办 44 | if (!right.equals("$")) { // 右侧的字符串不为空(任意一个都不为空) 45 | // 遍历每一个右侧字符串的First集合,即 First(右侧字符串) 46 | // 这个就类似于一个递归 47 | for (int l = 0; l < firsts.get(right).size(); l++) { 48 | // First(left) 包括了 First(oneOfRights) 49 | if (firsts.get(left).contains(firsts.get(right).get(l))) { 50 | continue; 51 | } else { 52 | // 不包括, 就加入 53 | firsts.get(left).add(firsts.get(right).get(l)); 54 | flag = false; 55 | } 56 | } 57 | } 58 | // OneOfRights -> $ 59 | if (isCanBeNull(formulas, right)) { 60 | continue; 61 | } else { 62 | break; 63 | } 64 | } 65 | } 66 | if (flag) { 67 | break; 68 | } 69 | } 70 | // 非终结符的first集 71 | 72 | // -------------------------------------------- 73 | // 加空 E -> $ 74 | // for (Formula formula : formulas) { 75 | // if (formula.returnRights()[0].equals("$")) { 76 | // firsts.get(formula.returnLeft()).add("$"); 77 | // } 78 | // } 79 | 80 | // for (Formula formula : formulas) { 81 | // String left = formula.returnLeft(); 82 | // String firstRights = formula.returnRights()[0]; 83 | // // 文法右侧数据的第一个 84 | // if (terminals.contains(firstRights)) { // 第一个是终结符 85 | // firsts.get(left).add(firstRights); // 加入 86 | // } else { // 非终结符 87 | //// firsts.get(left) = firsts.get(firstRights); 88 | // } 89 | // } 90 | 91 | // for (Formula formula : formulas) { 92 | // recursion(formula.left); 93 | // } 94 | // -------------------------------------------------- 95 | } 96 | 97 | // 递归函数 98 | // 暂时用不到 99 | // -------------------------------- 100 | private static ArrayList recursion(String cur) { 101 | if (terminals.contains(cur)) { // 如果是终结符,则直接返回, 则直接返回,因为First(left)已经有了 102 | return firsts.get(cur); 103 | } 104 | if (firsts.get(cur).size() != 0) { // 非终结符,但是也已经递归过了 105 | return firsts.get(cur); 106 | } 107 | for (Formula formula : formulas) { 108 | if (formula.returnLeft().equals(cur)) { // 找到文法 109 | String firstRight = formula.returnRights()[0]; // 文法右侧第一个 110 | // 递归 111 | ArrayList tmp = recursion(firstRight); 112 | for (String s : tmp) { 113 | firsts.get(cur).add(s); 114 | } 115 | } 116 | } 117 | return firsts.get(cur); 118 | } 119 | // ---------------------------------------- 120 | 121 | // 判断是否产生$ 122 | static boolean isCanBeNull(ArrayList formulas, String symbol){ 123 | String[] rights; 124 | // 遍历每一个文法 125 | for (Formula formula : formulas) { 126 | // 找到产生式 127 | if (formula.returnLeft().equals(symbol)) { 128 | // symbol -> [rights] 129 | rights = formula.returnRights(); 130 | // symbol -> $ 131 | if (rights[0].equals("$")) { // 第一个就是$, 即类似于 E -> $ 132 | return true; 133 | } 134 | } 135 | } 136 | return false; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/FollowTable.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.HashMap; 3 | 4 | public class FollowTable { 5 | static void setFollow(ArrayList formulas, ArrayList terminals, 6 | ArrayList nonTerminals, HashMap> firsts, 7 | HashMap> follows) { 8 | // 所有非终结符的follow集初始化一下 9 | ArrayList follow; 10 | for (String nonTerminal : nonTerminals) { 11 | follow = new ArrayList(); 12 | follows.put(nonTerminal, follow); 13 | } 14 | // 将#加入到follow(S)中 15 | // follows.get("S").add("#"); // 开始文法的入口必须是S 16 | follows.get(Config.initSymbol).add("#"); 17 | 18 | boolean flag; 19 | boolean fab; 20 | while (true) { 21 | flag = true; 22 | // 循环 23 | for (Formula formula : formulas) { 24 | String left; 25 | String right; 26 | String[] rights; 27 | rights = formula.returnRights(); 28 | for (int j = 0; j < rights.length; j++) { 29 | right = rights[j]; 30 | 31 | // 非终结符 32 | if (nonTerminals.contains(right)) { 33 | fab = true; 34 | for (int k = j + 1; k < rights.length; k++) { 35 | 36 | // 查找first集 37 | for (int v = 0; v < firsts.get(rights[k]).size(); v++) { 38 | // 将后一个元素的first集加入到前一个元素的follow集中 39 | if (follows.get(right).contains(firsts.get(rights[k]).get(v))) { 40 | continue; 41 | } else { 42 | follows.get(right).add(firsts.get(rights[k]).get(v)); 43 | flag = false; 44 | } 45 | } 46 | if (isCanBeNull(formulas, rights[k])) { 47 | continue; 48 | } else { 49 | fab = false; 50 | break; 51 | } 52 | } 53 | if (fab) { 54 | left = formula.returnLeft(); 55 | for (int p = 0; p < follows.get(left).size(); p++) { 56 | if (follows.get(right).contains(follows.get(left).get(p))) { 57 | continue; 58 | } else { 59 | follows.get(right).add(follows.get(left).get(p)); 60 | flag = false; 61 | } 62 | } 63 | } 64 | } 65 | 66 | } 67 | } 68 | if(flag){ 69 | break; 70 | } 71 | } 72 | 73 | // 清除follow集中的# 74 | String left; 75 | for (String nonterminal : nonTerminals) { 76 | left = nonterminal; 77 | for (int v = 0; v < follows.get(left).size(); v++) { 78 | if (follows.get(left).get(v).equals("#")) 79 | follows.get(left).remove(v); 80 | } 81 | } 82 | 83 | // ------------------- 84 | // 为Follow加上# 85 | for (String notTerminal : nonTerminals) { 86 | follows.get(notTerminal).add("#"); 87 | } 88 | // ------------------- 89 | } 90 | 91 | // 判断是否产生$ 92 | static boolean isCanBeNull(ArrayList formulas, String symbol){ 93 | String[] rights; 94 | for (Formula formula : formulas) { 95 | // 找到产生式 96 | if (formula.returnLeft().equals(symbol)) { 97 | rights = formula.returnRights(); 98 | if (rights[0].equals("$")) { 99 | return true; 100 | } 101 | } 102 | } 103 | return false; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/Main.java: -------------------------------------------------------------------------------- 1 | public class Main { 2 | public static void main(String[] args) { 3 | MainLexicon.DoLex(); // 词法分析 4 | TextParseInput.setLex_result_stack(MainLexicon.getLex_result_stack()); // 设置语法分析的输入 5 | MainParse.DoParse(); // 语法分析 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/MainLexicon.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedWriter; 2 | import java.io.FileWriter; 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.HashMap; 6 | 7 | public class MainLexicon { 8 | private static ArrayList lex_result_stack; 9 | // 词法分析的入口类 10 | public static void DoLex() { 11 | String content = TextLexiconInput.input(); // 得到文本内容 12 | TextLexicon textLexicon = new TextLexicon(content); // 将文本内容给词法编译器 13 | textLexicon.scannerAll(); // 入口函数 14 | ArrayList> lex_error_stack = textLexicon.get_Lex_Error(); 15 | if (lex_error_stack.size() != 0) { // 错误信息不为空 16 | System.out.println("词法分析阶段出现错误!"); 17 | for (HashMap stringStringHashMap : lex_error_stack) { // 输出错误信息 18 | System.out.println(stringStringHashMap); 19 | } 20 | return; // 词法分析中断 21 | } 22 | ArrayList> threeElements = textLexicon.getThreeElements(); // 得到要输出的三元组 23 | // 打印 24 | System.out.println("开始输出词法分析结果: ---------------------"); 25 | for (ArrayList threeElement : threeElements) { 26 | System.out.println(threeElement.get(0) + " <" 27 | + threeElement.get(1) + "," 28 | + threeElement.get(2) + ">" 29 | ); 30 | } 31 | // 输出到文件中 32 | try { 33 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.lexiconResultPath)); 34 | for (ArrayList threeElement : threeElements) { 35 | out.write(threeElement.get(0) + "\t" + "<" 36 | + threeElement.get(1) + "," 37 | + threeElement.get(2) + ">" 38 | + "\n" 39 | ); 40 | } 41 | out.close(); 42 | } catch(IOException e) { 43 | throw new RuntimeException(e); 44 | } 45 | lex_result_stack = textLexicon.get_Lex_Result(); 46 | } 47 | 48 | public static ArrayList getLex_result_stack() { 49 | return lex_result_stack; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/MainParse.java: -------------------------------------------------------------------------------- 1 | import java.io.BufferedWriter; 2 | import java.io.FileWriter; 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.HashMap; 7 | 8 | public class MainParse { 9 | static HashMap predictMap; // 预测表 10 | static ArrayList input_str; // 输入串, 词法分析的结果 11 | static ArrayList symbol_stack; // 符号栈 12 | // static ArrayList parse_error_stack; // 语法分析输出可能的错误结果 13 | static ArrayList parse_result_stack; // 语法分析输出展示的结果 14 | static int parse_result_counter; // 语法分析输出结果的计数器 15 | 16 | // 入口函数 17 | static void DoParse() { 18 | input_str = TextParseInput.getLex_result_stack(); // 词法分析的输入 19 | symbol_stack = new ArrayList<>(); 20 | parse_result_stack = new ArrayList<>(); 21 | parse_result_counter = 0; 22 | 23 | TextParse.Do(); // 生成各种表,First,Follow,预测表 24 | predictMap = TextParse.predictions; // 预测表 25 | 26 | TextParse.writeAllIntoFile(); // 将语法分析开始前生成的所有表打印出来 27 | writeLexiconMiddleResultIntoFile(); // 将词法分析的中间结果打印出来 28 | 29 | parse(); // 开始语法分析 30 | 31 | printParseResult(); // 打印语法分析结果 32 | } 33 | 34 | // 将词法分析传递给语法分析的中间结果打印出来 35 | static void writeLexiconMiddleResultIntoFile() { 36 | try { 37 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.lexiconMiddleResult)); 38 | for (String s : input_str) { 39 | out.write(s + "\n"); 40 | } 41 | out.close(); 42 | } catch (IOException e) { 43 | throw new RuntimeException(e); 44 | } 45 | } 46 | 47 | // 利用预测表和词法分析的输入来解析 48 | // 语法分析 49 | static void parse() { 50 | // ------ 51 | // 将 # 压入栈 52 | symbol_stack.add("#"); 53 | input_str.add("#"); //输入串在最后也需要放 # 54 | // ------ 55 | 56 | // 初始符号压入栈 57 | // symbol_stack.add("S"); 58 | symbol_stack.add(Config.initSymbol); 59 | 60 | String predictMapKey; // PredictMap-Key 61 | // String process=""; 62 | 63 | 64 | // 符号栈和输入串如果同时为0,那么语法分析结束 65 | // while (symbol_stack.size()>0 && input_str.size()>0 ) { 66 | while (true) { 67 | parse_result_counter++; // 语法分析结果的计数器加一 68 | if (symbol_stack.get(symbol_stack.size()-1).equals("#") && input_str.get(0).equals("#")) { 69 | parse_result_stack.add(parse_result_counter + "\t" 70 | + "EOF" + "#" 71 | + "EOF" + "\t" + "accept"); 72 | break; 73 | } 74 | // 输入缓冲区与推导符号串第一个字符相等的话,删掉 75 | try { 76 | if(input_str.get(0).equals(symbol_stack.get(symbol_stack.size()-1))){ 77 | // 语法分析的结果写入栈中 78 | parse_result_stack.add(parse_result_counter + "\t" 79 | + symbol_stack.get(symbol_stack.size()-1) + "#" 80 | + input_str.get(0) + "\t" + "move"); 81 | input_str.remove(0); // 输入字符移除第一个,类似于指针向后遍历 82 | symbol_stack.remove(symbol_stack.size()-1); // 符号栈移除栈顶 83 | continue; 84 | } 85 | } catch (Exception e) { 86 | // TODO: handle exception 87 | e.printStackTrace(); 88 | } 89 | 90 | // 匹配字符 91 | predictMapKey = PredictMap.getMapKey(input_str.get(0), symbol_stack.get(symbol_stack.size()-1)); 92 | 93 | // 能够找到匹配的 94 | Formula formula = predictMap.get(predictMapKey); // 找到文法 95 | if (formula != null) { // 文法不为空,为空报错 96 | // 语法分析的结果写入栈中 97 | parse_result_stack.add(parse_result_counter + "\t" 98 | + symbol_stack.get(symbol_stack.size()-1) + "#" 99 | + input_str.get(0) + "\t" + "reduction"); 100 | // 符号栈的最后一个元素如果是 #, 就不能删除了 101 | if (symbol_stack.get(symbol_stack.size()-1).equals("#")) { 102 | } else { 103 | symbol_stack.remove(symbol_stack.size()-1); // 删除符号栈中最后一个元素 104 | } 105 | String[] rights = formula.returnRights(); // 文法的右侧 106 | if (rights[0].equals("$")) { // E->$,不能压入空 107 | continue; 108 | } 109 | for (int i = rights.length-1; i >= 0; i--) { 110 | // 将文法右侧的非终结符反向压入栈中 111 | symbol_stack.add(rights[i]); 112 | } 113 | } 114 | 115 | else { 116 | // 语法分析的结果写入栈中 117 | parse_result_stack.add(parse_result_counter + "\t" 118 | + symbol_stack.get(symbol_stack.size()-1) + "#" 119 | + input_str.get(0) + "\t" + "error"); 120 | return; // 遇到error直接返回 121 | } 122 | } 123 | } 124 | 125 | // 输出语法分析结果 126 | static void printParseResult() { 127 | System.out.println("开始输出语法分析结果: --------------------"); 128 | for (String s : parse_result_stack) { 129 | System.out.println(s); 130 | } 131 | try { 132 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.parseResultPath)); 133 | for (String s : parse_result_stack) { 134 | out.write(s + "\n"); 135 | } 136 | out.close(); 137 | } catch (Exception e) { 138 | e.printStackTrace(); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/PredictMap.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.HashMap; 3 | 4 | public class PredictMap { 5 | static void setPrediction(ArrayList formulas, ArrayList terminals, 6 | ArrayList nonTerminals, HashMap> firsts, 7 | HashMap> follows, 8 | HashMap predictions) { 9 | // (2) 10 | for (Formula formula : formulas) { 11 | // First(formula.right[0]) 12 | try { 13 | if (formula.right[0].equals("$")) { // 类似于 value' -> $ 这种文法 14 | // First集合中First($)是不存在的 15 | // 遇到这种文法,直接跳过就行 16 | continue; 17 | } 18 | for (String terminalInFirsts : firsts.get(formula.right[0])) { 19 | // 空 20 | if (terminalInFirsts.equals("$")) { 21 | // Follow(formula.left) 22 | for (String terminalInFollows : follows.get(formula.left)) { 23 | predictions.put(getMapKey(terminalInFollows, formula.left), 24 | new Formula(formula.left, new String[]{"$"})); 25 | } 26 | } 27 | // 不空 28 | // [Terminal, notTerminal] : formula 29 | predictions.put(getMapKey(terminalInFirsts, formula.left), formula); 30 | } 31 | } catch (Exception e) { 32 | System.out.println("first结合中没有 key: " + formula.right[0]); 33 | e.printStackTrace(); 34 | } 35 | } 36 | 37 | // (3) 38 | // E -> $ 39 | for (Formula formula : formulas) { 40 | if (formula.returnRights()[0].equals("$")) { // E -> $ 41 | for (String followElement : follows.get(formula.returnLeft())) { // Follow(E) 42 | // [FollowElement(E), E] : E - > $ 43 | predictions.put(getMapKey(followElement, formula.returnLeft()), formula); 44 | } 45 | } 46 | } 47 | } 48 | 49 | // 以固定的格式产生分析表的 Key 50 | static String getMapKey(String terminal, String nonTerminal) { 51 | // i 为终结符,横坐标 52 | // j 为非终结符,纵坐标 53 | return "{横坐标: " + terminal + " " + "纵坐标: " + nonTerminal + "}"; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/TextLexicon.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.Arrays; 3 | import java.util.HashMap; 4 | 5 | public class TextLexicon { 6 | private String text; 7 | private ArrayList> threeElements; // 要输出的三元组! 8 | private ArrayList lex_result_stack; // 得出的文本的值,这里是用于语法分析的 9 | private ArrayList> lex_error_stack; // 可能出现的错误都放在这里了 10 | private int text_length; // 输入文本的长度 11 | private int row_number=1; // 输入文本行号,从一开始 12 | String[] Key = {"void", "int", "long", "double", "char", "float", "else", "if", 13 | "return", "for", "goto", "short", "static", "while", "do", "main","const"}; // 关键词 14 | 15 | public TextLexicon(String text){ 16 | lex_result_stack = new ArrayList(); 17 | lex_error_stack = new ArrayList>(); 18 | this.text = text; 19 | text_length = text.length(); 20 | this.threeElements = new ArrayList<>(); 21 | } 22 | 23 | public ArrayList get_Lex_Result(){ 24 | return lex_result_stack; 25 | } 26 | public ArrayList> get_Lex_Error() { 27 | // TODO Auto-generated constructor stub 28 | return lex_error_stack; 29 | } 30 | public ArrayList> getThreeElements() { 31 | return threeElements; 32 | } 33 | 34 | public int isAlpha(char c){ 35 | if(((c<='z')&&(c>='a')) || ((c<='Z')&&(c>='A')) || (c=='_')) 36 | return 1; 37 | else 38 | return 0; 39 | } 40 | 41 | public int isNumber(char c){ 42 | if((c>='0')&&(c<='9')) 43 | return 1; 44 | else 45 | return 0; 46 | } 47 | 48 | public int isKey(String t){ 49 | for(int i=0;i': 162 | return handleMore(i, s); 163 | case '<': 164 | return handleLess(i, s); 165 | case '%': 166 | ch = text.charAt(++i); 167 | if (ch=='=') { 168 | // 输出运算符 169 | s = s+ch; 170 | printResult(s, "运算符"); 171 | return ++i; 172 | } 173 | else if(ch=='s'||ch=='c'||ch=='d'||ch=='f'||ch=='l'){ 174 | // 输出类型标识符 175 | s = s+ch; 176 | printResult(s, "输出类型标识符"); 177 | return ++i; 178 | } 179 | else { 180 | // 输出求余标识符 181 | printResult(s, "求余标识符"); 182 | return i; 183 | } 184 | default: 185 | // 输出暂时无法识别的字符,制表符也被当成了有问题的字符 186 | printError(row_number, s, "暂时无法识别的标识符"); 187 | return ++i; 188 | } 189 | } 190 | } 191 | 192 | public int handleFirstAlpha(int arg, String arg0){ 193 | int i=arg; 194 | String s = arg0; 195 | char ch=text.charAt(++i); 196 | while(isAlpha(ch)==1 || isNumber(ch)==1){ 197 | s = s+ch; 198 | ch=text.charAt(++i); 199 | } 200 | // if(s.length()==1){ 201 | // printResult(s, "字符常数"); 202 | // return i; 203 | // } 204 | // 到了结尾 205 | if(isKey(s)==1){ 206 | // 输出key 207 | printResult(s, "关键字"); 208 | return i; 209 | 210 | } 211 | else { 212 | // 输出普通的标识符 213 | printResult(s, "标识符"); 214 | return i; 215 | } 216 | } 217 | 218 | public int handleFirstNum(int arg, String arg0) { 219 | int i = arg; 220 | char ch = text.charAt(++i); 221 | String s = arg0; 222 | while(isNumber(ch)==1){ 223 | s = s+ch; 224 | ch = text.charAt(++i); 225 | } 226 | if((text.charAt(i)==' ')|| 227 | (text.charAt(i)=='\t')|| 228 | (text.charAt(i)=='\n')|| 229 | (text.charAt(i)=='\r')|| 230 | (text.charAt(i)=='\0')||ch==';'||ch==','||ch==')'||ch==']'||ch=='['||ch=='('){ 231 | // 到了结尾,输出数字 232 | printResult(s, "整数"); 233 | return i; 234 | } 235 | else if (ch=='E') { 236 | if (text.charAt(i+1)=='+') { 237 | s = s+ch; 238 | ch = text.charAt(++i); 239 | s = s+ch; 240 | ch = text.charAt(++i); 241 | while (isNumber(ch)==1) { 242 | s = s+ch; 243 | ch = text.charAt(++i); 244 | } 245 | if(ch=='\r'||ch=='\n'||ch==';'||ch=='\t'){ 246 | printResult(s, "科学计数"); 247 | return ++i; 248 | } 249 | else { 250 | printError(i, s, "浮点数错误"); 251 | return i; 252 | } 253 | } 254 | else if (isNumber(text.charAt(i+1))==1) { 255 | s = s+ch; 256 | ch = text.charAt(++i); 257 | while (isNumber(ch)==1) { 258 | s = s+ch; 259 | ch = text.charAt(++i); 260 | } 261 | if(ch=='\r'||ch=='\n'||ch==';'||ch=='\t'){ 262 | printResult(s, "科学计数"); 263 | return ++i; 264 | } 265 | else { 266 | printError(row_number, s, "浮点数错误"); 267 | return i; 268 | } 269 | } 270 | else { 271 | printError(row_number, s, "科学计数法错误"); 272 | return ++i; 273 | } 274 | } 275 | 276 | // 浮点数判断 277 | else if (text.charAt(i)=='.'&&(isNumber(text.charAt(i+1))==1)) { 278 | s = s +'.'; 279 | ch = text.charAt(++i); 280 | while (isNumber(ch)==1) { 281 | s = s+ch; 282 | ch = text.charAt(++i); 283 | } 284 | if (ch=='E') { 285 | if (text.charAt(i+1)=='+') { 286 | s = s+ch; 287 | ch = text.charAt(++i); 288 | s = s+ch; 289 | ch = text.charAt(++i); 290 | while (isNumber(ch)==1) { 291 | s = s+ch; 292 | ch = text.charAt(++i); 293 | } 294 | if(ch=='\r'||ch=='\n'||ch==';'||ch=='\t'){ 295 | printResult(s, "科学计数"); 296 | return ++i; 297 | } 298 | else { 299 | printError(i, s, "浮点数错误"); 300 | return i; 301 | } 302 | } 303 | else if (isNumber(text.charAt(i+1))==1) { 304 | s = s+ch; 305 | ch = text.charAt(++i); 306 | while (isNumber(ch)==1) { 307 | s = s+ch; 308 | ch = text.charAt(++i); 309 | } 310 | if(ch=='\r'||ch=='\n'||ch==';'||ch=='\t'){ 311 | printResult(s, "科学计数"); 312 | return ++i; 313 | } 314 | else { 315 | printError(row_number, s, "浮点数错误"); 316 | return i; 317 | } 318 | } 319 | else { 320 | printError(row_number, s, "科学计数法错误"); 321 | return ++i; 322 | } 323 | } 324 | else if (ch=='\n'||ch=='\r'||ch=='\t'||ch==' '||ch=='\0'||ch!=','||ch!=';') { 325 | printResult(s, "浮点数"); 326 | return i; 327 | } 328 | else if (ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='\0') { 329 | printResult(s, "浮点数"); 330 | return i; 331 | } 332 | else { 333 | while (ch!='\n'&&ch!='\t'&&ch!=' '&&ch!='\r'&&ch!='\0'&&ch!=';'&&ch!='.'&&ch!=',') { 334 | s = s+ch; 335 | ch = text.charAt(++i); 336 | } 337 | printError(row_number, s, "不合法的字符"); 338 | return i; 339 | } 340 | } 341 | else if (ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='\0') { 342 | printResult(s, "整数"); 343 | return i; 344 | } 345 | else { 346 | do { 347 | ch = text.charAt(i++); 348 | s = s+ch; 349 | } while ((text.charAt(i)!=' ') 350 | &&(text.charAt(i)!='\t') 351 | &&(text.charAt(i)!='\n') 352 | &&(text.charAt(i)!='\r') 353 | &&(text.charAt(i)!='\0')); 354 | printError(row_number, s, "错误的标识符"); 355 | return i; 356 | } 357 | } 358 | public int handleChar(int arg, String arg0){ 359 | String s = arg0; 360 | int i = arg; 361 | char ch = text.charAt(++i); 362 | while(ch!='\''){ 363 | if (ch=='\r'||ch=='\n') { 364 | row_number++; 365 | } 366 | else if(ch=='\0'){ 367 | printError(row_number, s, "单字符错误"); 368 | return i; 369 | } 370 | s = s+ch; 371 | ch = text.charAt(++i); 372 | } 373 | s = s+ch; 374 | System.out.println(s); 375 | if (s.length()==3|| 376 | s.equals("\'"+"\\"+"t"+"\'")|| 377 | s.equals("\'"+"\\"+"n"+"\'")|| 378 | s.equals("\'"+"\\"+"r"+"\'")) { 379 | printResult(s, "单字符"); 380 | } 381 | else 382 | printError(row_number, s, "字符溢出"); 383 | return ++i; 384 | } 385 | 386 | // 单行注释处理 387 | public int handleSingleLineNote(int arg, String arg0){ 388 | String s = arg0; 389 | int i = arg; 390 | char ch = text.charAt(++i); 391 | while (ch!='\r'&&ch!='\n'&&ch!='\0') { 392 | s = s+ch; 393 | ch = text.charAt(++i); 394 | } 395 | printResult(s, "单行注释"); 396 | return i; 397 | } 398 | 399 | // 字符串处理 400 | public int handleString(int arg, String arg0){ 401 | String s = arg0; 402 | int i=arg; 403 | char ch = text.charAt(++i); 404 | while(ch!='"'){ 405 | if (ch=='\r'||ch=='\n') { 406 | row_number++; 407 | } 408 | else if(ch=='\0'){ 409 | printError(row_number, s, "字符串没有闭合"); 410 | return i; 411 | } 412 | s = s+ch; 413 | ch = text.charAt(++i); 414 | } 415 | s = s+ch; 416 | printResult(s, "字符串"); 417 | return ++i; 418 | } 419 | 420 | public int handlePlus(int arg, String arg0){ 421 | int i=arg; 422 | char ch = text.charAt(++i); 423 | String s = arg0; 424 | if (ch=='+'){ 425 | // 输出运算符 426 | s = s+ch; 427 | printResult(s, "运算符"); 428 | return ++i; 429 | } 430 | 431 | else if(ch=='='){ 432 | s = s+ch; 433 | // 输出运算符 434 | printResult(s, "运算符"); 435 | return ++i; 436 | } 437 | else{ 438 | // 输出运算符 439 | printResult(s, "运算符"); 440 | return i; 441 | } 442 | } 443 | 444 | // 处理注释,没有考虑不闭合的情况 445 | public int handleNote(int arg, String arg0){ 446 | int i = arg; 447 | char ch=text.charAt(++i); 448 | String s = arg0+ch; 449 | ch = text.charAt(++i); 450 | while (ch!='*' || ((i+1)'){ 503 | s = s+ch; 504 | // 输出运算符 505 | printResult(s, "运算符"); 506 | return ++i; 507 | } 508 | else{ 509 | // 输出运算符 510 | printResult(s, "运算符"); 511 | return i; 512 | } 513 | } 514 | 515 | public int handleLess(int arg, String arg0){ 516 | int i=arg; 517 | String s = arg0; 518 | char ch = text.charAt(++i); 519 | if (ch=='='){ 520 | s = s+ch; 521 | // 输出运算符 522 | printResult(s, "运算符"); 523 | // handLess_1(s, ch); 524 | return ++i; 525 | } 526 | 527 | else if(ch=='<'){ 528 | s = s+ch; 529 | // 输出运算符 530 | printResult(s, "运算符"); 531 | return ++i; 532 | } 533 | else{ 534 | // 输出运算符 535 | printResult(s, "运算符"); 536 | return i; 537 | } 538 | } 539 | 540 | // public String handLess_1(String s, char ch) { 541 | // s = s+ch; 542 | // // 输出运算符 543 | // printResult(s, "运算符"); 544 | // return s; 545 | // } 546 | 547 | // 打印结果 548 | public void printResult(String rs_value, String rs_name){ 549 | if (rs_name.equals("标识符")) { 550 | lex_result_stack.add("Ident"); 551 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "IDN", rs_value))); 552 | } 553 | else if(rs_name.equals("整数")){ 554 | lex_result_stack.add("INT"); 555 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "INT", rs_value))); 556 | } 557 | else if (rs_name.equals("科学计数")||rs_name.equals("浮点数")) { 558 | lex_result_stack.add("float"); 559 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "FLOAT", rs_value))); 560 | } 561 | else if(rs_name.equals("单字符")){ 562 | lex_result_stack.add("char"); 563 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "CHAR", rs_value))); 564 | } 565 | else if(rs_name.equals("字符串")){ 566 | lex_result_stack.add("str"); 567 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "STR", rs_value))); 568 | } 569 | else if(rs_name.equals("运算符")) { 570 | lex_result_stack.add(rs_value); 571 | if (rs_value.equals("+")) { 572 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "6"))); 573 | } else if (rs_value.equals("-")) { 574 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "7"))); 575 | } else if (rs_value.equals("*")) { 576 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "8"))); 577 | } else if (rs_value.equals("/")) { 578 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "9"))); 579 | } else if (rs_value.equals("%")) { 580 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "10"))); 581 | } else if (rs_value.equals("=")) { 582 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "11"))); 583 | } else if (rs_value.equals(">")) { 584 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "12"))); 585 | } else if (rs_value.equals("<")) { 586 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "13"))); 587 | } else if (rs_value.equals("==")) { 588 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "14"))); 589 | } else if (rs_value.equals("<=")) { 590 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "15"))); 591 | } else if (rs_value.equals(">=")) { 592 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "16"))); 593 | } else if (rs_value.equals("!=")) { 594 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "17"))); 595 | } else if (rs_value.equals("&&")) { 596 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "18"))); 597 | } else if (rs_value.equals("||")) { 598 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "OP", "19"))); 599 | } 600 | } 601 | else if(rs_name.equals("单界符") || rs_name.equals("双界符")) { 602 | lex_result_stack.add(rs_value); 603 | if (rs_value.equals("(")) { 604 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "20"))); 605 | } else if (rs_value.equals(")")) { 606 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "21"))); 607 | } else if (rs_value.equals("{")) { 608 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "22"))); 609 | } else if (rs_value.equals("}")) { 610 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "23"))); 611 | } else if (rs_value.equals(";")) { 612 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "24"))); 613 | } else if (rs_value.equals(",")) { 614 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "SE", "25"))); 615 | } 616 | } 617 | else if(rs_name.equals("关键字")) { 618 | lex_result_stack.add(rs_value); 619 | if (rs_value.equals("int")) { 620 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", "1"))); 621 | } else if (rs_value.equals("void")) { 622 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", "2"))); 623 | } else if (rs_value.equals("return")) { 624 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", "3"))); 625 | } else if (rs_value.equals("const")) { 626 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", "4"))); 627 | } else if (rs_value.equals("main")) { 628 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", "5"))); 629 | } else { 630 | threeElements.add(new ArrayList<>(Arrays.asList(rs_value, "KW", rs_value))); 631 | } 632 | } 633 | } 634 | 635 | // 打印错误信息 636 | public void printError(int row_num, String rs_value, String rs_name) { 637 | HashMap hashMap = new HashMap(); 638 | hashMap.put("行号:", row_num+""); 639 | hashMap.put("输入:", rs_value); 640 | hashMap.put("错误类型: ", rs_name); 641 | lex_error_stack.add(hashMap); 642 | // tbModel_lex_result.addRow(new String[]{"ERROR,"+rs_name, rs_value}); 643 | } 644 | } 645 | -------------------------------------------------------------------------------- /src/TextLexiconInput.java: -------------------------------------------------------------------------------- 1 | import java.io.IOException; 2 | import java.nio.file.Files; 3 | import java.nio.file.Paths; 4 | 5 | public class TextLexiconInput { 6 | // 这个类是处理词法分析输入的,将文件转换成为字符串。 7 | static String input() { 8 | String path = Config.lexInputPath; 9 | String content = ""; 10 | try { 11 | content = Files.readString(Paths.get(path)); 12 | // System.out.println(content); 13 | } catch (IOException e) { 14 | throw new RuntimeException(e); 15 | } 16 | return content; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/TextParse.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.nio.Buffer; 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashMap; 6 | 7 | public class TextParse { 8 | static ArrayList formulas; // 产生式 9 | static ArrayList terminals; // 终结符 10 | static ArrayList nonTerminals; // 非终结符 11 | static HashMap> firsts; 12 | static HashMap> follows; 13 | static HashMap predictions; 14 | 15 | static void writeAllIntoFile() { 16 | try { 17 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.formulaPath)); 18 | for (Formula formula : formulas) { 19 | out.write("文法左侧: " + formula.left + "\t" + "文法右侧: " + Arrays.toString(formula.right) + "\n"); 20 | } 21 | out.close(); 22 | } catch (IOException e) { 23 | throw new RuntimeException(e); 24 | } 25 | 26 | try { 27 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.terminalPath)); 28 | for (String s : terminals) { 29 | out.write(s + "\n"); 30 | } 31 | out.close(); 32 | } catch (IOException e) { 33 | throw new RuntimeException(e); 34 | } 35 | 36 | try { 37 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.nonTerminalPath)); 38 | for (String s : nonTerminals) { 39 | out.write(s + "\n"); 40 | } 41 | out.close(); 42 | } catch (IOException e) { 43 | throw new RuntimeException(e); 44 | } 45 | 46 | try { 47 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.firstTablePath)); 48 | for (String s : firsts.keySet()) { 49 | out.write(s + "\t" + firsts.get(s) + "\n"); 50 | } 51 | out.close(); 52 | } catch (IOException e) { 53 | throw new RuntimeException(e); 54 | } 55 | 56 | try { 57 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.followTablePath)); 58 | for (String s : follows.keySet()) { 59 | out.write(s + "\t" + follows.get(s) + "\n"); 60 | } 61 | out.close(); 62 | } catch (IOException e) { 63 | throw new RuntimeException(e); 64 | } 65 | 66 | try { 67 | BufferedWriter out = new BufferedWriter(new FileWriter(Config.predictMapPath)); 68 | for (String s : predictions.keySet()) { 69 | out.write(s + "\t" + "文法: " + predictions.get(s).left + "->" + 70 | Arrays.toString(predictions.get(s).right) + "\n"); 71 | } 72 | out.close(); 73 | } catch (IOException e) { 74 | throw new RuntimeException(e); 75 | } 76 | } 77 | 78 | // 入口 79 | static void Do() { 80 | formulas = new ArrayList<>(); 81 | terminals = new ArrayList<>(); 82 | nonTerminals = new ArrayList<>(); 83 | firsts = new HashMap<>(); 84 | follows = new HashMap<>(); 85 | predictions = new HashMap<>(); 86 | setFormulas(); 87 | setNonTerminals(); 88 | setTerminals(); 89 | setFirsts(); 90 | setFollows(); 91 | setPrediction(); 92 | } 93 | 94 | // 这个函数会生成文法规则 95 | public static void setFormulas() { 96 | try { 97 | File file = new File(Config.grammarPath); 98 | RandomAccessFile randomfile = new RandomAccessFile(file, "r"); 99 | String line; 100 | String left; 101 | String right; 102 | Formula formula; 103 | while ((line=randomfile.readLine())!=null) { 104 | // System.out.println(line); 105 | // System.out.println("split: " + Arrays.toString(line.split("->"))); 106 | left = line.split("->")[0].trim(); 107 | right = line.split("->")[1].trim(); // 将右侧所有的值都算进去 108 | formula = new Formula(left, right.split(" ")); // 根据空格分离右侧的值 109 | formulas.add(formula); 110 | } 111 | randomfile.close(); 112 | } catch (Exception e) { 113 | // TODO: handle exception 114 | e.printStackTrace(); 115 | } 116 | } 117 | 118 | // 解析文法中的非终结符,并设置 119 | // 非终结符在文法中就是所有的left 120 | static void setNonTerminals() { 121 | for (Formula formula : formulas) { 122 | if (nonTerminals.contains(formula.left)) { 123 | continue; 124 | } else { 125 | nonTerminals.add(formula.left); 126 | } 127 | } 128 | } 129 | 130 | // 生成终结符 131 | static void setTerminals() { 132 | for (Formula formula : formulas) { 133 | String[] rights = formula.returnRights(); 134 | // 从右侧去掉非终结符,剩下的就是终结符 135 | for (String s : rights) { 136 | // 去掉非终结符和空 137 | if (nonTerminals.contains(s) || s.equals("$")) { 138 | continue; 139 | } else { // 剩下的就是终结符 140 | terminals.add(s); 141 | } 142 | } 143 | } 144 | } 145 | 146 | // 生成 First 集合 147 | static void setFirsts() { 148 | FirstTable.setFirst(formulas,terminals,nonTerminals,firsts); 149 | } 150 | 151 | // 生成 Follow 集合 152 | static void setFollows() { 153 | FollowTable.setFollow(formulas,terminals,nonTerminals,firsts,follows); 154 | } 155 | 156 | static void setPrediction() { 157 | PredictMap.setPrediction(formulas,terminals,nonTerminals,firsts,follows,predictions); 158 | } 159 | } 160 | 161 | // 产生式类(在这里解析文法) 162 | class Formula { 163 | String left; 164 | String[] right; 165 | public Formula(String left, String[] right){ 166 | this.left = left; 167 | this.right = right; 168 | } 169 | 170 | public String[] returnRights(){ 171 | return right; 172 | } 173 | 174 | public String returnLeft(){ 175 | return left; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/TextParseInput.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | 3 | public class TextParseInput { 4 | private static ArrayList lex_result_stack; 5 | 6 | public static void setLex_result_stack(ArrayList lex) { 7 | lex_result_stack = lex; 8 | } 9 | 10 | public static ArrayList getLex_result_stack() { 11 | return lex_result_stack; 12 | } 13 | } 14 | --------------------------------------------------------------------------------