# C0Compiler **Repository Path**: PositiveMumu/C0Compiler ## Basic Information - **Project Name**: C0Compiler - **Description**: 基于java语言和JavaCC的C0语言编译器(包括编译程序和解释执行程序) - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2019-12-03 - **Last Updated**: 2023-04-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # C0Compiler **作者:积极向上小木木            联系方式:PositiveMumu@126.com** *2018年编译原理大作业,基于java语言和JavaCC工具的C0语言编译器* # 1.C0语言介绍 **C0语言的语法结构定义如下:** ``` <程序>->[<变量定义部分>] {<自定义函数定义部分>} <主函数> <变量定义部分>-> int id {, id}; <自定义函数定义部分>-> ( int id | void id) '(' ')' <分程序> <主函数>->void main'(' ')' <分程序> <分程序>->'{' [<变量定义部分>] <语句序列> '}' <语句序列>-><语句> {<语句>} <语句>-> <条件语句>|<循环语句> | '{'<语句序列>'}' | <自定义函数调用语句> | <赋值语句> | <返回语句> | <读语句> | <写语句> | ; <条件语句>->if '('<表达式>')' <语句> [else <语句> ] <循环语句>->while '(' <表达式>')' <语句> <自定义函数调用语句>-><自定义函数调用>; <赋值语句>->id = <表达式>; <返回语句>->return ['(' <表达式> ')'] ; <读语句>->scanf '(' id ')'; <写语句>->printf '(' [ <表达式>] ')'; <表达式>-> [+|-] <项> { (+|-) <项>} <项> -> <因子>{(*|/) <因子>} <因子> -> id|'(' <表达式>')' | num | <自定义函数调用> <自定义函数调用>->id '(' ')' ``` 其中,id代表标识符,num代表整数,其含义及构成方式与C语言相一致; C0源程序中的变量需先定义后使用,其作用域与生存期与C语言相一致; 自定义函数可超前使用(调用在前,定义在后); 其它方面的语义与C语言相一致。 **假想的栈式指令系统表:** | 指令 | 含义 | | ------- | -------------------------------------------------- | | LIT 0 a | 将常数值取到栈顶,a为常数值 | | LOD t a | 将变量值取到栈顶,a为相对地址,t为层差 | | STO t a | 将栈顶内容送入某变量单元中,a为相对地址,t为层差 | | CAL 0 a | 调用函数,a为函数地址 | | INT 0 a | 在运行栈中为被调用的过程开辟a个单元的数据区 | | JMP 0 a | 无条件跳转至a地址 | | JPC 0 a | 条件跳转,当栈顶值为0,则跳转至a地址,否则顺序执行 | | ADD 0 0 | 次栈顶与栈顶相加,退两个栈元素,结果值进栈 | | SUB 0 0 | 次栈顶减去栈顶,退两个栈元素,结果值进栈 | | MUL 0 0 | 次栈顶乘以栈顶,退两个栈元素,结果值进栈 | | DIV 0 0 | 次栈顶除以栈顶,退两个栈元素,结果值进栈 | | RED 0 0 | 从命令行读入一个输入置于栈顶 | | WRT 0 0 | 栈顶值输出至屏幕并换行 | | RET 0 0 | 函数调用结束后,返回调用点并退栈 | # 2.项目功能 1. 该编译器可以实现对C0程序的编译(由源代码编译成指令序列的过程)及解释执行(执行指令序列,输出结果)。 2. 编译器功能: 1. 输入: 1. 源代码地址。在工程中位于testFile目录下的Sources目录中,若使用提供的测试文件,可输入testFile/Sources/xxx.txt。 2. 是否输出中间代码(Y/N)。中间代码即为指令序列,输入Y的话会将指令序列输出在控制台(没啥用)。 3. 是否输出分程序列表(Y/N)。即在控制台输出函数调用关系。 4. 是否解释执行(Y/N)。即是否直接解释执行,选择否的话需要单独调用解释执行模块来执行程序。 5. 请输入目标文件输出路径。指令序列文件将要存储的路径,想存储在默认路径填写testFile/ExecutedLists/xxx.txt即可。 2. 输出: 1. 如果未选择解释执行,程序运行结束后将在目标文件输出路径生成一个txt文件,供给解释执行程序使用。 2. 如果选择解释执行,则将进入解释执行程序的输入部分。 3. 解释执行器功能: 1. 输入: 1. 解释执行文件地址。即指令序列文件地址,在工程中位于testFile目录下的ExecutedLists目录中,若使用提供的测试文件,可输入testFile/ExecutedLists/xxx.txt。 2. 程序参数参数。即源程序执行需要的参数,如果源程序不需要参数则不用输入。 2. 输出:执行结果。 # 3.项目介绍 1. 本项目由解释执行程序(Eexcute)和编译程序(Compiler)两个主要模块构成。编译程序负责将C0源代码编译并生成中间指令序列,解释执行程序负责将指令序列解释执行并生成结果。编译程序由JavaCC工具编译生成。 2. 在Compiler包下的文件Compiler.jj、ErrorCode.java、MyError.java、SymbolItem.java是手动添加的,其他的.java文件均由JavaCC工具Compiler.jj编译得到,具体方法详见JavaCC官网(https://javacc.org/)。 3. 测试文件存放在testFile文件夹下。 1. Sources目录下为源程序,主要包括: 1. A+AA+AAASource.txt : 输入A,N计算A+AA+....知道N个A的值。 2. AddMoreSource.txt : 输入N,计算从1加到N的值。 3. factorialSource.txt : 输入N,计算N的阶乘。 4. GCD&LCMSource.txt : 输入M,N计算M与N的最大公约数,最小公倍数。 2. ExecutedLists目录下为编译后的指令序列文件,与上述一一对应。 4. 注意:若你的源程序为放置在指定目录中,请输入你源程序的绝对路径。生成的指令序列文件也请输入绝对路径,在运行解释执行器的时候也要输入绝对路径。