├── .gitattributes ├── .gitignore ├── Docs ├── ClassAndMethods.md ├── PascalCompilerCode.md ├── QuaterInstr.md ├── ReadAndTest.md └── SymbolSetDesign.md ├── LICENSE ├── Project ├── Compiler.sln └── Compiler │ ├── Compiler.vcxproj │ ├── Compiler.vcxproj.filters │ ├── Error.cpp │ ├── Lexer.cpp │ ├── Main.cpp │ ├── MiddleCode.cpp │ ├── MipsInstr.cpp │ ├── Parser.cpp │ ├── QuaterInstr.cpp │ ├── RootSymbolSet.cpp │ ├── SymbolSet.cpp │ ├── SymbolTable.cpp │ ├── error.h │ ├── lexer.h │ ├── middlecode.h │ ├── mipsinstr.h │ ├── parser.h │ ├── quaterinstr.h │ ├── rootsymbolset.h │ ├── symbolset.h │ └── token.h ├── README.md └── Tests ├── ComplexSamples ├── test_correct_1.txt ├── test_correct_2.txt ├── test_correct_3.txt ├── test_correct_4.txt ├── test_correct_5.txt ├── test_error_1.txt ├── test_error_2.txt ├── test_error_3.txt ├── test_error_4.txt └── test_error_5.txt └── SmallSamples ├── 13061193_test.txt ├── array.txt ├── array2.txt ├── call.txt ├── call_2.txt ├── char.txt ├── com.txt ├── compiler_one.txt ├── const.txt ├── expr.txt ├── fish.txt ├── fo2.txt ├── for.txt ├── function.txt ├── function2.txt ├── funvar.txt ├── if.txt ├── if_2.txt ├── if_fun.txt ├── min_rec.txt ├── mult-func.txt ├── multi.txt ├── multi_call.txt ├── procedure.txt ├── read.txt ├── rec.txt ├── ssss.txt ├── temp.txt ├── test.txt ├── test_write.txt ├── var.txt ├── while.txt ├── write.txt └── write_func.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | # NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | # DNX 42 | project.lock.json 43 | artifacts/ 44 | 45 | *_i.c 46 | *_p.c 47 | *_i.h 48 | *.ilk 49 | *.meta 50 | *.obj 51 | *.pch 52 | *.pdb 53 | *.pgc 54 | *.pgd 55 | *.rsp 56 | *.sbr 57 | *.tlb 58 | *.tli 59 | *.tlh 60 | *.tmp 61 | *.tmp_proj 62 | *.log 63 | *.vspscc 64 | *.vssscc 65 | .builds 66 | *.pidb 67 | *.svclog 68 | *.scc 69 | 70 | # Chutzpah Test files 71 | _Chutzpah* 72 | 73 | # Visual C++ cache files 74 | ipch/ 75 | *.aps 76 | *.ncb 77 | *.opensdf 78 | *.sdf 79 | *.cachefile 80 | 81 | # Visual Studio profiler 82 | *.psess 83 | *.vsp 84 | *.vspx 85 | 86 | # TFS 2012 Local Workspace 87 | $tf/ 88 | 89 | # Guidance Automation Toolkit 90 | *.gpState 91 | 92 | # ReSharper is a .NET coding add-in 93 | _ReSharper*/ 94 | *.[Rr]e[Ss]harper 95 | *.DotSettings.user 96 | 97 | # JustCode is a .NET coding add-in 98 | .JustCode 99 | 100 | # TeamCity is a build add-in 101 | _TeamCity* 102 | 103 | # DotCover is a Code Coverage Tool 104 | *.dotCover 105 | 106 | # NCrunch 107 | _NCrunch_* 108 | .*crunch*.local.xml 109 | 110 | # MightyMoose 111 | *.mm.* 112 | AutoTest.Net/ 113 | 114 | # Web workbench (sass) 115 | .sass-cache/ 116 | 117 | # Installshield output folder 118 | [Ee]xpress/ 119 | 120 | # DocProject is a documentation generator add-in 121 | DocProject/buildhelp/ 122 | DocProject/Help/*.HxT 123 | DocProject/Help/*.HxC 124 | DocProject/Help/*.hhc 125 | DocProject/Help/*.hhk 126 | DocProject/Help/*.hhp 127 | DocProject/Help/Html2 128 | DocProject/Help/html 129 | 130 | # Click-Once directory 131 | publish/ 132 | 133 | # Publish Web Output 134 | *.[Pp]ublish.xml 135 | *.azurePubxml 136 | ## TODO: Comment the next line if you want to checkin your 137 | ## web deploy settings but do note that will include unencrypted 138 | ## passwords 139 | #*.pubxml 140 | 141 | *.publishproj 142 | 143 | # NuGet Packages 144 | *.nupkg 145 | # The packages folder can be ignored because of Package Restore 146 | **/packages/* 147 | # except build/, which is used as an MSBuild target. 148 | !**/packages/build/ 149 | # Uncomment if necessary however generally it will be regenerated when needed 150 | #!**/packages/repositories.config 151 | 152 | # Windows Azure Build Output 153 | csx/ 154 | *.build.csdef 155 | 156 | # Windows Store app package directory 157 | AppPackages/ 158 | 159 | # Visual Studio cache files 160 | # files ending in .cache can be ignored 161 | *.[Cc]ache 162 | # but keep track of directories ending in .cache 163 | !*.[Cc]ache/ 164 | 165 | # Others 166 | ClientBin/ 167 | [Ss]tyle[Cc]op.* 168 | ~$* 169 | *~ 170 | *.dbmdl 171 | *.dbproj.schemaview 172 | *.pfx 173 | *.publishsettings 174 | node_modules/ 175 | orleans.codegen.cs 176 | 177 | # RIA/Silverlight projects 178 | Generated_Code/ 179 | 180 | # Backup & report files from converting an old project file 181 | # to a newer Visual Studio version. Backup files are not needed, 182 | # because we have git ;-) 183 | _UpgradeReport_Files/ 184 | Backup*/ 185 | UpgradeLog*.XML 186 | UpgradeLog*.htm 187 | 188 | # SQL Server files 189 | *.mdf 190 | *.ldf 191 | 192 | # Business Intelligence projects 193 | *.rdl.data 194 | *.bim.layout 195 | *.bim_*.settings 196 | 197 | # Microsoft Fakes 198 | FakesAssemblies/ 199 | 200 | # Node.js Tools for Visual Studio 201 | .ntvs_analysis.dat 202 | 203 | # Visual Studio 6 build log 204 | *.plg 205 | 206 | # Visual Studio 6 workspace options file 207 | *.opt 208 | 209 | # LightSwitch generated files 210 | GeneratedArtifacts/ 211 | _Pvt_Extensions/ 212 | ModelManifest.xml 213 | -------------------------------------------------------------------------------- /Docs/ClassAndMethods.md: -------------------------------------------------------------------------------- 1 | # Class and Methods 2 | 3 | ## Overview 4 | 5 | - **public class:** Error、Lexer、MiddleCode、MipsInstr、Parser、QuaterInstr、RootSymbolSet、SymbolSet、Token 6 | - **private class:** Dataseg、Instruction、SymbolItem 7 | - **Enum class:** MipsCode、TokenKind、TokenType、Symbol、Opcode 8 | 9 | 目录: 10 | - [Error](#error) 11 | - [Lexer](#lexer) 12 | - [MiddleCode](#middlecode) 13 | - [MipsInstr](#mipsInstr) 14 | - [Parser](#parser) 15 | - [QuaterInstr](#quaterInstr) 16 | - [RootSymbolSet](#rootsymbolset) 17 | - [SymbolSet](#symbolset) 18 | - [Token](#token) 19 | 20 | 21 | ## Error 22 | 23 | 专门用于错误处理的类 24 | 25 | ```c++ 26 | int getErrorCount() 27 | ``` 28 | 29 | 该函数用于获得编译错误的总数 30 | 31 | ```c++ 32 | bool IsSuccess() 33 | ``` 34 | 在Error类中设置了类属性success,只要有错误信息被加入到错误信息向量中,就会自动将success属性置为false。该函数返回success的值,即表示编译是否成功,是否要打印错误信息等行为。 35 | 36 | ```c++ 37 | void print() 38 | ``` 39 | 将错误信息向量中插入的错误信息全部打印出来 40 | 41 | ```c++ 42 | void errorMessage(int errortype, int line); 43 | void errorMessage(int errortype, int line, string message1); 44 | void errorMessage(int errortype, int line, string message1, string message2); 45 | ``` 46 | 这三个是分别应用于不同场景的报错函数,其中无法明确指代错误发生或者错误类别本身定义比较模糊的使用第一个报错函数;只能准确指出错在哪个地方使用第二个错误函数;既能指出错在哪个地方,还能得知期望符号串的,使用第三个错误函数。 47 | 48 | ## Lexer 49 | 50 | 用于词法分析的类 51 | 52 | ```c++ 53 | void getch() 54 | ``` 55 | 读取单个字符,字符存放于peek中 56 | ```c++ 57 | Token getsym() 58 | ``` 59 | 根据语法将单个或多个字符拼成单词,单词存放于current_token中。如果遇到非法字符或一些其他的错误情况会报错。 60 | 61 | ```c++ 62 | void initialReserved() 63 | ``` 64 | 初始化保留字数组 65 | 66 | ## MiddleCode 67 | 68 | 用于产生并存放所有四元式的中间代码类 69 | 70 | ```c++ 71 | QuaterInstr* gen(Opcode _op, SymbolItem* _des , SymbolItem* _src1 , SymbolItem* _src2 ) 72 | ``` 73 | 这个方法用于产生一个四元式,并且自动将其插入到middle_codes(四元式向量)中去。 74 | 75 | ```c++ 76 | void printMiddleCode() 77 | ``` 78 | 该方法用于打印所有的四元式,主要是用于前期中间代码生成时的对照调试 79 | 80 | ```c++ 81 | void addDataSeg(string _stringconst) 82 | ``` 83 | 该方法用于产生一个aciiz的数据段字符串,并将其加入到data段中,最后统一放置于text段前。 84 | ```c++ 85 | vector* getMiddleCode() 86 | ``` 87 | 该方法用于从middle_codes中获取生成的所有四元式。 88 | 89 | ## MipsInstr 90 | 91 | 将四元式转换为mips汇编指令的类 92 | 93 | ```c++ 94 | void add(MipsCode _op); 95 | void add(MipsCode _op, string _des); 96 | void add(MipsCode _op, string _des, string _src1); 97 | void add(MipsCode _op, string _des, string _src1, string _src2); 98 | ``` 99 | 以上这四个add的功能一致,都是生成一个正确的符合格式要求的mips汇编指令。由于各种指令需要的寄存器、label数等不同,故重载了四个函数。 100 | 101 | ```c++ 102 | void addData(string _name, string _conststring); 103 | ``` 104 | _name是生成的编号不重复的字符串标识符,_conststring是字符串本身的内容,这个方法的作用是将字符串_conststring以_name的名字存入dataseg中。 105 | 106 | ```c++ 107 | void Handle(QuaterInstr* middle); 108 | ``` 109 | 这个方法的作用是根据不同的Opcode进行挑选,寻找对应的Handle进行处理。 110 | 111 | ```c++ 112 | void translate() 113 | ``` 114 | 将四元式翻译为mips汇编指令 115 | 116 | ```c++ 117 | void HandleWrite(SymbolItem* des); 118 | void HandleBegin(SymbolItem* des); 119 | void HandleEnd(SymbolItem* des); 120 | void HandleCalc(Opcode choose, SymbolItem* des, SymbolItem* src1, SymbolItem* src2); 121 | void HandleNeg(SymbolItem* des,SymbolItem* src); 122 | void HandleAssignAddr(SymbolItem* addr, SymbolItem* value); 123 | void HandleArrayAddr(SymbolItem* addr, SymbolItem* base, SymbolItem* offset); 124 | void HandleArrayAssign(SymbolItem* value,SymbolItem* addr); 125 | void HandleAssign(SymbolItem* des,SymbolItem* src); 126 | void HandleBranch(Opcode branch,SymbolItem* des,SymbolItem* src1,SymbolItem* src2); 127 | void HandleCall(SymbolItem* caller,SymbolItem* callee); 128 | void HandleInc(SymbolItem* src); 129 | void HandleDec(SymbolItem* src); 130 | void HandleSetLabel(SymbolItem* des); 131 | void HandleJump(SymbolItem* des); 132 | void HandlePush(SymbolItem* des); 133 | void HandlePushVar(SymbolItem* des); 134 | void HandleRead(SymbolItem* des); 135 | ``` 136 | 以上这些所有的Handle函数都是针对不同的四元式进行各式各样的处理,将他们翻译成mips指令。 137 | 138 | ```c++ 139 | void loadReg(SymbolItem* item,const string _$i,bool _loadaddrvalue=false); 140 | ``` 141 | loadReg这个函数的主要作用是将item在运行栈中的值取到_$i中。最后的_loadaddrvalue主要用于控制是否为两次var嵌套使用的情况。 142 | 143 | ```c++ 144 | void storeMemory(const string _$i, SymbolItem* item); 145 | ``` 146 | storeMemory的作用和loadReg的作用相反,它将_$i的值存入item在运行栈中的实际地址中。 147 | ```c++ 148 | string genString(); 149 | ``` 150 | 产生编号不重复的字符串标识符用来标记要输出的字符串 151 | ```c++ 152 | void getRef(SymbolItem* item); 153 | ``` 154 | 这个函数的作用是将item在运行栈中的绝对地址通过display区或者本层符号表算出后,存入$t0(已限制死)中,让之后在想load或者sw时可以直接使用$t0作为地址。 155 | 156 | ## Parser 157 | Parser是递归下降子程序进行语法语义分析的类。 158 | 159 | ```c++ 160 | bool match(Symbol sym); 161 | ``` 162 | match是用于检测当前current_token的类型与sym是否匹配,匹配则返回true,否则返回false; 163 | ```c++ 164 | void next(); 165 | ``` 166 | next()函数主要是调用了getsym()进行读取单词,同时进行了文件末尾的判断。 167 | ```c++ 168 | void parser(); 169 | ``` 170 | parser是所有递归下降子程序的开头程序。在我的设计中,递归下降子程序开始只需要直接读即可,所有的递归下降子程序都会在末尾提前读一个准备好。 171 | ```c++ 172 | void translate(); 173 | ``` 174 | translate首先要判断当前是否有错误产生,之后要调用计算偏移量的函数,将四元式翻译为目标代码。 175 | ```c++ 176 | void expect(Symbol sym,string message); 177 | void expect(Symbol sym, string message1, string message2); 178 | ``` 179 | 这两个函数的作用是判断sym是否和当前current_token的Symbol相同,不同的话就按照给出的参数报错,错误号是固定的。 180 | ```c++ 181 | SymbolItem* get(string _ident_name); 182 | ``` 183 | get函数用于根据当前标识符的名字逐层检索,最终得到其对应的符号表项或者是一个未定义的临时生成的符号表项指针。 184 | ```c++ 185 | void skip(symset fsys, int error_code); 186 | void skip(symset fsys); 187 | void test(symset s1); 188 | ``` 189 | 以上的skip和test均是为跳读进行处理的。其中skip的意思是略过所有符号,直到遇到fsys中的某个符号为止,一般在入口处用。而test的意思是如果遇到了s1的某个符号为止会停下来,然后再读一个,一般用于出口控制。 190 | 191 | ```c++ 192 | string getErrorString(Token token); 193 | ``` 194 | 这个函数用于更好地报错,可以将token根据不同的类型返回不同的string,更详细地展示了错误的信息。 195 | ```c++ 196 | void block(symset blockbegin); 197 | ``` 198 | 分程序分析的递归下降子程序,对应文法中的 199 | <分程序> ::= [<常量说明部分>][<变量说明部分>]{[<过程说明部分>]| [<函数说明部分>]}<复合语句> 200 | <过程说明部分> ::= <过程首部><分程序>{; <过程首部><分程序>}; 201 | <函数说明部分> ::= <函数首部><分程序>{; <函数首部><分程序>}; 202 | ```c++ 203 | void constDec(); 204 | ``` 205 | <常量说明部分> :: = const<常量定义>{,<常量定义>}; 206 | ```c++ 207 | void constDef(); 208 | ``` 209 | <常量定义> ::= <标识符>= <常量> 210 | <常量> ::= [+| -] <无符号整数>|<字符> 211 | ```c++ 212 | void variableDec(); 213 | ``` 214 | <变量说明部分> :: = var <变量说明>; {<变量说明>; } 215 | ```c++ 216 | void variableDef(); 217 | ``` 218 | <变量说明> ::= <标识符>{, <标识符>} : <类型> 219 | ```c++ 220 | void varType(queue* var_name); 221 | ``` 222 | <类型> :: = <基本类型> | <数组类型> 223 | ```c++ 224 | void procDec(); 225 | ``` 226 | <过程首部> ::= procedure<标识符>[<形式参数表>]; 227 | <形式参数表> ::= '('<形式参数段>{; <形式参数段>}')' 228 | ```c++ 229 | void parameterList(); 230 | ``` 231 | <形式参数段> ::= [var]<标识符>{, <标识符>}: <基本类型> 232 | ```c++ 233 | void basicType(queue* args_name,TokenKind kind); 234 | ``` 235 | <基本类型> ::= integer | char 236 | ```c++ 237 | void funcDec(); 238 | ``` 239 | <函数首部> ::= function <标识符>[<形式参数表>]: <基本类型>; 240 | <形式参数表> :: = '('<形式参数段>{; <形式参数段>}')' 241 | ```c++ 242 | void statement(); 243 | ``` 244 | <语句> ::= <赋值语句>|<条件语句>|<当循环语句>|<过程调用语句>|<复合语句>|<读语句>|<写语句>||<空> 245 | ```c++ 246 | void selector(queue* var_name); 247 | ``` 248 | <数组类型> ::= array'['<无符号整数>']' of <基本类型> 249 | ```c++ 250 | void forStatement(); 251 | ``` 252 | :: = for <标识符> : = <表达式> (downto | to) <表达式> do <语句> //步长为1 253 | ```c++ 254 | void whileStatement(); 255 | ``` 256 | <当循环语句> :: = do<语句> while<条件> 257 | ```c++ 258 | void ifStatement(); 259 | ``` 260 | <条件语句> :: = if<条件>then<语句> | if<条件>then<语句>else<语句> 261 | ```c++ 262 | void condition(SymbolItem* label,bool _ifsuccess); 263 | ``` 264 | <条件> ::= <表达式><关系运算符><表达式> 265 | <关系运算符> ::= <|<=|>|>= |=|<> 266 | ```c++ 267 | void compoundStatement(); 268 | ``` 269 | <复合语句> ::= begin<语句>{; <语句>}end 270 | ```c++ 271 | void assignment(SymbolItem* ident,string func_name = ""); 272 | ``` 273 | <赋值语句> ::= <标识符> := <表达式>| <函数标识符> := <表达式> | <标识符>'['<表达式>']':= <表达式> 274 | ```c++ 275 | void callPro(SymbolItem* proc,string proc_name); 276 | ``` 277 | <过程调用语句> :: = <标识符>[<实在参数表>] 278 | ```c++ 279 | SymbolItem* callFunc(SymbolItem* func,string func_name); 280 | ``` 281 | <函数调用语句> :: = <标识符>[<实在参数表>] 282 | ```c++ 283 | SymbolItem* realParameter(SymbolItem* func,string func_name); 284 | ``` 285 | <实在参数表> :: = '(' <实在参数> {, <实在参数>}')' 286 | <实在参数> :: = <表达式> 287 | ```c++ 288 | SymbolItem* item(); 289 | ``` 290 | <项>::= <因子>{<乘法运算符><因子>} 291 | ```c++ 292 | SymbolItem* expression(); 293 | ``` 294 | <表达式> ::= [+|-]<项>{<加法运算符><项>} 295 | ```c++ 296 | SymbolItem* factor(); 297 | ``` 298 | <因子> ::= <标识符>|<标识符>'['<表达式>']'|<无符号整数>| '('<表达式>')' | <函数调用语句> 299 | ```c++ 300 | void readStatement(); 301 | ``` 302 | <读语句> ::= read'('<标识符>{,<标识符>}')' 303 | ```c++ 304 | void writeStatement(); 305 | ``` 306 | <写语句> :: = write'('<字符串>, <表达式>')' | write'('<字符串>')' | write'('<表达式>')' 307 | 308 | ## QuaterInstr 309 | QauterInstr是单个四元式的类,主要是一些get操作。 310 | ```c++ 311 | SymbolItem* getDes(); 312 | ``` 313 | 获取四元式中des对应的符号表项指针 314 | ```c++ 315 | SymbolItem* getSrc1(); 316 | ``` 317 | 获取四元式中src1对应的符号表项指针 318 | ```c++ 319 | SymbolItem* getSrc2(); 320 | ``` 321 | 获取四元式中src2对应的符号表项指针 322 | ```c++ 323 | Opcode getOpType(); 324 | ``` 325 | 获取四元式的Opcode 326 | ```c++ 327 | void printQuater(); 328 | ``` 329 | 打印单个四元式 330 | ```c++ 331 | string printOpcode(); 332 | ``` 333 | 获取四元式Opcode对应的字符串 334 | 335 | ## RootSymbolSet 336 | RootSymbolSet封装了符号表的一系列操作,并且包含了指向根符号表和当前符号表的两个指针。 337 | 338 | ```c++ 339 | SymbolItem* search(string _name); 340 | ``` 341 | 根据名字在符号表中查询是否寻在,如果存在返回对应的符号表项的指针,如果不存在返回NULL 342 | ```c++ 343 | SymbolItem* insert(string _name, TokenKind _kind, TokenType _type,int _value=0); 344 | ``` 345 | 将新的信息登入到符号表中,如果符号表中已经存在,则返回NULL,否则返回新建的符号表项。 346 | ```c++ 347 | SymbolItem* genTemp(TokenKind _kind,TokenType _type,string _tag_string=""); 348 | ``` 349 | 产生一个临时变量,临时变量使用static int控制统一编号。 350 | ```c++ 351 | SymbolItem* genLabel(); 352 | ``` 353 | 产生一个不会重复的Label,并且返回构造的符号表项指针 354 | ```c++ 355 | vector getArgList(string _name); 356 | ``` 357 | 根据_name获得其对应的参数列表,_name一般是funciton或procedure. 358 | ```c++ 359 | void printSymbolSet(); 360 | ``` 361 | 打印符号表信息 362 | ```c++ 363 | SymbolSet* getRootSet(); 364 | ``` 365 | 获取根符号表,即名为”root_”的根符号表,类似于C里的main函数。 366 | ```c++ 367 | SymbolSet* getCurrentSet(); 368 | ``` 369 | 获取当前符号表,获取current_table指向的符号表 370 | ```c++ 371 | SymbolSet* serachTable(string _name); 372 | ``` 373 | 根据_name在table_map中进行查询,并返回相应的直接子符号表 374 | ```c++ 375 | bool RootSymbolSet::goback(); 376 | ``` 377 | 函数的符号表退出,将当前符号表指针置为本符号表的父符号表指针值 378 | ```c++ 379 | void calcOffset(); 380 | ``` 381 | 计算每个变量在运行栈中的偏移量 382 | ```c++ 383 | string getCurrentName(); 384 | ``` 385 | 获取当前符号表对应的函数/过程的名字 386 | 387 | ## SymbolSet 388 | SymbolSet是符号表类,统一管理符号表有关操作。 389 | 390 | ```c++ 391 | SymbolItem* getItem(string _name); 392 | ``` 393 | 根据名字获取当前符号表中的符号表项指针,如果没找到返回NULL 394 | ```c++ 395 | bool enterItem(SymbolItem* _item); 396 | ``` 397 | 将符号表项item插入到符号表中 398 | ```c++ 399 | SymbolItem* getProcItem(); 400 | ``` 401 | 获取当前符号表对应的函数/过程的符号表项 402 | ```c++ 403 | SymbolSet* getProcTable(string _procname); 404 | ``` 405 | 根据_procname获取当前符号表的子符号表 406 | ```c++ 407 | string getProcName(); 408 | ``` 409 | 获取当前符号表对应的函数/过程的名称 410 | ```c++ 411 | string getProcLabelName(); 412 | ``` 413 | 获取当前符号表对应的函数/过程的label名称,即重命名过的名称 414 | ```c++ 415 | SymbolSet* enterProc(SymbolItem* _proc); 416 | ``` 417 | 根据_proc构造一个与之匹配的新符号表,并返回该符号表的指针 418 | ```c++ 419 | vector getArgList(); 420 | ``` 421 | 获取当前符号表对应的所有参数的集合 422 | ```c++ 423 | void printData(); 424 | ``` 425 | 打印当前符号表 426 | ```c++ 427 | void calcOffset(); 428 | ``` 429 | 计算偏移量 430 | 431 | ## Token 432 | Token是单词类,current_token是Token类,永远保存读到的最新的单词。 433 | 434 | ```c++ 435 | Symbol getType(); 436 | ``` 437 | 获取单词对应的Symbol 438 | ```c++ 439 | int getLineNo(); 440 | ``` 441 | 获取单词所在的行数,用于报错 442 | ```c++ 443 | string getName(); 444 | ``` 445 | 获取单词的名字 446 | ```c++ 447 | int getValue(); 448 | ``` 449 | 获取单词的值,如果不是有值的单词,默认值为0 450 | ```c++ 451 | string getTypeName(); 452 | ``` 453 | 获取单词的种类的名字 454 | -------------------------------------------------------------------------------- /Docs/PascalCompilerCode.md: -------------------------------------------------------------------------------- 1 | ```pascal 2 | program pl0(input,output,fin) ; { version 1.0 oct.1989 } 3 | { PL/0 compiler with code generation } 4 | const norw = 13; { no. of reserved words }{保留字的数量} 5 | txmax = 100; { length of identifier table }{标识符表的长度} 6 | nmax = 14; { max. no. of digits in numbers }{数字最大长度} 7 | al = 10; { length of identifiers }{*标识符的数量*} 8 | amax = 2047; { maximum address }{*这个不是最大地址吧...明明是最大的值...*} 9 | levmax = 3; { maximum depth of block nesting }{* 最大嵌套层次 *} 10 | cxmax = 200; { size of code array }{*指令数组一次存储最大的指令数*} 11 | {* 查询资料得知,()是子界类型,类似于java和C#里的枚举类,以下为查找的一个示例: 12 | type 13 | months = (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); *} 14 | 15 | type symbol = 16 | ( nul,ident,number,plus,minus,times,slash,oddsym,eql,neq,lss, 17 | leq,gtr,geq,lparen,rparen,comma,semicolon,period,becomes, 18 | beginsym,endsym,ifsym,thensym,whilesym,dosym,callsym,constsym, 19 | varsym,procsym,readsym,writesym );{* 单词集,即定义的单词*} 20 | alfa = packed array[1..al] of char;{*查阅资料得知,packed是为了压缩数组,但是很奇怪,没有给相应的标识符集合,怎么判断是否是标识符呢?*} 21 | objecttyp = (constant,variable,prosedure); 22 | symset = set of symbol; 23 | fct = ( lit,opr,lod,sto,cal,int,jmp,jpc,red,wrt ); { functions }{* 抽象机定义的10条汇编指令*} 24 | instruction = packed record {*record是记录类型,类似于C里结构体的感觉*} 25 | f : fct; { function code }{* 这个记录类型记录了目标代码集,层次域以及地址空间范围*} 26 | l : 0..levmax; { level }{*指令嵌套层次*} 27 | a : 0..amax; { displacement address }{*指令的参数!不是displacement address...*} 28 | end; 29 | { lit 0, a : load constant a 30 | opr 0, a : execute operation a 31 | lod l, a : load variable l,a 32 | sto l, a : store variable l,a 33 | cal l, a : call procedure a at level l 34 | int 0, a : increment t-register by a 35 | jmp 0, a : jump to a 36 | jpc 0, a : jump conditional to a 37 | red l, a : read variable l,a 38 | wrt 0, 0 : write stack-top 39 | } 40 | 41 | var ch : char; { last character read }{*读的最后一个字符*} 42 | sym: symbol; { last symbol read }{*读到的最后一个单词*} 43 | id : alfa; { last identifier read }{*读到的最后一个标识符*} 44 | num: integer; { last number read }{*读到的最后一个数字,应该是用来参与计算的*} 45 | cc : integer; { character count }{*字符的数量*} 46 | ll : integer; { line length }{*读入的一行的长度*} 47 | kk,err: integer;{* kk 是什么?根据下面的推测,err应该是错误的个数*} 48 | cx : integer; { code allocation index }{*代码分配序号,代码地址?*} 49 | line: array[1..81] of char; 50 | a : alfa; 51 | code : array[0..cxmax] of instruction; 52 | word : array[1..norw] of alfa; 53 | wsym : array[1..norw] of symbol; 54 | ssym : array[char] of symbol; 55 | mnemonic : array[fct] of 56 | packed array[1..5] of char; 57 | declbegsys, statbegsys, facbegsys : symset; 58 | table : array[0..txmax] of{* 符号表的设计,其中包含了符号的名字:alfa,符号的类型 *} 59 | record 60 | name : alfa;{*单词的名字*} 61 | case kind: objecttyp of{*kind 是个 objecttype类型,有constant常量,variable变量,prosedure过程*} 62 | constant : (val:integer );{*如果是常量,则在table里记录一个名为val的变量*} 63 | variable,prosedure: (level,adr: integer ){*如果是变量或者过程的话,符号表中需要记录其层次与地址*} 64 | end; 65 | fin : text; { source program file }{* 源代码 *} 66 | sfile: string; { source program file name }{* 源文件的名字*} 67 | 68 | procedure error( n : integer ); { P384 } 69 | begin 70 | writeln( '****', ' ':cc-1, '^', n:2 );{* 在第几个符号处犯了错误码为n的错误?*} 71 | err := err+1{*记录error被调用的次数,即记录错误的个数*} 72 | end; { error } 73 | 74 | {*该过程为词法分析,读取一个单词*} 75 | procedure getsym; 76 | var i,j,k : integer; 77 | {* 取字符过程,实际上先读入缓冲区,然后再一个一个字符地读取*} 78 | procedure getch; 79 | begin 80 | if cc = ll { get character to end of line }{*如果当前已经读到最后一个字符结束,就开始读下一行*} 81 | then begin { read next line } 82 | if eof(fin){*如果读到文件末尾,则打印结束信息,关闭文件并退出*} 83 | then begin 84 | writeln('program incomplete'); 85 | close(fin); 86 | exit; 87 | end; 88 | ll := 0;{*开始读取本行内容*} 89 | cc := 0; 90 | write(cx:4,' '); { print code address }{*以4个字符宽度来输出cx,cx是代码地址*} 91 | while not eoln(fin) do{*一直到读到换行符为止*} 92 | begin 93 | ll := ll+1; {*行的长度+1*} 94 | read(fin,ch);{*把字符读入*} 95 | write(ch);{*字符串打印*} 96 | line[ll] := ch{*将本行的缓冲区填满*} 97 | end;{*至此将一行已经读入到内存中,存储在line数组中*} 98 | writeln;{*输出源程序*} 99 | readln(fin);{*跳过一个换行符*} 100 | ll := ll+1;{*最后一个字符,填入字符串终结符*} 101 | line[ll] := ' ' { process end-line } 102 | end; 103 | {*如果不是到了行末尾,就正常读字符*} 104 | cc := cc+1;{*开始读缓冲区中的字符*} 105 | ch := line[cc]{*ch中保存最后一个读到的字符,这个程序居然是以1为下标开始序号*} 106 | end; { getch } 107 | begin { procedure getsym; P384 }{*getsym函数开始*} 108 | while ch = ' ' do{*如果读到的字符为空白符就一直向后读*} 109 | getch; 110 | if ch in ['a'..'z']{*如果读到的字符是a-z之间,要么是标识符,要么是保留字(起始处字符必须是小写字母)*} 111 | then begin { identifier of reserved word } 112 | k := 0;{*开始读字符*} 113 | repeat 114 | if k < al{*如果k小于标识符的最大长度*} 115 | then begin 116 | k := k+1; 117 | a[k] := ch{*a是个临时数组,用来存放读到的字符串*} 118 | end; 119 | getch 120 | until not( ch in ['a'..'z','0'..'9']);{*直到不是a-z且不是0-9*} 121 | if k >= kk { kk : last identifier length }{*kk表示所有单词中的最长字符长度,长度不足的用空格补足*} 122 | then kk := k 123 | else repeat {*否则要进行对齐处理,但是不太明白,为什么是kk-而不是k+,这样kk下一次的时候不就不一样了吗?*} 124 | a[kk] := ' '; 125 | kk := kk-1 126 | until kk = k; 127 | id := a;{*id存放字符串*} 128 | i := 1; 129 | j := norw; { binary search reserved word table }{*norw是保留字的个数,使用二分法来查找保留字*} 130 | repeat{二分法确认标识符是否为保留字} 131 | k := (i+j) div 2; 132 | if id <= word[k] 133 | then j := k-1; 134 | if id >= word[k] 135 | then i := k+1 136 | until i > j; 137 | if i-1 > j{*为什么这里i-1>j时就是保留字符?*} 138 | then sym := wsym[k]{} 139 | else sym := ident{*没有找到,单词记录为标识符*} 140 | end 141 | else if ch in ['0'..'9']{*数字*} 142 | then begin { number } 143 | k := 0;{*单词长度重置为0*} 144 | num := 0; 145 | sym := number;{*类型记录为number*} 146 | repeat{*循环将字符串的值转变为数字*} 147 | num := 10*num+(ord(ch)-ord('0')); 148 | k := k+1; 149 | getch 150 | until not( ch in ['0'..'9']); 151 | if k > nmax{*如果超过数字单词规定长度,则报错*} 152 | then error(30) 153 | end 154 | else if ch = ':'{*如果是冒号*} 155 | then begin 156 | getch;{*再读入一个单词*} 157 | if ch = '='{*赋值符号读入*} 158 | then begin 159 | sym := becomes;{*赋值符号语义单词*} 160 | getch 161 | end 162 | else sym := nul{*否则冒号无效*} 163 | end 164 | else if ch = '<'{*如果是小于号*} 165 | then begin 166 | getch; 167 | if ch = '='{*如果是<=号*} 168 | then begin 169 | sym := leq;{*leq表示小于等于比较,less equal*} 170 | getch 171 | end 172 | else if ch = '>'{*如果是<>号*} 173 | then begin 174 | sym := neq;{*neq表示不等于,not equal*} 175 | getch 176 | end 177 | else sym := lss{*否则的话就是一个简单的小于号,less*} 178 | end 179 | else if ch = '>'{*如果是大于号*} 180 | then begin 181 | getch; 182 | if ch = '='{*>=符号标识*} 183 | then begin 184 | sym := geq;{*geq 即 greater equal*} 185 | getch 186 | end 187 | else sym := gtr{*否则就是普通的大于号,即greater*} 188 | end 189 | else begin 190 | sym := ssym[ch];{*操作符集合,字符作为下标进行索引*} 191 | getch 192 | end 193 | end; { getsym } 194 | 195 | {*目标代码生成*} 196 | procedure gen( x: fct; y,z : integer ); {*fct是目标代码指令集*} 197 | begin 198 | if cx > cxmax{*如果目标代码生成位置超出规定的地址边界*} 199 | then begin 200 | writeln('program too long');{*如果程序过长...才200行就过长了...*} 201 | close(fin); 202 | exit 203 | end; 204 | with code[cx] do{*将符合条件的代码存入code*} 205 | begin 206 | f := x;{*指令*} 207 | l := y;{*层级*} 208 | a := z{*操作编码*} 209 | end; 210 | cx := cx+1{*存储下一句符合条件的代码*} 211 | end; { gen } 212 | 213 | {*用于分析错误并处理*} 214 | procedure test( s1,s2 :symset; n: integer ); { P386 }{*S1为合法头符号集合,S2为停止符号集合,n为错误编码*} 215 | begin 216 | if not ( sym in s1 ){*如果sym不在s1里,就报错*} 217 | then begin 218 | error(n);{*错误类型为n*} 219 | s1 := s1+s2;{*报错后s2加入头符号集合中,检测后面是否出现错误*} 220 | while not( sym in s1) do{*如果后面再遇到非法符号全部略过*} 221 | getsym 222 | end 223 | end; { test } 224 | 225 | {*分程序分析处理程序,lev是层次,tx是*} 226 | procedure block( lev,tx : integer; fsys : symset ); { P386 } 227 | var dx : integer; { data allocation index }{*数据段分配的初始地址*} 228 | tx0: integer; { initial table index }{*初始符号表中的下标*} 229 | cx0: integer; { initial code index }{*初始代码数组的下标} 230 | 231 | {*将符号插入符号表中,objecttyp是符号的类型*} 232 | procedure enter( k : objecttyp ); { P386 } 233 | begin { enter object into table } 234 | tx := tx+1;{*符号表下标+1*} 235 | with table[tx] do{*在table[tx]*} 236 | begin 237 | name := id;{*符号表中有名字*} 238 | kind := k;{*问题:k现在类型未知,赋值之后可以决定kind的类型,即k的类型决定kind的类型*} 239 | case k of 240 | constant : begin{*如果k是常量类型的话*} 241 | if num > amax{*如果数字的值比预计最大位数多,则抛出错误30*} 242 | then begin 243 | error(30); 244 | num := 0 245 | end; 246 | val := num{*如果数字的位宽在接受范围内,则将num赋值给val*} 247 | end; 248 | variable : begin{*如果k是变量类型的话*} 249 | level := lev;{*记录变量当前所处于的层次*} 250 | adr := dx;{*记录变量的地址*} 251 | dx := dx+1{*变量的地址+1?[FIXME]*} 252 | end; 253 | prosedure: level := lev;{*过程的话,就记录其层次关系,过程不应该也有adr吗?不赋值了?*} 254 | end 255 | end 256 | end; { enter } 257 | 258 | {*返回值类型为整型的,传入参数为alfa类型,alfa是标识符,此函数的作用是给定标识符,从符号表中查出其位置?*} 259 | function position ( id : alfa ): integer; { P386 } 260 | var i : integer; 261 | begin 262 | table[0].name := id;{*为啥一进来就让table[0].name=id??[FIXME]} 263 | i := tx; 264 | while table[i].name <> id do 265 | i := i-1; 266 | position := i 267 | end; { position } 268 | 269 | {*常量声明*} 270 | procedure constdeclaration; { P386 } 271 | begin 272 | if sym = ident{*获取一个标识符*} 273 | then begin 274 | getsym; 275 | if sym in [eql,becomes]{*eql 为= becomes即:=,起始符是两个都行*} 276 | then begin 277 | if sym = becomes{*既然不想让becomes进来,为什么还要判断becomes?为了错误处理更好?*} 278 | then error(1); 279 | getsym;{*读入又一个单词*} 280 | if sym = number{*如果读入的是数字*} 281 | then begin 282 | enter(constant);{*把常量插入符号表中*} 283 | getsym{*再次读入符号*} 284 | end 285 | else error(2){*如果不是数字的话,抛出错误2*} 286 | end 287 | else error(3){*如果既不是becomes也不是eql,则抛出错误3*} 288 | end 289 | {*这里的sym可以是有多个标识符,标识符之间插入逗号的!*} 290 | else error(4){*如果不是标识符,则抛出错误4—const后应为标识符*} 291 | end; { constdeclaration } 292 | 293 | {*变量声明处理程序,在检测到var之后使用*} 294 | procedure vardeclaration; { P387 } 295 | begin 296 | if sym = ident{*如果读到的是标识符*} 297 | then begin 298 | enter(variable);{*则以variable的类型添加到符号表中去*} 299 | getsym 300 | end 301 | else error(4){*否则抛出错误4号的错误*} 302 | end; { vardeclaration } 303 | 304 | {*列出P-code指令清单*} 305 | procedure listcode; { P387 } 306 | var i : integer; 307 | begin 308 | 309 | for i := cx0 to cx-1 do{*cx0是本段代码对应指令的起始位置*} 310 | with code[i] do 311 | writeln( i:4, mnemonic[f]:7,l:3, a:5){*输出地址,指令名称与其参数的值*} 312 | end; { listcode } 313 | 314 | {*分程序主体代码解析*} 315 | procedure statement( fsys : symset ); { P387 } 316 | var i,cx1,cx2: integer; 317 | procedure expression( fsys: symset); {P387 } 318 | var addop : symbol; 319 | procedure term( fsys : symset); { P387 } 320 | var mulop: symbol ; 321 | procedure factor( fsys : symset ); { P387 }{*因子解析*} 322 | var i : integer; 323 | begin 324 | test( facbegsys, fsys, 24 );{*在因子语法解析的入口处设置test进行检测和跳读*} 325 | while sym in facbegsys do{*facbegsys是factor的合法符号开始集,设置循环是为了将一些特殊的出错情况可以跳读过*} 326 | begin 327 | if sym = ident 328 | then begin 329 | i := position(id);{*查询标识符在符号表中的位置*} 330 | if i= 0 331 | then error(11){*如果标识符在符号表中找不到*} 332 | else 333 | with table[i] do 334 | case kind of 335 | constant : gen(lit,0,val);{*如果是常量的话,取常量val放到数据栈栈顶*} 336 | variable : gen(lod,lev-level,adr);{*如果是变量的话,取变量放到数据栈栈顶*} 337 | prosedure: error(21){*如果在因子分析中发现是个proc,则报错:表达式内不能有过程标识符*} 338 | end; 339 | getsym 340 | end 341 | else if sym = number{*如果识别到是个数字*} 342 | then begin 343 | if num > amax{*判断数字是否大于amx,数字不超过2047(感觉为啥这么逗。。不能超过2047是为啥)*} 344 | then begin 345 | error(30); 346 | num := 0 347 | end; 348 | gen(lit,0,num);{*将num常量存到数据栈栈顶*} 349 | getsym 350 | end 351 | else if sym = lparen{*如果是个左括号,表明因子是个表达式*} 352 | then begin 353 | getsym; 354 | expression([rparen]+fsys);{*左括号是表达式的开始,就进入表达式的分析成分*} 355 | if sym = rparen{*出表达式后判断是否是右括号,右括号即匹配成功*} 356 | then getsym 357 | else error(22){*否则抛出22号错误,没写右括号,括号不匹配*} 358 | end; 359 | test(fsys,[lparen],23){*在因子分析完成后进行检测与跳读操作,终止符号集为下一个因子的左括号开始?*} 360 | end 361 | end; { factor } 362 | begin { procedure term( fsys : symset);{*Term的项读取分析*} 363 | var mulop: symbol ; } 364 | factor( fsys+[times,slash]);{*slash是'/',是除法号*} 365 | while sym in [times,slash] do 366 | begin 367 | mulop := sym;{*记录sym以在后面进行选择*} 368 | getsym; 369 | factor( fsys+[times,slash] );{*乘除法作为有效符号集*} 370 | if mulop = times 371 | then gen( opr,0,4 ){*如果是乘法,则生成参数为4的opr指令*} 372 | else gen( opr,0,5){*如果是除法,则生成参数为5的opr指令*} 373 | end 374 | end; { term }{*term的读取结束*} 375 | begin { procedure expression( fsys: symset);{*expression表达式分析语句部分*} 376 | var addop : symbol; } 377 | if sym in [plus, minus] 378 | then begin 379 | addop := sym;{*sym的值赋值给addop,像上面那个multop一样*} 380 | getsym; 381 | term( fsys+[plus,minus]);{*term分析子表达式*} 382 | if addop = minus 383 | then gen(opr,0,1){*如果是负数,则生成参数为0的opr指令,但是奇怪的是,为什么这时候没有先把0加载至栈顶?*} 384 | end 385 | else term( fsys+[plus,minus]);{如果sym不在+或-之间,则直接使用term直接分析其结构*} 386 | while sym in [plus,minus] do{*当sym一直都是-或者+时*} 387 | begin 388 | addop := sym; 389 | getsym; 390 | term( fsys+[plus,minus] );{*为什么这里要写一个循环来判断呢?*} 391 | if addop = plus 392 | then gen( opr,0,2) 393 | else gen( opr,0,3) 394 | end 395 | end; { expression } 396 | 397 | procedure condition( fsys : symset ); {*条件判断语句*} 398 | var relop : symbol; 399 | begin 400 | if sym = oddsym{*判断sym是否为保留字odd*} 401 | then begin 402 | getsym; 403 | expression(fsys); 404 | gen(opr,0,6){*如果是保留字odd的话则生成指令参数为6的opr指令*} 405 | end 406 | else begin 407 | expression( [eql,neq,lss,gtr,leq,geq]+fsys);{*否则就一定在剩下的操作符集合中*} 408 | if not( sym in [eql,neq,lss,leq,gtr,geq]){*如果sym不在制定的操作符集合中,则报错*} 409 | then error(20) 410 | else begin 411 | relop := sym;{*将sym读入到relop中等待判断*} 412 | getsym; 413 | expression(fsys); 414 | case relop of{*relop可能有六种类型,分别生成不同参数的opr指令*} 415 | eql : gen(opr,0,8); 416 | neq : gen(opr,0,9); 417 | lss : gen(opr,0,10); 418 | geq : gen(opr,0,11); 419 | gtr : gen(opr,0,12); 420 | leq : gen(opr,0,13); 421 | end 422 | end 423 | end 424 | end; { condition }{*条件判断语句结束*} 425 | begin { procedure statement( fsys : symset ); {*语句主体分析部分开始*} 426 | var i,cx1,cx2: integer; } 427 | if sym = ident{*如果sym是一个标识符的话*} 428 | then begin 429 | i := position(id);{*查询其在符号表中的位置,如果没有找到则抛出11号错误*} 430 | if i= 0 431 | then error(11) 432 | else if table[i].kind <> variable{*如果类型和符号表中的类型不匹配,则报12号错误*} 433 | then begin { giving value to non-variation } 434 | error(12); 435 | i := 0 436 | end; 437 | getsym; 438 | if sym = becomes{*如果标识符后读入的是一个:=号*} 439 | then getsym 440 | else error(13);{*再读入一个符号后报错为13号错误*} 441 | expression(fsys);{*以表达式的格式来读取*} 442 | if i <> 0 443 | then 444 | with table[i] do 445 | gen(sto,lev-level,adr){*如果i不等於0,说明查到了,这时将变量的地址与层次关系压入栈顶*} 446 | end 447 | else if sym = callsym{*如果是call*} 448 | then begin 449 | getsym; 450 | if sym <> ident{*call后面如果不是一个标识符则报错*} 451 | then error(14) 452 | else begin 453 | i := position(id);{*否则找到id对应的符号表中的位置*} 454 | if i = 0 455 | then error(11) 456 | else 457 | with table[i] do 458 | if kind = prosedure{*如果判断符号表中是程序标识符的话,则*} 459 | then gen(cal,lev-level,adr){*生成一条cal指令,参数为所在的层级以及指令所在的地址*} 460 | else error(15); 461 | getsym 462 | end 463 | end 464 | else if sym = ifsym{*如果是if语句*} 465 | then begin 466 | {*if expression then statement else statement*} 467 | getsym; 468 | condition([thensym,dosym]+fsys);{*使用condition分析 if 后的表达式*} 469 | if sym = thensym{*如果if之后陈述已经结束,那么应该是then*} 470 | then getsym 471 | else error(16); 472 | cx1 := cx; 473 | gen(jpc,0,0);{*生成一条jpc指令,暂时不填跳转地址*} 474 | statement(fsys);{*分析语句*} 475 | code[cx1].a := cx 476 | end 477 | else if sym = beginsym 478 | then begin 479 | getsym; 480 | statement([semicolon,endsym]+fsys);{*如果是begin开始的保留字符号,则分析begin后面的陈述句*} 481 | while sym in ([semicolon]+statbegsys) do 482 | begin 483 | if sym = semicolon{*semicolon是终结符号"."*} 484 | then getsym 485 | else error(10); 486 | statement([semicolon,endsym]+fsys) 487 | end; 488 | if sym = endsym{*如果sysm是end保留字符号*} 489 | then getsym 490 | else error(17){*则抛出异常号,号为17[FIXME]这里为啥要抛出啊?*} 491 | end 492 | else if sym = whilesym{*当读到while符号时*} 493 | then begin 494 | cx1 := cx; 495 | getsym; 496 | condition([dosym]+fsys); 497 | cx2 := cx; 498 | gen(jpc,0,0);{*生成jpc代码,之后会回来返填*} 499 | if sym = dosym 500 | then getsym 501 | else error(18); 502 | statement(fsys);{*将第一个 503 | gen(jmp,0,cx1);{*生成一条跳转到cx1的jmp的指令*} 504 | code[cx2].a := cx 505 | end 506 | else if sym = readsym{*如果是读符号保留字*} 507 | then begin 508 | getsym; 509 | if sym = lparen{*如果读入的第一个符号是左括号时*} 510 | then 511 | repeat 512 | getsym; 513 | if sym = ident{*则开始循环读入标识符*} 514 | then begin 515 | i := position(id);{*寻找符号表中的位置*} 516 | if i = 0 517 | then error(11) 518 | else if table[i].kind <> variable{*如果符号表中的类型和标识符的类型是不一样的*} 519 | then begin 520 | error(12);{*报错,错误号为12*} 521 | i := 0 522 | end 523 | else with table[i] do 524 | gen(red,lev-level,adr){*如果正确的话 525 | end 526 | else error(4); 527 | getsym; 528 | until sym <> comma 529 | else error(40); 530 | if sym <> rparen 531 | then error(22); 532 | getsym 533 | end 534 | else if sym = writesym{*当读取到的符号是写符号时*} 535 | then begin 536 | getsym; 537 | if sym = lparen{*如果读取到的符号是左括号*} 538 | then begin 539 | repeat 540 | getsym; 541 | expression([rparen,comma]+fsys);{*利用expression表达式进行语法分析*} 542 | gen(wrt,0,0); 543 | until sym <> comma;{*直到sym不是逗号为止*} 544 | if sym <> rparen{*如果sym不是右括号—结束符时,报错22号*} 545 | then error(22); 546 | getsym 547 | end 548 | else error(40) 549 | end; 550 | test(fsys,[],19) 551 | end; { statement } 552 | 553 | {*block函数的主体开始,先将过程的名字添入符号表中*} 554 | begin { procedure block( lev,tx : integer; fsys : symset ); 555 | var dx : integer; /* data allocation index */ 556 | tx0: integer; /*initial table index */ 557 | cx0: integer; /* initial code index */ } 558 | dx := 3;{*为什么一上来dx=3?前两个放什么东西了吗...*} 559 | tx0 := tx;{*tx0=tx,tx是指起始地址吧[FIXME]*} 560 | table[tx].adr := cx;{*符号表中将该过程的地址插入*} 561 | gen(jmp,0,0); { jump from declaration part to statement part } 562 | {*生成一条暂时没有参数的jmp指令存放在code数组中*} 563 | if lev > levmax{*如果嵌套层次太深则报错,抛出号为32的错误*} 564 | then error(32); 565 | 566 | repeat 567 | {*const常量声明格式如下: 568 | const a = 123;在我们的文法中,右侧目前只能是数字 569 | } 570 | if sym = constsym{*在调用block前必然是已经getsym()过的,所以sym=constsym表明是一个常量*} 571 | then begin 572 | getsym;{*获取一个单词*} 573 | repeat 574 | constdeclaration;{*常量定义函数,将常量符号插入符号表中*} 575 | while sym = comma do{*在constdeclaration函数成功的最后一句有读入字符串,这里如果有多个常量则要全部读进来。*} 576 | begin 577 | getsym; 578 | constdeclaration 579 | end; 580 | if sym = semicolon{*如果遇到分号则表示常量定义结束*} 581 | then getsym 582 | else error(5){*否则抛出错误5—没有以分号结尾} 583 | until sym <> ident{*直到符号不是标识符为止,表明此时常量定义已经完成} 584 | end; 585 | {*var变量声明格式如下: 586 | var 587 | a ,b : real; 588 | } 589 | if sym = varsym{* 如果遇到了var打头的变量声明*} 590 | then begin 591 | getsym; 592 | repeat 593 | vardeclaration;{*变量声明定义过程,将变量插入符号表中*} 594 | while sym = comma do{*如果是逗号的话则一直读取并插入符号表*} 595 | begin 596 | getsym; 597 | vardeclaration 598 | end; 599 | if sym = semicolon{*遇到分号表明本行结束,下一行继续开始} 600 | then getsym 601 | else error(5) 602 | until sym <> ident; 603 | end; 604 | while sym = procsym do{*如果是分程序的定义标识符*} 605 | begin 606 | getsym; 607 | if sym = ident{*分程序的定义标识符后是分程序的名字*} 608 | then begin 609 | enter(prosedure);{*以prosedure的类型插入符号表*} 610 | getsym 611 | end 612 | else error(4);{*否则抛出错误4*} 613 | if sym = semicolon{*如果结束符号是;的话*} 614 | then getsym 615 | else error(5); 616 | block(lev+1,tx,[semicolon]+fsys);{*开始编译分程序,分程序层次在当前程序的层次上+1,但是比较奇怪的是,为什么要有[semicolon]?[FIXME]*} 617 | if sym = semicolon 618 | then begin 619 | getsym; 620 | {*在一个语法分析子程序的出口处调用test进行合法后继符号的判断,合法的后继符号有状态起始符,标识符,以及另一个子程序。*} 621 | test( statbegsys+[ident,procsym],fsys,6){*这里的fsys是符号集吗?有什么特殊的用处吗?...奇怪>.<[FIXME]*} 622 | end 623 | else error(5) 624 | end; 625 | test( statbegsys+[ident],declbegsys,7){*在非最后一个语法分析子程序的后面进行合法后继符号判断*} 626 | until not ( sym in declbegsys );{*如果sym不是合法后继集合,则退出*} 627 | code[table[tx0].adr].a := cx; { back enter statement code's start adr. }{*返填过程开头处的地址,一开始有一个gen(jmp,0,0),用于跳到本处开始执行语句的开始*} 628 | with table[tx0] do 629 | begin 630 | adr := cx; { code's start address }{*生成的指令的地址*} 631 | end; 632 | cx0 := cx;{**} 633 | gen(int,0,dx); { topstack point to operation area }{*T寄存器的数增加dx*} 634 | statement( [semicolon,endsym]+fsys);{*函数主体部分解析*} 635 | gen(opr,0,0); { return }{*返回地址*} 636 | test( fsys, [],8 );{} 637 | listcode;{*打印与本段分程序执行内容有关的指令码,} 638 | end { block }; 639 | 640 | {*解释执行P-code指令清单*} 641 | procedure interpret; { P391 } 642 | const stacksize = 500; 643 | var p,b,t: integer; { program-,base-,topstack-register }{*程序,基址,栈顶寄存器*} 644 | i : instruction;{ instruction register }{*指令寄存器*} 645 | s : array[1..stacksize] of integer; { data store }{*栈的深度*} 646 | function base( l : integer ): integer;{*通过静态链求出数据区的基地址*} 647 | var b1 : integer; 648 | {*使用静态链SL进行逐层寻找基址*} 649 | begin { find base l levels down } 650 | b1 := b;{*b是取当前基址*} 651 | while l > 0 do{*层次大于0就循环*} 652 | begin 653 | b1 := s[b1];{*取上一层的层基址*} 654 | l := l-1{*层次减1*} 655 | end; 656 | base := b1{*返回最后找到的基址*} 657 | end; { base } 658 | begin { P392 } 659 | writeln( 'START PL/0' ); 660 | t := 0; 661 | b := 1; 662 | p := 0; 663 | s[1] := 0;{*静态链的位置*} 664 | s[2] := 0;{*动态链的位置*} 665 | s[3] := 0;{*函数的返回地址存放位置*} 666 | repeat 667 | i := code[p];{*从指令数组中取出一条指令为i*} 668 | p := p+1;{*指令指针+1*} 669 | with i do 670 | case f of 671 | lit : begin{*当指令是lit时,先+1,然后将栈顶赋值为a*} 672 | t := t+1; 673 | s[t]:= a; 674 | end; 675 | opr : case a of { operator } 676 | 0 : begin { return }{*返回指令*} 677 | t := b-1; 678 | p := s[t+3];{* 679 | b := s[t+2]; 680 | end; 681 | 1 : s[t] := -s[t];{*取反操作*} 682 | 2 : begin{*栈顶退格,将原栈顶的原次栈顶的数想加,放入新栈顶地址中*} 683 | t := t-1; 684 | s[t] := s[t]+s[t+1] 685 | end; 686 | 3 : begin{*栈顶退格,次栈顶减去原栈顶的值,赋值给新栈顶*} 687 | t := t-1; 688 | s[t] := s[t]-s[t+1] 689 | end; 690 | 4 : begin{*栈顶退格,新栈顶的值等于原栈顶与原次栈顶的乘积*} 691 | t := t-1; 692 | s[t] := s[t]*s[t+1] 693 | end; 694 | 5 : begin{*栈顶退格,新栈顶的值等于原栈顶与原次栈顶的除*} 695 | t := t-1; 696 | s[t] := s[t]div s[t+1] 697 | end; 698 | 6 : s[t] := ord(odd(s[t]));{*把odd(s[t])的结果放到栈顶*} 699 | 8 : begin{*把odd(s[t])的结果放到栈顶*} 700 | t := t-1; 701 | s[t] := ord(s[t]=s[t+1]) 702 | end; 703 | 9 : begin{*把s[t]!=s[t+1]的结果放到栈顶*} 704 | t := t-1; 705 | s[t] := ord(s[t]<>s[t+1]) 706 | end; 707 | 10: begin{*把s[t]=s[t+1]的结果放到栈顶*} 712 | t := t-1; 713 | s[t] := ord(s[t] >= s[t+1]) 714 | end; 715 | 12: begin{*把s[t]>s[t+1]的结果放到栈顶*} 716 | t := t-1; 717 | s[t] := ord(s[t] > s[t+1]) 718 | end; 719 | 13: begin{*把s[t]<=s[t+1]的结果放到栈顶*} 720 | t := t-1; 721 | s[t] := ord(s[t] <= s[t+1]) 722 | end; 723 | end; 724 | lod : begin{*取变量(相对地址为a,层次差为l)放到数据栈的栈顶*} 725 | t := t+1; 726 | s[t] := s[base(l)+a] 727 | end; 728 | sto : begin{*将数据栈栈顶内容存入变量(相对地址为a,层次差为l)*} 729 | s[base(l)+a] := s[t]; { writeln(s[t]); } 730 | t := t-1 731 | end; 732 | cal : begin { generate new block mark }{*在调用一个过程时,入口地址为a,层次差为l,要将SL(base(l)),DL(b),RA(p)栈顶地址压入栈内*} 733 | s[t+1] := base(l); 734 | s[t+2] := b; 735 | s[t+3] := p; 736 | b := t+1;{*t+1*} 737 | p := a; 738 | end; 739 | int : t := t+a;{*数据栈栈顶指针增加a*} 740 | jmp : p := a;{*无条件跳转到a地址*} 741 | jpc : begin 742 | if s[t] = 0 743 | then p := a;{*如果栈顶的值为0,则跳转到a,否则不跳转*} 744 | t := t-1; 745 | end; 746 | red : begin 747 | writeln('??:');{*这是啥...*} 748 | readln(s[base(l)+a]);{*读数据并存入变量*} 749 | end; 750 | wrt : begin 751 | writeln(s[t]);{*将栈顶的内容输出*} 752 | t := t+1 753 | end 754 | end { with,case } 755 | until p = 0; 756 | writeln('END PL/0'); 757 | end; { interpret } 758 | 759 | {* main函数 *} 760 | begin { main } 761 | writeln('please input source program file name : '); 762 | {*通过源文件的名字将要编译的文件读入*} 763 | readln(sfile); 764 | {*fin是源代码文件,assign的作用是将文件名字符串sfile赋给文件变量fin,程序对文件变量fin的操作代替对文件sfile的操作。*} 765 | assign(fin,sfile); 766 | {*以只读的方式打开文件fin*} 767 | reset(fin); 768 | for ch := 'A' to ';' do 769 | ssym[ch] := nul; 770 | {*13个保留字,用于二分查找,所以是按序排列的*} 771 | word[1] := 'begin '; word[2] := 'call '; 772 | word[3] := 'const '; word[4] := 'do '; 773 | word[5] := 'end '; word[6] := 'if '; 774 | word[7] := 'odd '; word[8] := 'procedure '; 775 | word[9] := 'read '; word[10]:= 'then '; 776 | word[11]:= 'var '; word[12]:= 'while '; 777 | word[13]:= 'write '; 778 | 779 | {*保留字对应的13个symbol*} 780 | wsym[1] := beginsym; wsym[2] := callsym; 781 | wsym[3] := constsym; wsym[4] := dosym; 782 | wsym[5] := endsym; wsym[6] := ifsym; 783 | wsym[7] := oddsym; wsym[8] := procsym; 784 | wsym[9] := readsym; wsym[10]:= thensym; 785 | wsym[11]:= varsym; wsym[12]:= whilesym; 786 | wsym[13]:= writesym; 787 | 788 | {*操作符集合,但是ssym['<']和ssym['>']没有必要设置,前面没有使用到这个数组来赋值*} 789 | ssym['+'] := plus; ssym['-'] := minus; 790 | ssym['*'] := times; ssym['/'] := slash; 791 | ssym['('] := lparen; ssym[')'] := rparen; 792 | ssym['='] := eql; ssym[','] := comma; 793 | ssym['.'] := period; 794 | ssym['<'] := lss; ssym['>'] := gtr; 795 | ssym[';'] := semicolon; 796 | 797 | {*mnemonic是汇编指令,在前面被定义为枚举类型下标的数组*} 798 | mnemonic[lit] := 'LIT '; mnemonic[opr] := 'OPR '; 799 | mnemonic[lod] := 'LOD '; mnemonic[sto] := 'STO '; 800 | mnemonic[cal] := 'CAL '; mnemonic[int] := 'INT '; 801 | mnemonic[jmp] := 'JMP '; mnemonic[jpc] := 'JPC '; 802 | mnemonic[red] := 'RED '; mnemonic[wrt] := 'WRT '; 803 | 804 | {*声明符号*} 805 | declbegsys := [ constsym, varsym, procsym ]; 806 | {*控制结构状态符号*} 807 | statbegsys := [ beginsym, callsym, ifsym, whilesym]; 808 | facbegsys := [ ident, number, lparen ]; 809 | err := 0;{*重置错误计数器*} 810 | cc := 0;{*重置指针位置*} 811 | cx := 0;{*重置code数组中的指令下标指示*} 812 | ll := 0;{*重置单行长度计数器*} 813 | ch := ' ';{*初始化读入的最后一个字符*} 814 | kk := al;{*如果上一个标识符的长度比这个标识符长,就要把这个标识符后面的那些上一个残留的字符清除掉*} 815 | getsym;{*读入一个单词,如果是标识符或保留字则读入a数组,如果是纯数字,数字将存在num中,如果是其他symbol,则将存在sym中*} 816 | block( 0,0,[period]+declbegsys+statbegsys );{*开始读取主程序代码*} 817 | if sym <> period{*如果读取主程序结束后最后一个单词不是.的话说明程序不是以.结尾,抛出9号错误*} 818 | then error(9); 819 | if err = 0 820 | then interpret{*如果编译没有出错的话,就开始执行P-code?*} 821 | else write('ERRORS IN PL/0 PROGRAM');{*否则就输出在程序中存在错误*} 822 | writeln; 823 | close(fin) 824 | end. 825 | ``` -------------------------------------------------------------------------------- /Docs/QuaterInstr.md: -------------------------------------------------------------------------------- 1 | # QuaterInstr Design 2 | 3 | 在四元式的设计中,为了能够在四元式中获取更多的信息,进行更多的判断,我使用了符号表项指针作为四元式的基本单位。四元式类的属性定义如下: 4 | ```c++ 5 | class QuaterInstr { 6 | //op des src1 src2 7 | private: 8 | Opcode op; 9 | SymbolItem* des; 10 | SymbolItem* src1; 11 | SymbolItem* src2; 12 | }; 13 | ``` 14 | 其中`Opcode`是枚举类,其中包含了如下表的26种四元式操作码。 15 | 16 | 下表中的属性分为三种:`Label`、`SymbolSet*`、`SymbolItem*`。 17 | 18 | `SymbolItem*`是指向符号表项的指针,而`SymbolSet*`是指向某个符号表的指针,`Label`是标明跳转点的标签 19 | 20 | 21 | | 四元式操作码 | 语义 |公式表示 | 属性 | 22 | | ---- | :----: | :---: | :---: | 23 | |ADD |两个数相加,将结果存放在目标操作数中 | des = src1 + src2 |des: SymbolItem\*、src1:SymbolItem\*、src2:SymbolItem\* | 24 | |SUB |两个数相减,将结果存放在目标操作数中 |des = src1 - src2 |des:SymbolItem\*、src1:SymbolItem\*、src2:SymbolItem\*| 25 | |MUL |两个数相乘,将结果存放在目标操作数中 |des = src1 * src2 |des:SymbolItem\*、src1:SymbolItem\*、src2:SymbolItem\*| 26 | |DIV |两个数相除,将结果的低32位放在目标操作数中 |des = src1 / src2 | des:SymbolItem\*、src1:SymbolItem\*、src2:SymbolItem\*| 27 | |NEG |源操作数值取反,赋给目标操作数| des = -src1 |des:SymbolItem\*、src1:SymbolItem\*| 28 | |BGR |如果源操作数1大于源操作数2,则跳转向目标label预定位置 |if src1 > src2 then goto des |des: Label、src1:SymbolItem\*、src2:SymbolItem\*| 29 | |BGE |如果源操作数1大于等于源操作数2,则跳转向目标label预定位置 |if src1>= src2 then goto des | des: Label、src1:SymbolItem\*、src2:SymbolItem\*| 30 | |BLS |如果源操作数1小于等于源操作数2,则跳转向目标label预定位置 |if src1> src2 then goto des | des: Label、src1:SymbolItem\*、src2:SymbolItem\*| 31 | |BLE |如果源操作数1小于源操作数2,则跳转向目标label预定位置 |if src1<=src2 then goto des| des: Label、src1:SymbolItem\* 、src2:SymbolItem\*| 32 | |BEQ |如果源操作数1等于源操作数2,则跳转向目标label预定位置 |if src1 == src2 then goto des | des: Label、src1:SymbolItem\*、src2:SymbolItem\*| 33 | |BNE |如果源操作数1不等于源操作数2,则跳转向目标label预定位置| if src1 <> 0 then goto des | des:Label、src1:SymbolItem\*、src2:SymbolItem\*| 34 | |ASS |将源操作数1的值赋给目标操作数|des = src1 | des:SymbolItem\*、src1:SymbolItem\*| 35 | |ASSADD |将源操作数1的值赋给目标操作数作为地址所指向的变量 |[des] = src1| des:SymbolItem\*、src1:SymbolItem\*| 36 | |ARRADD |将源操作数1的地址取出,加上偏移量源操作数2的值,结果赋给目标操作数 |des = &src1 + src2 |des:SymbolItem\*、src1:SymbolItem\*、src2:SymbolItem\*| 37 | |ARRASS |将源操作数1作为地址所指向变量的值取出,赋给目标操作数| des = [src1]|des:SymbolItem\*、src1:SymbolItem\*| 38 | |JUMP |无条件跳转到目标Label |Goto des|des: Label| 39 | |SETL |打一个标签Label用于在汇编中的跳转 |set a lable:des | des: Label| 40 | |READ |通过mips中的系统调用实现输入 |Read using syscall | des:SymbolItem\*| 41 | |WRITE |通过mips中的系统调用和asciiz实现包括常量、变量、数组元素、字符串等的输出 |Print using syscall | des:SymbolItem\* | 42 | |BEGIN |函数的运行部分开始 | Get the symbolset | des:SymbolSet\* | 43 | |END |函数的运行部分编译结束,退栈操作 |Symbolset goback| des:SymbolSet\*| 44 | |CALL |调用des,需要调用者和被调用者对应的符号表的信息 |call src1 in des| des:SymbolSet\*、src1:SymbolSet\*| 45 | |PUSH |普通参数压栈 |push des | des:SymbolItem\*| 46 | |PUSHVAR |将带var的参数压入栈 |push des | des:SymbolItem\*| 47 | |INC |在for循环中循环变量每次自增 |des = des +1 | des:SymbolItem\*| 48 | |DEC |在for循环中循环变量每次自减 |des = des - 1 | des:SymbolItem\*| 49 | 50 | -------------------------------------------------------------------------------- /Docs/ReadAndTest.md: -------------------------------------------------------------------------------- 1 | ## 正确测试程序 2 | 3 | 也可以在这里获取测试程序的txt版本:[链接](https://github.com/SivilTaram/Compiler/tree/master/Tests/ComplexSamples) 4 | 5 | ### 1、全覆盖正确测试程序 6 | ```pascal 7 | const test1j = ' ', test5c5='s',const77=233; 8 | var i,index,test22,test33,test44,test55,test77,test88,test99,test1010:integer; 9 | hehe:char; 10 | test66:array[10] of integer; 11 | test5c:array[10] of char; 12 | procedure Test1(j:char); 13 | begin 14 | write("Test1 begin"); 15 | write(j); 16 | write("success"); 17 | write("\n"); 18 | end; 19 | procedure Test2(var j:integer); 20 | procedure Test2T2(var j:integer); 21 | begin 22 | j := 5; 23 | end; 24 | begin 25 | write("Test2 begin"); 26 | j := 3; 27 | Test2T2(j); 28 | end; 29 | function Test3(i:integer):integer; 30 | begin 31 | write("Test3 begin"); 32 | Test3 := i; 33 | end; 34 | function Test4(i:integer):integer; 35 | var j:integer; 36 | begin 37 | if i=0 then 38 | begin 39 | write("Test4 begin"); 40 | Test4 := 0 41 | end 42 | else 43 | begin 44 | j := i + Test4(i-1); 45 | Test4 := j; 46 | end 47 | end; 48 | function Test5:char; 49 | const s = 's'; 50 | begin 51 | write("Test5 begin"); 52 | Test5 := s; 53 | end; 54 | procedure Test6(var i:integer); 55 | begin 56 | write("Test6 begin"); 57 | do 58 | i:=i+2 59 | while i<5; 60 | end; 61 | function Test7(i,j,k,h:integer;m:char):integer; 62 | var temp:integer; 63 | begin 64 | write("Test7 begin"); 65 | temp := (m * h + k)/j - i +27; 66 | j := +temp; 67 | j := -j; 68 | Test7 := j; 69 | end; 70 | function Test8(j:integer):integer; 71 | var i,ret:integer; 72 | begin 73 | write("Test8 begin"); 74 | ret := 0; 75 | for j:=(23-20) downto 2 do 76 | for i:= 1 to index do 77 | ret := ret+i*j; 78 | Test8 := -ret; 79 | end; 80 | function Test9(para:integer):integer; 81 | begin 82 | if para = 3 then 83 | write("Test9 begin"); 84 | Test9 := para*3; 85 | end; 86 | procedure Test10; 87 | procedure Test1010; 88 | var test1010:integer; 89 | begin 90 | test1010:=1010; 91 | end; 92 | begin 93 | write("Test10 begin"); 94 | test1010:=test1010 * 6; 95 | Test1010; 96 | end; 97 | procedure Test11; 98 | procedure Test11; 99 | begin 100 | write("Test11 begin"); 101 | end; 102 | begin 103 | Test11; 104 | end; 105 | begin 106 | test22 := 3; 107 | for i:= 1 to 110/10 do 108 | begin 109 | read(index); 110 | if index = 1 then 111 | Test1(test1j) 112 | else if index = 2 then 113 | begin 114 | Test2(test22); 115 | if test22 = 5 then 116 | begin 117 | write(" success"); 118 | write("\n") 119 | end 120 | else 121 | write("fail"); 122 | end 123 | else if index = 3 then 124 | begin 125 | test33 := Test3(55); 126 | if test33 = 55 then 127 | begin 128 | write(" success"); 129 | write("\n") 130 | end 131 | end 132 | else if index = 4 then 133 | begin 134 | test44 := Test4(5); 135 | if test44 = 15 then 136 | begin 137 | write(" success"); 138 | write("\n") 139 | end 140 | end 141 | else if index = 5 then 142 | begin 143 | test5c[5] := Test5; 144 | if test5c[5] = test5c5 then 145 | write(" success\n"); 146 | end 147 | else if index = 6 then 148 | begin 149 | Test6(test66[3]); 150 | test22 := test66[3]; 151 | if test22 = 6 then 152 | write(" success\n"); 153 | end 154 | else if index = 7 then 155 | begin 156 | test77 := Test7(27,5,20,3,test5c5); 157 | if test77 = -73 then 158 | write(" success\n"); 159 | end 160 | else if index = 8 then 161 | begin 162 | test88 := Test8(233); 163 | if test88 = -180 then 164 | write(" success\n"); 165 | end 166 | else if index = 9 then 167 | begin 168 | test99 := Test9(Test9(Test9(3))); 169 | if test99 = 81 then 170 | write(" success\n"); 171 | end 172 | else if index = 10 then 173 | begin 174 | test1010 := 5; 175 | Test10; 176 | if test1010 = 30 then 177 | write(" success\n"); 178 | end 179 | else if index = 11 then 180 | begin 181 | Test11; 182 | end 183 | end; 184 | read(hehe); 185 | test5c[6] := hehe; 186 | write("You input",test5c[6]); 187 | write("Finished!\n"); 188 | end. 189 | ``` 190 | ### 2、全覆盖正确测试程序2 191 | ```pascal 192 | const constchar='c'; 193 | var vara : integer; 194 | arr:array[100] of integer; 195 | procedure testmulti(var c :integer); 196 | begin 197 | c := c+6; 198 | end; 199 | procedure testvar(var b :integer); 200 | begin 201 | b := b+1; 202 | write("|",b); 203 | testmulti(b); 204 | end; 205 | procedure testPara(c,j:integer;a:char); 206 | var b:integer; 207 | begin 208 | b := c; 209 | c := -c; 210 | if b = -c then 211 | write("|success neg"); 212 | write("|a:",a); 213 | j :=12 / c; 214 | write("|j:",j); 215 | c := a + (vara * j); 216 | write("|c:",c); 217 | end; 218 | function testFuncReturn:integer; 219 | begin 220 | testFuncReturn := 999; 221 | end; 222 | procedure f(b:integer); 223 | begin 224 | if b = 1 then 225 | write("|",b) 226 | else 227 | begin 228 | write("|",b); 229 | f(b-1); 230 | end 231 | end; 232 | procedure testFor; 233 | begin 234 | for vara:=1 to 10 do 235 | write("|",vara) 236 | end; 237 | procedure testDo; 238 | begin 239 | do 240 | begin 241 | write("|",vara); 242 | vara := vara -1 ; 243 | end 244 | while vara >= 1; 245 | end; 246 | begin 247 | vara := 0; 248 | testvar(vara); 249 | write("|vara:",vara); 250 | vara := testFuncReturn; 251 | if vara = 999 then 252 | write("|success fun return") 253 | else 254 | write("|fail fun return"); 255 | testPara(4,6,constchar); 256 | f(8); 257 | arr[1] := 6; 258 | arr[2] := arr[1] * arr[1]; 259 | write("|arr[1]:",arr[1]); 260 | write("|arr[2]:",arr[2]); 261 | testFor; 262 | testDo; 263 | read(vara); 264 | write("|readint vara:",vara); 265 | end. 266 | ``` 267 | 268 | ### 3、条件判断 269 | ```pascal 270 | procedure testCondition(x,y:integer); 271 | begin 272 | write(" testCondition begin:"); 273 | if x=y then write(" x=y:true") else write(" x=y:false"); 274 | if x>y then write(" x>y:true") else write(" x>y:false"); 275 | if x=y then write(" x>=y:true") else write(" x>=y:false"); 277 | if x<=y then write(" x<=y:true") else write(" x<=y:false"); 278 | if x<>y then write(" x<>y:true") else write(" x<>y:false"); 279 | write(" test end \r\n") 280 | end; 281 | begin 282 | testCondition(2,2); 283 | testCondition(1,3); 284 | testCondition(3,1); 285 | end. 286 | ``` 287 | ### 4、类型转换 288 | ```pascal 289 | const sc='c'; 290 | var c,a,j,vara:integer; 291 | i:char; 292 | cc:array[100] of char; 293 | cc2:array[100] of integer; 294 | function A:char; 295 | begin 296 | A := sc; 297 | end; 298 | begin 299 | i := A; 300 | write(i); 301 | c := i; 302 | write(c); 303 | cc[2] := i; 304 | write(cc[2]); 305 | cc2[2] := cc[2]; 306 | write(cc2[2]); 307 | a := i+j-c; 308 | write(a); 309 | end. 310 | ``` 311 | 312 | ### 5、正确程序之测试函数与变量的作用域 313 | ```pascal 314 | var B:integer; 315 | function A:integer; 316 | var B:char; 317 | function C:integer; 318 | begin 319 | write("this is the second C\n"); 320 | C := 2; 321 | end; 322 | begin 323 | write("this is the second A\n"); 324 | A := 97; 325 | end; 326 | function C:integer; 327 | var B:integer; 328 | function A:integer; 329 | begin 330 | write("this is the second A\n"); 331 | A := 99; 332 | end; 333 | begin 334 | if A = 99 then 335 | write("correct,call inner A:") 336 | else 337 | write("not correct,call the wrong A"); 338 | B := 5; 339 | write("the inner B:",B); 340 | write("\n"); 341 | C := -1; 342 | end; 343 | procedure D; 344 | var D:integer; 345 | begin 346 | write("this is the procedure D\n"); 347 | if C = -1 then 348 | begin 349 | D := C; 350 | write("correct,this is the var D:",D); 351 | end 352 | else 353 | write("not correct,call the wrong C"); 354 | write("\n"); 355 | D := A; 356 | end; 357 | begin 358 | write("the init of outter B:",B); 359 | write("\n"); 360 | B := C; 361 | write("the last of outter B:",B); 362 | write("\n"); 363 | D; 364 | end. 365 | ``` 366 | 367 | 正确程序的输出结果依次是: 368 | 369 | 1、顺次输入1到11,再输入一个a,有如下结果 370 | ``` 371 | **** user input : 1 372 | Test1 begin success 373 | **** user input : 2 374 | Test2 begin success 375 | **** user input : 3 376 | Test3 begin success 377 | **** user input : 4 378 | Test4 begin success 379 | **** user input : 5 380 | Test5 begin success 381 | **** user input : 6 382 | Test6 begin success 383 | **** user input : 7 384 | Test7 begin success 385 | **** user input : 8 386 | Test8 begin success 387 | **** user input : 9 388 | Test9 begin success 389 | **** user input : 10 390 | Test10 begin success 391 | **** user input : 11 392 | Test11 begin**** user input : a 393 | You inputaFinished! 394 | ``` 395 | 2、输入1个数字12,直接运行即可 396 | ``` 397 | |1|vara:7|success fun return|success neg|a:c|j:-3|c:-2898|8|7|6|5|4|3|2|1|arr[1]:6|arr[2]:36|1|2|3|4|5|6|7|8|9|10|11|10|9|8|7|6|5|4|3|2|1**** user input : 12 398 | |readint vara:12 399 | ``` 400 | 401 | 3、无输入,直接运行即可 402 | ``` 403 | testCondition begin: x=y:true x>y:false x=y:true x<=y:true x<>y:false test end 404 | testCondition begin: x=y:false x>y:false x=y:false x<=y:true x<>y:true test end 405 | testCondition begin: x=y:false x>y:true x=y:true x<=y:false x<>y:true test end 406 | ``` 407 | 408 | 4、无输入,直接运行即可 409 | ``` 410 | c99c990 411 | ``` 412 | 5、无输入,直接运行即可 413 | ``` 414 | the init of outter B:0 415 | this is the second A 416 | correct,call inner A:the inner B:5 417 | the last of outter B:-1 418 | this is the procedure D 419 | this is the second A 420 | correct,call inner A:the inner B:5 421 | this is the second A 422 | correct,call inner A:the inner B:5 423 | correct,this is the var D:-1 424 | this is the second A 425 | ``` -------------------------------------------------------------------------------- /Docs/SymbolSetDesign.md: -------------------------------------------------------------------------------- 1 | # SymbolSet Design 2 | 3 | 在我的设计中,符号表中有着如下信息: 4 | ```c++ 5 | class SymbolSet{ 6 | public: 7 | // the pointer to the father of a procedure or a function. 8 | SymbolSet* father_table; 9 | private: 10 | SymbolItem* proc; 11 | vector local_list; 12 | map symbol_map; 13 | //store the names of current level function or procedure. 14 | map table_map; 15 | int level; 16 | int stack_size; 17 | int args_size; 18 | int display_size; 19 | }; 20 | ``` 21 | 22 | `father_table`是指向父符号表的指针,`proc`是该符号表对应的符号表项。 23 | 24 | 在我的设计中,编译某个分程序的声明部分时,会在其父符号表中插入一个该分程序对应的符号表项,并且生成一个新的符号表。 25 | 26 | - *local_list* 是局部变量集合 27 | - *symbol_map* 和 *table_map* 的设计会在后面详述。 28 | - *Level* 是当前符号表的层次,0为起始值。 29 | - *Stack_size* 是符号表在生成四元式时计算偏移时所用的,记录了该分程序所使用的所有栈空间大小。 30 | - *args_size* 是该分程序所有的参数所占空间的大小 31 | - *display_size* 是display区的大小。 32 | 33 | 在我的设计中,符号表设计了很久,符号表设计很久主要是考虑了几点问题: 34 | 35 | 1. 函数与过程互相的调用关系 36 | 2. 同名变量的不同作用域 37 | 3. 同名函数、同名过程的不同作用域 38 | 4. 函数与过程互相之间的可见与封装 39 | 40 | 最终采用的方案是经过跟同学探讨后得到的一种方案,这种方案设计上很像一颗B树,但是其中加入了一个很重要的东西:父指针,这种方案的设计如下图可以很清楚地可以看出。 41 | 42 | ![SymbolSetDesign.png](http://static.zybuluo.com/lq372899855/pcbpxktusurznusvgbdxh3cn/SymbolDesign.png) 43 | 44 | 在此图中可以看出,我设置了一个root_table来作为根符号表,是SymbolSet类的一个实例化对象。实际上在RootSymbolSet类的设计中,除了需要设置一个根符号表外,还需要一个符号表指针指向当前的符号表,即current_table。它永远指向当前的符号表,只有四元式BEGIN和END能够改变current_table指针,其中BEGIN是将current_table指向要编译的某个子函数/过程,而END则是将current_table设置为当前符号表的father_table,回退到上一级符号表。 45 | 46 | 插入符号表时需要判断是否重复定义,为了方便地实现这一点,我在SymbolSet符号表类中加入了 47 | ```c++ 48 | map symbol_map 49 | ``` 50 | HashMap可以方便地寻找是否在当前符号表中已经有过定义。 51 | 52 | 在符号表中查找时,主要面临的问题在于跨域使用,并且最重要的问题在于要从本层符号表开始向上寻找,即一个变量或常量等如果不在本层中定义过,则要到其父符号表中去搜索,如果还没有就继续向上搜索,直到搜索到root_table,root_table的父符号表为NULL。 53 | 54 | 在函数和过程调用的作用域的查找上,和变量/常量的查找思路是一致的,首先在本层的符号表中进行检索,再向上检索。这样的做法和pascal中对不同函数的作用域和互相隐藏的原则是一致的:即一个函数/过程只能调用的有: 55 | 56 | 1. 在其前出现过的同层函数/过程(在本层符号表的父符号表中) 57 | 2. 本层符号表中记录的直接子函数/过程(在本层的符号表中) 58 | 3. 包括父亲在内的祖先函数/过程(祖先符号表中) 59 | 60 | 因为调用函数/过程的语句从四元式生成到汇编时需要计算每个变量是否分配空间,偏移量是多少,数组如何分配空间等问题,在查找到某个函数/过程时,光能查找到其所对应的符号表项是不够的,因为在我的符号表项中没有记录多余的信息。所以这时候必须借助函数/过程对应的符号表,所以有必要在符号表中设置其直接子符号表的集合,我设置的子符号表的集合即 61 | ```c++ 62 | map table_map 63 | ``` 64 | 65 | 还有一点需要额外提到的是,从四元式到目标代码的过程中,需要符号表中登记的各个变量的(包括分配空间的临时变量)偏移信息。而这一步计算我没有放在插入符号表的时候进行,而是放在了从四元式生成到目标代码前所做的预操作——计算偏移量。 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /Project/Compiler.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Compiler", "Compiler\Compiler.vcxproj", "{B0F527E3-94F8-4055-ACB9-6CDE4D2196B0}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {B0F527E3-94F8-4055-ACB9-6CDE4D2196B0}.Debug|x64.ActiveCfg = Debug|x64 17 | {B0F527E3-94F8-4055-ACB9-6CDE4D2196B0}.Debug|x64.Build.0 = Debug|x64 18 | {B0F527E3-94F8-4055-ACB9-6CDE4D2196B0}.Debug|x86.ActiveCfg = Debug|Win32 19 | {B0F527E3-94F8-4055-ACB9-6CDE4D2196B0}.Debug|x86.Build.0 = Debug|Win32 20 | {B0F527E3-94F8-4055-ACB9-6CDE4D2196B0}.Release|x64.ActiveCfg = Release|x64 21 | {B0F527E3-94F8-4055-ACB9-6CDE4D2196B0}.Release|x64.Build.0 = Release|x64 22 | {B0F527E3-94F8-4055-ACB9-6CDE4D2196B0}.Release|x86.ActiveCfg = Release|Win32 23 | {B0F527E3-94F8-4055-ACB9-6CDE4D2196B0}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Project/Compiler/Compiler.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {B0F527E3-94F8-4055-ACB9-6CDE4D2196B0} 23 | Win32Proj 24 | Compiler 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | true 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | true 106 | 107 | 108 | Console 109 | true 110 | 111 | 112 | 113 | 114 | Level3 115 | 116 | 117 | MaxSpeed 118 | true 119 | true 120 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 121 | true 122 | 123 | 124 | Console 125 | true 126 | true 127 | true 128 | 129 | 130 | 131 | 132 | Level3 133 | 134 | 135 | MaxSpeed 136 | true 137 | true 138 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 139 | true 140 | 141 | 142 | Console 143 | true 144 | true 145 | true 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /Project/Compiler/Compiler.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | 源文件 26 | 27 | 28 | 源文件 29 | 30 | 31 | 源文件 32 | 33 | 34 | 35 | 36 | 头文件 37 | 38 | 39 | 头文件 40 | 41 | 42 | 头文件 43 | 44 | 45 | 头文件 46 | 47 | 48 | -------------------------------------------------------------------------------- /Project/Compiler/Error.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SivilTaram/Compiler/6b8072617c5acffcc7eb1a5a1b89cc42d28314ca/Project/Compiler/Error.cpp -------------------------------------------------------------------------------- /Project/Compiler/Lexer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SivilTaram/Compiler/6b8072617c5acffcc7eb1a5a1b89cc42d28314ca/Project/Compiler/Lexer.cpp -------------------------------------------------------------------------------- /Project/Compiler/Main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SivilTaram/Compiler/6b8072617c5acffcc7eb1a5a1b89cc42d28314ca/Project/Compiler/Main.cpp -------------------------------------------------------------------------------- /Project/Compiler/MiddleCode.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include"middlecode.h" 3 | 4 | QuaterInstr* MiddleCode::gen(Opcode _op, SymbolItem* _des, SymbolItem* _src1, SymbolItem* _src2) { 5 | QuaterInstr* new_quater_instr = new QuaterInstr(_op, _des, _src1, _src2); 6 | //add the quater code to the middle code. 7 | middle_codes.push_back(new_quater_instr); 8 | return new_quater_instr; 9 | } 10 | 11 | //print all of the middle codes. 12 | void MiddleCode::printMiddleCode() { 13 | vector::iterator it = middle_codes.begin(); 14 | while (it != middle_codes.end()) { 15 | (*it)->printQuater(); 16 | it++; 17 | cout << endl; 18 | } 19 | } 20 | 21 | //.asciiz 22 | //.data for print 23 | void MiddleCode::addDataSeg(string _stringconst) { 24 | data_const_string.push_back(_stringconst); 25 | } 26 | 27 | vector* MiddleCode::getMiddleCode() { 28 | return &middle_codes; 29 | } -------------------------------------------------------------------------------- /Project/Compiler/MipsInstr.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SivilTaram/Compiler/6b8072617c5acffcc7eb1a5a1b89cc42d28314ca/Project/Compiler/MipsInstr.cpp -------------------------------------------------------------------------------- /Project/Compiler/Parser.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SivilTaram/Compiler/6b8072617c5acffcc7eb1a5a1b89cc42d28314ca/Project/Compiler/Parser.cpp -------------------------------------------------------------------------------- /Project/Compiler/QuaterInstr.cpp: -------------------------------------------------------------------------------- 1 | #include "quaterinstr.h" 2 | #include "sstream" 3 | 4 | void QuaterInstr::printQuater() { 5 | string opcode_name = printOpcode(); 6 | stringstream output; 7 | 8 | if(op!=Opcode::SETL) 9 | output << "\t" << opcode_name << "\t"; 10 | 11 | if (op == Opcode::BEGIN || op == Opcode::END) { 12 | output << ((SymbolSet *)des)->getProcLabelName() << "\t"; 13 | } 14 | else if (des == NULL && op != Opcode::SETL) 15 | output << "-\t"; 16 | else if (des->getKind() == TokenKind::TEMP_CON && des->getType() == TokenType::inttyp) 17 | output << des->getValue() << "\t"; 18 | else if (des->getKind() == TokenKind::TEMP_CON && des->getType() == TokenType::stringtyp) 19 | output << des->getString() << "\t"; 20 | else if (des->getKind() == TokenKind::TEMP_CON && des->getType() == TokenType::chartyp) 21 | output << (char)des->getValue() << "\t"; 22 | else if (des->getKind() == TokenKind::TEMP_ADD &&( op == Opcode::ASSADD || op==Opcode::ARRASS)) 23 | output << "[" << des->getName() << "]\t"; 24 | else if (des->getKind() == TokenKind::TEMP_ADD && op == Opcode::ARRADD) 25 | output << des->getName() << "\t"; 26 | else if (des->getKind() == TokenKind::VAR) 27 | output << des->getName() << "\t"; 28 | else if (des->getKind() == TokenKind::TEMP) 29 | output << des->getName() << "\t"; 30 | else if (des->getKind() == TokenKind::LABEL) 31 | output << des->getName() << "\t"; 32 | else if (des->getKind() == TokenKind::FUNC) 33 | output << des->getString() << "\t"; 34 | else if (des->getKind() == TokenKind::PROC) 35 | output << des->getString() << "\t"; 36 | else if (des->getKind() == TokenKind::ARRAY) 37 | output << des->getName() << "\t"; 38 | else if (des->getKind() == TokenKind::CONST) 39 | output << des->getName() << "\t"; 40 | 41 | if (op == Opcode::SETL) 42 | output << ""; 43 | else if (src1 == NULL) 44 | output << "-\t"; 45 | else if (src1->getKind() == TokenKind::TEMP_CON && src1->getType() == TokenType::inttyp) 46 | output << src1->getValue() << "\t"; 47 | else if (src1->getKind() == TokenKind::TEMP_CON && src1->getType() == TokenType::stringtyp) 48 | output << src1->getString() << "\t"; 49 | else if (src1->getKind() == TokenKind::TEMP_CON && src1->getType() == TokenType::chartyp) 50 | output << (char)src1->getValue() << "\t"; 51 | else if (src1->getKind() == TokenKind::TEMP_ADD && (op == Opcode::ASSADD || op == Opcode::ARRASS)) 52 | output << "[" << src1->getName() << "]\t"; 53 | else if (src1->getKind() == TokenKind::TEMP_ADD && op == Opcode::ARRADD) 54 | output << src1->getName() << "\t"; 55 | else if (src1->getKind() == TokenKind::TEMP) 56 | output << src1->getName() << "\t"; 57 | else if (src1->getKind() == TokenKind::VAR) 58 | output << src1->getName() << "\t"; 59 | else if (src1->getKind() == TokenKind::FUNC) 60 | output << src1->getString() << "\t"; 61 | else if (src1->getKind() == TokenKind::PROC) 62 | output << src1->getString() << "\t"; 63 | else if (src1->getKind() == TokenKind::ARRAY) 64 | output << src1->getName() << "\t"; 65 | else if (src1->getKind() == TokenKind::CONST) 66 | output << src1->getName() << "\t"; 67 | 68 | if (op == Opcode::SETL) 69 | output << ""; 70 | else if (src2 == NULL) 71 | output << "-\t"; 72 | else if (src2->getKind() == TokenKind::TEMP_CON && src2->getType() == TokenType::inttyp) 73 | output << src2->getValue() << "\t"; 74 | else if (src2->getKind() == TokenKind::TEMP_CON && src2->getType() == TokenType::stringtyp) 75 | output << src2->getString() << "\t"; 76 | else if (src2->getKind() == TokenKind::TEMP_CON && src2->getType() == TokenType::chartyp) 77 | output << (char)src2->getValue() << "\t"; 78 | else if (src2->getKind() == TokenKind::TEMP_ADD && (op == Opcode::ASSADD || op == Opcode::ARRASS)) 79 | output << "[" << src2->getName() << "]\t"; 80 | else if (src2->getKind() == TokenKind::TEMP_ADD && op == Opcode::ARRADD) 81 | output << src2->getName() << "\t"; 82 | else if (src2->getKind() == TokenKind::VAR) 83 | output << src2->getName() << "\t"; 84 | else if (src2->getKind() == TokenKind::TEMP) 85 | output << src2->getName() << "\t"; 86 | else if (src2->getKind() == TokenKind::LABEL) 87 | output << src2->getName() << "\t"; 88 | else if (src2->getKind() == TokenKind::FUNC) 89 | output << src2->getString() << "\t"; 90 | else if (src2->getKind() == TokenKind::PROC) 91 | output << src2->getString() << "\t"; 92 | else if (src2->getKind() == TokenKind::ARRAY) 93 | output << src2->getName() << "\t"; 94 | else if (src1->getKind() == TokenKind::CONST) 95 | output << src1->getName() << "\t"; 96 | 97 | cout << output.str(); 98 | } 99 | 100 | string QuaterInstr::printOpcode() { 101 | switch (op) 102 | { 103 | case ADD:return "ADD\t"; 104 | case SUB:return "SUB\t"; 105 | case MUL:return "MUL\t"; 106 | case DIV:return "DIV\t"; 107 | case NEG:return "NEG\t"; 108 | case BGR:return "BGR\t"; 109 | case BGE:return "BGE\t"; 110 | case BLS:return "BLS\t"; 111 | case BLE:return "BLE\t"; 112 | case BEQ:return "BEQ\t"; 113 | case BNE:return "BNE\t"; 114 | case ASS:return "ASS\t"; 115 | case ARRADD:return "ARRADD\t"; 116 | case ASSADD:return "ASSDD\t"; 117 | case JUMP:return "JUMP\t"; 118 | case SETL:return ""; 119 | case READ:return "READ\t"; 120 | case WRITE:return "WRITE\t"; 121 | case BEGIN:return "BEGIN\t"; 122 | case END:return "END\t"; 123 | case PUSH:return "PUSH\t"; 124 | case PUSHVAR:return "PUSHVAR\t"; 125 | case CALL:return "CALL\t"; 126 | case RETURN:return "RET\t"; 127 | case INC:return "INC\t"; 128 | case DEC:return "DEC\t"; 129 | case ARRASS:return "ARRASS\t"; 130 | default: 131 | break; 132 | } 133 | return "NULL\t"; 134 | } 135 | 136 | SymbolItem* QuaterInstr::getDes() { 137 | return des; 138 | } 139 | 140 | SymbolItem* QuaterInstr::getSrc1() { 141 | return src1; 142 | } 143 | 144 | SymbolItem* QuaterInstr::getSrc2() { 145 | return src2; 146 | } 147 | 148 | Opcode QuaterInstr::getOpType() { 149 | return op; 150 | } 151 | 152 | QuaterInstr::QuaterInstr(Opcode _op, SymbolItem* _des, SymbolItem* _src1, SymbolItem* _src2) { 153 | op = _op; 154 | des = _des; 155 | src1 = _src1; 156 | src2 = _src2; 157 | } -------------------------------------------------------------------------------- /Project/Compiler/RootSymbolSet.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "rootsymbolset.h" 3 | #include 4 | RootSymbolSet::RootSymbolSet() { 5 | SymbolItem* root_item = new SymbolItem("root_",TokenKind::PROC,TokenType::voidtyp); 6 | root_item->setString("root_"); 7 | //allocate a new table for root function. 8 | root_table = new SymbolSet(root_item, NULL, 0); 9 | current_table = root_table; 10 | } 11 | //look up to search the variable _name 12 | //util the root. 13 | SymbolItem* RootSymbolSet::search(string _name) { 14 | SymbolSet* temp = current_table; 15 | SymbolItem* result = NULL; 16 | while (temp != NULL) { 17 | result = temp->getItem(_name); 18 | //if found,then exit; 19 | if (result != NULL) 20 | return result; 21 | //else look up and search. 22 | temp = temp->father_table; 23 | } 24 | temp = current_table; 25 | result = NULL; 26 | while (temp != NULL) { 27 | //find the func 28 | result = temp->getItem(temp->getProcName() + _name + "_"); 29 | if (result != NULL) 30 | return result; 31 | temp = temp->father_table; 32 | } 33 | return NULL; 34 | } 35 | 36 | //Insert new Symbol to SymbolSet if no item with same name already exists. 37 | SymbolItem* RootSymbolSet::insert(string _name, TokenKind _kind, TokenType _type, int _value) { 38 | SymbolItem* item = new SymbolItem(_name, _kind, _type, _value); 39 | string ident_name = item->getName(); 40 | //if item already exist,return NULL; 41 | if (!(current_table->enterItem(item))) 42 | return NULL; 43 | if (_kind == TokenKind::FUNC 44 | || _kind == TokenKind::PROC) 45 | current_table = current_table->enterProc(item); 46 | return item; 47 | } 48 | 49 | //go back to the father table. 50 | // true means back success. false means back failure. 51 | bool RootSymbolSet::goback() { 52 | if (current_table->father_table == NULL) 53 | return false; 54 | current_table = current_table->father_table; 55 | return true; 56 | } 57 | 58 | //generate temporatory variable to store the value of 59 | // middle for QuaterInstr. 60 | SymbolItem* RootSymbolSet::genTemp(TokenKind _kind,TokenType _type,string _tag_string) { 61 | SymbolItem *temp = NULL; 62 | //the temp's count for not repeating. 63 | static int temp_count = 1; 64 | //string name = "!t" + temp_count; 65 | stringstream name; 66 | name << "!TEMP" << temp_count; 67 | temp = new SymbolItem(name.str(), _kind, _type,0,_tag_string); 68 | current_table->enterItem(temp); 69 | temp_count++; 70 | return temp; 71 | } 72 | 73 | //look up to search table; 74 | //[FIXME] 75 | //IMPORTANT!!! 76 | //the proc can call a proc as a result of what reason?! 77 | //We can just conclude that the procedure can call the procedure 78 | //which is the direct son of it and its brother proc, 79 | //and its ancestors. 80 | SymbolSet* RootSymbolSet::serachTable(string _name) { 81 | //look up from this table. 82 | SymbolSet *temp = current_table; 83 | SymbolSet *table = NULL; 84 | while (temp != NULL) { 85 | table = temp->getProcTable(_name); 86 | if (table != NULL) 87 | break; 88 | temp = temp->father_table; 89 | } 90 | //if table is null,there is no reference. 91 | return table; 92 | } 93 | 94 | //find the procedure or function. 95 | //bool RootSymbolSet::findProc(string _name) { 96 | // SymbolSet *temp = current_table; 97 | // while (temp != NULL) { 98 | // if (temp->getProcName()==_name) 99 | // return true; 100 | // temp = temp->father_table; 101 | // } 102 | // //if table is null,there is no reference. 103 | // return false; 104 | //} 105 | 106 | //we should use the name to 107 | string RootSymbolSet::getCurrentName() { 108 | return current_table->getProcName(); 109 | } 110 | 111 | //get the root of the all symbols tables; 112 | SymbolSet* RootSymbolSet::getRootSet() { 113 | return root_table; 114 | } 115 | 116 | //get the current symbol table. 117 | SymbolSet* RootSymbolSet::getCurrentSet() { 118 | return current_table; 119 | } 120 | 121 | //get a label for those for or if statement 122 | SymbolItem* RootSymbolSet::genLabel() { 123 | static int count = 1; 124 | SymbolItem* label = NULL; 125 | stringstream name; 126 | name<< "L_" << count; 127 | //string name = "_L" + count; 128 | label = new SymbolItem(name.str(), TokenKind::LABEL, TokenType::notyp); 129 | current_table->enterItem(label); 130 | //the size of label is zero. 131 | label->setSize(0); 132 | count++; 133 | return label; 134 | } 135 | 136 | vector RootSymbolSet::getArgList(string _name) 137 | { 138 | SymbolSet* table = serachTable(_name); 139 | return table->getArgList(); 140 | } 141 | 142 | void RootSymbolSet::printSymbolSet() { 143 | root_table->printData(); 144 | } 145 | 146 | void RootSymbolSet::calcOffset() { 147 | root_table->calcOffset(); 148 | } -------------------------------------------------------------------------------- /Project/Compiler/SymbolSet.cpp: -------------------------------------------------------------------------------- 1 | #include "symbolset.h" 2 | #include "error.h" 3 | #include 4 | 5 | 6 | SymbolSet::SymbolSet(SymbolItem* _proc, SymbolSet* _father, int _level) { 7 | proc = _proc; 8 | father_table = _father; 9 | level = _level; 10 | } 11 | 12 | //get the item from the symboltable using _name; 13 | SymbolItem* SymbolSet::getItem(string _name) { 14 | map::iterator symbol_it = symbol_map.find(_name); 15 | //if found,we can assert that the name existed. 16 | if (symbol_it != symbol_map.end()) 17 | return symbol_map[_name]; 18 | else 19 | //if return NULL,we can assert the symbolitem is null; 20 | return NULL; 21 | } 22 | 23 | bool SymbolSet::enterItem(SymbolItem * _item) { 24 | string item_name = _item->getName(); 25 | //not found,can insert. 26 | //change the local_list and symbol_map. 27 | if (getItem(item_name) == NULL) 28 | { 29 | _item->setLevel(level); 30 | local_list.push_back(_item); 31 | symbol_map[item_name] = _item; 32 | return true; 33 | } 34 | else 35 | return false; 36 | } 37 | 38 | //get the proc's item. 39 | SymbolItem* SymbolSet::getProcItem() { 40 | return proc; 41 | } 42 | 43 | //get the procedure or function's name mapping SymbolSet. 44 | SymbolSet* SymbolSet::getProcTable(string _name) { 45 | map::iterator it_table = table_map.find(_name); 46 | if (it_table != table_map.end()) 47 | // the it_table's second of 48 | return it_table->second; 49 | else 50 | return NULL; 51 | } 52 | 53 | string SymbolSet::getProcName() { 54 | return proc->getName(); 55 | } 56 | 57 | string SymbolSet::getProcLabelName() { 58 | return proc->getString(); 59 | } 60 | 61 | //get arguments of the procedure or function. 62 | //[FIXME]:IMPORTANT!!! 63 | //The arglist should be in order !!! 64 | vector SymbolSet::getArgList() { 65 | vector args; 66 | vector::iterator it_args = local_list.begin(); 67 | // This is a confused problem 68 | // when I wrote vector 69 | // I can do it. 70 | // but when I replaced it with ARGLIST.It didn't work! 71 | // Why????? 72 | while (it_args != local_list.end()) { 73 | if ((*it_args)->getKind() == TokenKind::PARA 74 | || (*it_args)->getKind() == TokenKind::PARAVAR) 75 | args.push_back(*it_args); 76 | it_args++; 77 | } 78 | return args; 79 | } 80 | 81 | int SymbolSet::getLevel() { 82 | return level; 83 | } 84 | 85 | //enter a Proc into the symbolset,and return a symbolset of the procedure. 86 | SymbolSet* SymbolSet::enterProc(SymbolItem* _proc) { 87 | SymbolSet* son_proc = new SymbolSet(_proc, this, level + 1); 88 | //update the table_map of this table's sons. 89 | table_map[_proc->getName()] = son_proc; 90 | return son_proc; 91 | } 92 | 93 | 94 | void SymbolItem::printData() { 95 | cout << "Name:" << name << " | Kind:" << getKindName() << " | Type:" << getTypeName() << " | Value:" << value << " | size:" << size << " | level:"<< level << "| Offset:"<< offset << endl; 96 | } 97 | 98 | void SymbolSet::printData() { 99 | vector::iterator local_iter = local_list.begin(); 100 | while (local_iter != local_list.end()) { 101 | if ((*local_iter)->getKind() == TokenKind::FUNC || (*local_iter)->getKind() == TokenKind::PROC) { 102 | (*local_iter)->printData(); 103 | string func_name = (*local_iter)->getName(); 104 | SymbolSet* temp_table = table_map[func_name]; 105 | temp_table->printData(); 106 | } 107 | else { 108 | (*local_iter)->printData(); 109 | } 110 | local_iter++; 111 | } 112 | } 113 | 114 | 115 | /* 116 | STACK STRUCTURE 117 | ----------------------------- $fp 118 | arguments: 119 | args_1 120 | args_2 121 | ... 122 | args_n 123 | pre abp 124 | abp(n) 125 | abp(n-1)... 126 | abp(0) 127 | saved return addresss 128 | local variables and structures 129 | saved Regs $s0-$s7 130 | ----------------------------- $sp 131 | 132 | */ 133 | 134 | void SymbolSet::calcOffset() { 135 | //calculate the offset of the arguments. 136 | 137 | int current_offset = 0; 138 | 139 | current_offset += level * 4 + 8; 140 | 141 | //as a reserve order to set the offset. 142 | for (int i = local_list.size() - 1; i >= 0; i--) { 143 | SymbolItem* iter = local_list[i]; 144 | if (iter->getKind() == TokenKind::PARAVAR || iter->getKind() == TokenKind::PARA) 145 | { 146 | args_size += iter->getSize(); 147 | iter->setOffset(current_offset); 148 | current_offset += iter->getSize() * 4; 149 | } 150 | } 151 | 152 | //the return address and s0~s7 153 | stack_size += 9; 154 | 155 | if (this->getProcItem()->getKind() == TokenKind::FUNC) 156 | { 157 | current_offset = -40; 158 | stack_size += 1; 159 | } 160 | else 161 | current_offset = -36; 162 | 163 | vector::iterator iter = local_list.begin(); 164 | 165 | while (iter != local_list.end()) { 166 | SymbolItem* item = *iter; 167 | if (item->getKind() == TokenKind::TEMP 168 | || item->getKind() == TokenKind::VAR 169 | || item->getKind() == TokenKind::TEMP_ADD 170 | ) 171 | { 172 | stack_size += 1; 173 | item->setOffset(current_offset); 174 | current_offset -= 4; 175 | } 176 | else if (item->getKind() == TokenKind::ARRAY) 177 | { 178 | stack_size += item->getSize(); 179 | item->setOffset(current_offset); 180 | current_offset -= item->getSize() * 4; 181 | } 182 | else if (item->getKind() == TokenKind::PROC 183 | || item->getKind() == TokenKind::FUNC) 184 | { 185 | //Recursively; 186 | item->setOffset(0); 187 | SymbolSet* next_table = table_map[item->getName()]; 188 | next_table->calcOffset(); 189 | } 190 | iter++; 191 | } 192 | //if the level = 1,then the SL should be like this: 193 | // abp(0) 194 | // abp(1) 195 | // ... 196 | // abp(n) 197 | display_size = level; 198 | 199 | } 200 | 201 | 202 | int SymbolSet::getDisplaySize() { 203 | if (level >= 1) 204 | return getLevel() * 4; 205 | return 0; 206 | } 207 | 208 | int SymbolSet::getArgsSize() { 209 | return args_size * 4; 210 | } 211 | 212 | int SymbolSet::getStackSize() { 213 | return stack_size * 4; 214 | } -------------------------------------------------------------------------------- /Project/Compiler/SymbolTable.cpp: -------------------------------------------------------------------------------- 1 | #include "symbolset.h" 2 | #include "error.h" 3 | #include 4 | 5 | SymbolSet::SymbolSet() { 6 | level = 0; 7 | } 8 | 9 | int SymbolSet::enter(SymbolItem& item) { 10 | int offset = table.end()->getOffset(); 11 | int itemsize = item.getSize(); 12 | //[FIXME] will we be 4 incedent? 13 | item.setOffset(offset+itemsize); 14 | table.push_back(item); 15 | return (table.size()-1); 16 | } 17 | 18 | int SymbolSet::locIdent(string name) { 19 | int i = level; 20 | int j = 0; 21 | do { 22 | j = display[i]->getLast(); 23 | while (table[j].getName() != name) 24 | j = table[j].getLink(); 25 | i--; 26 | } while (i >= 0 && j == -1); 27 | return j; 28 | } 29 | 30 | TokenType SymbolSet::getType(string name) { 31 | int index = locIdent(name); 32 | if (index == -1) 33 | return TokenType::notyp; 34 | 35 | } 36 | 37 | void SymbolSet::enterproc(SymbolItem& _item, SymbolPro& _pro) { 38 | level++; 39 | table.push_back(_item); 40 | protable.push_back(_pro); 41 | display[level] = &_pro; 42 | } 43 | 44 | void SymbolSet::exitproc() { 45 | level--; 46 | } -------------------------------------------------------------------------------- /Project/Compiler/error.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | class Error { 10 | public: 11 | Error(); 12 | int getErrorCount(); 13 | bool IsSuccess(); 14 | void print(); 15 | void errorMessage(int errortype, int line); 16 | void errorMessage(int errortype, int line, string message1); 17 | void errorMessage(int errortype, int line, string message1, string message2); 18 | private: 19 | bool is_success; 20 | int error_count; 21 | vector error_messages; 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /Project/Compiler/lexer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include"error.h" 3 | #define LINEMAX 1024 4 | #define NMAX 20 5 | using namespace std; 6 | 7 | class Lexer { 8 | //reserved 9 | private: 10 | reserved_map reserved; 11 | //one token. 12 | vector token; 13 | char peek = ' '; 14 | //infile if the source code file; 15 | ifstream infile; 16 | int ll = 0; 17 | int cc = 0; 18 | int linenum = 0; 19 | char buf[LINEMAX]; 20 | Error& error_handle; 21 | 22 | public: 23 | //values for token 24 | Symbol sym; 25 | Lexer(string filename, Error &_error_handle); 26 | void getch(); 27 | Token getsym(); 28 | void initialReserved(); 29 | }; -------------------------------------------------------------------------------- /Project/Compiler/middlecode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "quaterinstr.h" 3 | 4 | class MiddleCode { 5 | private: 6 | vector middle_codes; 7 | vector data_const_string; 8 | public: 9 | QuaterInstr* gen(Opcode _op, SymbolItem* _des , SymbolItem* _src1 , SymbolItem* _src2 ); 10 | void printMiddleCode(); 11 | void addDataSeg(string _stringconst); 12 | vector* getMiddleCode(); 13 | }; -------------------------------------------------------------------------------- /Project/Compiler/mipsinstr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "symbolset.h" 4 | #include "middlecode.h" 5 | #include "quaterinstr.h" 6 | #include "rootsymbolset.h" 7 | 8 | using namespace std; 9 | 10 | 11 | enum MipsCode { 12 | //load to the register 13 | lw, 14 | //store to the memory 15 | sw, 16 | //load the immdiate number. 17 | li, 18 | //load address 19 | la, 20 | //jump and link 21 | jal, 22 | // 23 | jr, 24 | //jumpd 25 | j, 26 | //add the ident 27 | add, 28 | addi, 29 | //sub 30 | sub, 31 | subi, 32 | //mult 33 | mult, 34 | //dive 35 | ddiv, 36 | //assign 37 | move, 38 | //branch 39 | bgez, 40 | blez, 41 | bgtz, 42 | bltz, 43 | beq, 44 | bne, 45 | syscall, 46 | label, 47 | mflo, 48 | note 49 | }; 50 | 51 | 52 | class Instruction { 53 | private: 54 | string op = ""; 55 | string des = ""; 56 | string src1 = ""; 57 | string src2 = ""; 58 | public: 59 | Instruction(MipsCode _op) { 60 | op = getOpName(_op); 61 | } 62 | Instruction(MipsCode _op, string _des) { 63 | op = getOpName(_op); 64 | des = _des; 65 | } 66 | Instruction(MipsCode _op, string _des, string _src1) { 67 | op = getOpName(_op); 68 | des = _des; 69 | src1 = _src1; 70 | } 71 | Instruction(MipsCode _op, string _des, string _src1, string _src2) { 72 | op = getOpName(_op); 73 | des = _des; 74 | src1 = _src1; 75 | src2 = _src2; 76 | } 77 | 78 | string getOpName(MipsCode _opcode) { 79 | switch (_opcode) 80 | { 81 | case lw: 82 | return "lw"; break; 83 | case sw: 84 | return "sw"; break; 85 | case li: 86 | return "li"; break; 87 | case la: 88 | return "la"; break; 89 | case jal: 90 | return "jal"; break; 91 | case jr: 92 | return "jr"; break; 93 | case add: 94 | return "add"; break; 95 | case addi: 96 | return "addi"; break; 97 | case sub: 98 | return "sub"; break; 99 | case subi: 100 | return "subi"; break; 101 | case mult: 102 | return "mul"; break; 103 | case MipsCode::ddiv: 104 | return "div"; break; 105 | case MipsCode::move: 106 | return "move"; break; 107 | case mflo: 108 | return "mflo"; break; 109 | case bgez: 110 | return "bgez"; break; 111 | case blez: 112 | return "blez"; break; 113 | case bgtz: 114 | return "bgtz"; break; 115 | case bltz: 116 | return "bltz"; break; 117 | case beq: 118 | return "beq"; break; 119 | case bne: 120 | return "bne"; break; 121 | case syscall: 122 | return "syscall"; break; 123 | case label: 124 | return ""; break; 125 | case j: 126 | return "j"; break; 127 | case note: 128 | return "#"; break; 129 | default: 130 | break; 131 | } 132 | } 133 | string printInstr() { 134 | return op + des + src1 + src2; 135 | } 136 | }; 137 | 138 | class Dataseg { 139 | private: 140 | string label; 141 | string conststring; 142 | public: 143 | string setData() { 144 | return label + ":" + ".asciiz " + conststring; 145 | } 146 | Dataseg(string _label, string _conststring) { 147 | label = _label; 148 | conststring = _conststring; 149 | } 150 | }; 151 | 152 | class MipsInstr { 153 | public: 154 | //add the instruction to the vector. 155 | MiddleCode middle_code; 156 | RootSymbolSet root_table; 157 | SymbolSet* current_table = NULL; 158 | MipsInstr(MiddleCode& _code, RootSymbolSet& _root); 159 | void add(MipsCode _op) { 160 | object_insrtuctions.push_back(Instruction(_op)); 161 | } 162 | void add(MipsCode _op, string _des) { 163 | object_insrtuctions.push_back(Instruction(_op," "+_des)); 164 | } 165 | void add(MipsCode _op, string _des, string _src1) { 166 | object_insrtuctions.push_back(Instruction(_op, " "+_des, ","+_src1)); 167 | } 168 | void add(MipsCode _op, string _des, string _src1, string _src2) { 169 | if (_op == MipsCode::sw || _op == MipsCode::lw) 170 | object_insrtuctions.push_back(Instruction(_op, " " + _des, "," + _src1, "(" + _src2 + ")")); 171 | else 172 | object_insrtuctions.push_back(Instruction(_op, " "+_des, ","+_src1, ","+_src2)); 173 | } 174 | void addData(string _name, string _conststring) { 175 | object_datas.push_back(Dataseg(_name, _conststring)); 176 | } 177 | void Handle(QuaterInstr* middle); 178 | void translate(); 179 | private: 180 | vector object_insrtuctions; 181 | vector object_datas; 182 | void HandleWrite(SymbolItem* des); 183 | void HandleBegin(SymbolItem* des); 184 | void HandleEnd(SymbolItem* des); 185 | void HandleCalc(Opcode choose, SymbolItem* des, SymbolItem* src1, SymbolItem* src2); 186 | void HandleNeg(SymbolItem* des,SymbolItem* src); 187 | void HandleAssignAddr(SymbolItem* addr, SymbolItem* value); 188 | void HandleArrayAddr(SymbolItem* addr, SymbolItem* base, SymbolItem* offset); 189 | void HandleArrayAssign(SymbolItem* value,SymbolItem* addr); 190 | void HandleAssign(SymbolItem* des,SymbolItem* src); 191 | void HandleBranch(Opcode branch,SymbolItem* des,SymbolItem* src1,SymbolItem* src2); 192 | void HandleCall(SymbolItem* caller,SymbolItem* callee); 193 | void HandleInc(SymbolItem* src); 194 | void HandleDec(SymbolItem* src); 195 | void HandleSetLabel(SymbolItem* des); 196 | void HandleJump(SymbolItem* des); 197 | void HandlePush(SymbolItem* des); 198 | void HandlePushVar(SymbolItem* des); 199 | void HandleRead(SymbolItem* des); 200 | void loadReg(SymbolItem* item,const string _$i,bool _loadaddrvalue=false); 201 | void storeMemory(const string _$i, SymbolItem* item); 202 | string genString(); 203 | void getRef(SymbolItem* item); 204 | }; 205 | 206 | -------------------------------------------------------------------------------- /Project/Compiler/parser.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SivilTaram/Compiler/6b8072617c5acffcc7eb1a5a1b89cc42d28314ca/Project/Compiler/parser.h -------------------------------------------------------------------------------- /Project/Compiler/quaterinstr.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SivilTaram/Compiler/6b8072617c5acffcc7eb1a5a1b89cc42d28314ca/Project/Compiler/quaterinstr.h -------------------------------------------------------------------------------- /Project/Compiler/rootsymbolset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "symbolset.h" 4 | 5 | class RootSymbolSet { 6 | public: 7 | RootSymbolSet(); 8 | 9 | SymbolItem* search(string _name); 10 | SymbolItem* insert(string _name, TokenKind _kind, TokenType _type,int _value=0); 11 | SymbolItem* genTemp(TokenKind _kind,TokenType _type,string _tag_string=""); 12 | SymbolItem* genLabel(); 13 | vector getArgList(string _name); 14 | void printSymbolSet(); 15 | 16 | SymbolSet* getRootSet(); 17 | SymbolSet* getCurrentSet(); 18 | SymbolSet* serachTable(string _name); 19 | bool RootSymbolSet::goback(); 20 | 21 | //bool findProc(string _name); 22 | void calcOffset(); 23 | string getCurrentName(); 24 | 25 | 26 | private: 27 | //the pointer to the current table; 28 | SymbolSet* current_table; 29 | //the pointer to the root table; 30 | SymbolSet* root_table; 31 | 32 | }; -------------------------------------------------------------------------------- /Project/Compiler/symbolset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "token.h" 6 | #include 7 | #include 8 | #include 9 | 10 | #define MAX_LEVEL (3+1) 11 | 12 | using namespace std; 13 | 14 | 15 | 16 | enum TokenKind { 17 | CONST,// .data 18 | VAR, 19 | PARA, // we should put it on the stack. 20 | PARAVAR, // stack. 21 | ARRAY, // array must be integer or char. 22 | PROC, 23 | FUNC, 24 | LABEL,// we should use it in three address code. 25 | TEMP, // Temporary varibale. 26 | TEMP_ADD,// Temporary variable address(in array). 27 | TEMP_CON,// immediate number. Temporary constant. 28 | UNDEFINE 29 | }; 30 | 31 | enum TokenType { 32 | voidtyp, 33 | inttyp, 34 | chartyp, 35 | notyp, 36 | stringtyp 37 | }; 38 | 39 | class SymbolItem { 40 | private: 41 | string name; 42 | TokenKind kind; 43 | TokenType type; 44 | int value; 45 | int size; 46 | int level; 47 | 48 | //for coude generation.Offset of base label. 49 | int offset; 50 | string conststring; 51 | public: 52 | // get methods. 53 | SymbolItem(string _name, TokenKind _kind, TokenType _type,int _value = 0,string _tag_string ="") { 54 | name = _name; 55 | kind = _kind; 56 | type = _type; 57 | value = _value; 58 | size = 1; 59 | offset = 0; 60 | conststring = _tag_string; 61 | //the char here will be regarded as the int. 62 | //This may be changed. 63 | } 64 | string getName() { 65 | stringstream ss; 66 | if (kind == TokenKind::TEMP_CON) 67 | { 68 | if (type == TokenType::chartyp) 69 | // return tostring((char)value); 70 | ss << (char)value; 71 | else if (type == TokenType::inttyp) 72 | // return tostring(value); 73 | ss << value; 74 | return ss.str(); 75 | } 76 | else 77 | return name; 78 | } 79 | TokenKind getKind() { return kind; } 80 | TokenType getType() { return type; } 81 | int getValue() { return value; } 82 | int getSize() { return size; } 83 | int getLevel() { return level; } 84 | int getOffset() { return offset; } 85 | string getString() { return conststring; } 86 | 87 | string getKindName() { 88 | switch (kind) 89 | { 90 | case TokenKind::CONST:return "const"; 91 | case TokenKind::ARRAY:return "array"; 92 | case TokenKind::FUNC:return "function"; 93 | case TokenKind::PARA:return "parameter"; 94 | case TokenKind::PARAVAR:return "var parameter"; 95 | case TokenKind::PROC:return "procedure"; 96 | case TokenKind::VAR:return "var"; 97 | case TokenKind::TEMP:return "temp"; 98 | case TokenKind::LABEL:return "label"; 99 | case TokenKind::TEMP_ADD:return "temp_add"; 100 | case TokenKind::TEMP_CON:return "temp_const"; 101 | default: return "unknown"; 102 | } 103 | } 104 | 105 | string getTypeName() { 106 | switch (type) 107 | { 108 | case TokenType::chartyp:return "char"; 109 | case TokenType::inttyp:return "integer"; 110 | case TokenType::notyp:return "notype"; 111 | case TokenType::voidtyp:return "void"; 112 | default: return "unknowntype"; 113 | } 114 | } 115 | 116 | // set methods. 117 | void setName(string _name) { name = _name; } 118 | void setKind(TokenKind _kind) { kind = _kind; } 119 | void setType(TokenType _type) { type = _type; } 120 | void setValue(int _value) { value = _value; } 121 | void setSize(int _size) { size = _size; } 122 | void setLevel(int _level) { level = _level; } 123 | void setString(string _conststring) { conststring = _conststring; } 124 | void setOffset(int _offset) { offset = _offset; } 125 | 126 | 127 | void printData(); 128 | }; 129 | 130 | class SymbolPro { 131 | private: 132 | int lastpar; 133 | int last; 134 | public: 135 | SymbolPro(int _lastpar, int _last) :lastpar(_lastpar), last(_last) { assert(last - lastpar); }//lastpar < last 136 | int getLast() { return last; } 137 | int getLastPar() { return lastpar; } 138 | }; 139 | 140 | enum ArrayType { 141 | arrayint, 142 | arraychar 143 | }; 144 | class SymbolArray { 145 | private: 146 | ArrayType ele_type; 147 | int low = 0; 148 | int high; 149 | int ele_size; 150 | int array_size; 151 | public: 152 | SymbolArray(ArrayType _ele_type, int _high, int _ele_size):ele_type(_ele_type),high(_high),ele_size(_ele_size) { 153 | // for size indent. 154 | array_size = (1 + high)*ele_size; 155 | array_size = 4 - array_size % 4 + array_size; 156 | assert(array_size % 4 == 0); 157 | } 158 | }; 159 | 160 | class SymbolSet{ 161 | public: 162 | // the pointer to the father of a procedure or a function. 163 | SymbolSet* father_table; 164 | 165 | //create and the delete method. 166 | SymbolSet(SymbolItem* _proc, SymbolSet* _father, int _level); 167 | 168 | //get the item from the table according to the name. 169 | SymbolItem* getItem(string _name); 170 | bool enterItem(SymbolItem* _item); 171 | 172 | //get the table the proc mapping to. 173 | 174 | SymbolItem* getProcItem(); 175 | SymbolSet* getProcTable(string _procname); 176 | string getProcName(); 177 | string getProcLabelName(); 178 | SymbolSet* enterProc(SymbolItem* _proc); 179 | 180 | vector getArgList(); 181 | 182 | void printData(); 183 | void calcOffset(); 184 | //get the table's mapping item. 185 | 186 | #ifdef DEBUG_SYMBOL 187 | void debug_printer(); 188 | #endif // DEBUG 189 | 190 | int getLevel(); 191 | int getArgsSize(); 192 | int getStackSize(); 193 | int getDisplaySize(); 194 | //calculate offset of var,para,var para,array based on base pointer($fp) 195 | 196 | private: 197 | 198 | SymbolItem* proc; 199 | vector local_list; 200 | map symbol_map; 201 | //store the names of current level function or procedure. 202 | map table_map; 203 | int level; 204 | int stack_size; 205 | int args_size; 206 | int display_size; 207 | }; -------------------------------------------------------------------------------- /Project/Compiler/token.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | #define reserved_map map 14 | 15 | enum Symbol { 16 | nullsym,/* not any one */ 17 | 18 | ident, /* ab */ 19 | number,/* 123 */ 20 | charconst/* 'a' */, 21 | strconst/* "absdas" */, 22 | 23 | /* operator */ 24 | minus,/* '-' */ 25 | times,/* '*' */ 26 | plus, /* '+' */ 27 | slash,/* '/' */ 28 | eql/* = */, 29 | neq/*'<>'*/, 30 | lss/*'<'*/, 31 | leq/*'<='*/, 32 | gtr/*'>'*/, 33 | geq/*'>='*/, 34 | lparen/*'('*/, 35 | rparen/*')'*/, 36 | lsquare/*'['*/, 37 | rsquare/*']'*/, 38 | comma/*','*/, 39 | semicolon/*';'*/, 40 | period/*'.'*/, 41 | becomes/*':='*/, 42 | colon,// : 43 | quote,/* ' */ 44 | dquote,/* " */ 45 | 46 | /* statment */ 47 | beginsym, 48 | endsym, 49 | ifsym, 50 | thensym, 51 | elsesym, 52 | dosym, 53 | whilesym, 54 | forsym, 55 | downtosym, 56 | tosym, 57 | 58 | // 'a' 59 | constsym, 60 | // var 61 | varsym, 62 | procsym, 63 | funcsym, 64 | charsym, 65 | integersym, 66 | arraysym, 67 | ofsym, 68 | 69 | /* read & write syscall */ 70 | readsym, 71 | writesym, 72 | 73 | /* The end of the file */ 74 | eofsym 75 | }; 76 | 77 | class Token { 78 | private: 79 | Symbol type; 80 | string ident_name; 81 | int num_value; 82 | //line_num for error message 83 | int line_num; 84 | public: 85 | Token(Symbol _type,int _line_num,string _ident_name = "", int _num_value = 0); 86 | Token() {} 87 | Symbol getType(); 88 | int getLineNo(); 89 | string getName(); 90 | int getValue(); 91 | string getTypeName(); 92 | }; 93 | 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Compiler 2 | 3 | Qian(SivilTaram)在北航编译课程设计的工程项目与文档。 4 | 5 | 目录: 6 | 7 | - [完整工程](https://github.com/SivilTaram/Compiler/tree/master/Project) 8 | - [PL0源代码分析](Docs/PascalCompilerCode.md) 9 | - [类,方法与函数](Docs/ClassAndMethods.md) 10 | - [四元式的设计方案](Docs/QuaterInstr.md) 11 | - [符号表的设计方案](Docs/SymbolSetDesign.md) 12 | - [测试样例与输出结果](Docs/ReadAndTest.md) 13 | 14 | 注意事项: 15 | 16 | 工程可以直接使用`VS2015`打开,如果使用其他版本的VS,请手动更改依赖的`.NET`框架版本号。 17 | 18 | [作者博客链接](http://cnblogs.com/SivilTaram) 19 | -------------------------------------------------------------------------------- /Tests/ComplexSamples/test_correct_1.txt: -------------------------------------------------------------------------------- 1 | const test1j = ' ', test5c5='s',const77=233; 2 | var i,index,test22,test33,test44,test55,test77,test88,test99,test1010:integer; 3 | hehe:char; 4 | test66:array[10] of integer; 5 | test5c:array[10] of char; 6 | procedure Test1(j:char); 7 | begin 8 | write("Test1 begin"); 9 | write(j); 10 | write("success"); 11 | write("\n"); 12 | end; 13 | procedure Test2(var j:integer); 14 | procedure Test2T2(var j:integer); 15 | begin 16 | j := 5; 17 | end; 18 | begin 19 | write("Test2 begin"); 20 | j := 3; 21 | Test2T2(j); 22 | end; 23 | function Test3(i:integer):integer; 24 | begin 25 | write("Test3 begin"); 26 | Test3 := i; 27 | end; 28 | function Test4(i:integer):integer; 29 | var j:integer; 30 | begin 31 | if i=0 then 32 | begin 33 | write("Test4 begin"); 34 | Test4 := 0 35 | end 36 | else 37 | begin 38 | j := i + Test4(i-1); 39 | Test4 := j; 40 | end 41 | end; 42 | function Test5:char; 43 | const s = 's'; 44 | begin 45 | write("Test5 begin"); 46 | Test5 := s; 47 | end; 48 | procedure Test6(var i:integer); 49 | begin 50 | write("Test6 begin"); 51 | do 52 | i:=i+2 53 | while i<5; 54 | end; 55 | function Test7(i,j,k,h:integer;m:char):integer; 56 | var temp:integer; 57 | begin 58 | write("Test7 begin"); 59 | temp := (m * h + k)/j - i +27; 60 | j := +temp; 61 | j := -j; 62 | Test7 := j; 63 | end; 64 | function Test8(j:integer):integer; 65 | var i,ret:integer; 66 | begin 67 | write("Test8 begin"); 68 | ret := 0; 69 | for j:=(23-20) downto 2 do 70 | for i:= 1 to index do 71 | ret := ret+i*j; 72 | Test8 := -ret; 73 | end; 74 | function Test9(para:integer):integer; 75 | begin 76 | if para = 3 then 77 | write("Test9 begin"); 78 | Test9 := para*3; 79 | end; 80 | procedure Test10; 81 | procedure Test1010; 82 | var test1010:integer; 83 | begin 84 | test1010:=1010; 85 | end; 86 | begin 87 | write("Test10 begin"); 88 | test1010:=test1010 * 6; 89 | Test1010; 90 | end; 91 | procedure Test11; 92 | procedure Test11; 93 | begin 94 | write("Test11 begin"); 95 | end; 96 | begin 97 | Test11; 98 | end; 99 | begin 100 | test22 := 3; 101 | for i:= 1 to 110/10 do 102 | begin 103 | read(index); 104 | if index = 1 then 105 | Test1(test1j) 106 | else if index = 2 then 107 | begin 108 | Test2(test22); 109 | if test22 = 5 then 110 | begin 111 | write(" success"); 112 | write("\n") 113 | end 114 | else 115 | write("fail"); 116 | end 117 | else if index = 3 then 118 | begin 119 | test33 := Test3(55); 120 | if test33 = 55 then 121 | begin 122 | write(" success"); 123 | write("\n") 124 | end 125 | end 126 | else if index = 4 then 127 | begin 128 | test44 := Test4(5); 129 | if test44 = 15 then 130 | begin 131 | write(" success"); 132 | write("\n") 133 | end 134 | end 135 | else if index = 5 then 136 | begin 137 | test5c[5] := Test5; 138 | if test5c[5] = test5c5 then 139 | write(" success\n"); 140 | end 141 | else if index = 6 then 142 | begin 143 | Test6(test66[3]); 144 | test22 := test66[3]; 145 | if test22 = 6 then 146 | write(" success\n"); 147 | end 148 | else if index = 7 then 149 | begin 150 | test77 := Test7(27,5,20,3,test5c5); 151 | if test77 = -73 then 152 | write(" success\n"); 153 | end 154 | else if index = 8 then 155 | begin 156 | test88 := Test8(233); 157 | if test88 = -180 then 158 | write(" success\n"); 159 | end 160 | else if index = 9 then 161 | begin 162 | test99 := Test9(Test9(Test9(3))); 163 | if test99 = 81 then 164 | write(" success\n"); 165 | end 166 | else if index = 10 then 167 | begin 168 | test1010 := 5; 169 | Test10; 170 | if test1010 = 30 then 171 | write(" success\n"); 172 | end 173 | else if index = 11 then 174 | begin 175 | Test11; 176 | end 177 | end; 178 | read(hehe); 179 | test5c[6] := hehe; 180 | write("You input",test5c[6]); 181 | write("Finished!\n"); 182 | end. -------------------------------------------------------------------------------- /Tests/ComplexSamples/test_correct_2.txt: -------------------------------------------------------------------------------- 1 | const constchar='c'; 2 | var vara : integer; 3 | arr:array[100] of integer; 4 | procedure testmulti(var c :integer); 5 | begin 6 | c := c+6; 7 | end; 8 | procedure testvar(var b :integer); 9 | begin 10 | b := b+1; 11 | write("|",b); 12 | testmulti(b); 13 | end; 14 | procedure testPara(c,j:integer;a:char); 15 | var b:integer; 16 | begin 17 | b := c; 18 | c := -c; 19 | if b = -c then 20 | write("|success neg"); 21 | write("|a:",a); 22 | j :=12 / c; 23 | write("|j:",j); 24 | c := a + (vara * j); 25 | write("|c:",c); 26 | end; 27 | function testFuncReturn:integer; 28 | begin 29 | testFuncReturn := 999; 30 | end; 31 | procedure f(b:integer); 32 | begin 33 | if b = 1 then 34 | write("|",b) 35 | else 36 | begin 37 | write("|",b); 38 | f(b-1); 39 | end 40 | end; 41 | procedure testFor; 42 | begin 43 | for vara:=1 to 10 do 44 | write("|",vara) 45 | end; 46 | procedure testDo; 47 | begin 48 | do 49 | begin 50 | write("|",vara); 51 | vara := vara -1 ; 52 | end 53 | while vara >= 1; 54 | end; 55 | begin 56 | vara := 0; 57 | testvar(vara); 58 | write("|vara:",vara); 59 | vara := testFuncReturn; 60 | if vara = 999 then 61 | write("|success fun return") 62 | else 63 | write("|fail fun return"); 64 | testPara(4,6,constchar); 65 | f(8); 66 | arr[1] := 6; 67 | arr[2] := arr[1] * arr[1]; 68 | write("|arr[1]:",arr[1]); 69 | write("|arr[2]:",arr[2]); 70 | testFor; 71 | testDo; 72 | read(vara); 73 | write("|readint vara:",vara); 74 | end. -------------------------------------------------------------------------------- /Tests/ComplexSamples/test_correct_3.txt: -------------------------------------------------------------------------------- 1 | procedure testCondition(x,y:integer); 2 | begin 3 | write(" testCondition begin:"); 4 | if x=y then write(" x=y:true") else write(" x=y:false"); 5 | if x>y then write(" x>y:true") else write(" x>y:false"); 6 | if x=y then write(" x>=y:true") else write(" x>=y:false"); 8 | if x<=y then write(" x<=y:true") else write(" x<=y:false"); 9 | if x<>y then write(" x<>y:true") else write(" x<>y:false"); 10 | write(" test end \r\n") 11 | end; 12 | begin 13 | testCondition(2,2); 14 | testCondition(1,3); 15 | testCondition(3,1); 16 | end. -------------------------------------------------------------------------------- /Tests/ComplexSamples/test_correct_4.txt: -------------------------------------------------------------------------------- 1 | const sc='c'; 2 | var c,a,j,vara:integer; 3 | i:char; 4 | cc:array[100] of char; 5 | cc2:array[100] of integer; 6 | function A:char; 7 | begin 8 | A := sc; 9 | end; 10 | begin 11 | i := A; 12 | write(i); 13 | c := i; 14 | write(c); 15 | cc[2] := i; 16 | write(cc[2]); 17 | cc2[2] := cc[2]; 18 | write(cc2[2]); 19 | a := i+j-c; 20 | write(a); 21 | end. -------------------------------------------------------------------------------- /Tests/ComplexSamples/test_correct_5.txt: -------------------------------------------------------------------------------- 1 | var B:integer; 2 | function A:integer; 3 | var B:char; 4 | function C:integer; 5 | begin 6 | write("this is the second C\n"); 7 | C := 2; 8 | end; 9 | begin 10 | write("this is the second A\n"); 11 | A := 97; 12 | end; 13 | function C:integer; 14 | var B:integer; 15 | function A:integer; 16 | begin 17 | write("this is the second A\n"); 18 | A := 99; 19 | end; 20 | begin 21 | if A = 99 then 22 | write("correct,call inner A:") 23 | else 24 | write("not correct,call the wrong A"); 25 | B := 5; 26 | write("the inner B:",B); 27 | write("\n"); 28 | C := -1; 29 | end; 30 | procedure D; 31 | var D:integer; 32 | begin 33 | write("this is the procedure D\n"); 34 | if C = -1 then 35 | begin 36 | D := C; 37 | write("correct,this is the var D:",D); 38 | end 39 | else 40 | write("not correct,call the wrong C"); 41 | write("\n"); 42 | D := A; 43 | end; 44 | begin 45 | write("the init of outter B:",B); 46 | write("\n"); 47 | B := C; 48 | write("the last of outter B:",B); 49 | write("\n"); 50 | D; 51 | end. -------------------------------------------------------------------------------- /Tests/ComplexSamples/test_error_1.txt: -------------------------------------------------------------------------------- 1 | const constchar='c'; 2 | var vara : integer; 3 | arr:array[100] of integer; 4 | procedure testPara(c,j:integer;a:char); 5 | var b:integer; 6 | begin 7 | b := c; 8 | c := -c; 9 | if b = -c then 10 | write("|success neg"); 11 | a := 97; 12 | write("|a:",a,); 13 | j :=12 / c + 'c'; 14 | write("|j:",j); 15 | c := a + (vara * j / ); 16 | write("|c:",c); 17 | end; 18 | begin 19 | testPara(4,6,constchar); 20 | end. -------------------------------------------------------------------------------- /Tests/ComplexSamples/test_error_2.txt: -------------------------------------------------------------------------------- 1 | const constchar='c'; 2 | var vara : integer; 3 | arr:array[100] of integer; 4 | procedure testmulti(var c :integer); 5 | begin 6 | c := c+6; 7 | end; 8 | procedure testvar(var b :integer); 9 | begin 10 | b := b+1; 11 | write("|",b); 12 | testmulti(b); 13 | end; 14 | procedure testPara(c,j:integer;a:char); 15 | var b:integer; 16 | begin 17 | b := c; 18 | c := -c; 19 | if b = -c then 20 | write("|success neg"); 21 | write("|a:",a); 22 | j :=12 / c; 23 | write("|j:",j); 24 | c := a + (vara * j); 25 | write("|c:",c); 26 | end; 27 | function testFuncReturn:integer; 28 | begin 29 | testFuncReturn := 999; 30 | end; 31 | procedure f(b:integer); 32 | begin 33 | if b = 1 then 34 | write("|",b) 35 | else 36 | begin 37 | write("|",b); 38 | f(b-1); 39 | end 40 | end; 41 | procedure testFor; 42 | begin 43 | for vara:=1 to 10 do 44 | write("|",vara) 45 | end; 46 | procedure testDo; 47 | begin 48 | do 49 | begin 50 | write("|",vara); 51 | vara := vara -1 ; 52 | end 53 | while vara >= 1; 54 | end; 55 | begin 56 | vara := 0; 57 | testvar(vara); 58 | write("|vara:",vara); 59 | vara := testFuncReturn; 60 | if vara = 999 then 61 | write("|success fun return") 62 | else 63 | write("|fail fun return"); 64 | testPara(4,6,constchar; 65 | f; 66 | arr[1] := 6; 67 | arr[2] := arr[1] sds arr[1]; 68 | write("|arr[1]:",arr[1]); 69 | write("|arr[2]:",arr[2]); 70 | testFor; 71 | testDo; 72 | read(vara); 73 | write("|readint vara:",vara); 74 | end. -------------------------------------------------------------------------------- /Tests/ComplexSamples/test_error_3.txt: -------------------------------------------------------------------------------- 1 | const a='a'; 2 | var s:char; 3 | function gcd(a:char):char; 4 | begin 5 | a := a + 1; 6 | gcd := a; 7 | end; 8 | function gcd; 9 | begin 10 | s := gcd(a); 11 | s1 := 3; 12 | end. -------------------------------------------------------------------------------- /Tests/ComplexSamples/test_error_4.txt: -------------------------------------------------------------------------------- 1 | const test1j = ' ', test5c5='s',const77=233; 2 | var i,index,test22,test33,test44,test55,test77,test88,test99,test1010:integer; 3 | hehe:char; 4 | test66:array[10] of integer; 5 | test5c:array[10] of char; 6 | procedure Test1(j:char); 7 | begin 8 | write("Test1 begin"); 9 | write(j); 10 | write("success"); 11 | write("\n"); 12 | end; 13 | procedure Test2(var j:integer); 14 | procedure Test2T2(var j:integer); 15 | begin 16 | j := 5; 17 | end; 18 | begin 19 | write("Test2 begin"); 20 | j := 3; 21 | Test2T2(j); 22 | end; 23 | function Test3(i:integ):integ; 24 | begin 25 | write("Test3 begin"); 26 | Test3 := i; 27 | end; 28 | function Test4(i:integer):integer; 29 | var j:integer; 30 | begin 31 | if i=0 then 32 | begin 33 | write("Test4 begin"); 34 | Test4 := 0 35 | end 36 | else 37 | begin 38 | j := i + Test4(i-1); 39 | Test4 := j; 40 | end 41 | end; 42 | function Test5:char; 43 | const s = 's'; 44 | begin 45 | write("Test5 begin"); 46 | Test5 := s; 47 | end; 48 | procedure Test6(var i:integer); 49 | begin 50 | write("Test6 begin"); 51 | do 52 | i:=i+2 53 | while i<5; 54 | end; 55 | function Test7(i,j,k,h:integer;m:char):integer; 56 | var temp:integer; 57 | begin 58 | write("Test7 begin"); 59 | temp := (m * h + k)/j - i +27; 60 | j := +temp; 61 | j := -j; 62 | Test7 := j; 63 | end; 64 | function Test8(j:integer):integer; 65 | var i,ret:integer; 66 | begin 67 | write("Test8 begin"); 68 | ret := 0; 69 | for j:=(23-20) downto 2 do 70 | for i:= 1 to index do 71 | ret := ret+i*j; 72 | Test8 := -ret; 73 | end; 74 | function Test9(para:integer):integer; 75 | begin 76 | if para = 3 then 77 | write("Test9 begin"); 78 | Test9 := para*3; 79 | end; 80 | procedure Test10; 81 | procedure Test1010; 82 | var test1010:integer; 83 | begin 84 | test1010:=1010; 85 | end; 86 | begin 87 | write("Test10 begin"); 88 | test1010:=test1010 * 6; 89 | Test1010; 90 | end; 91 | procedure Test11; 92 | procedure Test11; 93 | begin 94 | write("Test11 begin"); 95 | end; 96 | begin 97 | Test11; 98 | end; 99 | begin 100 | test22 := 3; 101 | for 2:= 1 to 110/10 do 102 | begin 103 | read(index); 104 | if index = 1 then 105 | Test1(test1j) 106 | else if index = 2 then 107 | begin 108 | Test2(test22); 109 | if test22 = 5 then 110 | begin 111 | write(" success"); 112 | write("\n") 113 | end 114 | else 115 | write("fail"); 116 | end 117 | else if index = 3 then 118 | begin 119 | test33 := Test3(55); 120 | if test33 = 55 then 121 | begin 122 | write(" success"); 123 | write("\n") 124 | end 125 | end 126 | else if index = 4 then 127 | begin 128 | test44 := Test4(5); 129 | if test44 = 15 then 130 | begin 131 | write(" success"); 132 | write("\n") 133 | end 134 | end 135 | else if index = 5 then 136 | begin 137 | test5c[5] := Test5; 138 | if test5c[5] = test5c5 then 139 | write(" success\n"); 140 | end 141 | else if index = 6 then 142 | begin 143 | Test6(test66[3]); 144 | test22 := test66[3]; 145 | if test22 = 6 then 146 | write(" success\n"); 147 | end 148 | else if index = 7 then 149 | begin 150 | test77 := Test7(27,5,20,3,test5c5); 151 | if test77 = -73 then 152 | write(" success\n"); 153 | end 154 | else if index = 8 then 155 | begin 156 | test88 := Test8(233); 157 | if test88 !== -180 then 158 | ssss write(" sdsuccess\n"); 159 | end 160 | else if index = 9 then 161 | begin 162 | test99 := Test9(Test9(Test9(3))); 163 | if test99 = 81 then 164 | write(" success\n"); 165 | end 166 | else if index = 10 then 167 | begin 168 | test1010 := 5; 169 | Test10; 170 | if test1010 = 30 then 171 | write(" success\n"); 172 | end 173 | else if index = 11 then 174 | begin 175 | Test11; 176 | end 177 | end; 178 | read(hehe); 179 | test5c[6] := hehe; 180 | write("You input",test5c[6]); 181 | write("Finished!\n"); 182 | end. -------------------------------------------------------------------------------- /Tests/ComplexSamples/test_error_5.txt: -------------------------------------------------------------------------------- 1 | const sc='c'; 2 | var c,a,j,vara:integer; 3 | i:char; 4 | cc:array[100] of char; 5 | cc2:array[100] of integer; 6 | function A:char; 7 | begin 8 | A := sc; 9 | end; 10 | begin 11 | i := A; 12 | write(i) 13 | c := i+'c'; 14 | write(c,); 15 | cc[2] := i; 16 | write(cc[2]); 17 | cc2[2,3] := cc[2]; 18 | write(cc2[2]); 19 | a := i+j-c/; 20 | write(a); 21 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/13061193_test.txt: -------------------------------------------------------------------------------- 1 | const constchar='c'; 2 | var vara : integer; 3 | arr:array[100] of integer; 4 | procedure testmulti(var c :integer); 5 | begin 6 | c := c+6; 7 | end; 8 | procedure testvar(var b :integer); 9 | begin 10 | b := b+1; 11 | write("|",b); 12 | testmulti(b); 13 | end; 14 | procedure testPara(c,j:integer;a:char); 15 | var b:integer; 16 | begin 17 | b := c; 18 | c := -c; 19 | if b = -c then 20 | write("|success neg"); 21 | a := constchar; 22 | write("|a:",a); 23 | j :=12 / c; 24 | write("|j:",j); 25 | c := a + (vara * j); 26 | write("|c:",c); 27 | end; 28 | function testFuncReturn:integer; 29 | begin 30 | testFuncReturn := 999; 31 | end; 32 | procedure f(b:integer); 33 | begin 34 | if b = 1 then 35 | write("|",b) 36 | else 37 | begin 38 | write("|",b); 39 | f(b-1); 40 | end 41 | end; 42 | procedure testFor; 43 | begin 44 | for vara:=1 to 10 do 45 | write("|",vara) 46 | end; 47 | procedure testDo; 48 | begin 49 | do 50 | begin 51 | write("|",vara); 52 | vara := vara -1 ; 53 | end 54 | while vara >= 1; 55 | end; 56 | begin 57 | vara := 0; 58 | testvar(vara); 59 | write("|vara:",vara); 60 | vara := testFuncReturn; 61 | if vara = 999 then 62 | write("|success fun return") 63 | else 64 | write("|fail fun return"); 65 | testPara(4,6,constchar); 66 | f(8); 67 | arr[1] := 6; 68 | arr[2] := arr[1] * arr[1]; 69 | write("|arr[1]:",arr[1]); 70 | write("|arr[2]:",arr[2]); 71 | testFor; 72 | testDo; 73 | read(vara); 74 | write("|readint vara:",vara); 75 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/array.txt: -------------------------------------------------------------------------------- 1 | var i:array[15] of integer; 2 | j,k:integer; 3 | begin 4 | i[3] := 5; 5 | j := i[3]; 6 | write(j); 7 | k := i[4]; 8 | j := k; 9 | write(j); 10 | write(k); 11 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/array2.txt: -------------------------------------------------------------------------------- 1 | var i : integer; array1 : array[14] of integer; 2 | begin 3 | array1[0] := 0; 4 | array1[1] := 1; 5 | for i := 2 to 13 6 | do 7 | array1[i] := array1[i-1]+array1[i-2]; 8 | if array1[13] = 233 then 9 | write("array operation right.") 10 | else 11 | write("array operation failed."); 12 | end. 13 | -------------------------------------------------------------------------------- /Tests/SmallSamples/call.txt: -------------------------------------------------------------------------------- 1 | var i:integer; 2 | function p3loop(n, i:integer):integer; 3 | begin 4 | if n=0 then 5 | p3loop := 3 6 | end; 7 | begin 8 | i := p3loop(0,4); 9 | write(i); 10 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/call_2.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SivilTaram/Compiler/6b8072617c5acffcc7eb1a5a1b89cc42d28314ca/Tests/SmallSamples/call_2.txt -------------------------------------------------------------------------------- /Tests/SmallSamples/char.txt: -------------------------------------------------------------------------------- 1 | const A='s',B='b'; 2 | var a,b:integer; 3 | c:char; 4 | begin 5 | c := A; 6 | a := c; 7 | b := c + c; 8 | write(b); 9 | write(a); 10 | write(c); 11 | c := c; 12 | c := c + c; 13 | c := a ; 14 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/com.txt: -------------------------------------------------------------------------------- 1 | var j:char; 2 | begin 3 | j:='2' 4 | end -------------------------------------------------------------------------------- /Tests/SmallSamples/compiler_one.txt: -------------------------------------------------------------------------------- 1 | const constchar='c'; 2 | var vara : integer; 3 | function testRec(var b:integer):integer; 4 | begin 5 | testRec := 1; 6 | if b>=1 then 7 | b := b + testRec(b) 8 | else 9 | write("|",b); 10 | end; 11 | begin 12 | vara := 4; 13 | vara := testRec(vara); 14 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/const.txt: -------------------------------------------------------------------------------- 1 | .data 2 | .text 3 | j root_ 4 | # begin 5 | root_: 6 | move $fp,$sp 7 | sw $ra,0($fp) 8 | sw $s0,-4($fp) 9 | sw $s1,-8($fp) 10 | sw $s2,-12($fp) 11 | sw $s3,-16($fp) 12 | sw $s4,-20($fp) 13 | sw $s5,-24($fp) 14 | sw $s6,-28($fp) 15 | sw $s7,-32($fp) 16 | subi $sp,$sp,52 17 | # assign 18 | li $t0,11 19 | sw $t0,-36($fp) 20 | # assign 21 | li $t0,-7 22 | sw $t0,-40($fp) 23 | # write 24 | lw $t0,-36($fp) 25 | add $a0,$0,$t0 26 | li $v0,1 27 | syscall 28 | # write 29 | lw $t0,-40($fp) 30 | add $a0,$0,$t0 31 | li $v0,1 32 | syscall 33 | # end 34 | -------------------------------------------------------------------------------- /Tests/SmallSamples/expr.txt: -------------------------------------------------------------------------------- 1 | const a = 1,c='c'; 2 | var i,j,k:integer; 3 | begin 4 | i := a; 5 | write(i); 6 | j := c * a + i; 7 | write(j); 8 | k := c/a - j; 9 | write(k); 10 | write("this is a big data"); 11 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/fish.txt: -------------------------------------------------------------------------------- 1 | const x='a'; 2 | var arr:array[10] of char; 3 | iter:integer; 4 | begin 5 | arr[1] := x; 6 | arr[2] := x; 7 | arr[3] := x; 8 | arr[4] := arr[1]; 9 | arr[5] := arr[2]; 10 | for iter:=1 to 5 do 11 | write(arr[iter]); 12 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/fo2.txt: -------------------------------------------------------------------------------- 1 | const c = 1; 2 | var a,b,i : integer; 3 | begin 4 | for i:= 0 to 10 do 5 | begin 6 | b := a + c; 7 | a := b; 8 | end; 9 | if a = 11 then 10 | write("for success.") 11 | else 12 | write("for failed."); 13 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/for.txt: -------------------------------------------------------------------------------- 1 | var b,i,j: integer; 2 | begin 3 | b := 1; 4 | j := 2; 5 | for i:=10 downto 1 do 6 | write(b) 7 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/function.txt: -------------------------------------------------------------------------------- 1 | function String2Number:integer; 2 | var i:integer; 3 | s:array[10] of integer; 4 | begin 5 | i := 0; 6 | do 7 | if s[i] >= 0 then 8 | if s[i] <= 9 then 9 | sint := sint * 10 + s[i] 10 | else 11 | write("Not valid") 12 | else 13 | write("Not valid") 14 | while i<= length-1; 15 | String2Number:=sint 16 | end; 17 | begin 18 | end; -------------------------------------------------------------------------------- /Tests/SmallSamples/function2.txt: -------------------------------------------------------------------------------- 1 | function String2Number:integer; 2 | begin 3 | sint := sint * 10; 4 | String2Number:=sint 5 | end; 6 | begin 7 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/funvar.txt: -------------------------------------------------------------------------------- 1 | var a : integer; 2 | procedure p1(var c :integer); 3 | begin 4 | c := c+6; 5 | end; 6 | procedure p2(var b :integer); 7 | begin 8 | b := b+1; 9 | write(b); 10 | p1(b); 11 | end; 12 | begin 13 | a := 0; 14 | p2(a); 15 | write(a); 16 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/if.txt: -------------------------------------------------------------------------------- 1 | const a = 1,b = 2, c = 'c'; 2 | var i,j:integer; 3 | begin 4 | i := 2; 5 | if i = 2 then 6 | begin 7 | write(a); 8 | write(b); 9 | end 10 | else 11 | begin 12 | i := -2; 13 | write(i); 14 | end 15 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/if_2.txt: -------------------------------------------------------------------------------- 1 | var a,b:integer; 2 | begin 3 | if a = 0 then 4 | if b = 0 then 5 | a := a + 1 6 | else 7 | b := b + 1 8 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/if_fun.txt: -------------------------------------------------------------------------------- 1 | var i:integer; 2 | procedure f1; 3 | procedure f2; 4 | begin 5 | write(1) 6 | end; 7 | procedure f3; 8 | begin 9 | write(2) 10 | end; 11 | begin 12 | for i:=2 downto 1 do 13 | if i=1 then 14 | f1 15 | else 16 | f2 17 | end; 18 | begin 19 | f3; 20 | end. 21 | -------------------------------------------------------------------------------- /Tests/SmallSamples/min_rec.txt: -------------------------------------------------------------------------------- 1 | procedure f(b:integer); 2 | begin 3 | if b = 1 then 4 | write(b) 5 | else 6 | begin 7 | write(b); 8 | f(b-1); 9 | end 10 | end; 11 | begin 12 | f(8); 13 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/mult-func.txt: -------------------------------------------------------------------------------- 1 | procedure A; 2 | var a:integer; 3 | procedure B; 4 | var b:integer; 5 | procedure C; 6 | var c:integer; 7 | begin 8 | c := 2; 9 | b := b + 1; 10 | a := a + 2; 11 | write(a); 12 | write(b); 13 | end; 14 | begin 15 | b := 0; 16 | C; 17 | end; 18 | begin 19 | a := 3; 20 | B; 21 | end; 22 | begin 23 | A; 24 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/multi.txt: -------------------------------------------------------------------------------- 1 | var i,j,k:integer; 2 | begin 3 | i := j+k+k*k/k-2+(i-2)/3; 4 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/multi_call.txt: -------------------------------------------------------------------------------- 1 | var i:integer; 2 | function gcd(var i:integer;j:integer):integer; 3 | begin 4 | i := i + 1; 5 | gcd := i + j; 6 | end; 7 | begin 8 | i := 2; 9 | write(i+gcd(i,gcd(i,2))); 10 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/procedure.txt: -------------------------------------------------------------------------------- 1 | var j:integer; 2 | i:char; 3 | begin 4 | j := i + '2'; 5 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/read.txt: -------------------------------------------------------------------------------- 1 | var s:integer; 2 | s1,s2:char; 3 | begin 4 | read(s); 5 | read(s1,s2) 6 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/rec.txt: -------------------------------------------------------------------------------- 1 | const a = 1; 2 | var c:integer; 3 | function f(b:integer):integer; 4 | begin 5 | if b = a 6 | then f:= 1 7 | else 8 | f := b+f(b-1); 9 | end; 10 | begin 11 | c := f(3); 12 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/ssss.txt: -------------------------------------------------------------------------------- 1 | const con1=+01,con2=-002,con3='a',con4='1'; 2 | var var1:integer; 3 | var2:char; 4 | arr1:array[10] of integer; 5 | arr2:array[10] of char; 6 | procedure init; 7 | var i:integer; 8 | begin 9 | for i:=0 to 9 do 10 | begin 11 | arr1[i]:=i; 12 | arr2[i]:=con3 13 | end 14 | end; 15 | procedure output; 16 | var i:integer; 17 | procedure output1; 18 | var i:integer; 19 | begin 20 | i:=0; 21 | do 22 | begin 23 | write("||arr1:",arr1[i]); 24 | i:=i+1 25 | end 26 | while i<10 27 | end; 28 | procedure output2; 29 | var i:integer; 30 | begin 31 | i:=0; 32 | do 33 | begin 34 | write("||arr2:",arr2[i]); 35 | i:=i+1 36 | end 37 | while i<10 38 | end; 39 | begin 40 | for i:=2 downto 1 do 41 | begin 42 | if i=1 then 43 | output1 44 | else 45 | output2 46 | end 47 | end; 48 | function n2(a:integer):integer; 49 | var b:integer; 50 | begin 51 | if a>1 then 52 | begin 53 | a:=a-a/2; 54 | b:=n2(a)+1; 55 | n2:=b; 56 | end 57 | else 58 | n2:=0 59 | end; 60 | procedure pass(var a:integer); 61 | begin 62 | a:=0 63 | end; 64 | begin 65 | init; 66 | output; 67 | read(var1); 68 | write("|read result is ",var1); 69 | pass(var1); 70 | write("|test pass address result is ",var1); 71 | write("|function n2(8) result is ",n2(arr1[8])); 72 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/temp.txt: -------------------------------------------------------------------------------- 1 | var a,b,c,d,i,r:integer; 2 | arr : array[10] of integer; 3 | begin 4 | a:= 10 - 9 ; 5 | b:= 20 / 10; 6 | c:= 4 * 6 - 21; 7 | d:= - 5 + 9; 8 | for i:= a to 9 do 9 | arr[i] := i*i; 10 | r := ( arr[4] - c * d )/( arr[2] * ( arr[3] - b * ( 5 -1 ))); 11 | write(" a = ", a); 12 | write(" b = ", b); 13 | write(" c = ", c); 14 | write(" d = ", d); 15 | write(" r = ", r) 16 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/test.txt: -------------------------------------------------------------------------------- 1 | var i,j:integer; 2 | function mod(i,j:integer):integer; 3 | begin 4 | i := i * i; 5 | write("get mod"); 6 | end; 7 | function gcd(i,j:integer):integer; 8 | begin 9 | gcd := j ; 10 | end; 11 | begin 12 | i := 1; 13 | write(gcd(i,mod(i,j))); 14 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/test_write.txt: -------------------------------------------------------------------------------- 1 | const a = 'a' , b = 98; 2 | var i:integer; 3 | j:char; 4 | arr:array[100] of char; 5 | arr1:array[100] of integer; 6 | begin 7 | arr[b] := a; 8 | write(arr[b]); 9 | arr1[a] := b; 10 | i := 37; 11 | write(arr1[a]); 12 | write(a); 13 | write(b); 14 | write(i); 15 | j := a + b; 16 | write(a+b); 17 | write(j+i); 18 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/var.txt: -------------------------------------------------------------------------------- 1 | var 2 | i,j:integer; 3 | ss,d3:char; 4 | h5:array[10] of char; -------------------------------------------------------------------------------- /Tests/SmallSamples/while.txt: -------------------------------------------------------------------------------- 1 | var s:array[10] of integer; 2 | sint,length:integer; 3 | begin 4 | do 5 | if s[i] >= 0 then 6 | if s[i] <=9 then 7 | sint := sint * 10 + s[i] 8 | else 9 | write("Not valid") 10 | else 11 | write("Not valid") 12 | while i<= length-1 13 | end -------------------------------------------------------------------------------- /Tests/SmallSamples/write.txt: -------------------------------------------------------------------------------- 1 | begin 2 | write("Not valid",sint); 3 | write("Not valid"); 4 | write(sint) 5 | end. -------------------------------------------------------------------------------- /Tests/SmallSamples/write_func.txt: -------------------------------------------------------------------------------- 1 | function A:integer; 2 | begin 3 | A := 3; 4 | end; 5 | begin 6 | write("A:",A); 7 | end. --------------------------------------------------------------------------------