├── .gitignore ├── CMakeLists.txt ├── README.md ├── api ├── Array.jack ├── IO.jack ├── Input.jack ├── Math.jack ├── Memory.jack ├── Output.jack ├── String.jack └── Sys.jack ├── folder ├── 1.png ├── 2.png ├── 3.png ├── 4.jpg ├── 5.png └── 6.png ├── jack ├── CMakeLists.txt ├── include │ └── VM.h └── src │ ├── VM.cpp │ └── jack.cpp └── jackc ├── CMakeLists.txt ├── driver └── jackc.cpp ├── include ├── Analyzer.h ├── CodeGen.h ├── Error.h ├── Parser.h ├── Scanner.h └── SymbolTable.h └── src ├── Analyzer.cpp ├── CodeGen.cpp ├── Error.cpp ├── Parser.cpp ├── Scanner.cpp └── SymbolTable.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | # QtCreator .user files 31 | *.user 32 | *.user.* 33 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (jack) 3 | add_subdirectory (jack) 4 | add_subdirectory (jackc) 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jack-Compiler 2 | 3 | ### 效果 4 | ##### Demo1: 5 | ```C++ 6 | class Main 7 | { 8 | function void main() 9 | { 10 | String s; 11 | 12 | Output.printString("Hello, world!"); 13 | Output.println(); 14 | 15 | Output.printString("What's your name?"); 16 | Output.println(); 17 | s = Input.readLine(); 18 | Output.printString("Your name is: "); 19 | Output.printString(s); 20 | Output.println(); 21 | 22 | return; 23 | } 24 | 25 | } 26 | ``` 27 | ##### 运行结果: 28 | ![图片4](https://github.com/Xiang1993/C-Mini-Compiler/blob/master/folder/4.jpg) 29 | 30 | 31 | ##### Demo2 32 | ```C++ 33 | class Main 34 | { 35 | function void main() 36 | { 37 | Array arr; 38 | String s; 39 | int i; 40 | 41 | arr = Array.new(5); // 创建一个大小为5的数组 42 | i = 0; 43 | while (i < 5) 44 | { 45 | s = Input.readLine(); 46 | arr[i] = s.intValue(); 47 | i = i + 1; 48 | } 49 | 50 | Main.bubble_sort(arr, 5); 51 | 52 | i = 0; 53 | while (i < 5) 54 | { 55 | Output.printInt(arr[i]); 56 | i = i + 1; 57 | } 58 | Output.println(); 59 | 60 | return; 61 | } 62 | 63 | /* 冒泡排序 */ 64 | function void bubble_sort(Array arr, int n) 65 | { 66 | int i, j, tmp; 67 | i = n - 1; 68 | 69 | while (i > 0 | i == 0) // 由于还没有加上 >= 运算符, 所以暂时用这个代替 70 | { 71 | j = 0; 72 | while (j < i) 73 | { 74 | if (arr[j] > arr[j + 1]) 75 | { 76 | tmp = arr[j]; 77 | arr[j] = arr[j + 1]; 78 | arr[j + 1] = tmp; 79 | } 80 | j = j + 1; 81 | } 82 | i = i - 1; 83 | } 84 | 85 | return; 86 | } 87 | } 88 | ``` 89 | ##### 运行结果: 90 | ![图片6](https://github.com/Xiang1993/C-Mini-Compiler/blob/master/folder/6.png) 91 | 92 | ##### Demo3: 93 | ```C++ 94 | class Main 95 | { 96 | function void main() 97 | { 98 | int a, b, c; 99 | String s; 100 | 101 | s = Input.readLine(); 102 | a = s.intValue(); 103 | 104 | s = Input.readLine(); 105 | b = s.intValue(); 106 | 107 | c = Main.gcd(a, b); 108 | 109 | Output.printInt(c); 110 | Output.println(); 111 | 112 | return; 113 | } 114 | 115 | // 求最大公约数 116 | function int gcd(int a, int b) 117 | { 118 | if (b == 0) 119 | { 120 | return a; 121 | } 122 | else 123 | { 124 | return Main.gcd(b, a - a / b * b); 125 | /* a - a / b * b相当于 a % b */ 126 | } 127 | } 128 | 129 | } 130 | ``` 131 | ##### 运行结果: 132 | ![图片5](https://github.com/Xiang1993/C-Mini-Compiler/blob/master/folder/5.png) 133 | 134 | 135 | 136 | [TOC] 137 | 138 | # 背景介绍 139 | 140 | 去年学了编译原理,但是这门课的理论太多了,而且很难,学得是云里雾里.网上很多大神说学了编译原理之后最好能够实际动手做一个编译器出来,这样对能力有很大的提升.于是就下了定决心,带着写一个编译器的目的来重新学习编译原理.然后开始找公开课,买书,就这样开始了. 141 | 142 | ## jack--语言介绍 143 | ### 语法要素 144 | 145 | 1, 保留字: 146 | 147 | class, constructor, method, function, int, boolean, char, void, 148 | static, field, if, else, while, return, true, false, null, this 149 | 2, 标识符: 150 | 151 | 由字母或下划线开头, 后接任意任意个字母或数字或下划线 152 | 3, 常量: 153 | 154 | int类型的常数规定都是正整数, 没有负整数, 但是可以在正整数前面加上负号, 这是对正整数取负值的一元运算表达式 155 | String类型的常量是把一个字符串用一对双引号括起来, 与java和C里面的字符串一样 156 | boolean类型的常量可以是true和false 157 | 常数null表示一个空引用, 实际上就是数值0 158 | 4, 合法的符号: 159 | 160 | ( ) [ ] , . ; = + - * / & | ~ < > <= >= == 161 | 5, 注释: 162 | 163 | 与C语言和java一样, 支持两种注释形式, 单行注释// 和多行注释 /* */ 164 | 165 | ### 程序结构 166 | 167 | 1, jack的基本编程单元是类, 每个类存在于独立的文件中, 可以单独编译, 下面是类的定义形式: 168 | 169 | class 类名 170 | { 171 | 成员变量(field)声明 和 静态变量(static)声明 // 比如放在子程序声明之前 172 | 子程序声明 // 子程序声明可以是构造函数声明(construtor), 静态函数声明(function)和方法声明(method) 173 | } 174 | 175 | 2, 子程序声明: 176 | 177 | subroutine 类型 名称 (参数列表) 178 | { 179 | 局部变量声明 180 | 语句 181 | } 182 | 3, jack必须至少包含一个Main类, 而且在Main类中必须包含一个function void main() 函数 183 | 184 | ### 变量 185 | 186 | 1, 变量分类 187 | 188 | jack中有四种变量类型: 成员变量, 静态变量, 局部变量和参数变量 189 | 成员变量通过field关键字来声明 190 | 静态变量通过static来声明 191 | 在函数体的开始声明的变量是局部变量 192 | 在函数声明中声明的变量是参数变量 193 | 194 | 2, 数据类型 195 | 196 | 基本数据类型和对象类型 197 | 198 | 3, 基本类型 199 | 200 | int, boolean, char 201 | 4, 对象类型 202 | 203 | 同java一样, 声明一个对象实际上只是创建一个指向该对象的引用 204 | 5, 数组 205 | 206 | 数组是通过内置类Array类声明的, 用Array声明的对象也是一个引用, 指向堆内存. 207 | 对数组的引用可以与传统的一样 208 | Array arr; 209 | arr[3] = 4; 210 | 不支持多维数组. 211 | 6, 字符串 212 | 213 | 字符串是通过内置类String类来声明的, 同样, 用String声明的对象也是一个引用, 指向堆内存, 例如: 214 | String s; 215 | char c; 216 | s = String.new("hello, world!\n"); 217 | c = s.charAt(4); 218 | 7, 类型转换 219 | 220 | jack是弱类型语言, 没有禁止不同类型之间的转换 221 | 222 | ### 语句 223 | 224 | 1, 赋值语句 225 | 226 | 变量 = 表达式 227 | 变量[表达式] = 表达式 228 | 2, if语句 229 | 230 | if(表达式) // 不能省略大括号 231 | { 232 | 语句 233 | } 234 | else 235 | { 236 | 语句 237 | } 238 | 3, while语句 239 | 240 | while(表达式) 241 | { 242 | 语句 243 | } 244 | 4, 函数调用语句 245 | 246 | 方法名(表达式) 247 | 类名.函数名(表达式) 248 | 5, return语句 249 | 250 | return 表达式 251 | return ; // 即使子程序返回void, 也要有return语句 252 | 253 | ### 表达式 254 | 255 | jack--表达式必须是下列之一: 256 | 257 | * 常数 258 | * 在作用域内的变量名(变量可以是静态、局部、成员或参数类型) 259 | * 关键字this, 引用当前对象 (不能用于函数中) 260 | * 数组语法是: 数组名称[表达式], 其中数组名称是Array类型的变量名 261 | * 返回值为非空类型的子程序调用 262 | * 一元运算符 "-" 或 "~" 作前缀的表达式 263 | ** - 表达式: 算术求反 264 | ** ~ 表达式: 布尔求反 265 | * 形如 "表达式 运算符 表达式" 的表达式, 其中运算符可以是以下二元运算符中的一种; 266 | *** + - * / & | <= < >= > == 267 | * (表达式): 位于圆括号内的表达式 268 | 269 | 270 | ### 标准库 271 | 272 | 标准库包括下面的类 273 | 274 | Math 提供基本的数学运算 275 | String 实现字符串String类型和字符串相关操作 276 | Array 实现数组Array类型和数组相关操作 277 | Output 处理屏幕上的文字输出 278 | Input 处理键盘的输入 279 | Memory 处理内存操作 280 | Sys 提供与程序执行相关的服务 281 | 282 | 283 | #### Math类 284 | 285 | 该类实现各种数学运算操作 286 | 287 | #### String类 288 | 289 | 该类实现String数据类型以及与字符串相关的操作 290 | 291 | #### Array类 292 | 该类构造和清除数组 293 | 294 | #### Output类 295 | 296 | 该类提供在屏幕上打印文本的服务 297 | 298 | #### Input类 299 | 300 | 该类提供从标准键盘上读取输入的服务 301 | 302 | #### Memory类 303 | 304 | 该类允许直接访问宿主平台的主内存的服务 305 | 306 | #### Sys类 307 | 308 | 该类提供与程序指向相关的服务 309 | 310 | ### Demo 311 | 312 | ##项目介绍 313 | 314 | ## 使用说明 315 | 在linux下运行compiler.sh或者make就可以编译出jackc.exe和jack.exe了 316 | 317 | ## 模块介绍 318 | 319 | jack编译器主要有词法分析器,语法分析器,语义分析器,vm代码生成 和 虚拟机 320 | 321 | ### 词法分析器 322 | 323 | 词法分析器的源代码为Scanner.cpp 使用的手工编码的方法实现的 324 |     词法分析器的主要任务是识别源程序中的单词(Token),假如有下面的C代码: 325 | ```C++ 326 | int main() 327 | { 328 | printf("Hello, world!\n"); 329 | return 0; 330 | } 331 | ``` 332 |     通过词法分析器的扫描之后,返回的是一个一个单词(Token): 333 | 334 | 关键字 int 335 | 标识符 main 336 | 左圆括号 '(' 337 | 左花括号 '{' 338 | 标识符 printf 339 | 左圆括号 '(' 340 | 字符串 "Hello, world!\n" 341 | 右圆括号 ')' 342 | 分号 ';' 343 | 标识符 return 344 | 数字 0 345 | 右花括号 '}' 346 | 347 | #### 词法规则 348 | 349 | 首先定义一些词法规则,即这门语言对能够识别出来的单词,词法规则是用正则表达式来定义的 350 | 351 | #### 转移图 352 | 353 | 根据上面的词法规则可以画出状态转移图(FA),以方便编程 354 | 355 | 1, 简单的转移图示例: 356 | 357 | 358 | 2, 标识符,整型和浮点型的转移图: 359 | 360 | ![图片1](https://github.com/Xiang1993/C-Mini-Compiler/blob/master/folder/1.png) 361 | 362 | 3, 字符串的转移图: 363 | 364 | ![图片2](https://github.com/Xiang1993/C-Mini-Compiler/blob/master/folder/2.png) 365 | 366 | 4, 字符的转移图 367 | ![图片3](https://github.com/Xiang1993/C-Mini-Compiler/blob/master/folder/3.png) 368 | 369 | ### 语法分析器 370 | 371 | 语法分析器的源代码文件是Parser.cpp 使用的是递归下降的方法实现的 372 | 语法分析器有两个任务: 373 | 1, 判断源程序是否符合语法规则 374 | 2, 生成抽象语法树 375 | 376 | #### jack语言的语法 377 | 378 | jack语言的语法由如下的上下文无关文法(BNF)定义. 379 | 非粗体字表示非终结符, 粗体字表示终结符 380 | 381 |
382 |     program -> classlist
383 |     classlist -> classlist class
384 |                | class
385 |     class -> class ID { classVarDecList subroutineDecList }
386 |     classVarDecList -> classVarDecList classVarDec
387 |              	     |
388 |     classVarDec -> static type varNameList ;
389 |                  | field type varNameList ;
390 |     varNameList -> varNameList , ID
391 |                  | ID
392 |     type -> int
393 |           | float
394 |           | char
395 |           | boolean
396 |           | void
397 |           | ID
398 |     subroutineDecList -> subroutineDecList subroutineDec
399 |                        | 
400 |     subroutineDec -> constructor type ID ( params ) subroutineBody
401 |                    | function type ID ( params ) subroutineBody
402 |                    | method type ID (params ) subroutineBody
403 |     params -> paramList
404 |             | 
405 |     paramList -> paramList , param
406 |                | param
407 |     param -> type ID
408 |     subroutineBody -> { varDecList statements }
409 |     varDecList -> varDecList varDec
410 |                 | 
411 |     varDec -> type varNameList ;
412 |     statements -> statements statement
413 |                 | 
414 |     statement -> assign_statement
415 |                | if_statement
416 |                | while_statement
417 |                | return_statement
418 |                | call_statement ;
419 |     assign_statement -> leftValue = expression ; 
420 |     leftValue -> ID
421 |                | ID [ expression ]
422 |     if_statement -> if ( expression ) statement
423 |                   | if ( expression ) statement else statement
424 |     while_statement -> while ( expression ) { statement }
425 |     return_statement -> return ; 
426 |                       | return expression ;
427 |     call_statement -> ID ( expressions ) 
428 |                     | ID . ID ( expressions )
429 |     expressions -> expression_list
430 |                  | 
431 |     expression_list -> expression_list , expression
432 |                      | expression
433 |     expression -> expression & boolExpression
434 |                 | expression | boolExpression
435 |                 | boolExpression
436 |     boolExpression -> additive_expression relational_operator additive_expression
437 |                     | additive_expression
438 |     relational_operator -> <= 
439 |                          | >=
440 |                          | ==
441 |                          | <
442 |                          | >
443 |                          | !=
444 |     additive_expression -> additive_expression + term
445 |                          | additive_expression  term
446 |                          | term    
447 |     term -> term * factor
448 |           | term / factor
449 |           | factor
450 |     factor -> - positive_factor
451 |             | positive_factor
452 |     positive_factor -> ~ not_factor
453 |                      | not_factor
454 |     not_factor -> INT_CONST
455 |                 | CHAR_CONST
456 |                 | STRING_CONST
457 |                 | keywordConstant
458 |                 | ID
459 |                 | ID [ expression ]
460 |                 | call_expression
461 |                 | ( expression )
462 |     keywordConstant -> true
463 |                      | false
464 |                      | null
465 |                      | this
466 |     call_expression -> ID ( expression )
467 |                      | ID . ID ( expression )
468 | 
469 | 470 | #### 语法树 471 | 树的节点类型: 472 | 473 | ### 语义分析器 474 | 475 | #### 语义规则 476 | 477 | #### 符号表 478 | 479 | #### 虚拟机 480 | 481 | -------------------------------------------------------------------------------- /api/Array.jack: -------------------------------------------------------------------------------- 1 | class Array 2 | { 3 | /** 构造大小为size的新数组 */ 4 | function Array new(int size) 5 | { 6 | Array a; 7 | a = Memory.alloc(size); 8 | return a; 9 | } 10 | 11 | /** 清除数组 */ 12 | method void dispose() 13 | { 14 | Memory.deAlloc(this); 15 | return; 16 | } 17 | } -------------------------------------------------------------------------------- /api/IO.jack: -------------------------------------------------------------------------------- 1 | class IO 2 | { 3 | function void putchar(char ch) 4 | { 5 | return; 6 | } 7 | function char getchar() 8 | { 9 | return '0'; 10 | } 11 | } -------------------------------------------------------------------------------- /api/Input.jack: -------------------------------------------------------------------------------- 1 | class Input 2 | { 3 | function char readChar() 4 | { 5 | char ch; 6 | ch = IO.getchar(); 7 | return ch; 8 | } 9 | 10 | function String readLine() 11 | { 12 | char ch; 13 | String s; 14 | s = String.new(100); 15 | while (true) 16 | { 17 | ch = IO.getchar(); 18 | if (ch == 10) 19 | { 20 | return s; 21 | } 22 | s = s.appendChar(ch); 23 | } 24 | return s; 25 | } 26 | } -------------------------------------------------------------------------------- /api/Math.jack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shellphy/jack-compiler/5ddc42d40abc6c479506496d530cfdae90de19d0/api/Math.jack -------------------------------------------------------------------------------- /api/Memory.jack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shellphy/jack-compiler/5ddc42d40abc6c479506496d530cfdae90de19d0/api/Memory.jack -------------------------------------------------------------------------------- /api/Output.jack: -------------------------------------------------------------------------------- 1 | class Output 2 | { 3 | function void printChar(char ch) 4 | { 5 | IO.putchar(ch); 6 | return; 7 | } 8 | 9 | function void printString(String s) 10 | { 11 | int strLength; 12 | char temp; 13 | int i; 14 | i = 0; 15 | strLength = s.length(); 16 | while(i < strLength) 17 | { 18 | temp = s.charAt(i); 19 | Output.printChar(temp); 20 | i = i + 1; 21 | } 22 | return; 23 | } 24 | 25 | function void printInt(int i) 26 | { 27 | String str; 28 | str = String.new(6); 29 | str.setInt(i); 30 | Output.printString(str); 31 | return; 32 | } 33 | 34 | function void println() 35 | { 36 | IO.putchar(10); 37 | return; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /api/String.jack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shellphy/jack-compiler/5ddc42d40abc6c479506496d530cfdae90de19d0/api/String.jack -------------------------------------------------------------------------------- /api/Sys.jack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shellphy/jack-compiler/5ddc42d40abc6c479506496d530cfdae90de19d0/api/Sys.jack -------------------------------------------------------------------------------- /folder/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shellphy/jack-compiler/5ddc42d40abc6c479506496d530cfdae90de19d0/folder/1.png -------------------------------------------------------------------------------- /folder/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shellphy/jack-compiler/5ddc42d40abc6c479506496d530cfdae90de19d0/folder/2.png -------------------------------------------------------------------------------- /folder/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shellphy/jack-compiler/5ddc42d40abc6c479506496d530cfdae90de19d0/folder/3.png -------------------------------------------------------------------------------- /folder/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shellphy/jack-compiler/5ddc42d40abc6c479506496d530cfdae90de19d0/folder/4.jpg -------------------------------------------------------------------------------- /folder/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shellphy/jack-compiler/5ddc42d40abc6c479506496d530cfdae90de19d0/folder/5.png -------------------------------------------------------------------------------- /folder/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shellphy/jack-compiler/5ddc42d40abc6c479506496d530cfdae90de19d0/folder/6.png -------------------------------------------------------------------------------- /jack/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | project (jack) 4 | 5 | set (CMAKE_CXX_STANDARD 11) 6 | if (CMAKE_CXX_COMPILER_ID MATCHES "GCC" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 7 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror") 8 | endif() 9 | 10 | include_directories (include) 11 | add_executable(${PROJECT_NAME} src/jack.cpp src/VM.cpp) 12 | -------------------------------------------------------------------------------- /jack/include/VM.h: -------------------------------------------------------------------------------- 1 | #ifndef _VM_H 2 | #define _VM_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | extern vector filenames; 11 | 12 | void executeArithmetic(string const& command); // 执行算术指令 13 | void executePush(string const& segment, int index); // 执行push指令 14 | void executePop(string const& segment, int index); // 执行pop指令 15 | void executeLabel(string const& label); // 执行label指令 16 | void executeGoto(string const& label); // 执行goto指令 17 | void executeIf(string const& label); // 执行if-goto指令 18 | void executeCall(string const& functionName, int numArgs); // 执行call指令 19 | void executeReturn(); // 执行return指令 20 | void executeFunction(string const& functionName, int numLocals); // 执行function指令 21 | void executeEnd(); // 程序结束 22 | 23 | void init(); // cpu通电之后初始化ip 24 | void instructionFetch(); // cpu取指令 25 | void execute(); // cpu执行指令 26 | 27 | void setKeyboardValue(short val); 28 | void loadProgram(); // 载入程序到指令存储器中 29 | void run(); // CPU通电开始运行 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /jack/src/VM.cpp: -------------------------------------------------------------------------------- 1 | #include "VM.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static int sp; // 寄存器 栈指针: 指向栈中下一个最顶的基址 8 | static int local; // 寄存器 指向当前VM函数local的基址 9 | static int argument; // 寄存器 指向当前VM函数argument段的基址 10 | static int _this; // 寄存器 指向当前this段(在堆中)的基址 11 | static int that; // 寄存器 指向当前that段(在堆中)的基址 12 | static int ip; // 寄存器 指向下一条要执行的指令 13 | static int temp[7]; // 寄存器 存储临时值 14 | /* 15 | * RAM地址 功能 16 | * 0~15 保留着,未使用 17 | * 16~155 VM程序的所有VM函数的静态变量 18 | * 256~2047 栈 19 | * 2048~16383 堆(用于存放对象和数组) 20 | **/ 21 | static short ram[266385]; // 数据存储器 22 | static vector> instructions_ram; // 指令存储器 23 | static int staticCount; // 记录静态变量已经分配的数量 24 | static unordered_map staticVarNames; // 记录静态变量在内存中的位置 25 | static unordered_map 26 | instruction_address; // 保存label和function指令在指令存储器中的地址 27 | static vector currentInstruction; // 保存当前正在执行的指令 28 | static string currentClassName; // 保存当前正在执行的指令所在的类的名字 29 | static bool arriveEnd = false; // 标记是否到达程序结尾 30 | 31 | void executeArithmetic(const string &command) { 32 | if (command == "add") { 33 | ram[sp - 2] = ram[sp - 2] + ram[sp - 1]; 34 | sp--; 35 | } else if (command == "sub") { 36 | ram[sp - 2] = ram[sp - 2] - ram[sp - 1]; 37 | sp--; 38 | } else if (command == "neg") { 39 | ram[sp - 1] = -ram[sp - 1]; 40 | } else if (command == "eq") { 41 | if (ram[sp - 2] == ram[sp - 1]) 42 | ram[sp - 2] = -1; 43 | else 44 | ram[sp - 2] = 0; 45 | sp--; 46 | } else if (command == "gt") { 47 | if (ram[sp - 2] > ram[sp - 1]) 48 | ram[sp - 2] = -1; 49 | else 50 | ram[sp - 2] = 0; 51 | sp--; 52 | } else if (command == "lt") { 53 | if (ram[sp - 2] < ram[sp - 1]) 54 | ram[sp - 2] = -1; 55 | else 56 | ram[sp - 2] = 0; 57 | sp--; 58 | } else if (command == "and") { 59 | ram[sp - 2] = ram[sp - 2] & ram[sp - 1]; 60 | sp--; 61 | } else if (command == "or") { 62 | ram[sp - 2] = ram[sp - 2] | ram[sp - 1]; 63 | sp--; 64 | } else if (command == "not") { 65 | ram[sp - 1] = ~ram[sp - 1]; 66 | } 67 | } 68 | 69 | void executePush(const string &segment, int index) { 70 | if (segment == "static") { 71 | string t; 72 | ostringstream iss(t); 73 | iss << index; 74 | string staticVarName = currentClassName + "." + t; 75 | auto result = staticVarNames.find(staticVarName); 76 | if (result == staticVarNames.end()) { 77 | staticVarNames.insert({staticVarName, staticCount}); 78 | staticCount++; 79 | } else { 80 | int temp = ram[16 + result->second]; 81 | ram[sp++] = temp; 82 | } 83 | } else if (segment == "argument") 84 | ram[sp++] = ram[argument + index]; 85 | else if (segment == "local") 86 | ram[sp++] = ram[local + index]; 87 | else if (segment == "constant") 88 | ram[sp++] = index; 89 | else if (segment == "this") 90 | ram[sp++] = ram[_this + index]; 91 | else if (segment == "that") 92 | ram[sp++] = ram[that + index]; 93 | else if (segment == "pointer") { 94 | if (index == 0) 95 | ram[sp++] = _this; 96 | else if (index == 1) 97 | ram[sp++] = that; 98 | } else if (segment == "temp") 99 | ram[sp++] = temp[index]; 100 | } 101 | 102 | void executePop(const string &segment, int index) { 103 | if (segment == "static") { 104 | string t; 105 | ostringstream iss(t); 106 | iss << index; 107 | string staticVarName = currentClassName + "." + t; 108 | auto result = staticVarNames.find(staticVarName); 109 | if (result == staticVarNames.end()) { 110 | staticVarNames.insert({staticVarName, staticCount}); 111 | staticCount++; 112 | } else { 113 | int temp = ram[--sp]; 114 | ram[16 + result->second] = temp; 115 | } 116 | } 117 | if (segment == "argument") 118 | ram[argument + index] = ram[--sp]; 119 | else if (segment == "local") 120 | ram[local + index] = ram[--sp]; 121 | else if (segment == "this") 122 | ram[_this + index] = ram[--sp]; 123 | else if (segment == "that") 124 | ram[that + index] = ram[--sp]; 125 | else if (segment == "pointer") { 126 | if (index == 0) 127 | _this = ram[--sp]; 128 | else if (index == 1) 129 | that = ram[--sp]; 130 | } else if (segment == "temp") 131 | temp[index] = ram[--sp]; 132 | } 133 | void executeLabel(const string &label) { 134 | // do nothing 135 | } 136 | 137 | void executeGoto(const string &label) { ip = instruction_address.find(label)->second; } 138 | 139 | void executeIf(const string &label) { 140 | int temp = ram[--sp]; 141 | if (temp != 0) 142 | ip = instruction_address.find(label)->second; 143 | } 144 | 145 | void executeCall(const string &functionName, int numArgs) { 146 | if (functionName == "IO.putchar") { 147 | putchar(ram[sp - 1]); 148 | return; 149 | } else if (functionName == "IO.getchar") { 150 | ram[sp++] = getchar(); 151 | return; 152 | } 153 | ram[sp++] = ip; 154 | ram[sp++] = local; 155 | ram[sp++] = argument; 156 | ram[sp++] = _this; 157 | ram[sp++] = that; 158 | argument = sp - numArgs - 5; 159 | local = sp; 160 | ip = instruction_address.find(functionName)->second; 161 | } 162 | 163 | void executeReturn() { 164 | int temp = local; 165 | ip = ram[temp - 5]; 166 | ram[argument] = ram[--sp]; // 重置调用者的返回值 167 | sp = argument + 1; 168 | that = ram[temp - 1]; 169 | _this = ram[temp - 2]; 170 | argument = ram[temp - 3]; 171 | local = ram[temp - 4]; 172 | } 173 | 174 | void executeFunction(const string &functionName, int numLocals) { 175 | auto iter = functionName.cbegin(); 176 | while (iter != functionName.cend()) 177 | if (*iter++ == '.') 178 | break; 179 | currentClassName = string(functionName.cbegin(), --iter); 180 | for (int i = 0; i < numLocals; i++) 181 | ram[sp++] = 0; 182 | } 183 | 184 | void loadProgram() { 185 | std::ifstream fin; 186 | int count = 0; 187 | 188 | for (auto iter = filenames.cbegin(); iter != filenames.cend(); ++iter) { 189 | fin.open(*iter); 190 | if (fin.fail()) { 191 | std::cerr << "Error: file " << *iter << "does not exsist!\n"; 192 | exit(-1); 193 | } 194 | string temp; 195 | while (std::getline(fin, temp)) { 196 | vector instruction; 197 | std::istringstream iss(temp); 198 | string word; 199 | while (iss >> word) { 200 | instruction.push_back(word); 201 | } 202 | if (instruction[0] == "label" || instruction[0] == "function") 203 | instruction_address.insert({instruction[1], count}); 204 | instructions_ram.push_back(instruction); 205 | count++; 206 | } 207 | fin.close(); 208 | } 209 | vector end; 210 | end.push_back("end"); 211 | instructions_ram.push_back(end); 212 | } 213 | 214 | void init() { 215 | ip = instruction_address.find("Sys.init")->second; 216 | sp = 50; 217 | local = sp; 218 | ram[local - 5] = instructions_ram.size() - 1; 219 | } 220 | 221 | void run() { 222 | init(); 223 | while (true) { 224 | instructionFetch(); 225 | if (ip == 1) { 226 | int temp; 227 | temp = 0; 228 | /// @todo find out what this makes 229 | // sp; 230 | // local; 231 | // argument; 232 | // _this; 233 | // that; 234 | // currentInstruction; 235 | } 236 | ++ip; 237 | execute(); 238 | if (arriveEnd == true) 239 | break; 240 | } 241 | } 242 | 243 | void instructionFetch() { currentInstruction = instructions_ram[ip]; } 244 | 245 | void execute() { 246 | string command = currentInstruction[0]; 247 | if (command == "add" || command == "sub" || command == "neg" || 248 | command == "eq" || command == "gt" || command == "lt" || 249 | command == "and" || command == "or" || command == "not") 250 | executeArithmetic(currentInstruction[0]); 251 | else if (command == "push") 252 | executePush(currentInstruction[1], atoi(currentInstruction[2].c_str())); 253 | else if (command == "pop") 254 | executePop(currentInstruction[1], atoi(currentInstruction[2].c_str())); 255 | else if (command == "label") 256 | executeLabel(currentInstruction[1]); 257 | else if (command == "goto") 258 | executeGoto(currentInstruction[1]); 259 | else if (command == "if-goto") 260 | executeIf(currentInstruction[1]); 261 | else if (command == "call") 262 | executeCall(currentInstruction[1], atoi(currentInstruction[2].c_str())); 263 | else if (command == "return") 264 | executeReturn(); 265 | else if (command == "function") 266 | executeFunction(currentInstruction[1], atoi(currentInstruction[2].c_str())); 267 | else if (command == "end") 268 | arriveEnd = true; 269 | } 270 | -------------------------------------------------------------------------------- /jack/src/jack.cpp: -------------------------------------------------------------------------------- 1 | #include "VM.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | vector filenames; 10 | 11 | int main(int argc, char *argv[]) { 12 | if (argc == 1) { 13 | cout << "Usage: vm sourcefiles\n"; 14 | exit(-1); 15 | } 16 | ifstream fin; 17 | for (int i = 1; i < argc; i++) { 18 | fin.open(argv[i]); 19 | if (fin.fail()) { 20 | cerr << "file '" << argv[i] << "' not exist!"; 21 | exit(-1); 22 | } 23 | filenames.push_back(argv[i]); 24 | fin.close(); 25 | } 26 | // 未判断文件是否存在 27 | filenames.push_back("./api/Array.vm"); 28 | filenames.push_back("./api/Memory.vm"); 29 | filenames.push_back("./api/Math.vm"); 30 | filenames.push_back("./api/Input.vm"); 31 | filenames.push_back("./api/Output.vm"); 32 | filenames.push_back("./api/Sys.vm"); 33 | filenames.push_back("./api/String.vm"); 34 | filenames.push_back("./api/IO.vm"); 35 | 36 | loadProgram(); 37 | run(); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /jackc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project(jackc) 3 | 4 | set (CMAKE_CXX_STANDARD 11) 5 | if (CMAKE_CXX_COMPILER_ID MATCHES "GCC" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 6 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror") 7 | endif() 8 | 9 | include_directories (include) 10 | aux_source_directory (src JACKC_LIB_SRC) 11 | add_library (jackclib "${JACKC_LIB_SRC}") 12 | add_executable (${PROJECT_NAME} driver/jackc.cpp) 13 | target_link_libraries (${PROJECT_NAME} jackclib) 14 | -------------------------------------------------------------------------------- /jackc/driver/jackc.cpp: -------------------------------------------------------------------------------- 1 | #include "Analyzer.h" 2 | #include "CodeGen.h" 3 | #include "Parser.h" 4 | #include "Scanner.h" 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | int main(int argc, char *argv[]) { 12 | if (argc < 2) { 13 | cerr << "usage: " << argv[0] << " " << endl; 14 | exit(-1); 15 | } 16 | ifstream fin; 17 | vector filenames; 18 | for (int i = 1; i < argc; i++) { 19 | fin.open(argv[i]); 20 | if (fin.fail()) { 21 | cerr << "file '" << argv[i] << "' not exist!"; 22 | exit(-1); 23 | } 24 | filenames.push_back(argv[i]); 25 | fin.close(); 26 | } 27 | filenames.push_back("./api/Sys.jack"); 28 | filenames.push_back("./api/Math.jack"); 29 | filenames.push_back("./api/Array.jack"); 30 | filenames.push_back("./api/Memory.jack"); 31 | filenames.push_back("./api/String.jack"); 32 | filenames.push_back("./api/Output.jack"); 33 | filenames.push_back("./api/Input.jack"); 34 | filenames.push_back("./api/IO.jack"); 35 | Parser parser(filenames); 36 | parser.parse_program(); 37 | if (!hasError()) { 38 | Analyzer analyzer(parser.getSyntaxTree()); 39 | analyzer.check(); 40 | } 41 | if (!hasError()) { 42 | CodeGen cgen; 43 | cgen.write(parser.getSyntaxTree()); 44 | } 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /jackc/include/Analyzer.h: -------------------------------------------------------------------------------- 1 | #ifndef _ANALYZER_H 2 | #define _ANALYZER_H 3 | 4 | #include "Error.h" 5 | #include "Parser.h" 6 | #include "SymbolTable.h" 7 | #include 8 | 9 | class Analyzer { 10 | private: 11 | Parser::TreeNode *tree; 12 | SymbolTable *symbolTable; 13 | string currentClassName; // 遍历树的时候, 保存当前类的名称 14 | string currentFunctionName; // 遍历树的时候, 保存当前函数的名称 15 | void buildClassesTable(Parser::TreeNode *t); 16 | void checkStatements(Parser::TreeNode *t); 17 | void checkStatement(Parser::TreeNode *t); 18 | void checkExpression(Parser::TreeNode *t); 19 | void checkArguments(Parser::TreeNode *t, vector const& parameter, 20 | string const& functionName); 21 | void checkMain(); 22 | 23 | public: 24 | Analyzer(Parser::TreeNode *t); 25 | void check(); 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /jackc/include/CodeGen.h: -------------------------------------------------------------------------------- 1 | #ifndef _CODE_GEN_H 2 | #define _CODE_GEN_H 3 | 4 | #include "Parser.h" 5 | #include "SymbolTable.h" 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | class CodeGen { 12 | private: 13 | enum Segment { CONST, ARG, LOCAL, STATIC, THIS, THAT, POINTER, TEMP }; 14 | enum Command { ADD, SUB, NEG, EQ, GT, LT, AND, OR, NOT }; 15 | SymbolTable *symbolTable; 16 | Parser::TreeNode *tree; 17 | string currentClassName; 18 | string currentFunctionName; 19 | int ifLabelCount; 20 | int whileLabelCount; 21 | ofstream fout; 22 | bool isMethod; 23 | void writePush(Segment segment, int index); 24 | void writePop(Segment segment, int index); 25 | void writeArithmetic(Command command); 26 | void writeLabel(string const& label); 27 | void writeGoto(string const& label); 28 | void writeIf(string const& label); 29 | void writeCall(string const& name, int nArgs); 30 | void writeFunction(string const& name, int nArgs); 31 | void writeReturn(); 32 | void writeExpression(Parser::TreeNode *t); 33 | void writeCallExpression(Parser::TreeNode *t); 34 | void translateCall(Parser::TreeNode *t); 35 | 36 | public: 37 | CodeGen(); 38 | void translate(Parser::TreeNode *t); 39 | void write(Parser::TreeNode *t); 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /jackc/include/Error.h: -------------------------------------------------------------------------------- 1 | #ifndef _ERROR_H 2 | #define _ERROR_H 3 | 4 | #include "Scanner.h" 5 | 6 | extern int errorNum; 7 | 8 | bool hasError(); 9 | void syntaxError(string currentParserFilename, string expected, 10 | Scanner::Token token); 11 | 12 | // 类名和函数名不一致 13 | void error1(string currentParserFilename); 14 | 15 | // 变量重定义 16 | void error2(string currentClass, int row, string type, string name); 17 | 18 | // 函数重定义 19 | void error3(string currentClass, int row, string type, string name); 20 | 21 | // 类型未定义 22 | void error4(string currentClassName, int row, string type); 23 | 24 | // 变量未定义 25 | void error5(string currentClassName, int row, string varName); 26 | 27 | // 类型不匹配 28 | void error6(string currentClassName, int row, string type); 29 | 30 | // 函数未定义 31 | void error7(string currentClassName, string callerName, int row, 32 | string functionName); 33 | 34 | // 函数类型不一样 35 | void error8(string currentClassName, int row, string functionName); 36 | 37 | // 函数类型错误 38 | void error9(string currentClassName, string callerName, int row, 39 | string functionName); 40 | 41 | // 函数类型错误 42 | void error10(string currentClassName, string callerName, int row, 43 | string functionName); 44 | 45 | // 返回值错误 46 | void error11(string currentClassName, string type, int row); 47 | 48 | // 返回值错误 49 | void error12(string currentClassName, int row); 50 | 51 | // 返回值错误 52 | void error13(string currentClassName, int row); 53 | 54 | // 参数太少 55 | void error14(string currentClassName, string functionName, int row); 56 | 57 | // 参数太多 58 | void error15(string currentClassName, string functionName, int row); 59 | 60 | void error16(); 61 | 62 | void error17(); 63 | 64 | void error18(); 65 | 66 | void error19(); 67 | 68 | void error20(); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /jackc/include/Parser.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARSER_H 2 | #define _PARSER_H 3 | 4 | #include "Error.h" 5 | #include "Scanner.h" 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | class Parser { 13 | public: 14 | enum NodeKind { 15 | None, 16 | CLASS_K, 17 | CLASS_VAR_DEC_K, 18 | SUBROUTINE_DEC_K, 19 | BASIC_TYPE_K, 20 | CLASS_TYPE_K, 21 | NULL_K, 22 | PARAM_K, 23 | VAR_DEC_K, 24 | ARRAY_K, 25 | VAR_K, 26 | IF_STATEMENT_K, 27 | WHILE_STATEMENT_K, 28 | CALL_EXPRESSION_K, 29 | RETURN_STATEMENT_K, 30 | CALL_STATEMENT_K, 31 | BOOL_EXPRESSION_K, 32 | FUNCTION_CALL_K, 33 | CONSTRUCTOR_CALL_K, 34 | COMPARE_K, 35 | OPERATION_K, 36 | BOOL_K, 37 | ASSIGN_K, 38 | SUBROUTINE_BODY_K, 39 | BOOL_CONST_K, 40 | NEGATIVE_K, 41 | METHOD_CALL_K, 42 | INT_CONST_K, 43 | CHAR_CONST_K, 44 | STRING_CONST_K, 45 | KEY_WORD_CONST, 46 | THIS_K 47 | }; 48 | class TreeNode { 49 | public: 50 | Scanner::Token token; 51 | TreeNode *child[5]; 52 | TreeNode *next; 53 | NodeKind nodeKind; 54 | TreeNode() { 55 | nodeKind = None; 56 | child[0] = child[1] = child[2] = child[3] = child[4] = nullptr; 57 | next = nullptr; 58 | } 59 | }; 60 | 61 | private: 62 | vector filenames; 63 | string currentParserFilename; 64 | TreeNode *syntaxTree; 65 | Scanner scanner; 66 | bool haveReturnStatement; // 要保证每个函数都有return语句, 即使返回值为void 67 | 68 | Scanner::Token getToken(); // 从缓冲区中取出一个token 69 | Scanner::Token ungetToken(); // 把上一次取出的token放入到缓冲区中 70 | deque tokenBuffer1; // 左缓冲区 71 | deque tokenBuffer2; // 右缓冲区 72 | string getFullName(string name); // 返回 73 | 74 | TreeNode *parseClassList(); 75 | TreeNode *parseClass(); 76 | TreeNode *parseClassVarDecList(); 77 | TreeNode *parseClassVarDec(); 78 | TreeNode *parseVarNameList(); 79 | TreeNode *parseType(); 80 | TreeNode *parseSubroutineDecList(); 81 | TreeNode *parseSubroutinDec(); 82 | TreeNode *parseParams(); 83 | TreeNode *parseParamList(); 84 | TreeNode *parseParam(); 85 | TreeNode *parseSubroutineBody(); 86 | TreeNode *parseVarDecList(); 87 | TreeNode *parseVarDec(); 88 | TreeNode *parseStatements(); 89 | TreeNode *parseStatement(); 90 | TreeNode *parseAssignStatement(); 91 | TreeNode *parseLeftValue(); 92 | TreeNode *parseIfStatement(); 93 | TreeNode *parseWhileStatement(); 94 | TreeNode *parseReturnStatement(); 95 | TreeNode *parseCallStatement(); 96 | TreeNode *parseExpressions(); 97 | TreeNode *parseExpressionList(); 98 | TreeNode *parseExpression(); 99 | TreeNode *parseBoolExpression(); 100 | TreeNode *parseAdditiveExpression(); 101 | TreeNode *parseTerm(); 102 | TreeNode *parseFactor(); 103 | TreeNode *parsePositiveFactor(); 104 | TreeNode *parseNotFactor(); 105 | TreeNode *parseCallExpression(); 106 | 107 | void printSyntaxTree(TreeNode *tree); 108 | 109 | public: 110 | Parser(vector &filenames); 111 | bool hasError(); 112 | TreeNode *getSyntaxTree(); 113 | void print(); 114 | void parse_program(); 115 | static string getCallerName(string const& fullName); 116 | static string getFunctionName(string const &fullName); 117 | }; 118 | 119 | #endif 120 | -------------------------------------------------------------------------------- /jackc/include/Scanner.h: -------------------------------------------------------------------------------- 1 | #ifndef _Scanner_H_ 2 | #define _Scanner_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | class Scanner { 12 | private: 13 | enum State // 转移图中的状态 14 | { START_STATE, // 开始状态 15 | ID_STATE, // 标识符状态 16 | INT_STATE, // 整型数状态 17 | CHAR_STATE, // 字符状态 18 | CHAR_STATE_A, 19 | CHAR_STATE_B, 20 | CHAR_STATE_C, 21 | FLOAT_STATE, // 浮点数状态 22 | D_FLOAT_STATE, // 接近带小数点的浮点数状态 23 | E_FLOAT_STATE, // 接近科学技术法的浮点数状态 24 | STRING_STATE, // 字符串状态 25 | S_STRING_STATE, // 含有转移字符的字符串 26 | SYMBOL_STATE, 27 | INCOMMENT_STATE, // 注释状态 28 | P_INCOMMENT_STATE, // 快要结束注释状态 29 | DONE_STATE, // 结束状态 30 | ERROR_STATE // 错误状态 31 | }; 32 | 33 | public: 34 | set keyWords; 35 | set symbols; 36 | enum TokenType { 37 | KEY_WORD, 38 | ID, // 标识符 39 | INT, // 整型数字 40 | BOOL, // 布尔类型 41 | CHAR, // 字符 42 | STRING, // 字符串 43 | SYMBOL, // 合法的符号 44 | NONE, // 无类型 45 | ERROR, // 错误 46 | ENDOFFILE // 文件结束 47 | }; 48 | struct Token { 49 | TokenType kind; // Token的类型 50 | string lexeme; // Token的值 51 | unsigned row; // 当前行 52 | }; 53 | void initKeyWords(); 54 | void initSymbols(); 55 | 56 | private: 57 | string lineBuffer; // 缓冲行, 保存源程序中的一行数据 58 | unsigned bufferPos; // 缓冲行的指针 59 | unsigned row; // 保存当前缓冲行在源程序中的行号 60 | ifstream fin; // 源程序文件的输入流对象 61 | char nextChar(); // 返回缓冲区中的下一个字符 62 | void rollBack(); // 回滚缓冲区 63 | TokenType searchReserved(string const&s); // 查找关键字 64 | public: 65 | Scanner(); 66 | void openFile(string const& filename); 67 | void closeFile(); 68 | Token nextToken(); // 返回下一个Token 69 | void resetRow(); 70 | }; 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /jackc/include/SymbolTable.h: -------------------------------------------------------------------------------- 1 | #ifndef _SYMBOL_TABLE_H 2 | #define _SYMBOL_TABLE_H 3 | 4 | #include "Parser.h" 5 | #include 6 | #include 7 | 8 | class SymbolTable { 9 | public: 10 | enum Kind { STATIC, FIELD, ARG, VAR, FUNCTION, METHOD, CONSTRUCTOR, NONE }; 11 | class Info { 12 | public: 13 | string type; // int, float, char, string 14 | Kind kind; // kind : static, field, var, argument 15 | int index; 16 | vector args; 17 | Info() { 18 | type = "0"; 19 | kind = NONE; 20 | index = 0; 21 | } 22 | friend bool operator==(Info info1, Info info2) { 23 | if (info1.type == info2.type && info1.kind == info2.kind && 24 | info1.args == info2.args) 25 | return true; 26 | else 27 | return false; 28 | } 29 | }; 30 | static Info None; 31 | 32 | private: 33 | int static_index; 34 | int field_index; 35 | int arg_index; 36 | int var_index; 37 | int errorNum; 38 | map classIndex; // 从类名到数组索引 39 | vector> 40 | classesTable; // 类符号表数组, 将一直保留着不会被销毁 41 | map subroutineTable; // 函数符号表 42 | int currentClassNumber; // 遍历语法树的时候, 保存当前类符号表数组索引 43 | string currentClass; // 遍历语法树的时候, 保存当前类名称 44 | void initialSubroutineTable(); // 销毁函数符号表 45 | SymbolTable(); 46 | static SymbolTable *instance; // 指向符号表单实例对象 47 | public: 48 | static SymbolTable *getInstance(); // 返回符号表单实例对象 49 | void classesTableInsert(Parser::TreeNode *t); // 类符号表的插入操作 50 | void subroutineTableInsert(Parser::TreeNode *t); // 函数符号表的插入操作 51 | 52 | Info subroutineTableFind(string const& name); // 函数符号表的查找操作 53 | Info classesTableFind(string const& className, 54 | string const& functionName); // 类符号表的查找操作 55 | bool classIndexFind(string const& className); // 判断className是不是合法的类名 56 | 57 | int getFieldNumber(string const& className); 58 | void printClassesTable(); // 测试程序, 打印类符号表 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /jackc/src/Analyzer.cpp: -------------------------------------------------------------------------------- 1 | #include "Analyzer.h" 2 | #include 3 | 4 | using namespace std; 5 | 6 | Analyzer::Analyzer(Parser::TreeNode *t) { 7 | symbolTable = SymbolTable::getInstance(); 8 | tree = t; 9 | } 10 | 11 | // 遍历表达式树 12 | void Analyzer::checkExpression(Parser::TreeNode *t) { 13 | if (t != nullptr) { 14 | for (int i = 0; i < 5; i++) 15 | checkExpression(t->child[i]); 16 | switch (t->nodeKind) { 17 | case Parser::VAR_K: { 18 | SymbolTable::Info info = 19 | symbolTable->subroutineTableFind(t->token.lexeme); 20 | if (info == SymbolTable::None) { 21 | info = symbolTable->classesTableFind(currentClassName, t->token.lexeme); 22 | if (info == SymbolTable::None) { 23 | error5(currentClassName, t->token.row, t->token.lexeme); 24 | } 25 | } 26 | } break; 27 | case Parser::ARRAY_K: { 28 | SymbolTable::Info info = 29 | symbolTable->subroutineTableFind(t->token.lexeme); 30 | if (info == SymbolTable::None) { 31 | info = symbolTable->classesTableFind(currentClassName, t->token.lexeme); 32 | if (info == SymbolTable::None) { 33 | error5(currentClassName, t->token.row, t->token.lexeme); 34 | } 35 | } 36 | if (info.type != "Array") { 37 | error6(currentClassName, t->token.row, t->token.lexeme); 38 | } 39 | } break; 40 | case Parser::CALL_EXPRESSION_K: 41 | case Parser::CALL_STATEMENT_K: { 42 | if (t->token.lexeme.find('.') == 43 | string::npos) // call_statement -> ID ( expressions ) 44 | { 45 | // 先检查函数有没有在当前类中声明 46 | string functionName = t->token.lexeme; 47 | if (symbolTable->classesTableFind(currentClassName, functionName) == 48 | SymbolTable::None) { 49 | error7(currentClassName, currentClassName, t->token.row, 50 | functionName); 51 | break; 52 | } 53 | SymbolTable::Kind currentFunctionKind = 54 | symbolTable->classesTableFind(currentClassName, currentFunctionName) 55 | .kind; 56 | SymbolTable::Kind calledFunctionKind = 57 | symbolTable->classesTableFind(currentClassName, functionName).kind; 58 | // 再检查当前子过程和被调用过程是否都是method 59 | if (currentFunctionKind == SymbolTable::FUNCTION && 60 | calledFunctionKind == SymbolTable::FUNCTION) { 61 | error8(currentClassName, t->token.row, functionName); 62 | break; 63 | } 64 | // 再检查函数的参数是否正确 65 | SymbolTable::Info info = 66 | symbolTable->classesTableFind(currentClassName, functionName); 67 | checkArguments(t, info.args, functionName); 68 | t->child[0]->nodeKind = Parser::METHOD_CALL_K; 69 | } else // call_statement -> ID . ID ( expressions ) 70 | { 71 | // 先检查caller 72 | string callerName = Parser::getCallerName(t->token.lexeme); 73 | string functionName = Parser::getFunctionName(t->token.lexeme); 74 | if (symbolTable->classIndexFind(callerName) == true) // 如果caller是类 75 | { 76 | // 再检查function 77 | SymbolTable::Info info = 78 | symbolTable->classesTableFind(callerName, functionName); 79 | if (info == SymbolTable::None) { 80 | error7(currentClassName, callerName, t->token.row, functionName); 81 | break; 82 | } 83 | if (info.kind == SymbolTable::METHOD) { 84 | error9(currentClassName, callerName, t->token.row, functionName); 85 | break; 86 | } 87 | // 再检查参数 88 | checkArguments(t, info.args, functionName); 89 | if (info.kind == SymbolTable::FUNCTION) 90 | t->child[0]->nodeKind = Parser::FUNCTION_CALL_K; 91 | else if (info.kind == SymbolTable::CONSTRUCTOR) 92 | t->child[0]->nodeKind = Parser::CONSTRUCTOR_CALL_K; 93 | } else // 如果调用者是对象 94 | { 95 | // 再检查caller有没有被声明 96 | SymbolTable::Info objInfo = 97 | symbolTable->subroutineTableFind(callerName); 98 | if (objInfo == SymbolTable::None) { 99 | objInfo = 100 | symbolTable->classesTableFind(currentClassName, callerName); 101 | if (objInfo == SymbolTable::None) { 102 | error5(currentClassName, t->token.row, callerName); 103 | break; 104 | } 105 | } 106 | // 再检查function 107 | SymbolTable::Info functionInfo = 108 | symbolTable->classesTableFind(objInfo.type, functionName); 109 | if (functionInfo == SymbolTable::None) { 110 | error7(currentClassName, callerName, t->token.row, functionName); 111 | break; 112 | } 113 | if (functionInfo.kind != SymbolTable::METHOD) { 114 | error10(currentClassName, callerName, t->token.row, functionName); 115 | break; 116 | } 117 | // 再检查参数 118 | checkArguments(t, functionInfo.args, functionName); 119 | t->child[0]->nodeKind = Parser::METHOD_CALL_K; 120 | // t->token.lexeme = objInfo.type + "." + 121 | // functionName; 122 | } 123 | } 124 | break; 125 | } 126 | default: 127 | /*fallthrough*/; 128 | } 129 | } 130 | } 131 | 132 | /* 133 | 检查赋值语句, if语句, while语句, return语句, 函数调用语句 134 | */ 135 | void Analyzer::checkStatement(Parser::TreeNode *t) { 136 | switch (t->nodeKind) { 137 | case Parser::CLASS_K: 138 | currentClassName = t->child[0]->token.lexeme; 139 | break; 140 | case Parser::ASSIGN_K: { 141 | checkExpression(t->child[0]); 142 | checkExpression(t->child[1]); 143 | } 144 | case Parser::IF_STATEMENT_K: 145 | case Parser::WHILE_STATEMENT_K: { 146 | checkExpression(t->child[0]); 147 | break; 148 | } 149 | case Parser::RETURN_STATEMENT_K: { 150 | checkExpression(t->child[0]); 151 | SymbolTable::Info info = symbolTable->subroutineTableFind("this"); 152 | if (t->child[0] == nullptr && info.type != "void") { 153 | error11(currentClassName, info.type, t->token.row); 154 | break; 155 | } else if (t->child[0] != nullptr && info.type == "void") { 156 | error12(currentClassName, t->token.row); 157 | break; 158 | } 159 | if (info.kind == SymbolTable::CONSTRUCTOR && 160 | t->child[0]->token.lexeme != "this") { 161 | error13(currentClassName, t->token.row); 162 | break; 163 | } 164 | break; 165 | } 166 | case Parser::CALL_STATEMENT_K: 167 | checkExpression(t); 168 | break; 169 | default: 170 | /*fallthrough*/; 171 | } 172 | } 173 | 174 | void Analyzer::checkArguments(Parser::TreeNode *t, const vector ¶meter, 175 | const string &functionName) { 176 | int argumentSize = 0; 177 | for (auto p = t->child[0]->next; p != nullptr; p = p->next) { 178 | checkExpression(p); 179 | argumentSize++; 180 | } 181 | if (argumentSize < parameter.size()) { 182 | error14(currentClassName, functionName, t->token.row); 183 | return; 184 | } else if (argumentSize > parameter.size()) { 185 | error15(currentClassName, functionName, t->token.row); 186 | return; 187 | } 188 | } 189 | 190 | void Analyzer::check() { 191 | buildClassesTable(tree); 192 | // symbolTable->printClassesTable(); 193 | checkMain(); 194 | checkStatements(tree); 195 | } 196 | 197 | void Analyzer::checkMain() { 198 | if (symbolTable->classIndexFind("Main") == false) { 199 | error16(); 200 | return; 201 | } 202 | auto info = symbolTable->classesTableFind("Main", "main"); 203 | if (info == SymbolTable::None) { 204 | error17(); 205 | return; 206 | } 207 | if (info.kind != SymbolTable::FUNCTION) { 208 | error18(); 209 | return; 210 | } 211 | if (info.type != "void") { 212 | error19(); 213 | return; 214 | } 215 | if (info.args.size() > 0) { 216 | error20(); 217 | return; 218 | } 219 | } 220 | 221 | void Analyzer::buildClassesTable(Parser::TreeNode *t) { 222 | static int depth = 0; 223 | if (depth > 2) 224 | return; 225 | while (t != nullptr) { 226 | symbolTable->classesTableInsert(t); 227 | for (int i = 0; i < 5; i++) { 228 | depth++; 229 | buildClassesTable(t->child[i]); 230 | depth--; 231 | } 232 | t = t->next; 233 | } 234 | } 235 | 236 | void Analyzer::checkStatements(Parser::TreeNode *t) { 237 | while (t != nullptr) { 238 | symbolTable->subroutineTableInsert(t); 239 | checkStatement(t); 240 | for (int i = 0; i < 5; i++) 241 | checkStatements(t->child[i]); 242 | t = t->next; 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /jackc/src/CodeGen.cpp: -------------------------------------------------------------------------------- 1 | #include "CodeGen.h" 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | //#define fout cout 7 | 8 | CodeGen::CodeGen() { 9 | ifLabelCount = 0; 10 | whileLabelCount = 0; 11 | symbolTable = SymbolTable::getInstance(); 12 | } 13 | 14 | void CodeGen::write(Parser::TreeNode *t) { 15 | static int depth = 0; 16 | if (depth > 3) 17 | return; 18 | while (t != nullptr) { 19 | symbolTable->subroutineTableInsert(t); 20 | translate(t); 21 | for (int i = 0; i < 5; i++) { 22 | depth++; 23 | write(t->child[i]); 24 | depth--; 25 | } 26 | t = t->next; 27 | } 28 | } 29 | 30 | void CodeGen::translate(Parser::TreeNode *t) { 31 | switch (t->nodeKind) { 32 | case Parser::CLASS_K: { 33 | fout.close(); 34 | string path = "./api/"; 35 | currentClassName = t->child[0]->token.lexeme; 36 | if (currentClassName == "Sys" || currentClassName == "Memory" || 37 | currentClassName == "Math" || currentClassName == "String" || 38 | currentClassName == "Output" || currentClassName == "Input" || 39 | currentClassName == "Array" || currentClassName == "IO") 40 | fout.open(path + currentClassName + ".vm"); 41 | else 42 | fout.open(currentClassName + ".vm"); 43 | break; 44 | } 45 | case Parser::SUBROUTINE_DEC_K: { 46 | isMethod = false; 47 | currentFunctionName = t->child[2]->token.lexeme; 48 | int nlocals = 0; 49 | for (auto p = t->child[4]->child[0]; p != nullptr; p = p->next) 50 | for (auto q = p->child[1]; q != nullptr; q = q->next) 51 | nlocals++; 52 | writeFunction(t->child[2]->token.lexeme, nlocals); 53 | if (t->child[0]->token.lexeme == "method") { 54 | writePush(ARG, 0); 55 | writePop(POINTER, 0); 56 | isMethod = true; 57 | } 58 | if (t->child[0]->token.lexeme == "constructor") { 59 | int nFields = symbolTable->getFieldNumber(currentClassName); 60 | writePush(CONST, nFields); 61 | writeCall("Memory.alloc", 1); 62 | writePop(POINTER, 0); 63 | } 64 | break; 65 | } 66 | case Parser::ASSIGN_K: { 67 | if (t->child[0]->nodeKind == Parser::VAR_K) { 68 | writeExpression(t->child[1]); 69 | string varName = t->child[0]->token.lexeme; 70 | SymbolTable::Info info = symbolTable->subroutineTableFind(varName); 71 | if (info == SymbolTable::None) 72 | info = symbolTable->classesTableFind(currentClassName, varName); 73 | if (info.kind == SymbolTable::FIELD) 74 | writePop(THIS, info.index); 75 | else if (info.kind == SymbolTable::STATIC) 76 | writePop(STATIC, info.index); 77 | else if (info.kind == SymbolTable::ARG) { 78 | if (isMethod) 79 | writePop(ARG, info.index + 1); 80 | else 81 | writePop(ARG, info.index); 82 | } else if (info.kind == SymbolTable::VAR) 83 | writePop(LOCAL, info.index); 84 | } else if (t->child[0]->nodeKind == Parser::ARRAY_K) { 85 | writeExpression(t->child[0]->child[0]); 86 | string varName = t->child[0]->token.lexeme; 87 | SymbolTable::Info info = symbolTable->subroutineTableFind(varName); 88 | if (info == SymbolTable::None) 89 | info = symbolTable->classesTableFind(currentClassName, varName); 90 | if (info.kind == SymbolTable::FIELD) 91 | writePush(THIS, info.index); 92 | else if (info.kind == SymbolTable::STATIC) 93 | writePush(STATIC, info.index); 94 | else if (info.kind == SymbolTable::ARG) { 95 | if (isMethod) 96 | writePush(ARG, info.index + 1); 97 | else 98 | writePush(ARG, info.index); 99 | } else if (info.kind == SymbolTable::VAR) 100 | writePush(LOCAL, info.index); 101 | writeArithmetic(ADD); 102 | writeExpression(t->child[1]); 103 | writePop(TEMP, 0); 104 | writePop(POINTER, 1); 105 | writePush(TEMP, 0); 106 | writePop(THAT, 0); 107 | } 108 | break; 109 | } 110 | case Parser::CALL_STATEMENT_K: { 111 | translateCall(t); 112 | writePop(TEMP, 0); 113 | break; 114 | } 115 | case Parser::RETURN_STATEMENT_K: { 116 | if (t->child[0] != nullptr) 117 | writeExpression(t->child[0]); 118 | else 119 | writePush(CONST, 0); 120 | writeReturn(); 121 | break; 122 | } 123 | case Parser::WHILE_STATEMENT_K: { 124 | stringstream ss; 125 | ss << whileLabelCount; 126 | whileLabelCount++; 127 | string whileBegin = "WHILE_EXP" + ss.str(); 128 | string whileEnd = "WHILE_END" + ss.str(); 129 | 130 | writeLabel(whileBegin); 131 | writeExpression(t->child[0]); 132 | writeArithmetic(NOT); 133 | writeIf(whileEnd); 134 | for (auto p = t->child[1]; p != nullptr; p = p->next) 135 | translate(p); 136 | writeGoto(whileBegin); 137 | writeLabel(whileEnd); 138 | 139 | break; 140 | } 141 | case Parser::IF_STATEMENT_K: { 142 | stringstream ss; 143 | ss << ifLabelCount; 144 | ifLabelCount++; 145 | string L1 = "IF_TRUE" + ss.str(); 146 | string L2 = "IF_FALSE" + ss.str(); 147 | string L3 = "IF_END" + ss.str(); 148 | 149 | writeExpression(t->child[0]); 150 | writeIf(L1); 151 | writeGoto(L2); 152 | writeLabel(L1); 153 | for (auto p = t->child[1]; p != nullptr; p = p->next) 154 | translate(p); 155 | if (t->child[2] == nullptr) 156 | writeLabel(L2); 157 | else { 158 | writeGoto(L3); 159 | writeLabel(L2); 160 | for (auto p = t->child[2]; p != nullptr; p = p->next) 161 | translate(p); 162 | writeLabel(L3); 163 | } 164 | break; 165 | } 166 | default: 167 | /*fallthrough*/; 168 | } 169 | } 170 | 171 | void CodeGen::translateCall(Parser::TreeNode *t) { 172 | if (t->child[0]->nodeKind == Parser::METHOD_CALL_K) { 173 | if (t->token.lexeme.find('.') == string::npos) // method() 调用 174 | { 175 | writePush(POINTER, 0); 176 | t->token.lexeme = currentClassName + "." + t->token.lexeme; 177 | } else // obj.method()调用 178 | { 179 | string objName = Parser::getCallerName(t->token.lexeme); 180 | SymbolTable::Info info = symbolTable->subroutineTableFind(objName); 181 | if (info == SymbolTable::None) 182 | info = symbolTable->classesTableFind(currentClassName, objName); 183 | if (info.kind == SymbolTable::FIELD) 184 | writePush(THIS, info.index); 185 | else if (info.kind == SymbolTable::VAR) 186 | writePush(LOCAL, info.index); 187 | else if (info.kind == SymbolTable::ARG) 188 | writePush(ARG, info.index); 189 | else if (info.kind == SymbolTable::STATIC) 190 | writePush(STATIC, info.index); 191 | string functionName = Parser::getFunctionName(t->token.lexeme); 192 | t->token.lexeme = info.type + "." + functionName; 193 | } 194 | } 195 | int nArgs = 0; 196 | for (auto p = t->child[0]->next; p != nullptr; p = p->next) { 197 | writeExpression(p); 198 | nArgs++; 199 | } 200 | if (t->child[0]->nodeKind == Parser::METHOD_CALL_K) 201 | nArgs++; 202 | writeCall(t->token.lexeme, nArgs); 203 | } 204 | 205 | // 后序遍历 206 | void CodeGen::writeExpression(Parser::TreeNode *t) { 207 | if (t != nullptr) { 208 | for (int i = 0; i < 5; i++) 209 | writeExpression(t->child[i]); 210 | switch (t->nodeKind) { 211 | case Parser::OPERATION_K: 212 | if (t->token.lexeme == "+") 213 | writeArithmetic(ADD); 214 | else if (t->token.lexeme == "-") 215 | writeArithmetic(SUB); 216 | else if (t->token.lexeme == "*") 217 | writeCall("Math.multiply", 2); 218 | else if (t->token.lexeme == "/") 219 | writeCall("Math.divide", 2); 220 | break; 221 | case Parser::COMPARE_K: { 222 | if (t->token.lexeme == ">") 223 | writeArithmetic(GT); 224 | else if (t->token.lexeme == "<") 225 | writeArithmetic(LT); 226 | else if (t->token.lexeme == "==") 227 | writeArithmetic(EQ); 228 | else if (t->token.lexeme == "<=") { 229 | writeArithmetic(GT); 230 | writeArithmetic(NOT); 231 | } else if (t->token.lexeme == ">=") { 232 | writeArithmetic(LT); 233 | writeArithmetic(NOT); 234 | } else if (t->token.lexeme == "!=") 235 | writeArithmetic(NOT); 236 | break; 237 | } 238 | case Parser::BOOL_EXPRESSION_K: { 239 | if (t->token.lexeme == "&") 240 | writeArithmetic(AND); 241 | else if (t->token.lexeme == "|") 242 | writeArithmetic(OR); 243 | else if (t->token.lexeme == "~") 244 | writeArithmetic(NOT); 245 | break; 246 | } 247 | case Parser::INT_CONST_K: 248 | writePush(CONST, atoi(t->token.lexeme.c_str())); 249 | break; 250 | case Parser::NEGATIVE_K: 251 | writeArithmetic(NEG); 252 | break; 253 | case Parser::CALL_EXPRESSION_K: { 254 | translateCall(t); 255 | break; 256 | } 257 | case Parser::VAR_K: { 258 | string varName = t->token.lexeme; 259 | SymbolTable::Info info = symbolTable->subroutineTableFind(varName); 260 | if (info == SymbolTable::None) 261 | info = symbolTable->classesTableFind(currentClassName, varName); 262 | if (info.kind == SymbolTable::FIELD) 263 | writePush(THIS, info.index); 264 | else if (info.kind == SymbolTable::STATIC) 265 | writePush(STATIC, info.index); 266 | else if (info.kind == SymbolTable::ARG) { 267 | if (isMethod) 268 | writePush(ARG, info.index + 1); 269 | else 270 | writePush(ARG, info.index); 271 | } else if (info.kind == SymbolTable::VAR) 272 | writePush(LOCAL, info.index); 273 | break; 274 | } 275 | case Parser::ARRAY_K: { 276 | string varName = t->token.lexeme; 277 | SymbolTable::Info info = symbolTable->subroutineTableFind(varName); 278 | if (info == SymbolTable::None) 279 | info = symbolTable->classesTableFind(currentClassName, varName); 280 | if (info.kind == SymbolTable::FIELD) 281 | writePush(THIS, info.index); 282 | else if (info.kind == SymbolTable::STATIC) 283 | writePush(STATIC, info.index); 284 | else if (info.kind == SymbolTable::ARG) 285 | writePush(ARG, info.index); 286 | else if (info.kind == SymbolTable::VAR) 287 | writePush(LOCAL, info.index); 288 | writeArithmetic(ADD); 289 | writePop(POINTER, 1); 290 | writePush(THAT, 0); 291 | break; 292 | } 293 | case Parser::BOOL_CONST_K: { 294 | writePush(CONST, 0); 295 | if (t->token.lexeme == "true") 296 | writeArithmetic(NOT); 297 | break; 298 | } 299 | case Parser::THIS_K: { 300 | writePush(POINTER, 0); 301 | break; 302 | } 303 | case Parser::NULL_K: { 304 | writePush(CONST, 0); 305 | break; 306 | } 307 | case Parser::STRING_CONST_K: { 308 | int stringlength = t->token.lexeme.length(); 309 | writePush(CONST, stringlength); 310 | writeCall("String.new", 1); 311 | for (int i = 0; i < stringlength; i++) { 312 | writePush(CONST, t->token.lexeme[i]); 313 | writeCall("String.appendChar", 2); 314 | } 315 | break; 316 | } 317 | default: 318 | /*fallthrough*/; 319 | } 320 | } 321 | } 322 | 323 | void CodeGen::writePush(Segment segment, int index) { 324 | switch (segment) { 325 | case CONST: 326 | fout << "push constant " << index << "\n"; 327 | break; 328 | case ARG: 329 | fout << "push argument " << index << "\n"; 330 | break; 331 | case LOCAL: 332 | fout << "push local " << index << "\n"; 333 | break; 334 | case STATIC: 335 | fout << "push static " << index << "\n"; 336 | break; 337 | case THIS: 338 | fout << "push this " << index << "\n"; 339 | break; 340 | case THAT: 341 | fout << "push that " << index << "\n"; 342 | break; 343 | case POINTER: 344 | fout << "push pointer " << index << "\n"; 345 | break; 346 | case TEMP: 347 | fout << "push temp " << index << "\n"; 348 | break; 349 | } 350 | } 351 | 352 | void CodeGen::writePop(Segment segment, int index) { 353 | switch (segment) { 354 | case CONST: 355 | fout << "pop constant " << index << "\n"; 356 | break; 357 | case ARG: 358 | fout << "pop argument " << index << "\n"; 359 | break; 360 | case LOCAL: 361 | fout << "pop local " << index << "\n"; 362 | break; 363 | case STATIC: 364 | fout << "pop static " << index << "\n"; 365 | break; 366 | case THIS: 367 | fout << "pop this " << index << "\n"; 368 | break; 369 | case THAT: 370 | fout << "pop that " << index << "\n"; 371 | break; 372 | case POINTER: 373 | fout << "pop pointer " << index << "\n"; 374 | break; 375 | case TEMP: 376 | fout << "pop temp " << index << "\n"; 377 | break; 378 | } 379 | } 380 | 381 | void CodeGen::writeArithmetic(Command command) { 382 | switch (command) { 383 | case ADD: 384 | fout << "add\n"; 385 | break; 386 | case SUB: 387 | fout << "sub\n"; 388 | break; 389 | case NEG: 390 | fout << "neg\n"; 391 | break; 392 | case EQ: 393 | fout << "eq\n"; 394 | break; 395 | case GT: 396 | fout << "gt\n"; 397 | break; 398 | case LT: 399 | fout << "lt\n"; 400 | break; 401 | case AND: 402 | fout << "and\n"; 403 | break; 404 | case OR: 405 | fout << "or\n"; 406 | break; 407 | case NOT: 408 | fout << "not\n"; 409 | break; 410 | } 411 | } 412 | 413 | void CodeGen::writeLabel(const string &label) { fout << "label " << label << "\n"; } 414 | 415 | void CodeGen::writeGoto(const string &label) { fout << "goto " << label << "\n"; } 416 | 417 | void CodeGen::writeIf(const string &label) { fout << "if-goto " << label << "\n"; } 418 | 419 | void CodeGen::writeCall(const string &name, int nArgs) { 420 | fout << "call " << name << " " << nArgs << "\n"; 421 | } 422 | 423 | void CodeGen::writeFunction(const string &name, int nArgs) { 424 | fout << "function " << name << " " << nArgs << "\n"; 425 | } 426 | 427 | void CodeGen::writeReturn() { fout << "return\n"; } 428 | -------------------------------------------------------------------------------- /jackc/src/Error.cpp: -------------------------------------------------------------------------------- 1 | #include "Error.h" 2 | #include 3 | 4 | using namespace std; 5 | 6 | int errorNum; 7 | 8 | bool hasError() { return errorNum; } 9 | 10 | void syntaxError(string currentParserFilename, string expected, 11 | Scanner::Token token) { 12 | errorNum++; 13 | cerr << "Error in class " << currentParserFilename << " in line " << token.row 14 | << ": expect a " << expected << ", but got a " << token.lexeme << "\n"; 15 | } 16 | 17 | // 类名和函数名不一致 18 | void error1(string currentParserFilename) { 19 | errorNum++; 20 | cerr << "Error in file " << currentParserFilename << ".jack: " 21 | << "classname should be same as filename" << endl; 22 | } 23 | 24 | // 变量重定义 25 | void error2(string currentClass, int row, string type, string name) { 26 | errorNum++; 27 | cerr << "Error in class " << currentClass << " in line " << row 28 | << ": redeclaration of '" << type << " " << name << "'" << endl; 29 | } 30 | 31 | // 函数重定义 32 | void error3(string currentClass, int row, string type, string name) { 33 | errorNum++; 34 | cerr << "Error in class " << currentClass << " in line " << row 35 | << ": redeclaration of '" << type << " " << name << "()" << endl; 36 | } 37 | 38 | // 类型未定义 39 | void error4(string currentClassName, int row, string type) { 40 | errorNum++; 41 | cerr << "Error in class " << currentClassName << " in line " << row << ": '" 42 | << type << "' not declaraed" << endl; 43 | } 44 | 45 | // 变量未定义 46 | void error5(string currentClassName, int row, string varName) { 47 | errorNum++; 48 | cerr << "Error in class " << currentClassName << " in line " << row << ": '" 49 | << varName << "' does not declared in this scope" << endl; 50 | } 51 | 52 | void error6(string currentClassName, int row, string type) { 53 | errorNum++; 54 | cerr << "Error in class " << currentClassName << " in line " << row << ": " 55 | << type << " does not an Array type" << endl; 56 | } 57 | 58 | void error7(string currentClassName, string callerName, int row, 59 | string functionName) { 60 | errorNum++; 61 | cerr << "Error in class " << currentClassName << " in line " << row 62 | << ": class " << callerName << " haven't a member function '" 63 | << functionName << "()'" << endl; 64 | } 65 | 66 | void error8(string currentClassName, int row, string functionName) { 67 | errorNum++; 68 | cerr << "Error in class " << currentClassName << " in line " << row 69 | << ": subroutine " << functionName 70 | << " called as a method from within a function" << endl; 71 | } 72 | 73 | void error9(string currentClassName, string callerName, int row, 74 | string functionName) { 75 | errorNum++; 76 | cerr << "Error in class " << currentClassName << " in line " << row << ": '" 77 | << functionName << "' is not a function in class " << callerName << endl; 78 | } 79 | 80 | // 函数类型错误 81 | void error10(string currentClassName, string callerName, int row, 82 | string functionName) { 83 | errorNum++; 84 | cerr << "Error in class " << currentClassName << " in line " << row << ": '" 85 | << functionName << "' is not a method in class " << callerName << endl; 86 | } 87 | 88 | // 返回值错误 89 | void error11(string currentClassName, string type, int row) { 90 | errorNum++; 91 | cerr << "Error in class " << currentClassName << " in line " << row 92 | << ": return-statement with no value, in function returning '" << type 93 | << "'" << endl; 94 | } 95 | 96 | // 返回值错误 97 | void error12(string currentClassName, int row) { 98 | errorNum++; 99 | cerr << "Error in class " << currentClassName << " in line " << row 100 | << ": return-statement with a value, in function returning void" << endl; 101 | } 102 | 103 | // 返回值错误 104 | void error13(string currentClassName, int row) { 105 | errorNum++; 106 | cerr << "Error in class " << currentClassName << " in line " << row 107 | << ": The return type of a constructor must be of the class type" 108 | << endl; 109 | } 110 | 111 | // 参数太少 112 | void error14(string currentClassName, string functionName, int row) { 113 | errorNum++; 114 | cerr << "Error in class " << currentClassName << " in line " << row 115 | << ": too few arguments to function " << functionName << "()" << endl; 116 | } 117 | 118 | // 参数太多 119 | void error15(string currentClassName, string functionName, int row) { 120 | errorNum++; 121 | cerr << "Error in class " << currentClassName << " in line " << row 122 | << ": too many arguments to function " << functionName << endl; 123 | } 124 | 125 | void error16() { 126 | errorNum++; 127 | cerr << "Error: Main class not exsist" << endl; 128 | } 129 | 130 | void error17() { 131 | errorNum++; 132 | cerr << "Error in class Main: main function does not exsit!" << endl; 133 | } 134 | 135 | void error18() { 136 | errorNum++; 137 | cerr << "Error in class Main: the kind of subroutine main must be a function" 138 | << endl; 139 | } 140 | 141 | void error19() { 142 | errorNum++; 143 | cerr << "Error in class Main: the type of subroutine main must be a void" 144 | << endl; 145 | } 146 | 147 | void error20() { 148 | errorNum++; 149 | cerr << "Error in class Main: the argument size of subroutine main must be " 150 | "null" 151 | << endl; 152 | } 153 | -------------------------------------------------------------------------------- /jackc/src/Parser.cpp: -------------------------------------------------------------------------------- 1 | #include "Parser.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | Parser::Parser(vector &filenames) { 10 | this->filenames = filenames; 11 | syntaxTree = nullptr; 12 | } 13 | 14 | Scanner::Token Parser::getToken() { 15 | if (tokenBuffer2.size() == 0) { 16 | auto token = scanner.nextToken(); 17 | tokenBuffer1.push_back(token); 18 | if (tokenBuffer1.size() > 10) 19 | tokenBuffer1.pop_front(); 20 | } else { 21 | auto token = tokenBuffer2.front(); 22 | tokenBuffer1.push_back(token); 23 | tokenBuffer2.pop_front(); 24 | } 25 | return tokenBuffer1.back(); 26 | } 27 | 28 | Scanner::Token Parser::ungetToken() { 29 | assert(tokenBuffer1.size() > 0); 30 | auto token = tokenBuffer1.back(); 31 | tokenBuffer2.push_front(token); 32 | tokenBuffer1.pop_back(); 33 | return tokenBuffer1.back(); 34 | } 35 | 36 | string Parser::getFullName(string name) { 37 | string fullname = currentParserFilename + "." + name; 38 | return fullname; 39 | } 40 | 41 | string Parser::getCallerName(const string &fullName) { 42 | auto iter = fullName.cbegin(); 43 | while (iter != fullName.cend()) { 44 | if (*iter == '.') 45 | break; 46 | ++iter; 47 | } 48 | return string(fullName.cbegin(), iter); 49 | } 50 | 51 | string Parser::getFunctionName(const string &fullName) { 52 | auto iter = fullName.cbegin(); 53 | while (iter != fullName.cend()) { 54 | if (*iter == '.') 55 | break; 56 | ++iter; 57 | } 58 | return string(++iter, fullName.cend()); 59 | } 60 | 61 | void Parser::parse_program() { syntaxTree = parseClassList(); } 62 | 63 | Parser::TreeNode *Parser::parseClassList() { 64 | TreeNode *t = nullptr; 65 | TreeNode *p = nullptr; 66 | for (auto filenameIter = filenames.cbegin(); filenameIter != filenames.cend(); 67 | ++filenameIter) { 68 | scanner.openFile(*filenameIter); 69 | auto classNameIter = filenameIter->rbegin(); 70 | int begin = 0; 71 | while (classNameIter != filenameIter->rend()) { 72 | if (*classNameIter == '/') 73 | break; 74 | begin++; 75 | ++classNameIter; 76 | } 77 | currentParserFilename = 78 | filenameIter->substr(filenameIter->size() - begin, begin - 5); 79 | scanner.resetRow(); 80 | TreeNode *q = parseClass(); 81 | if (getToken().kind != Scanner::ENDOFFILE) 82 | cerr << "Syntax Error in class " << currentParserFilename 83 | << ": unexpected token before EOF " << endl; 84 | if (q != nullptr) { 85 | if (t == nullptr) { 86 | t = p = q; 87 | } else { 88 | p->next = q; 89 | p = q; 90 | } 91 | } 92 | scanner.closeFile(); 93 | } 94 | return t; 95 | } 96 | 97 | Parser::TreeNode *Parser::parseClass() { 98 | TreeNode *t = new TreeNode; 99 | Scanner::Token token = getToken(); 100 | t->nodeKind = CLASS_K; 101 | token = getToken(); 102 | if (token.kind != Scanner::ID) { 103 | syntaxError(currentParserFilename, "identifier", token); 104 | return t; 105 | } 106 | t->child[0] = new TreeNode; 107 | t->child[0]->token = token; 108 | if (currentParserFilename != token.lexeme) { 109 | error1(currentParserFilename); 110 | return t; 111 | } 112 | token = getToken(); 113 | if (token.lexeme != "{") { 114 | syntaxError(currentParserFilename, "{", token); 115 | return t; 116 | } 117 | t->child[1] = parseClassVarDecList(); 118 | t->child[2] = parseSubroutineDecList(); 119 | token = getToken(); 120 | if (token.lexeme != "}") { 121 | syntaxError(currentParserFilename, "}", token); 122 | return t; 123 | } 124 | return t; 125 | } 126 | 127 | Parser::TreeNode *Parser::parseClassVarDecList() { 128 | TreeNode *t = nullptr; 129 | TreeNode *p = t; 130 | auto token = getToken(); 131 | while (token.lexeme == "static" || token.lexeme == "field") { 132 | ungetToken(); 133 | TreeNode *q = parseClassVarDec(); 134 | if (q != nullptr) { 135 | if (t == nullptr) 136 | t = p = q; 137 | else { 138 | p->next = q; 139 | p = q; 140 | } 141 | } 142 | token = getToken(); 143 | } 144 | ungetToken(); 145 | return t; 146 | } 147 | 148 | Parser::TreeNode *Parser::parseClassVarDec() { 149 | TreeNode *t = new TreeNode; 150 | t->nodeKind = CLASS_VAR_DEC_K; 151 | Scanner::Token token = getToken(); 152 | if (token.lexeme != "static" && token.lexeme != "field") { 153 | syntaxError(currentParserFilename, "static or filed", token); 154 | return t; 155 | } 156 | t->child[0] = new TreeNode; 157 | t->child[0]->token.lexeme = token.lexeme; 158 | t->child[1] = parseType(); 159 | t->child[2] = parseVarNameList(); 160 | token = getToken(); 161 | if (token.lexeme != ";") { 162 | syntaxError(currentParserFilename, ";", token); 163 | return t; 164 | } 165 | return t; 166 | } 167 | 168 | Parser::TreeNode *Parser::parseVarNameList() { 169 | TreeNode *t = new TreeNode; 170 | Scanner::Token token = getToken(); 171 | if (token.kind != Scanner::ID) { 172 | syntaxError(currentParserFilename, "identifier", token); 173 | return t; 174 | } 175 | t->token = token; 176 | TreeNode *p = t; 177 | token = getToken(); 178 | while (token.lexeme == ",") { 179 | token = getToken(); 180 | if (token.kind != Scanner::ID) { 181 | syntaxError(currentParserFilename, "identifier", token); 182 | return t; 183 | } 184 | TreeNode *q = new TreeNode; 185 | q->token = token; 186 | p->next = q; 187 | p = q; 188 | token = getToken(); 189 | } 190 | ungetToken(); 191 | return t; 192 | } 193 | 194 | Parser::TreeNode *Parser::parseType() { 195 | TreeNode *t = nullptr; 196 | Scanner::Token token = getToken(); 197 | if (token.kind == Scanner::ID) { 198 | t = new TreeNode; 199 | t->nodeKind = CLASS_TYPE_K; 200 | t->token.lexeme = token.lexeme; 201 | } else if (token.lexeme == "int" || token.lexeme == "char" || 202 | token.lexeme == "boolean" || token.lexeme == "void") { 203 | t = new TreeNode; 204 | t->nodeKind = BASIC_TYPE_K; 205 | t->token.lexeme = token.lexeme; 206 | } else { 207 | syntaxError(currentParserFilename, "basic type or class type", token); 208 | return t; 209 | } 210 | return t; 211 | } 212 | 213 | Parser::TreeNode *Parser::parseSubroutineDecList() { 214 | TreeNode *t = nullptr; 215 | TreeNode *p = t; 216 | auto token = getToken(); 217 | while (token.lexeme == "constructor" || token.lexeme == "function" || 218 | token.lexeme == "method") { 219 | ungetToken(); 220 | TreeNode *q = parseSubroutinDec(); 221 | if (q != nullptr) { 222 | if (t == nullptr) 223 | t = p = q; 224 | else { 225 | p->next = q; 226 | p = q; 227 | } 228 | } 229 | token = getToken(); 230 | } 231 | ungetToken(); 232 | return t; 233 | } 234 | 235 | Parser::TreeNode *Parser::parseSubroutinDec() { 236 | TreeNode *t = new TreeNode; 237 | t->nodeKind = SUBROUTINE_DEC_K; 238 | Scanner::Token token = getToken(); 239 | if (token.lexeme == "constructor" || token.lexeme == "function" || 240 | token.lexeme == "method") { 241 | t->child[0] = new TreeNode; 242 | t->child[0]->token = token; 243 | } else { 244 | syntaxError(currentParserFilename, "constructor or function or method", 245 | token); 246 | return t; 247 | } 248 | t->child[1] = parseType(); 249 | token = getToken(); 250 | if (token.kind == Scanner::ID) { 251 | t->child[2] = new TreeNode; 252 | t->child[2]->token = token; 253 | t->child[2]->token.lexeme = getFullName(token.lexeme); 254 | } else { 255 | syntaxError(currentParserFilename, "identifile", token); 256 | return t; 257 | } 258 | 259 | token = getToken(); 260 | if (token.lexeme != "(") { 261 | syntaxError(currentParserFilename, "(", token); 262 | return t; 263 | } 264 | t->child[3] = parseParams(); 265 | token = getToken(); 266 | if (token.lexeme != ")") { 267 | syntaxError(currentParserFilename, ")", token); 268 | return t; 269 | } 270 | t->child[4] = parseSubroutineBody(); 271 | return t; 272 | } 273 | 274 | Parser::TreeNode *Parser::parseParams() { 275 | TreeNode *t = nullptr; 276 | Scanner::Token token = getToken(); 277 | if (token.lexeme != ")") { 278 | ungetToken(); 279 | t = parseParamList(); 280 | } else 281 | ungetToken(); 282 | return t; 283 | } 284 | 285 | Parser::TreeNode *Parser::parseParamList() { 286 | TreeNode *t = parseParam(); 287 | TreeNode *p = t; 288 | Scanner::Token token = getToken(); 289 | while (token.lexeme == ",") { 290 | TreeNode *q = parseParam(); 291 | p->next = q; 292 | p = q; 293 | token = getToken(); 294 | } 295 | ungetToken(); 296 | return t; 297 | } 298 | 299 | Parser::TreeNode *Parser::parseParam() { 300 | TreeNode *t = new TreeNode; 301 | t->nodeKind = PARAM_K; 302 | t->child[0] = parseType(); 303 | Scanner::Token token = getToken(); 304 | if (token.kind == Scanner::ID) { 305 | t->child[1] = new TreeNode; 306 | t->child[1]->token = token; 307 | } else { 308 | syntaxError(currentParserFilename, "identifier", token); 309 | return t; 310 | } 311 | return t; 312 | } 313 | 314 | Parser::TreeNode *Parser::parseSubroutineBody() { 315 | haveReturnStatement = false; 316 | 317 | TreeNode *t = new TreeNode; 318 | t->nodeKind = SUBROUTINE_BODY_K; 319 | Scanner::Token token = getToken(); 320 | if (token.lexeme != "{") { 321 | syntaxError(currentParserFilename, "{", token); 322 | return t; 323 | } 324 | t->child[0] = parseVarDecList(); 325 | t->child[1] = parseStatements(); 326 | 327 | token = getToken(); 328 | if (token.lexeme != "}") { 329 | syntaxError(currentParserFilename, "}", token); 330 | return t; 331 | } 332 | if (haveReturnStatement == false) { 333 | syntaxError(currentParserFilename, "return statement", token); 334 | return t; 335 | } 336 | return t; 337 | } 338 | 339 | Parser::TreeNode *Parser::parseVarDecList() { 340 | TreeNode *t = nullptr; 341 | TreeNode *p = t; 342 | 343 | Loop: 344 | Scanner::Token token = getToken(); 345 | if (token.lexeme == "int" || token.lexeme == "char" || 346 | token.lexeme == "boolean" || token.lexeme == "string") { 347 | ungetToken(); 348 | TreeNode *q = parseVarDec(); 349 | if (t == nullptr) 350 | t = p = q; 351 | else { 352 | p->next = q; 353 | p = q; 354 | } 355 | goto Loop; 356 | } else if (token.kind == Scanner::ID) // ��������� 357 | { 358 | token = getToken(); 359 | if (token.kind == Scanner::ID) { 360 | ungetToken(); 361 | ungetToken(); 362 | TreeNode *q = parseVarDec(); 363 | if (t == nullptr) 364 | t = p = q; 365 | else { 366 | p->next = q; 367 | p = q; 368 | } 369 | goto Loop; 370 | } 371 | ungetToken(); 372 | } 373 | ungetToken(); 374 | return t; 375 | } 376 | 377 | Parser::TreeNode *Parser::parseVarDec() { 378 | TreeNode *t = new TreeNode; 379 | t->nodeKind = VAR_DEC_K; 380 | Scanner::Token token; 381 | t->child[0] = parseType(); 382 | t->child[1] = parseVarNameList(); 383 | token = getToken(); 384 | if (token.lexeme != ";") { 385 | syntaxError(currentParserFilename, ";", token); 386 | return t; 387 | } 388 | return t; 389 | } 390 | 391 | Parser::TreeNode *Parser::parseStatements() { 392 | TreeNode *t = nullptr; 393 | TreeNode *p = t; 394 | Scanner::Token token = getToken(); 395 | while (token.lexeme == "if" || token.lexeme == "while" || 396 | token.lexeme == "return" || token.kind == Scanner::ID) { 397 | if (token.lexeme == "return") 398 | haveReturnStatement = true; 399 | if (token.kind == Scanner::ID) { 400 | token = getToken(); 401 | if (token.lexeme == "=" || token.lexeme == "[" || token.lexeme == "(" || 402 | token.lexeme == ".") { 403 | ungetToken(); 404 | ungetToken(); 405 | TreeNode *q = parseStatement(); 406 | if (t == nullptr) 407 | t = p = q; 408 | else { 409 | p->next = q; 410 | p = q; 411 | } 412 | } else { 413 | ungetToken(); 414 | break; 415 | } 416 | } else { 417 | ungetToken(); 418 | TreeNode *q = parseStatement(); 419 | if (t == nullptr) 420 | t = p = q; 421 | else { 422 | p->next = q; 423 | p = q; 424 | } 425 | } 426 | token = getToken(); 427 | } 428 | ungetToken(); 429 | 430 | return t; 431 | } 432 | 433 | Parser::TreeNode *Parser::parseStatement() { 434 | TreeNode *t = nullptr; 435 | Scanner::Token token = getToken(); 436 | if (token.lexeme == "if") { 437 | ungetToken(); 438 | t = parseIfStatement(); 439 | } else if (token.lexeme == "while") { 440 | ungetToken(); 441 | t = parseWhileStatement(); 442 | } else if (token.lexeme == "return") { 443 | ungetToken(); 444 | t = parseReturnStatement(); 445 | } else if (token.kind == Scanner::ID) { 446 | token = getToken(); 447 | if (token.lexeme == "=" || token.lexeme == "[") { 448 | ungetToken(); 449 | ungetToken(); 450 | t = parseAssignStatement(); 451 | 452 | } else if (token.lexeme == "(" || token.lexeme == ".") { 453 | ungetToken(); 454 | ungetToken(); 455 | t = parseCallStatement(); 456 | token = getToken(); 457 | if (token.lexeme != ";") { 458 | ungetToken(); 459 | syntaxError(currentParserFilename, ";", token); 460 | return t; 461 | } 462 | } else { 463 | ungetToken(); 464 | ungetToken(); 465 | syntaxError(currentParserFilename, "'=' or '[' or '(' or '.'", token); 466 | return t; 467 | } 468 | } else { 469 | ungetToken(); 470 | syntaxError(currentParserFilename, "identifier", token); 471 | return t; 472 | } 473 | return t; 474 | } 475 | 476 | Parser::TreeNode *Parser::parseAssignStatement() { 477 | TreeNode *t = new TreeNode; 478 | t->nodeKind = ASSIGN_K; 479 | t->child[0] = parseLeftValue(); 480 | Scanner::Token token = getToken(); 481 | t->child[1] = parseExpression(); 482 | token = getToken(); 483 | if (token.lexeme != ";") { 484 | syntaxError(currentParserFilename, ";", token); 485 | return t; 486 | } 487 | return t; 488 | } 489 | 490 | Parser::TreeNode *Parser::parseLeftValue() { 491 | TreeNode *t = new TreeNode; 492 | t->nodeKind = VAR_K; 493 | Scanner::Token token = getToken(); 494 | t->token = token; 495 | token = getToken(); 496 | if (token.lexeme == "[") { 497 | t->nodeKind = ARRAY_K; 498 | t->child[0] = parseExpression(); 499 | token = getToken(); 500 | if (token.lexeme != "]") { 501 | syntaxError(currentParserFilename, "]", token); 502 | return t; 503 | } 504 | t->nodeKind = ARRAY_K; 505 | } else if (token.lexeme == "=") { 506 | ungetToken(); 507 | } 508 | return t; 509 | } 510 | 511 | Parser::TreeNode *Parser::parseIfStatement() { 512 | TreeNode *t = new TreeNode; 513 | t->nodeKind = IF_STATEMENT_K; 514 | Scanner::Token token = getToken(); 515 | token = getToken(); 516 | if (token.lexeme != "(") { 517 | syntaxError(currentParserFilename, "(", token); 518 | return t; 519 | } 520 | t->child[0] = parseExpression(); 521 | token = getToken(); 522 | if (token.lexeme != ")") { 523 | syntaxError(currentParserFilename, ")", token); 524 | return t; 525 | } 526 | token = getToken(); 527 | if (token.lexeme != "{") { 528 | syntaxError(currentParserFilename, "{", token); 529 | return t; 530 | } 531 | t->child[1] = parseStatements(); 532 | token = getToken(); 533 | if (token.lexeme != "}") { 534 | syntaxError(currentParserFilename, "}", token); 535 | return t; 536 | } 537 | token = getToken(); 538 | if (token.lexeme == "else") { 539 | token = getToken(); 540 | if (token.lexeme != "{") { 541 | syntaxError(currentParserFilename, "{", token); 542 | return t; 543 | } 544 | t->child[2] = parseStatements(); 545 | token = getToken(); 546 | if (token.lexeme != "}") { 547 | syntaxError(currentParserFilename, "}", token); 548 | return t; 549 | } 550 | } else 551 | ungetToken(); 552 | return t; 553 | } 554 | 555 | Parser::TreeNode *Parser::parseWhileStatement() { 556 | TreeNode *t = new TreeNode; 557 | t->nodeKind = WHILE_STATEMENT_K; 558 | Scanner::Token token = getToken(); 559 | token = getToken(); 560 | if (token.lexeme != "(") { 561 | syntaxError(currentParserFilename, "(", token); 562 | return t; 563 | } 564 | t->child[0] = parseExpression(); 565 | token = getToken(); 566 | if (token.lexeme != ")") { 567 | syntaxError(currentParserFilename, ")", token); 568 | return t; 569 | } 570 | token = getToken(); 571 | if (token.lexeme != "{") { 572 | syntaxError(currentParserFilename, "{", token); 573 | return t; 574 | } 575 | t->child[1] = parseStatements(); 576 | token = getToken(); 577 | if (token.lexeme != "}") { 578 | syntaxError(currentParserFilename, "}", token); 579 | return t; 580 | } 581 | return t; 582 | } 583 | 584 | Parser::TreeNode *Parser::parseReturnStatement() { 585 | TreeNode *t = new TreeNode; 586 | t->nodeKind = RETURN_STATEMENT_K; 587 | Scanner::Token token = getToken(); 588 | t->token = token; 589 | token = getToken(); 590 | if (token.lexeme == ";") 591 | return t; 592 | else { 593 | ungetToken(); 594 | t->child[0] = parseExpression(); 595 | token = getToken(); 596 | if (token.lexeme != ";") { 597 | syntaxError(currentParserFilename, ";", token); 598 | return t; 599 | } 600 | } 601 | return t; 602 | } 603 | 604 | Parser::TreeNode *Parser::parseCallStatement() { 605 | TreeNode *t = new TreeNode; 606 | t->nodeKind = CALL_STATEMENT_K; 607 | Scanner::Token token = getToken(); 608 | Scanner::Token save = token; 609 | t->child[0] = new TreeNode; 610 | token = getToken(); 611 | if (token.lexeme == "(") { 612 | t->child[0]->next = parseExpressions(); 613 | token = getToken(); 614 | if (token.lexeme != ")") { 615 | syntaxError(currentParserFilename, ")", token); 616 | return t; 617 | } 618 | } else if (token.lexeme == ".") { 619 | token = getToken(); 620 | if (token.kind != Scanner::ID) { 621 | syntaxError(currentParserFilename, "identifier", token); 622 | return t; 623 | } 624 | save.lexeme = save.lexeme + "." + token.lexeme; 625 | token = getToken(); 626 | if (token.lexeme != "(") { 627 | syntaxError(currentParserFilename, "(", token); 628 | return t; 629 | } 630 | t->child[0]->next = parseExpressions(); 631 | token = getToken(); 632 | if (token.lexeme != ")") { 633 | syntaxError(currentParserFilename, ")", token); 634 | return t; 635 | } 636 | } 637 | t->token = save; 638 | return t; 639 | } 640 | 641 | Parser::TreeNode *Parser::parseExpressions() { 642 | TreeNode *t = nullptr; 643 | Scanner::Token token = getToken(); 644 | if (token.lexeme == ")") { 645 | ungetToken(); 646 | return t; 647 | } else { 648 | ungetToken(); 649 | t = parseExpressionList(); 650 | return t; 651 | } 652 | } 653 | 654 | Parser::TreeNode *Parser::parseExpressionList() { 655 | TreeNode *t = parseExpression(); 656 | TreeNode *p = t; 657 | Scanner::Token token = getToken(); 658 | while (token.lexeme == ",") { 659 | TreeNode *q = parseExpression(); 660 | p->next = q; 661 | p = q; 662 | token = getToken(); 663 | } 664 | ungetToken(); 665 | return t; 666 | } 667 | 668 | Parser::TreeNode *Parser::parseExpression() { 669 | TreeNode *t = parseBoolExpression(); 670 | Scanner::Token token = getToken(); 671 | while (token.lexeme == "&" || token.lexeme == "|") { 672 | TreeNode *p = new TreeNode(); 673 | p->nodeKind = BOOL_EXPRESSION_K; 674 | p->token = token; 675 | p->child[0] = t; 676 | t = p; 677 | t->child[1] = parseBoolExpression(); 678 | token = getToken(); 679 | } 680 | ungetToken(); 681 | return t; 682 | } 683 | 684 | Parser::TreeNode *Parser::parseBoolExpression() { 685 | TreeNode *t = parseAdditiveExpression(); 686 | Scanner::Token token = getToken(); 687 | if (token.lexeme == "<=" || token.lexeme == ">=" || token.lexeme == "==" || 688 | token.lexeme == "<" || token.lexeme == ">" || token.lexeme == "!=") { 689 | TreeNode *p = new TreeNode; 690 | p->nodeKind = COMPARE_K; 691 | p->token = token; 692 | p->child[0] = t; 693 | t = p; 694 | t->child[1] = parseAdditiveExpression(); 695 | } else 696 | ungetToken(); 697 | return t; 698 | } 699 | 700 | Parser::TreeNode *Parser::parseAdditiveExpression() { 701 | TreeNode *t = parseTerm(); 702 | Scanner::Token token = getToken(); 703 | while (token.lexeme == "+" || token.lexeme == "-") { 704 | TreeNode *p = new TreeNode; 705 | p->nodeKind = OPERATION_K; 706 | p->token = token; 707 | p->child[0] = t; 708 | t = p; 709 | p->child[1] = parseTerm(); 710 | token = getToken(); 711 | } 712 | ungetToken(); 713 | return t; 714 | } 715 | 716 | Parser::TreeNode *Parser::parseTerm() { 717 | TreeNode *t = parseFactor(); 718 | Scanner::Token token = getToken(); 719 | while (token.lexeme == "*" || token.lexeme == "/") { 720 | TreeNode *p = new TreeNode; 721 | p->nodeKind = OPERATION_K; 722 | p->token = token; 723 | p->child[0] = t; 724 | t = p; 725 | p->child[1] = parseFactor(); 726 | token = getToken(); 727 | } 728 | ungetToken(); 729 | return t; 730 | } 731 | 732 | Parser::TreeNode *Parser::parseFactor() { 733 | TreeNode *t = nullptr; 734 | Scanner::Token token = getToken(); 735 | if (token.lexeme == "-") { 736 | t = new TreeNode; 737 | t->nodeKind = NEGATIVE_K; 738 | t->token = token; 739 | t->child[0] = parsePositiveFactor(); 740 | } else { 741 | ungetToken(); 742 | t = parsePositiveFactor(); 743 | } 744 | return t; 745 | } 746 | 747 | Parser::TreeNode *Parser::parsePositiveFactor() { 748 | TreeNode *t = nullptr; 749 | Scanner::Token token = getToken(); 750 | if (token.lexeme == "~") { 751 | t = new TreeNode; 752 | t->token = token; 753 | t->nodeKind = BOOL_EXPRESSION_K; 754 | t->child[0] = parseNotFactor(); 755 | } else { 756 | ungetToken(); 757 | t = parseNotFactor(); 758 | } 759 | return t; 760 | } 761 | 762 | Parser::TreeNode *Parser::parseNotFactor() { 763 | TreeNode *t = nullptr; 764 | Scanner::Token token = getToken(); 765 | if (token.lexeme == "(") { 766 | t = parseExpression(); 767 | token = getToken(); 768 | if (token.lexeme != ")") { 769 | syntaxError(currentParserFilename, ")", token); 770 | return t; 771 | } 772 | } else if (token.kind == Scanner::INT) { 773 | t = new TreeNode; 774 | t->token = token; 775 | t->nodeKind = INT_CONST_K; 776 | } else if (token.kind == Scanner::CHAR) { 777 | t = new TreeNode; 778 | t->token = token; 779 | t->nodeKind = CHAR_CONST_K; 780 | } else if (token.kind == Scanner::STRING) { 781 | t = new TreeNode; 782 | t->token = token; 783 | t->nodeKind = STRING_CONST_K; 784 | } else if (token.lexeme == "true" || token.lexeme == "false") { 785 | t = new TreeNode; 786 | t->token = token; 787 | t->nodeKind = BOOL_CONST_K; 788 | } else if (token.lexeme == "this") { 789 | t = new TreeNode; 790 | t->token = token; 791 | t->nodeKind = THIS_K; 792 | } else if (token.lexeme == "null") { 793 | t = new TreeNode; 794 | t->token = token; 795 | t->nodeKind = NULL_K; 796 | } else if (token.kind == Scanner::ID) { 797 | t = new TreeNode; 798 | t->token = token; 799 | t->nodeKind = VAR_K; 800 | token = getToken(); 801 | if (token.lexeme == "[") { 802 | TreeNode *p = parseExpression(); 803 | t->child[0] = p; 804 | token = getToken(); 805 | if (token.lexeme != "]") { 806 | syntaxError(currentParserFilename, "]", token); 807 | return t; 808 | } 809 | t->nodeKind = ARRAY_K; 810 | } else if (token.lexeme == "(" || token.lexeme == ".") { 811 | ungetToken(); 812 | ungetToken(); 813 | t = parseCallExpression(); 814 | } else 815 | ungetToken(); 816 | } 817 | return t; 818 | } 819 | 820 | Parser::TreeNode *Parser::parseCallExpression() { 821 | TreeNode *t = new TreeNode; 822 | t->nodeKind = CALL_EXPRESSION_K; 823 | Scanner::Token token = getToken(); 824 | Scanner::Token save = token; 825 | t->child[0] = new TreeNode; 826 | token = getToken(); 827 | if (token.lexeme == "(") { 828 | t->child[0]->next = parseExpressions(); 829 | token = getToken(); 830 | if (token.lexeme != ")") { 831 | syntaxError(currentParserFilename, ")", token); 832 | return t; 833 | } 834 | } else if (token.lexeme == ".") { 835 | token = getToken(); 836 | if (token.kind != Scanner::ID) { 837 | syntaxError(currentParserFilename, "identifier", token); 838 | return t; 839 | } 840 | save.lexeme = save.lexeme + "." + token.lexeme; 841 | token = getToken(); 842 | if (token.lexeme != "(") { 843 | syntaxError(currentParserFilename, "(", token); 844 | return t; 845 | } 846 | t->child[0]->next = parseExpressions(); 847 | token = getToken(); 848 | if (token.lexeme != ")") { 849 | syntaxError(currentParserFilename, ")", token); 850 | return t; 851 | } 852 | } 853 | t->token = save; 854 | return t; 855 | } 856 | 857 | void Parser::print() { printSyntaxTree(syntaxTree); } 858 | 859 | void Parser::printSyntaxTree(TreeNode *tree) { 860 | static int indentno = 0; 861 | indentno += 2; 862 | while (tree != nullptr) { 863 | for (int i = 0; i < indentno; i++) 864 | cout << " "; 865 | switch (tree->nodeKind) { 866 | case CLASS_K: 867 | cout << "class" << endl; 868 | break; 869 | case CLASS_VAR_DEC_K: 870 | cout << "class_var_dec" << endl; 871 | break; 872 | case SUBROUTINE_DEC_K: 873 | cout << "subroutine_dec" << endl; 874 | break; 875 | case BASIC_TYPE_K: 876 | cout << "basic_type " << tree->token.lexeme << endl; 877 | break; 878 | case CLASS_TYPE_K: 879 | cout << "class_type " << tree->token.lexeme << endl; 880 | break; 881 | case PARAM_K: 882 | cout << "param" << endl; 883 | break; 884 | case VAR_DEC_K: 885 | cout << "var_dec" << endl; 886 | break; 887 | case ARRAY_K: 888 | cout << "array" << endl; 889 | break; 890 | case VAR_K: 891 | cout << "var" << endl; 892 | break; 893 | case IF_STATEMENT_K: 894 | cout << "if_statement" << endl; 895 | break; 896 | case WHILE_STATEMENT_K: 897 | cout << "while_statement" << endl; 898 | break; 899 | case RETURN_STATEMENT_K: 900 | cout << "return_statement" << endl; 901 | break; 902 | case CALL_STATEMENT_K: 903 | cout << "call_statement" << endl; 904 | break; 905 | case BOOL_EXPRESSION_K: 906 | cout << "bool_expression " << tree->token.lexeme << endl; 907 | break; 908 | case COMPARE_K: 909 | cout << "compare " << tree->token.lexeme << endl; 910 | break; 911 | case OPERATION_K: 912 | cout << "operation " << tree->token.lexeme << endl; 913 | break; 914 | case BOOL_K: 915 | cout << "bool" << endl; 916 | break; 917 | case ASSIGN_K: 918 | cout << "assign" << endl; 919 | break; 920 | case SUBROUTINE_BODY_K: 921 | cout << "subroutine_body" << endl; 922 | break; 923 | default: 924 | /*fallthrough*/; 925 | } 926 | printSyntaxTree(tree->child[0]); 927 | printSyntaxTree(tree->child[1]); 928 | printSyntaxTree(tree->child[2]); 929 | printSyntaxTree(tree->child[3]); 930 | printSyntaxTree(tree->child[4]); 931 | tree = tree->next; 932 | } 933 | indentno -= 2; 934 | } 935 | 936 | Parser::TreeNode *Parser::getSyntaxTree() { return syntaxTree; } 937 | -------------------------------------------------------------------------------- /jackc/src/Scanner.cpp: -------------------------------------------------------------------------------- 1 | #include "Scanner.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | Scanner::Scanner() { 12 | row = 0; 13 | bufferPos = 0; 14 | initKeyWords(); 15 | initSymbols(); 16 | } 17 | 18 | void Scanner::resetRow() { row = 0; } 19 | 20 | void Scanner::openFile(const string &filename) { 21 | string suffix = filename.substr(filename.size() - 5, 5); 22 | if (suffix != ".jack") { 23 | cerr << "file '" << filename 24 | << "' is not a standard java-- file, filename must be ended by '.j' " 25 | "or '.J'" 26 | << endl; 27 | exit(-1); 28 | } 29 | fin.open(filename); 30 | if (fin.fail()) { 31 | cerr << "file " << filename << " does not exit" << endl; 32 | exit(-1); 33 | } 34 | } 35 | 36 | void Scanner::closeFile() { fin.close(); } 37 | 38 | void Scanner::initKeyWords() { 39 | keyWords.insert("class"); 40 | keyWords.insert("constructor"); 41 | keyWords.insert("function"); 42 | keyWords.insert("method"); 43 | keyWords.insert("field"); 44 | keyWords.insert("static"); 45 | keyWords.insert("int"); 46 | keyWords.insert("char"); 47 | keyWords.insert("boolean"); 48 | keyWords.insert("void"); 49 | keyWords.insert("true"); 50 | keyWords.insert("false"); 51 | // keyWords.insert("null"); 52 | keyWords.insert("this"); 53 | keyWords.insert("if"); 54 | keyWords.insert("else"); 55 | keyWords.insert("while"); 56 | keyWords.insert("return"); 57 | } 58 | 59 | void Scanner::initSymbols() { 60 | symbols.insert("{"); 61 | symbols.insert("}"); 62 | symbols.insert("("); 63 | symbols.insert(")"); 64 | symbols.insert("["); 65 | symbols.insert("]"); 66 | symbols.insert("."); 67 | symbols.insert(","); 68 | symbols.insert(";"); 69 | symbols.insert("+"); 70 | symbols.insert("-"); 71 | symbols.insert("*"); 72 | symbols.insert("/"); 73 | symbols.insert("&"); 74 | symbols.insert("|"); 75 | symbols.insert("~"); 76 | symbols.insert("<"); 77 | symbols.insert(">"); 78 | symbols.insert("="); 79 | symbols.insert(">="); 80 | symbols.insert("<="); 81 | symbols.insert("=="); 82 | symbols.insert("!="); 83 | // symbols.insert("!"); 84 | // symbols.insert("&&"); 85 | // symbols.insert("||"); 86 | } 87 | 88 | Scanner::TokenType Scanner::searchReserved(const string &s) { 89 | if (keyWords.find(s) != keyWords.end()) 90 | return KEY_WORD; 91 | else 92 | return ID; 93 | } 94 | 95 | char Scanner::nextChar() { 96 | if (bufferPos >= lineBuffer.size()) { 97 | row++; 98 | getline(fin, lineBuffer); 99 | lineBuffer += '\n'; 100 | if (!fin.fail()) { 101 | bufferPos = 0; 102 | return lineBuffer[bufferPos++]; 103 | } else 104 | return EOF; 105 | } else { 106 | return lineBuffer[bufferPos++]; 107 | } 108 | } 109 | 110 | void Scanner::rollBack() { 111 | assert(bufferPos > 0); 112 | bufferPos--; 113 | } 114 | 115 | Scanner::Token Scanner::nextToken() { 116 | Token token; 117 | // unsigned tokenStringIndex = 0; 118 | State state = START_STATE; 119 | while (state != DONE_STATE) { 120 | char ch = nextChar(); 121 | if (ch == EOF) { 122 | token.kind = ENDOFFILE; 123 | break; 124 | } 125 | switch (state) { 126 | case START_STATE: // 开始状态 127 | if (ch == ' ' || ch == '\t' || ch == '\n') 128 | ; 129 | else if (isalpha(ch) || ch == '_') { 130 | state = ID_STATE; // 进入标识符状态 131 | token.kind = ID; 132 | token.lexeme += ch; 133 | token.row = row; 134 | } else if (isdigit(ch)) { 135 | state = INT_STATE; // 进入整数状态 136 | token.kind = INT; 137 | token.lexeme += ch; 138 | token.row = row; 139 | } 140 | 141 | else if (symbols.find({ch}) != symbols.end()) { 142 | state = SYMBOL_STATE; 143 | token.kind = SYMBOL; 144 | token.lexeme += ch; 145 | token.row = row; 146 | } else if (ch == '"') { 147 | state = STRING_STATE; // 进入字符串状态 148 | token.kind = STRING; 149 | token.row = row; 150 | } else if (ch == '\'') // 进入单字符状态 151 | { 152 | state = CHAR_STATE; 153 | token.kind = CHAR; 154 | token.row = row; 155 | } else // 其它非法字符 156 | { 157 | state = ERROR_STATE; 158 | token.kind = ERROR; 159 | token.lexeme += ch; 160 | token.row = row; 161 | } 162 | break; 163 | case INT_STATE: // 整数状态 164 | if (isdigit(ch)) { 165 | token.lexeme += ch; 166 | } else { 167 | rollBack(); 168 | state = DONE_STATE; 169 | } 170 | break; 171 | case ID_STATE: // 标识符状态 172 | if (isalpha(ch) || isdigit(ch) || ch == '_') { 173 | token.lexeme += ch; 174 | } else { 175 | rollBack(); 176 | state = DONE_STATE; 177 | } 178 | break; 179 | case STRING_STATE: // 字符串状态 180 | if (ch == '"') { 181 | state = DONE_STATE; 182 | } else if (ch == '\\') { 183 | state = S_STRING_STATE; 184 | token.lexeme += ch; 185 | } else { 186 | token.lexeme += ch; 187 | } 188 | break; 189 | case S_STRING_STATE: 190 | state = STRING_STATE; 191 | token.lexeme.pop_back(); 192 | token.lexeme += ch; 193 | break; 194 | case CHAR_STATE: // 字符状态 195 | if (ch != '\\' && ch != '\'') { 196 | state = CHAR_STATE_A; 197 | token.lexeme += ch; 198 | } else if (ch == '\\') { 199 | state = CHAR_STATE_B; 200 | token.lexeme += ch; 201 | } else if (ch == '\'') { 202 | state = ERROR_STATE; 203 | token.kind = ERROR; 204 | token.lexeme += ch; 205 | token.lexeme += ch; 206 | } 207 | break; 208 | case SYMBOL_STATE: 209 | if (token.lexeme == "/") { 210 | if (ch == '*') { 211 | state = INCOMMENT_STATE; 212 | token.lexeme.pop_back(); 213 | } else if (ch == '/') { 214 | state = START_STATE; 215 | bufferPos = lineBuffer.length(); 216 | token.lexeme.pop_back(); 217 | } else { 218 | rollBack(); 219 | state = DONE_STATE; 220 | } 221 | } else if (token.lexeme == "<") { 222 | if (ch == '=') { 223 | token.lexeme += ch; 224 | state = DONE_STATE; 225 | } else { 226 | rollBack(); 227 | state = DONE_STATE; 228 | } 229 | } else if (token.lexeme == "=") { 230 | if (ch == '=') { 231 | token.lexeme += ch; 232 | state = DONE_STATE; 233 | } else { 234 | rollBack(); 235 | state = DONE_STATE; 236 | } 237 | } else if (token.lexeme == "!") { 238 | if (ch == '=') { 239 | token.lexeme += ch; 240 | state = DONE_STATE; 241 | } else { 242 | rollBack(); 243 | state = DONE_STATE; 244 | } 245 | } else if (token.lexeme == "&") { 246 | if (ch == '&') { 247 | token.lexeme += ch; 248 | state = DONE_STATE; 249 | } else { 250 | rollBack(); 251 | state = DONE_STATE; 252 | } 253 | } else if (token.lexeme == "|") { 254 | if (ch == '|') { 255 | token.lexeme += ch; 256 | state = DONE_STATE; 257 | } else { 258 | rollBack(); 259 | state = DONE_STATE; 260 | } 261 | } else { 262 | rollBack(); 263 | state = DONE_STATE; 264 | } 265 | break; 266 | case CHAR_STATE_A: 267 | if (ch == '\'') { 268 | state = DONE_STATE; 269 | } else { 270 | state = ERROR_STATE; 271 | token.kind = ERROR; 272 | string tmp = "'"; 273 | tmp.append(token.lexeme); 274 | tmp += ch; 275 | token.lexeme = tmp; 276 | } 277 | break; 278 | case CHAR_STATE_B: 279 | if (ch == 'a' || ch == 'b' || ch == 'f' || ch == 'n' || ch == 'r' || 280 | ch == 't' || ch == 'v' || ch == '\\' || ch == '?' || ch == '\'' || 281 | ch == '"') { 282 | state = CHAR_STATE_C; 283 | token.lexeme += ch; 284 | } else { 285 | state = ERROR_STATE; 286 | token.kind = ERROR; 287 | string tmp = "'\\"; 288 | tmp += ch; 289 | token.lexeme = tmp; 290 | } 291 | break; 292 | case CHAR_STATE_C: 293 | if (ch == '\'') { 294 | state = DONE_STATE; 295 | } else { 296 | state = ERROR_STATE; 297 | token.kind = ERROR; 298 | string tmp = "'"; 299 | tmp.append(token.lexeme); 300 | tmp += ch; 301 | token.lexeme = tmp; 302 | } 303 | break; 304 | case ERROR_STATE: // 错误状态 305 | if (ch == ' ' || ch == '\n' || ch == '\t') 306 | state = DONE_STATE; 307 | else 308 | token.lexeme += ch; 309 | break; 310 | case INCOMMENT_STATE: // 注释状态 311 | if (ch == '*') 312 | state = P_INCOMMENT_STATE; 313 | break; 314 | case P_INCOMMENT_STATE: // 接近退出注释状态 315 | if (ch == '/') 316 | state = START_STATE; 317 | else 318 | state = INCOMMENT_STATE; 319 | break; 320 | default: 321 | /*fallthrough*/; 322 | } 323 | if (state == DONE_STATE && token.kind == ID) 324 | token.kind = searchReserved(token.lexeme); 325 | } 326 | return token; 327 | } 328 | -------------------------------------------------------------------------------- /jackc/src/SymbolTable.cpp: -------------------------------------------------------------------------------- 1 | #include "SymbolTable.h" 2 | #include "Error.h" 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | SymbolTable::Info SymbolTable::None; 9 | 10 | SymbolTable *SymbolTable::instance = nullptr; 11 | 12 | SymbolTable *SymbolTable::getInstance() { 13 | if (instance == nullptr) 14 | instance = new SymbolTable(); 15 | return instance; 16 | } 17 | 18 | SymbolTable::SymbolTable() { 19 | currentClassNumber = 0; 20 | static_index = 0; 21 | field_index = 0; 22 | arg_index = 0; 23 | var_index = 0; 24 | errorNum = 0; 25 | } 26 | 27 | void SymbolTable::classesTableInsert(Parser::TreeNode *t) { 28 | if (t->nodeKind == Parser::CLASS_K) { 29 | map temp; 30 | classesTable.push_back(temp); 31 | currentClass = t->child[0]->token.lexeme; 32 | int index = classesTable.size() - 1; 33 | classIndex.insert({currentClass, index}); 34 | static_index = field_index = 0; 35 | } else if (t->nodeKind == Parser::CLASS_VAR_DEC_K) // t = CLASS_VAR_DEC_K 36 | { // t->child[0] = static | field 37 | Info info; // t->child[1] = type 38 | info.type = 39 | t->child[1] 40 | ->token.lexeme; // t->child[2] = varName - varName - varName ... 41 | for (auto p = t->child[2]; p != nullptr; p = p->next) { 42 | string name = p->token.lexeme; 43 | if (t->child[0]->token.lexeme == "field") { 44 | info.kind = FIELD; 45 | info.index = field_index++; 46 | } else if (t->child[0]->token.lexeme == "static") { 47 | info.kind = STATIC; 48 | info.index = static_index++; 49 | } 50 | 51 | if (classesTable.back().insert({name, info}).second == 52 | false) // 插入失败,符号表中有已经存在的元素 53 | { 54 | error2(currentClass, p->token.row, info.type, name); 55 | } 56 | } 57 | } else if (t->nodeKind == Parser::SUBROUTINE_DEC_K) // t = SUBROUTINE_DEC_K 58 | { // t->child[0] = function 59 | Info info; // t->child[1] = type 60 | if (t->child[0]->token.lexeme == "function") // t->child[2] = functionName 61 | info.kind = FUNCTION; // t->child[3] = arg - arg - arg ... 62 | else if (t->child[0]->token.lexeme == "method") 63 | info.kind = METHOD; 64 | else if (t->child[0]->token.lexeme == "constructor") 65 | info.kind = CONSTRUCTOR; 66 | info.type = t->child[1]->token.lexeme; 67 | for (auto p = t->child[3]; p != nullptr; p = p->next) { 68 | string type = p->child[0]->token.lexeme; 69 | info.args.push_back(type); 70 | } 71 | string name = Parser::getFunctionName(t->child[2]->token.lexeme); 72 | if (classesTable.back().insert({name, info}).second == false) { 73 | error3(currentClass, t->child[0]->token.row, info.type, name); 74 | } 75 | } 76 | } 77 | 78 | void SymbolTable::subroutineTableInsert(Parser::TreeNode *t) { 79 | if (t->nodeKind == Parser::CLASS_K) 80 | currentClass = t->child[0]->token.lexeme; 81 | else if (t->nodeKind == Parser::SUBROUTINE_DEC_K) // t = SUBROUTINE_DEC_K 82 | { // t->child[0] = function 83 | initialSubroutineTable(); // t->child[1] = type 84 | string className = Parser::getCallerName( 85 | t->child[2]->token.lexeme); // t->child[2] = functionName 86 | string functionName = Parser::getFunctionName( 87 | t->child[2]->token.lexeme); // t->child[3] = arg - arg - arg ... 88 | currentClassNumber = classIndex.find(className)->second; 89 | Info info = classesTable[currentClassNumber].find(functionName)->second; 90 | subroutineTable["this"] = info; 91 | var_index = arg_index = 0; 92 | } else if (t->nodeKind == Parser::PARAM_K) // t = PARAM_K 93 | { // t->child[0] = type 94 | // 先检查type是否合理 // t->child[1] = varName 95 | Info info; 96 | info.kind = ARG; 97 | info.index = arg_index++; 98 | info.type = t->child[0]->token.lexeme; 99 | if (info.type != "int" && info.type != "char" && info.type != "void" && 100 | info.type != "string" && info.type != "boolean") // 如果不是基本类型 101 | { 102 | if (classIndexFind(info.type) == false) // 也不是类类型 103 | { 104 | error4(currentClass, t->child[1]->token.row, info.type); 105 | return; 106 | } 107 | } 108 | // 再检查varName是否合理 109 | string varName = t->child[1]->token.lexeme; 110 | if (subroutineTable.insert({varName, info}).second == false) { 111 | error2(currentClass, t->child[1]->token.row, info.type, varName); 112 | return; 113 | } 114 | } else if (t->nodeKind == Parser::VAR_DEC_K) // t = VAR_DEC_K 115 | { // t->child[0] = type 116 | Info info; // t->child[1] = varName - varName - varName 117 | info.kind = VAR; 118 | info.type = t->child[0]->token.lexeme; 119 | // 先检查type是否合理 120 | if (info.type != "int" && info.type != "char" && info.type != "void" && 121 | info.type != "string" && info.type != "boolean") { 122 | if (classIndex.find(info.type) == classIndex.end()) { 123 | errorNum++; 124 | error4(currentClass, t->child[1]->token.row, info.type); 125 | return; 126 | } 127 | } 128 | // 再检查varName是否合理 129 | for (auto p = t->child[1]; p != nullptr; p = p->next) { 130 | string varName = p->token.lexeme; 131 | info.index = var_index++; 132 | if (subroutineTable.insert({varName, info}).second == false) { 133 | error2(currentClass, p->token.row, info.type, varName); 134 | } 135 | } 136 | } 137 | } 138 | 139 | SymbolTable::Info SymbolTable::subroutineTableFind(const string &name) { 140 | auto iter = subroutineTable.find(name); 141 | if (iter == subroutineTable.end()) 142 | return None; 143 | else 144 | return iter->second; 145 | } 146 | 147 | SymbolTable::Info SymbolTable::classesTableFind(const string &className, 148 | const string &functionName) { 149 | assert(classIndexFind(className) == true); 150 | int classTableNumber = classIndex.find(className)->second; 151 | auto iter = classesTable[classTableNumber].find(functionName); 152 | if (iter == classesTable[classTableNumber].end()) 153 | return None; 154 | else 155 | return iter->second; 156 | } 157 | 158 | void SymbolTable::initialSubroutineTable() { subroutineTable.clear(); } 159 | 160 | void SymbolTable::printClassesTable() { 161 | cout << "class index: " << endl; 162 | cout << "类名\t\t编号\t\t" << endl; 163 | for (auto iter = classIndex.cbegin(); iter != classIndex.cend(); ++iter) 164 | cout << iter->first << "\t\t" << iter->second << endl; 165 | cout << endl; 166 | cout << "********************符号表********************" << endl; 167 | for (int i = 0; i < classesTable.size(); i++) { 168 | cout << "class table: " << i << endl; 169 | cout << "name\ttype\tkind\tvars" << endl; 170 | for (auto iter = classesTable[i].cbegin(); iter != classesTable[i].cend(); 171 | ++iter) { 172 | cout << iter->first << "\t" << iter->second.type << "\t" 173 | << iter->second.kind << "\t" << iter->second.index; 174 | for (int k = 0; k < iter->second.args.size(); ++k) 175 | cout << iter->second.args[k] << "\t"; 176 | cout << endl; 177 | } 178 | cout << endl << endl; 179 | } 180 | } 181 | 182 | bool SymbolTable::classIndexFind(const string &className) { 183 | if (classIndex.find(className) == classIndex.end()) 184 | return false; 185 | else 186 | return true; 187 | } 188 | 189 | int SymbolTable::getFieldNumber(const string &className) { 190 | assert(classIndexFind(className) == true); 191 | int classNum = classIndex.find(className)->second; 192 | int nField = 0; 193 | for (auto iter = classesTable[classNum].cbegin(); 194 | iter != classesTable[classNum].cend(); ++iter) 195 | if (iter->second.kind == FIELD) 196 | nField++; 197 | return nField; 198 | } 199 | --------------------------------------------------------------------------------