├── .gitignore ├── README.md ├── imgs ├── for语句.png ├── if语句.png ├── repeat语句.png ├── while语句.png ├── 主函数流程图.png ├── 主程序.png ├── 主符号表结构.png ├── 函数调用.png ├── 函数过程定义.png ├── 分程序.png ├── 变量.png ├── 变量引用.png ├── 复合语句.png ├── 子符号表结构.png ├── 常量定义.png ├── 形式参数列表.png ├── 数据流图.png ├── 模块图.png ├── 模块图2.png ├── 类型.png ├── 表达式.png ├── 语句.png ├── 赋值语句.png ├── 过程调用语句.png └── 运行逻辑表.png ├── lex-yacc-src ├── PPT上的更正说明.txt ├── PascalProgram.pas ├── auto_compile.sh ├── auto_complie_and_run.bat ├── lex.l ├── main.cpp ├── main.h ├── pascal2c.exe ├── preProcessed.pas ├── unistd.h ├── yacc.output ├── yacc.tab.h ├── yacc.y └── 添加了错误个数控制的版本,与vs工程关联,所以无法单独正确运行 │ ├── lex.l │ ├── main.cpp │ ├── main.h │ └── yacc.y ├── src ├── ASTnodes.cpp ├── ASTnodes.h ├── CMakeLists.txt ├── FunctionReturnExistedCheck.cpp ├── PascalProgram.pas ├── codeGenerate.cpp ├── lex.yy.cpp ├── main.cpp ├── main.h ├── parseTree2AST.cpp ├── semanticAnalyse.cpp ├── symbolTable.cpp ├── symbolTable.h ├── yacc.tab.cpp └── yacc.tab.h ├── test-cases ├── lex错误测试样例.md ├── 代码生成测试样例.md ├── 综合测试用例.md ├── 语义分析测试样例.md └── 语法分析测试用例.md ├── 各模块测试文档 ├── 代码生成 - 测试文档.docx ├── 整体设计 - 测试文档.docx ├── 词法分析 - 测试文档.docx ├── 语义分析 - 测试文档.docx └── 语法分析 - 测试文档 - 不带调试输出.docx └── 各模块详细设计 ├── 代码生成 - 详细设计.docx ├── 整体设计 - 详细设计.docx ├── 词法分析 - 详细设计.docx ├── 语义分析 - 详细设计.docx └── 语法分析 - 详细设计.docx /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | src/cmake-build-debug/* 3 | .idea 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 项目说明 2 | - 此项目为本人大学期间的编译原理课程设计 3 | - 为PASCAL到C的编译器,本项目并不支持全部的PASCAL语法,只是其子集 4 | - 词法分析使用lex 5 | - 语法分析使用yacc 6 | - 整体工程使用C++,采用cmake构建 7 | 8 | ## 项目构建方式 9 | - 安装cmake 10 | - 安装MinGW,将mingw32-make.exe复制改名为make.exe 11 | - 在pascal2c-compiler/build目录下依次执行指令 12 | - cmake -G "MinGW Makefiles" ../src 13 | - make 14 | - make install 15 | - 在pascal2c-compiler/build/out/目录下,执行pascal2c.exe 16 | - 得到CProgram.c文件,该文件是将pascal源代码PascalProgram.pas编译为C代码的结果 17 | 18 | ## 目录结构 19 | - lex-yacc-src/ 20 | - 本项目的词法分析和语法分析使用lex和yacc 21 | - 该目录为lex和yacc的源代码目录 22 | - lex和yacc编译后得到c代码,加入src目录 23 | - src/ 24 | - pascal2c编译器的源代码 25 | - test-cases/ 26 | - 各种测试用例 27 | 28 | ## pascal2c.exe的使用 29 | | 参数接口 | 参数 | 参数功能 | 参数默认值 30 | | --- | --- | --- | --- 31 | | -inname | [file name] | 指定输入文件名 | PascalProgram.pas 32 | | -outname | [file name] | 指定输出文件名 | CProgram.c 33 | | -compiler | [compiler name] | 指定c编译器名,并将c程序编译成可执行文件 | gcc 34 | | -exename | [exe name] | 指定可执行文件名,自动编译 | CProcess.exe 35 | | -execute | 无 | 自动执行生成的可执行文件,如果未出现-e、-exename参数,则均按照默认方式进行操作 | 36 | | -errorbound | [n] | 指定错误上限,即编译器发现了指定个数的错误后,立即停止运行 | INF 37 | | -developer | 无 | 输出开发者信息 | 38 | | -version | 无 | 输出版本信息 | 39 | | -help | 无 | 输出所有命令行参数的帮助信息 | 40 | 41 | 注:中括号表示该参数可有可无 42 | ## 编译器功能模块图 43 |  44 | 45 | ## 主函数流程图 46 |  47 | 48 | ## 需求分析 49 | ### 整体需求分析 50 | 一个完整的编译器分成分析阶段和综合阶段。分析阶段由词法分析、语法分析、语义分析组成;综合阶段由中间代码生成、代码优化、代码生成组成。我们需要实现的是PASCAL_S到C的编译器,源语言和目标语言均为高级语言,因此应省略综合阶段的中间代码生成和代码优化这两部分,也就是说,综合阶段直接将分析阶段得到的输出转化为目标代码。另外,符号表的管理和访问、错误处理将贯穿整个编译过程。 51 | 52 | 下面的数据流图说明了每一部分的输入输出,及其相互之间的逻辑关系。 53 | 54 |  55 | 56 | ### 词法分析的需求分析 57 | 编译的整个过程从词法分析开始。从左至右逐个字符地对源程序进行扫描,按照源语言的词法规则识别出一个个单词符号,把识别出来的标识符存入符号表中,并产生用于语法分析的记号序列。另外,词法分析程序还可以完成用户接口有关的一些任务,如识别源程序中的注释和跳过空格,把来自编译程序的错误信息和源程序联系起来。在遇到错误时,为了使词法分析程序能够继续运行下去,还要对出现的错误进行适当的恢复。 58 | 59 | 词法分析的输入是用源语言编写的程序,输出是详细词法错误信息及记号序列。记号指的是某一类单词的类别编码,如常数的记号num,而单词指的是某一类单词符号中的一个实例,如标识符position就是一个单词。我们计划利用LEX进行词法分析。 60 | 61 | LEX能够自动生成词法分析程序的前提就是我们能够提供所有单词的模式。一般来说,在输入符号串中有很多子串具有相同的记号输出,每个这样的子串都是一个单词,并且都可以用同一构成规则(即模式或者说正则表达式)描述。所以需要给出所有记号的正则表达式(描述记号的模式)的定义。为此,我们要根据提供的文法和语法图,以及相关文档,学习PASCAL_S,从中整理出各个不同种类的单词(包括常数、标识符、各种关键字等),然后再分析得到正则表达式。在分析过程中,可以利用正则文法、自动机等辅助分析。 62 | 63 | LEX通过正则表达式的匹配,执行相应的动作。而我们需要输出记号序列。词法分析程序在识别出一个记号后,要把与之有关的信息作为它的属性保留下来,记号影响语法分析的决策,属性影响记号的翻译。如果每一个关键字、运算符或标点符号作为单独的一类,则记号所代表的单词是唯一的,所以属性域可以是空的。若记号所代表的单词不唯一,则需要给出属性。 64 | 65 | LEX遵循最长匹配和优先匹配规则。值得注意的一些词法约定细节有:1)标识符长度受限;2)PASCAL不区分大小写,在分析中识别出一个单词,要马上将其所有字母转化为小写(字符常量、关键字除外);3)PASCAL语言程序的注释规则是注释用一对花括号括起来,编译程序要能处理注释,并将注释以某种形式保存下来,以便代码生成部分能够在恰当的部分用C语言的形式恢复注释。 66 | 67 | 词法分析阶段的错误主要就是读到非法字符(不属于该语言的字符集的字符),通常的做法是跳过非法字符,继续进行词法分析,同时需要输出详细的词法错误列表(错误发生的行数等),以便程序员修改词法错误。 68 | 69 | ### 语法分析的需求分析 70 | 语法分析是编译过程的核心部分,语法分析程序的输入是词法分析程序在扫描字符串源程序的过程中识别并生成的记号序列,语法分析程序分析验证这个记号序列是不是符合该语言语法规则的一个程序,若是,则输出其语法树,若不是,则表明输入的记号序列中存在语法错误,需要报告错误的性质和位置。 71 | 72 | 语法分析需要输出一棵抽象语法树。 73 | 74 | 我们将借助YACC工具,以LALR(1)的自底向上分析方法进行语法分析。为此,我们需要学习PASCAL_S语言,从中抽象出其语法结构,以文法表示。 75 | 76 | 我们需要一层一层(从简单到复杂)的分析PASCAL_S的各种语法单位,为详细设计中的文法设计奠定基础。 77 | 78 | PASCAL程序由三大部分组成:程序首部(head),说明部分(变量、常量、子过程、子函数的定义),语句部分(body,主程序,是一个复合语句块)。 79 | 80 | #### 常量 81 | const关键字用以说明接下来的定义语句都属于常量定义。常量定义需要指定初值,且不必指定类型。常量的初值可以由整数、浮点数、字符常量、别的常量标识符等指明,可以是一个可以由编译器计算出结果的常量表达式(这里我们将其简化,限定为只能是+、-等弹幕运算符加上一个常量标识符组成的最简单的常量表达式)。PASCAL-S的常量定义不包含类型,因此其类型需要编译器判断。 82 | 83 | #### 变量的定义 84 | var关键字用以说明接下来的定义语句都属于变量定义。变量定义必须指明类型,无需指定初值。变量也可以是一维或多维数组,数组的各维下标由表达式组成。 85 | 86 | #### 类型 87 | 可以是最简单的基本类型:integer、real、boolean、char,也可以是由这些基本类型组成的数组。 88 | 89 | #### 参数表 90 | 函数/过程的头部最重要的就是参数列表,参数列表由一系列的标识符、类型关键字组成的参数变量定义组成。PASCAL_S的参数有两种,引用和传值,语法上的区别在于是否包含var关键字。 91 | 92 | #### 表达式 93 | 表达式是由一系列的操作符和操作数组成的,其定义一般是递归的,也就是说,操作数不止是“数”,也可以是一个表达式。我们从操作符优先级的角度进行了分层,使得表达式的语法结构更加清晰。 94 | 95 | 首先引入最底层的因子概念,因子包括:(1)一个常量;(2)一个变量;(3)由单目运算符not、-与另一因子组成的新的因子(这些单目运算符的优先级通常是最高的);(4)括号括起来的表达式;(5)函数调用; 96 | 97 | 然后是项的概念,项可以是一个因子,也可以是由*、/、div、mod、and等优先级较高的双目运算符和两个因子组成的。 98 | 99 | 接下来是简单表达式的概念,简单表达式可以是一个项,也可以是由+、-、or等优先级较低的双目运算符和两个项组成。 100 | 101 | 最终是表达式的概念,表达式可以是一个简单表达式,可以是由>、=、<、<=、>=、<>等优先级最低的关系双目运算符和两个简单表达式组成。 102 | 103 | #### 语句 104 | 语句除了函数(通常表现为赋值语句)、过程调用(过程调用单独作为一条语句,产生某种副作用)外,主要以顺序结构、分支结构、循环结构分成三类。 105 | 106 | 顺序结构是由begin和end关键字及其包括的递归定义的复合语句块。 107 | 108 | 分支结构我们只支持if条件语句,其结构如下: 109 |
110 | IF <条件> 111 | THEN <语句1> 112 | ELSE <语句2> 113 | 114 | 注:1、ELSE与最近的并且未被配对的ELSE配对; 115 | 2、 复合,如果THEN或ELSE带有多个语句,则要用BEGIN—END括起来; 116 |117 | 118 | 循环结构我们支持FOR语句、WHILE语句和REPEAT语句。 119 | 120 | FOR语句的结构如下: 121 |
122 | FOR<循环变量>:=<初值> TO<终值> DO<语句> 123 |124 | 125 | WHILE语句与C语言中的WHILE语句基本一致,其结构如下: 126 |
127 | WHILE <条件> DO <语句> 128 |129 | 130 | REPEAT语句则类似于C语言中的DO-WHILE语句,即至少会执行一次循环体,但是在条件测试上有所区别,REPEAT-UNTIL语句在UNTIL指明的条件为真时退出循环。其结构如下: 131 |
132 | REPEAT 133 | <循环体> 134 | UNTIL 135 | <条件>分程序 136 |137 | #### 子函数/过程 138 | 函数和过程的头部中都包括名称和参数表,此外函数头还需指明返回值的类型,然后是子函数/过程的主体。子函数/过程中不能再嵌套函数/过程,另外,常量定义、变量定义、复合语句块等都与主程序类似。 139 | 140 | #### 分程序 141 | 分程序指的是PASCAL-S的主程序部分,首先要给出常量和变量的定义,然后是函数/过程的定义,最后是语句主体(begin和end包括的复合语句块) 142 | 143 | #### 程序 144 | 程序由程序名称标识符、参数列表和分程序组成。这里的参数列表给出的参数标识符,通常用于命令行参数的指定。与子函数/过程不同的是,这里不指出标识符的类型。因此,如果程序主体中用到了该参数,就必须在变量定义区中再定义一次,指明具体类型。 145 | 146 | 语法分析和语义分析都可以用YACC进行,其中语法分析的侧重点在于错误处理和提示,以便为后续语义分析提供正确的语法结构(语法树)。接下来我们从语法分析的错误处理角度进行需求分析。 147 | 148 | #### 错误处理 149 | 据统计,源程序中出现的错误多是语法错误,所以,编译时大多数错误的诊断和恢复工作集中在语法分析阶段。 150 | 151 | 语法分析程序进行错误处理的基本目标如下: 152 | - 能够清楚而准确地报告发现的错误,如错误的位置和性质。 153 | - 能够迅速地从错误中恢复过来,以便继续诊断后面可能存在的错误。 154 | - 错误处理功能不应该明显地影响编译程序对正确程序的处理效率。 155 | 156 | 要完成目标(1),需要我们主观积累经验,收集可能的错误,如常见的算法表达式的括号不匹配、缺少运算对象等,并对症下药。其次,准确地识别到错误发生的位置后,应无误地将位置(错误代码行数)和性质输出。在我们采用的LALR(1)分析中,分析程序总是根据当前的栈顶状态和当前输入符号去查分析表,若找不到合法的动作,则意味着发现了一个语法错误。 157 | 实现目标(2)和(3),需要采用合理的错误恢复策略。例如小范围的短语级恢复,对于算法表达式的括号不匹配,可选择向前指针跳过当前符号,继续分析。结合利弊,对不同的错误进行分别处理和恢复。 158 | 159 | #### 二义性消除 160 | 所有的二义性文法都不是LR文法。但PASCAL的某些结构用二义性文法描述比较直观且使用方便,例如if条件语句的直观描述产生式为`S->if E then S else S | if E then S | others`,根据PASCAL规定语法,需要在语法分析阶段增加“最近最后匹配原则”解决可能引发的冲突问题。 161 | 总之,在PASCAL语言中,有的文法表示可能是二义性的,但都说明了消除二义性的一些规则,以保证对每个句子的解释是唯一的,我们需要利用这些规则,确保语法分析不会受困于二义性的陷阱。 162 | 163 | ### 语义分析的需求分析 164 | 语义分析的输入是语法树,输出是注释分析树和语义错误信息(错误的性质和位置)和符号表,主要完成符号表的建立和操作、类型检查与转化、作用域识别等3个方面的内容。 165 | 166 | #### 符号表的定义 167 | 主符号表要求记录: 168 | - 种类标志 169 | - 标识符名字 170 | - 行号 171 | - 类型 172 | - 常量取值 173 | - 参数个数/数组维数 174 | - 数组各维上下界 175 | - 指向函数/过程子符号表的指针 176 | 177 | 子符号表的表结构是主符号表的子集。由于不支持函数和过程的嵌套定义,所以子符号表相比于主符号表,少了函数/过程相关的域。子符号表要求记录: 178 | - 种类标志 179 | - 标识符名字 180 | - 行号 181 | - 类型 182 | - 常量取值 183 | - 数组维数 184 | - 数组各维上下界 185 | 186 | 下面对符号表各域进行具体介绍。 187 | 188 | **种类标志**:记录着标识符的符号种类。 189 | - "value parameter"表示传值参数 190 | - "var parameter"表示传引用参数 191 | - "normal variant"表示普通变量 192 | - "constant"表示常量 193 | - "array"表示数组 194 | - "procedure"表示过程 195 | - "function"表示函数。 196 | 197 | **标识符名字**:作为语义分析部分识别标识符的主键,在进行添加、查找、修改等操作时发挥重要作用。 198 | 199 | **行号**:词法分析和语法分析时,在进行报错时可以很方便的获取出错的具体位置,但语义分析通常都是在更抽象的树结构上进行的,所以需要记录下每个符号的行号,以便报错包含位置信息。 200 | 201 | **类型**:对于变量和常量来说,该域记录着变量或常量类型; 对于数组来说,该域记录着数组元素的类型;对于函数来说,该域记录着函数返回值类型。取值为”integer”、”real”、”char”、”boolean”。 202 | 203 | **常量取值**:需要将常量的取值保存下来,以便后续计算常量表达式的值、进行常量定义时的常数传播、检查除0错误、检查数组下标越界。 204 | 205 | **参数个数/数组维数**:在参数个数/数组维度部分,对于数组类型的变量,我们将存储其维数;对于函数类型,我们将存储其参数个数。 206 | 207 | **数组各维上下界**:对于数组而言,在符号表中记录其各维上下界,便于判断其是否越界。 208 | 209 | **指向函数/过程子符号表的指针**:在该指针域中保存该符号表中指向函数/过程子符号表的指针,便于进行定位和重定位处理。 210 | 211 | #### 符号表的管理 212 | 定位操作:在每个程序块的入口处我们需要执行定位操作来建立一个符号表的子表,将该块的声明的所有标识符属性记录到该表中。 213 | 214 | 重定位操作:在每个程序块的出口处我们需要返回到主符号表,实现重定位操作,保证已经执行完的块中声明的局部变量不能再次被引用。 215 | 216 | #### 类型检查与转化 217 | 我们的语义分析需要支持四种基本类型:integer、real、boolean、char,以及这四种基本类型声明的数组。 218 | 219 | 类型转化:我们仅支持隐式类型转化,且其中也仅支持从integer类型到real类型的隐式类型转化。需要特别注意的是,传引用参数不支持隐式类型转化。 220 | 221 | 表达式类型检查:每个运算符对于操作数的类型都有不同的要求,需要具体分析不同运算符的具体要求,例如mod运算符要求两个操作数均为”integer”类型,relop运算符要求两个操作数类型一致,或者符合隐式类型转化的规定。 222 | 223 | 语句类型检查:语句并没有“integer”、“real”、“char”、“boolean”这些类型。以if语句为例,如果其条件表达式的类型为“bool”,那我们认为该语句的类型正确,赋值为”void”,否则我们认为该语句的类型错误,赋值为“error”;再比如赋值语句就要求左值和右值的类型一致。不同的语句有不同的要求,需要具体分析。 224 | 225 | #### 作用域识别 226 | 由于PASCAL-S不支持函数/过程的嵌套定义,所以作用域规则是十分简单的。 227 | 228 | 定义在PASCAL程序一开始的常量、变量就可以是视作是全局作用域,不仅可以被主程序体引用,也可以被子程序引用(如果子程序没有定义同名标识符)。 229 | 230 | 另外,每一个子函数/过程中定义的常量、变量的作用域就局限在当前函数/过程,属于局部作用域。 231 | 232 | 检测标识符未定义错误时,除了局部作用域(如果当前在局部作用域中),还需退回到全局作用域中。 233 | 234 | 检测标识符重定义错误时,只需要在局部作用域(如果当前在局部作用域中)中检查。 235 | 236 | #### 代码生成需求分析 237 | 代码生成输入一般是注释分析树和信息较为完备的符号表,输出是目标代码。目标代码要求能在gcc编译器下正确编译,生成的可执行文件能够正确执行,在合法的输入下,得到正确的输出结果。 238 | 239 | 由于源语言和目标语言都是高级语言,所以我们直接生成目标代码,而不生成中间代码,否则会更加麻烦。借助经过了语义分析的抽象语法树和符号表,我们可以很轻松的进行目标代码生成。 240 | 241 | 接下来,我们从源语言的需求和目标语言的特点出发,通过对比来讨论代码生成的需求细节。 242 | 243 | pascal主程序中的变量可以被所有的过程、函数体访问,具有全局作用域,因此对应于C语言中的全局变量。 244 | 245 | pascal主程序头中包含了一个无类型的标识符列表。经查阅资料,这个标识符列表类似于c语言中main函数的参数列表,例如在命令行调用时可以指定这些参数。我们注意到在pascal的语法中,程序头对于这些标识符的声明没有类型的指示,而c语言有。这预示着在pascal中,我们仍需要定义这些标识符为具体的变量,才能使用,否则就属于未定义就引用的错误。input和output是两个特例,这两个标识符被隐含声明为程序参数且被隐含定义为文件变量,与标准输入,标准输出相关联。需要特别注意的是,程序标识符只能被定义为字符串、文件等类型,如果定义为其它类型,应忽略对应的参数(以避免一些类型错误,PASCAL编译器是这么做的),而我们并不考虑这些类型,所以我们暂时保留这个标识符列表,但在测试用例中并不涉及。如果后续我们有时间增加字符串等类型的支持再进行考虑。在PASCAL中使用命令行参数的一个较为方便的做法是利用paramcount和paramstr这两个变量,这与c语言中main函数的参数int argc, char **argv类似。但由于仍涉及字符串操作,我们仍不考虑。 246 | 247 | 对于常量定义,pascal中的const关键字作用域较大,不局限于下一个分号,而C语言中,每一分号隔出的部分都要单独使用一个const关键字。且pascal中的常量在定义时不需要指明类型,但是C语言需要。所以在我们需要在词法分析阶段完成对常量类型的自动识别,在目标代码生成时,指明对应的类型。 248 | 249 | pascal在声明变量时,除了要说明类型,还要再前面加上var关键字,C语言中没有这样的关键字,只需要指明类型即可。var关键字的作用域与const关键字相同。 250 | 251 | C语言中数组各维下标默认从0开始,而pascal中的范围可以任意指定,因此需要对数组下标进行相应的变换(在目标代码中需要新增定义临时变量以指明偏移量)。 252 | 253 | PASCAL中函数返回值用 函数标识符:=表达式 表示,对应于C语言中的return语句。 254 | 255 | PASCAL中如果函数或者过程没有参数,则无需包含空内容的括号,C语言中则需要。 256 | 257 | PASCAL中多维数组的访问方法是在一个中括号内部,用逗号隔开各维索引,而C语言中则直接用中括号隔开各维索引。 258 | 259 | C语言中一些基本的符号与PASCAL有所区别,例如C语言中的不等于用!=,而PASCAL中用<>。 260 | 261 | PASCAL中的复合语句块用begin和end包括,而在C语言中用花括号包括。 262 | 263 | 代码生成的测试用例同整体测试,不再单独给出。 264 | 265 | ## 总体设计 266 | 语法分析调用词法分析得到记号序列,并分析生成抽象语法树。在抽象语法树上进行语义分析,建立和完善符号表,最后进行代码生成。 267 | 268 | 具体到开发细节,用LEX生成词法分析程序(C++),该词法分析程序由语法分析程序调用生成记号序列,用YACC生成语法分析程序(C++),该语法分析程序可以生成语法分析树,然后用C++编写程序将语法分析树转化为抽象语法树,作为语法分析的最终输出,然后用C++编写语义分析和代码生成程序,最后将各部分代码整合在一起,生成一个完整的编译器。 269 |  270 | 271 | ### 模块划分 272 | #### 预处理 273 | - 输入 274 | - PASCAL-S源程序文件 275 | - 输出 276 | - 经过预处理的PASCAL-S程序文件 277 | - 功能 278 | - PASCAL-S程序大小写不敏感,所以需要将所有字母转化为小写字母。 279 | #### 词法分析 280 | - 输入 281 | - 经过预处理的PASCAL-S程序文件 282 | - 输出 283 | - 记号序列 284 | - 功能 285 | - 编译的整个过程从词法分析开始。从左至右逐个字符地对源程序进行扫描,按照源语言的词法规则识别出一个个单词符号,产生用于语法分析的记号序列。识别源程序中的注释和跳过空格。在遇到错误时,为了使词法分析程序能够继续运行下去,还要对出现的词法错误进行报告,并进行适当的恢复。 286 | #### 语法分析 287 | - 输入 288 | - 记号序列 289 | - 输出 290 | - 抽象语法树 291 | - 功能 292 | - 语法分析程序的输入是词法分析程序在扫描字符串源程序的过程中识别并生成的记号序列,语法分析程序分析验证这个记号序列是不是符合该语言语法规则的一个程序,若是,则输出其语法分析树,并转化为抽象语法树,若不是,则表明输入的记号序列中存在语法错误,需要对语法错误进行适当的恢复,并报告错误的性质和位置。 293 | #### 语义分析 294 | - 输入 295 | - 抽象语法树 296 | - 输出 297 | - 抽象语法树、符号表 298 | - 功能 299 | - 遍历抽象语法树,完成符号表的建立和操作、类型检查与转化、作用域识别等3个方面的内容,需要报告语义错误的性质和错误。 300 | #### 代码生成 301 | - 输入 302 | - 抽象语法树、符号表 303 | - 输出 304 | - C语言代码 305 | - 功能 306 | - 遍历抽象语法树,并借助符号表的信息生成目标代码。 307 | 308 | ### 运行逻辑设计 309 | 编译器的运行设计主要针对错误的宏观处理,可以分为如下三种策略。 310 | ``` 311 | (1)一旦发现任何一个错误,编译器立即终止运行。 312 | (2)编译器尝试从各种错误中恢复过来,并完成整个编译过程。 313 | (3)根据编译过程的模块划分,将错误恢复局限在一个模块中。即在任何一个模块中发现错误时,编译器将尝试从错误中恢复过来,并完成当前模块的处理,然后终止运行。 314 | 315 | 采用策略(1)时,每运行一次编译器,编译程序只能报告一个错误,编译人员的工作效率将大打折扣。 316 | 采用策略(2)时,极有可能出现错上加错的情况,导致后续的报错无法和源程序对应,给编译人员带来不必要的麻烦。 317 | 采用策略(3)时,编译人员可以一次处理成批的错误,工作效率较高,且报错信息准确。 318 | ``` 319 | 因此,采用策略(3)并根据源程序的错误情况,可以将编译器的运行情况表示为下表: 320 |  321 | 注:模块内部的接口设计、详细的错误处理方法,在详细设计中给出。 322 | ### 数据结构设计 323 | #### 记号 324 | 不同的记号有不同种类的属性,直观的想法是设计一个结构体,用不同类型的域去表示不同类型的属性,但是在词法和语法分析阶段,这些记号的属性的存储形式不会产生任何影响,因此记号的结构体中,直接用string类型去表示各种记号的属性,其具体类型的转换工作由后续模块进行。 325 | ```c++ 326 | 1. class node 327 | 2. { 328 | 3. string token; 329 | 4. string value; 330 | 5. }; 331 | ``` 332 | 其中,token表示的是记号或非终结符号的名称,value表示的是属性值。例如表达式的token域是”EXPRESSION”,value域为空;例如一个常数的123.456的token域是”NUMBER”, value域是”123.456”。 333 | 334 | #### 语法分析树 335 | 由于YACC的限制,我们将扩展记号的结构体,作为语法分析树的节点结构体。 336 | ```c++ 337 | 1. class node 338 | 2. { 339 | 3. string token; 340 | 4. string value; 341 | 5. vector
13 | program test(input,output); 14 | var aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:integer; 15 | begin 16 | 17 | end. 18 |19 | 20 | ### 标识符长度超过限制 21 |
22 | program test(input,output); 23 | var asadhsadsadsadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:integer; 24 | begin 25 | 26 | end. 27 |28 | 29 | ### 非法字符 30 |
31 | program test(input,output); 32 | var a:integer; 33 | begin? 34 | $$ 35 | end.## 36 |37 | 38 | ### 读取字符常量时遇到文件尾 39 |
40 | program test(input,output); 41 | const a=' 42 |43 | 44 | ### 读取的字符常量为空 45 |
46 | program test(input,output); 47 | const a='' 48 | begin 49 | 50 | end. 51 |52 | 53 | ### 读取的字符常量不止一个字符 54 |
55 | program test(input,output); 56 | const a='abc'; 57 | begin 58 | writeln(a); 59 | end. 60 |61 | 62 | ### 读取字符常量时,先遇到了换行符而不是右单引号 63 |
64 | program test(input,output); 65 | const a='a 66 | b=' 67 | c='cba 68 | begin 69 | 70 | end. 71 |72 | 73 | ### 读取多行注释时遇到文件尾 74 |
75 | program test(input,output); 76 | { 77 | begin 78 | 79 | end. 80 |81 | 82 | ## 错误组合测试 83 | ### 标识符长度超过限制、非法字符 84 |
85 | program test(input,output); 86 | var asadhsadsadsadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:integer; 87 | # 88 | begin 89 | 90 | end. 91 |92 | 93 | ### 读取的字符常量为空,读取字符常量时遇到文件尾 94 |
95 | program test(input,output); 96 | const a='' 97 | b='abc 98 |99 | 100 | ### 读取的字符常量不止一个字符、读取字符常量时,先遇到了换行符而不是右单引号、读取多行注释时遇到文件尾 101 |
102 | program test(input,output); 103 | const a='abc' 104 | b='bac 105 | begin 106 | {123 107 | end. 108 |109 | 110 | ## 综合测试 111 |
112 | program quicksort(input,output); 113 | var 114 | n,i:integer; 115 | a:array[0..100000] of integer; 116 | b:char; 117 | 118 | procedure kp(l,r:integer); 119 | var 120 | i,j,mid:integer; 121 | begin 122 | b:='a'; 123 | if l>=r then exit; 124 | i:=l;j:=r;mid:=a[(l+r) div 2]; 125 | repeat 126 | begin 127 | while a[i]-------------------------------------------------------------------------------- /test-cases/代码生成测试样例.md: -------------------------------------------------------------------------------- 1 | ## 单语法成分测试 2 | ### write/writeln语句 3 | #### 关注点 4 | 1. 编译成功,运行成功 5 | 2. writeln不带参数地调用,转化为printf("\n"); 6 | 3. 输出bool类型时,会转化为用大括号括起来的if判断语句 7 | 4. 不同格式的表达式正确对应到不同的格式控制符 8 | 9 | #### PASCAL源程序 10 |mid do dec(j); 129 | if i<=j then 130 | begin 131 | a[0]:=a[i];a[i]:=a[j];a[j]:=a[0]; 132 | inc(i);dec(j); 133 | end 134 | end 135 | until i>j; 136 | kp l,j); 137 | kp(i,r) 138 | end; 139 | 140 | begin 141 | readln(n); 142 | for i:=1 to n do 143 | read(a[i]); 144 | kp(1,n); 145 | for i:=1 to n do 146 | write(a[i]); 147 | end. 148 | 149 |
11 | program test(input,output); 12 | const a=1; //整型常量 13 | b=3.0; //浮点型常量 14 | c='c'; //字符型常量 15 | blank=' '; //空格 16 | var d:integer; //整型变量 17 | e:real; //浮点型变量 18 | f:char; //字符型变量 19 | g:boolean; //布尔型变量 20 | begin 21 | d:=6; 22 | e:=6.0; 23 | f:='f'; 24 | g:=2>1;//不支持true常量,所以这么写 25 | writeln(a,blank,b,blank,c,blank,1,blank,1.0,blank,'y'); 26 | write(a,blank,b,blank,c,blank,1,blank,1.0,blank,'y'); 27 | writeln; 28 | writeln(g); 29 | writeln(a+b,blank,a*b,blank,g,blank,a>b,blank,c,blank,d,blank,e,blank,d<>e); 30 | end. 31 |32 | 33 | #### C程序用例 34 | 无 35 | 36 | ### read语句 37 | #### 关注点 38 | 1. 编译成功,运行成功 39 | 2. 生成的C代码中,不同格式的表达式正确对应到不同的格式控制符 40 | 3. 生成的C代码中,读取到普通变量时,正确添加了取地址符 41 | 4. 生成的C代码中,读取到引用(指针)参数时,不需要添加取地址符,因为指针本身就已经代表地址了 42 | 5. 运行后,正确读取所有值,并原样输出所有值 43 | #### PASCAL源程序 44 |
45 | program test(input,output); 46 | var a,i:integer; //整型变量 47 | b:real; //浮点型变量 48 | c:char; //字符型变量 49 | d:array[1..6] of integer; //数组 50 | procedure pro(var a:integer); 51 | begin 52 | read(a); 53 | end; 54 | begin 55 | read(c,a); //读取字符和整数 56 | for i:=1 to 6 do 57 | pro(d[i]); //循环加调用程序读取6个整数 58 | read(b); //读取浮点数 59 | 60 | writeln(c,' ',a); //输出字符和整数 61 | for i:=1 to 6 do //输出6个整数,空格分隔 62 | write(d[i],' '); 63 | writeln; //输出换行 64 | writeln(b); //输出浮点数 65 | end. 66 |67 | 68 | #### C程序 69 |
70 | c 100 71 | 1 2 3 4 5 6 72 | 2.333 73 |74 | 75 | ### 头文件 76 | #### 关注点 77 | #### PASCAL-S源程序 78 |
79 | program test(input,output); 80 | var a,b:integer; 81 | begin 82 | a:=3*b; 83 | end. 84 |85 | 86 |
87 | program test(input,output); 88 | var a,b:integer; 89 | begin 90 | read(b); 91 | a:=3*b; 92 | writeln(a); 93 | end. 94 |95 | 96 | #### C程序用例 97 | 第二个程序的测试用例 98 |
99 | 100 100 |101 | 102 | ### 运算符和表达式 103 | #### 关注点 104 | 1. 生成的C代码中,各种运算符均转化正确 105 | 2. 生成的C代码中,对于a:=--b这种连着的单目运算符,添加了括号,更加易读 106 | 3. 生成的C代码中,对于不同类型的表达式,输出格式控制符正确 107 | 4. bool类型表达式的输出转化为了if-else语句 108 | 5. 输出结果符合预设值 109 | 110 | #### PASCAL-S源程序 111 |
112 | program test(input,output); 113 | const a=3; 114 | b=1.0; 115 | c='c'; 116 | var d,e,f:integer; 117 | g,h,i:real; 118 | j,k,l:char; 119 | m,n,o:boolean; 120 | function fun(a:integer):integer; 121 | begin 122 | exit(a+1); 123 | end; 124 | begin 125 | d:=5; e:=10; 126 | g:=0.25; h:=0.5; 127 | j:='a'; k:='b'; 128 | 129 | f:= d mod (e div fun(d)); //涉及mod、div和函数调用的复杂表达式 130 | writeln(f); //类型为integer 131 | 132 | g:= --d + e / d * ( - b); //涉及加减乘除、取相反数、加括号的复杂表达式 133 | writeln(g); //类型为real 134 | 135 | o:= ( ( f mod e ) <> d ) or ( a > b); //涉及<>、or的复杂表达式 136 | writeln(o); //类型为boolean 137 | 138 | m:= not not ( ( d + e ) = f ); //涉及取非、=的复杂表达式 139 | writeln(m); //类型为boolean 140 | 141 | n:= ( g * e < f ) and ( (f mod e) >= d ); //涉及and、<、>=、mode的复杂表达式 142 | writeln(n); //类型为boolean 143 | 144 | writeln( j <= c); //比较char的大小关系 145 | 146 | writeln( m > n); //比较boolean的大小关系 147 | end. 148 |149 | 150 | ### 引用参数与指针 151 | #### 关注点 152 | 1. PASCAL-S源程序中普通变量作为引用形参对应的实参调用时,在生成的C代码中加上&取地址符 153 | 2. PASCAL-S源程序中引用参数作为引用形参对应的实参调用时,在生成的C代码中无需前置任何符号,因为引用参数对应到C代码中已经是指针了,所以调用时,传本身就已经是地址了。 154 | 3. PASCAL-S源程序中,用到引用参数的地方(除了2中的情况),在生成的C代码中,都需加上前置的"*",表示解引用 155 | #### PASCAL-S源程序 156 |
157 | program test(input, output); 158 | var ans:integer; 159 | { 160 | 求斐波那契数列值的过程,利用引用参数保存结果; 161 | n表示求第n项斐波那契数列值; 162 | fib(0)=1, fib(1)=1, ……, fib(n)=fib(n-1)+fib(n-2); 163 | } 164 | procedure fib(n:integer;var res:integer); 165 | var tmp1,tmp2:integer; 166 | begin 167 | if n=0 then 168 | res:=1 169 | else 170 | if n=1 then 171 | res:=1 172 | else 173 | begin 174 | fib(n-1,tmp1); 175 | fib(n-2,tmp2); 176 | res:=tmp1+tmp2; 177 | end; 178 | end; 179 | { 180 | 自己编写的输出函数,可以实现输出n次out值; 181 | 递归调用自身,n每次减1; 182 | out值采用的是引用参数; 183 | } 184 | procedure mywrite(n:integer; var out:integer); 185 | begin 186 | if n=0 then 187 | exit 188 | else 189 | begin 190 | writeln(out); 191 | mywrite(n-1, out); 192 | end; 193 | end; 194 | 195 | begin 196 | fib(10, ans); //ans=fib(10) 197 | mywrite(3, ans); //输出ans 3次 198 | end. 199 |200 | 201 | #### C程序用例 202 | 无 203 | 204 | ### 常量和变量定义 205 | #### 关注点 206 | 1. 生成的C代码中,各种类型的常量定义均正确的加上了类型关键字,类型关键字的转化正确; 207 | 2. 生成的C代码中,各种类型的变量定义正确; 208 | 3. 生成的C代码中,各种类型的数组定义正确,各维大小正确; 209 | 210 | #### PASCAL-S源程序 211 |
212 | program test(input, output); 213 | const a=1; //整型常量定义 214 | b=2.0; //浮点型常量定义 215 | c='c'; //字符型常量定义 216 | var d,dd,ddd:integer; //整型变量定义 217 | e,ee,eee:real; //浮点型变量定义 218 | f,ff,fff:char; //字符型变量定义 219 | g,gg,ggg:boolean; //boolean型变量定义 220 | h,hh,hhh:array[1..3] of integer; //整型数组定义 221 | i,ii,iii:array[1..3, 4..9] of real; //浮点型数组定义 222 | j,jj,jjj:array[1..3, 4..9, 10..18] of char; //字符型数组定义 223 | k,kk,kkk:array[1..3, 4..9, 10..18, 19..30] of boolean; //布尔型数组定义 224 | procedure pro; 225 | const a=1; //整型常量定义 226 | b=2.0; //浮点型常量定义 227 | c='c'; //字符型常量定义 228 | var d,dd,ddd:integer; //整型变量定义 229 | e,ee,eee:real; //浮点型变量定义 230 | f,ff,fff:char; //字符型变量定义 231 | g,gg,ggg:boolean; //boolean型变量定义 232 | h,hh,hhh:array[1..3] of integer; //整型数组定义 233 | i,ii,iii:array[1..3, 4..9] of real; //浮点型数组定义 234 | j,jj,jjj:array[1..3, 4..9, 10..18] of char; //字符型数组定义 235 | k,kk,kkk:array[1..3, 4..9, 10..18, 19..30] of boolean; //布尔型数组定义 236 | begin 237 | 238 | end; 239 | begin 240 | 241 | end. 242 |243 | #### C程序用例 244 | 无 245 | 246 | ### 程序声明 247 | #### 关注点 248 | 1. 生成的C代码中,子程序声明正确; 249 | 2. 生成的C代码中,子程序定义的子程序头正确; 250 | 3. 生成的C代码中,子程序声明和子程序头的参数的声明顺序与PASCAL-S源程序一致 251 | 4. 生成的C代码中,子程序声明和子程序头的参数中,PASCAL-S源程序的引用参数成功的转化为了指针 252 | #### PASCAL-S源程序 253 |
254 | program test(input,output); 255 | procedure pro(var a,b,c:integer; d:real; e,f:char; var g,h,i:boolean); 256 | begin 257 | 258 | end; 259 | function fun(a:integer; var b,c,d:real; var e,f,g:boolean; h,i:char):real; 260 | begin 261 | fun:=1; 262 | end; 263 | begin 264 | 265 | end. 266 |267 | 268 | #### C程序用例 269 | 无 270 | 271 | ### 数组定义与数组元素引用 272 | #### 关注点 273 | 1. 生成的C代码中,数组定义的各维大小正确 274 | 2. 生成的C代码中,两个三重循环中,对数组元素的引用,下标表达式添加了正确的偏移量 275 | #### PASCAL-S源程序 276 |
277 | program test(input,output); 278 | var i,j,k:integer; 279 | a:array[0..1, 2..3, 4..5] of integer; //数组定义 280 | begin 281 | for i:=0 to 1 do 282 | for j:=2 to 3 do 283 | for k:=4 to 5 do 284 | read(a[i,j,k]); //三重循环,读入每一个数组元素,共8个 285 | for i:=0 to 1 do 286 | for j:=2 to 3 do 287 | for k:=4 to 5 do 288 | writeln(a[i,j,k]) //三重循环,输出每一个数组元素,换行符分隔 289 | end. 290 |291 | #### C程序用例 292 |
293 | 1 2 3 4 5 6 7 8 294 |295 | 296 | ### 返回语句 297 | #### 关注点 298 | 1. 赋值形式的返回值语句正确的转化为了C程序中的return语句; 299 | 2. exit带参数的返回值语句正确的转化为了C程序中的return语句; 300 | 3. exit不带参数的返回语句正确的转化为了C程序中的return语句; 301 | 4. 输出结果符合预设值 302 | #### PASCAL-S源程序 303 |
304 | program test(input,output); 305 | var b,c,d:integer; 306 | procedure pro; 307 | begin 308 | exit; 309 | end; 310 | function fun(a:integer):char; 311 | begin 312 | if a<60 then 313 | exit('l') 314 | else 315 | if a=60 then 316 | fun:='m' 317 | else 318 | exit('h'); 319 | end; 320 | function fun2(a:integer; var b,c,d:integer):integer; 321 | begin 322 | if a=0 then 323 | fun2:=b+c+d 324 | else 325 | if a=1 then 326 | fun2:=b*c*d 327 | else 328 | exit(-b-c-d); 329 | end; 330 | begin 331 | read(b,c,d); 332 | writeln(fun(b), ' ', fun(c), ' ', fun(d)); 333 | writeln(fun2(0, b, c, d), ' ', fun2(1, b, c, d), ' ', fun2(2, b, c, d)); 334 | end. 335 |336 | #### C程序用例 337 |
338 | 59 60 61 339 |340 | 341 | ### 程序的无参调用 342 | #### 关注点 343 | 1. 过程的无参调用正确的转化为了C代码,添加了一对括号 344 | 2. 函数的无参调用正确的转化为了C代码,添加了一对括号 345 | #### PASCAL-S源程序 346 |
347 | program test(input,output); 348 | var a:integer; 349 | procedure pro; 350 | begin 351 | writeln(a); 352 | end; 353 | function fun:integer; 354 | begin 355 | fun:=100; 356 | end; 357 | begin 358 | writeln(fun); 359 | a:=fun mod 3; 360 | pro; 361 | end. 362 |363 | 364 | #### C程序用例 365 | 无 366 | 367 | ### 各种语句混合与缩进 368 | #### 关注点 369 | 1. if语句转化正确 370 | 2. while语句转化正确 371 | 3. for语句转化正确 372 | 4. repeat语句转化正确,特别是条件表达式,需要取非 373 | 5. compound语句转化正确 374 | 6. 语句的缩进美观,且符合设计 375 | 7. 输入的10个数正确的被排序,按照从小到大的顺序输出 376 | #### PASCAL-S源程序 377 |
378 | program test(input, output); 379 | var i:integer; 380 | a:array[1..10] of integer; 381 | procedure swap(var a,b:integer); //交换两个数的值 382 | var tmp:integer; 383 | begin 384 | tmp:=a; 385 | a:=b; 386 | b:=tmp; 387 | end; 388 | procedure bubbleSort; //冒泡排序 389 | var i,j:integer; 390 | begin 391 | for i:= 1 to 10 do //for语句 392 | begin //compound语句 393 | j:=i+1; 394 | while j <= 10 do //while语句 395 | begin //compound语句 396 | if a[i]>a[j] then //if语句 397 | swap(a[i],a[j]); 398 | j:=j+1; 399 | end 400 | end; 401 | end; 402 | begin 403 | i:=1; 404 | repeat //repeat语句 405 | begin //compound语句 406 | read(a[i]); 407 | i:=i+1 408 | end 409 | until i=11; 410 | bubbleSort; 411 | for i:= 1 to 10 do //for语句 412 | write(a[i],' '); 413 | writeln; 414 | end. 415 |416 | #### C程序用例 417 |
418 | 8 3 5 4 0 6 9 7 1 2 419 |420 | 421 | ## 综合测试 422 | ### 快速排序 423 | #### PASCAL-S源程序 424 |
425 | program quicksort(input,output); 426 | var 427 | n,i:integer; 428 | a:array[0..100000] of integer; 429 | 430 | procedure kp(l,r:integer); 431 | var 432 | i,j,mid:integer; 433 | begin 434 | if l>=r then exit; 435 | i:=l;j:=r;mid:=a[(l+r) div 2]; 436 | repeat 437 | begin 438 | while a[i]460 | 461 | #### C程序用例 462 |mid do j:=j-1; 440 | if i<=j then 441 | begin 442 | a[0]:=a[i];a[i]:=a[j];a[j]:=a[0]; 443 | i:=i+1;j:=j-1; 444 | end 445 | end 446 | until i>j; 447 | kp(l,j); 448 | kp(i,r) 449 | end; 450 | 451 | begin 452 | read(n); 453 | for i:=1 to n do 454 | read(a[i]); 455 | kp(1,n); 456 | for i:=1 to n do 457 | write(a[i],' '); 458 | end. 459 |
463 | 10 464 | 5 9 2 1 0 8 3 4 6 7 465 |466 | 467 | ### 最大公因数 468 | #### PASCAL源程序 469 |
470 | program example(input,output); 471 | var n,i,x,y:integer; 472 | function gcd(a,b:integer):integer; 473 | begin 474 | if b=0 then gcd:=a 475 | else gcd:=gcd(b,a mod b); 476 | end; 477 | begin 478 | read(n); 479 | for i:= 1 to n do 480 | begin 481 | read(x,y); 482 | writeln(gcd(x,y)) 483 | end; 484 | end. 485 |486 | 487 | #### C程序用例 488 |
489 | 5 490 | 100 36 491 | 3 0 492 | 50 30 493 | 12 28 494 | 327 198321 495 |496 | 497 | -------------------------------------------------------------------------------- /test-cases/综合测试用例.md: -------------------------------------------------------------------------------- 1 | ### hello world 2 |
3 | program test(input,output); 4 | begin 5 | writeln('h','e','l','l','o',' ','w','o','r','l','d','!'); 6 | end. 7 |8 | 9 | ### 快速排序 10 |
11 | program quicksort(input,output); 12 | var 13 | n,i:integer; 14 | a:array[0..100000] of integer; 15 | 16 | procedure kp(l,r:integer); 17 | var 18 | i,j,mid:integer; 19 | begin 20 | if l>=r then exit; 21 | i:=l;j:=r;mid:=a[(l+r) div 2]; 22 | repeat 23 | begin 24 | while a[i]46 | 47 | ### 冒泡排序 48 |mid do j:=j-1; 26 | if i<=j then 27 | begin 28 | a[0]:=a[i];a[i]:=a[j];a[j]:=a[0]; 29 | i:=i+1;j:=j-1; 30 | end 31 | end 32 | until i>j; 33 | kp(l,j); 34 | kp(i,r) 35 | end; 36 | 37 | begin 38 | read(n); 39 | for i:=1 to n do 40 | read(a[i]); 41 | kp(1,n); 42 | for i:=1 to n do 43 | write(a[i],' '); 44 | end. 45 |
49 | program test(input, output); 50 | var i:integer; 51 | a:array[1..10] of integer; 52 | procedure swap(var a,b:integer); 53 | var tmp:integer; 54 | begin 55 | tmp:=a; 56 | a:=b; 57 | b:=tmp; 58 | end; 59 | procedure bubbleSort; 60 | var i,j:integer; 61 | begin 62 | for i:= 1 to 10 do 63 | begin 64 | j:=i+1; 65 | while j <= 10 do 66 | begin 67 | if a[i]>a[j] then 68 | swap(a[i],a[j]); 69 | j:=j+1; 70 | end 71 | end; 72 | end; 73 | begin 74 | i:=1; 75 | repeat 76 | begin 77 | read(a[i]); 78 | i:=i+1 79 | end 80 | until i=11; 81 | bubbleSort; 82 | for i:= 1 to 10 do 83 | write(a[i],' '); 84 | writeln; 85 | end. 86 |87 | 88 | ### 最大公因数 89 |
90 | program example(input,output); 91 | var n,i,x,y:integer; 92 | function gcd(a,b:integer):integer; 93 | begin 94 | if b=0 then gcd:=a 95 | else gcd:=gcd(b,a mod b); 96 | end; 97 | begin 98 | read(n); 99 | for i:= 1 to n do 100 | begin 101 | read(x,y); 102 | writeln(gcd(x,y)) 103 | end; 104 | end. 105 |106 | 107 | ### 词法+语法错误 108 |
109 | program test(input,output; 110 | # 111 | # 112 | # 113 | # 114 | # 115 | # 116 | # 117 | # 118 | # 119 | # 120 | begin 121 | 122 | end. 123 |124 | 125 | ### 很多语义错误 126 |
127 | program read(write,output);//主程序名和库程序同名 128 | const m=10; 129 | exit=m;//exit是库函数 130 | var a,x,y:integer; 131 | b:real; 132 | c:char; 133 | d:boolean; 134 | e:array[1..5] of integer; 135 | function fun1:integer;//报函数没有返回语句的警告 136 | begin 137 | v:=a;//v未定义 138 | end; 139 | 140 | function fun2:integer; 141 | begin 142 | fun2:=1; 143 | fun2:=e[6];//数组下标越界 144 | fun2;//函数不能作为一条单独的语句 145 | a:=fun2[1];//错把函数名当做数组 146 | end; 147 | 148 | procedure pro1(a:integer;b:real); 149 | var c:real; 150 | d:integer; 151 | begin 152 | c:=a+b;//integer可以隐式转换为real 153 | d:=a+b;//real不能隐式转换为integer 154 | end; 155 | 156 | procedure pro2(var a:real;b:integer); 157 | begin 158 | exit(a+b);//过程没有返回值 159 | end; 160 | 161 | begin 162 | a:=1; 163 | m:=a;//常量赋值语句右值不为常量 164 | b:=2; 165 | c:=3;//赋值语句左右类型不匹配 166 | d:=a>b;//d为false 167 | if a then b:=b+1;//if条件表达式不为boolean 168 | repeat a:=a+c until not d;//a:=a+c语句左右类型不匹配 169 | for b:=10 to 1 do e(a,a);//循环变量不可以是real;错把数组名当做函数 170 | while a<10 do a:=a+1; 171 | x:=pro1(x,y);//pro1为过程,没有返回值 172 | x:=1; 173 | y:=2; 174 | pro1(x,y);//传值参数支持integer到real的隐式转换 175 | pro2(x,y);//pro2的第一个参数为传引用,integer无法隐式转换为real 176 | pro1(x+y);//pro1有两个参数 177 | pro1(x+y,x+y);//传值参数支持复合表达式 178 | pro2(x+y);//pro2有两个参数 179 | pro2(x+y,x+y);//pro2第一个参数为引用参数,只能是变量或者数组元素,不能是复杂表达式 180 | end. 181 |-------------------------------------------------------------------------------- /test-cases/语法分析测试用例.md: -------------------------------------------------------------------------------- 1 | ### programstruct 2 | programstruct ---> program_head ';' program_body '.' 3 | 4 | #### 分析成功后有多余的内容 5 | programstruct ---> program_head ';' program_body '.' 6 |
7 | program test(input,output); 8 | var b:real; 9 | c:array[1..5,6..10] of integer; 10 | function fun(d,e:integer):integer; 11 | begin 12 | fun:=d+e; 13 | end; 14 | begin 15 | c[3,8]:=fun(3,8); 16 | end. 17 | b:=c[1,6]; 18 |19 | 20 | #### 主程序头尾部缺少分号 21 | programstruct ---> program_head error program_body '.' 22 |
23 | program test(input,output) 24 | begin 25 | 26 | end. 27 |28 | 29 | #### 结尾缺少点号(end后) 30 | programstruct ---> program_head ';' program_body error 31 |
32 | program test(input,output); 33 | begin 34 | 35 | end 36 |37 | 38 | #### 主程序头识别失败 39 | programstruct ---> error ';' program_body '.' 40 |
41 | ; 42 | begin 43 | 44 | end. 45 |46 | 47 |
48 | (input,output); 49 | begin 50 | 51 | end. 52 |53 | 54 | #### program_body识别失败 unchecked 55 | programstruct ---> program_head ';' error '.' 56 |
57 | program test(input,output); 58 | 59 | . 60 |61 | 62 | #### program_head前包含非法字符 63 | programstruct ---> error program_head ';' program_body '.' 64 |
65 | 1 program test(input,output); 66 | begin 67 | 68 | end. 69 |70 | 71 | #### program_head前包含非法记号、缺失分号 72 | programstruct ---> error program_head error program_body '.' 73 |
74 | 1 program test(input,output) 75 | begin 76 | 77 | end. 78 |79 | 80 | #### program_head前包含非法记号、缺失点号 81 | programstruct ---> error program_head ';' program_body error 82 |
83 | 1 program test(input,output); 84 | begin 85 | 86 | end 87 |88 | 89 | #### program_head前包含非法记号、program_body识别失败 unchecked 90 | programstruct ---> error program_head ';' error '.' 91 |
92 | 1 program test(input,output); 93 | 94 | . 95 |96 | 97 | ### program_head 98 | program_head ---> PROGRAM IDENTIFIER '(' idlist ')' 99 | 100 | #### 缺少左括号 101 | program_head ---> PROGRAM IDENTIFIER error idlist ')' 102 |
103 | program test input,ouput); 104 | begin 105 | 106 | end. 107 |108 | 109 | #### 缺少右括号 110 | program_head ---> PROGRAM IDENTIFIER '(' idlist error 111 |
112 | program test (input,output; 113 | begin 114 | 115 | end. 116 |117 | 118 |
119 | program test(); 120 | begin 121 | 122 | end. 123 |124 | 125 | #### 缺少主程序名 126 | program_head ---> PROGRAM error '(' idlist ')' 127 |
128 | program (input,output); 129 | begin 130 | 131 | end. 132 |133 | 134 | #### 主程序头不完整 135 | program_head ---> PROGRAM error 136 |
137 | program 138 | begin 139 | 140 | end. 141 |142 | 143 |
144 | program test 145 | begin 146 | 147 | end. 148 |149 | 150 | #### 主程序参数列表缺失 151 | program_head ---> PROGRAM IDENTIFIER '(' error ')' 152 |
153 | program test (1,2); 154 | begin 155 | 156 | end. 157 | 158 |159 | program_head ---> PROGRAM IDENTIFIER error 160 |
161 | program test 162 | begin 163 | 164 | end. 165 | 166 |167 | program_head ---> PROGRAM IDENTIFIER '(' error 168 |
169 | program test( 170 | begin 171 | 172 | end. 173 |174 | 175 | 176 | ### const_declarations 177 | const_declarations ---> CONST const_declaration ';' | empty 178 | 179 | #### 常量定义出现错误 180 | const_declarations ---> CONST error 181 |
182 | program test(input,output); 183 | const 1 184 | begin 185 | 186 | end. 187 | 188 |189 | const_declarations ---> CONST error ';' 190 |
191 | program test(input,output); 192 | const 1; 193 | begin 194 | 195 | end. 196 |197 | 198 | #### 缺少分号 199 | const_declarations ---> CONST const_declaration error 200 |
201 | program test(input,output); 202 | const a=3;b=5 203 | begin 204 | 205 | end. 206 |207 | 208 | ### const_declaration 209 | const_declaration ---> const_declaration ';' IDENTIFIER '=' const_value | IDENTIFIER '=' const_value 210 | 211 | #### 常数初始化右值缺失 212 | const_declaration ---> const_declaration ';' IDENTIFIER '=' error 213 |
214 | program test(input,output); 215 | const a=1;b=; 216 | begin 217 | 218 | end. 219 |220 | 221 | const_declaration ---> IDENTIFIER '=' error 222 |
223 | program test(input,output); 224 | const a=; 225 | begin 226 | 227 | end. 228 |229 | 230 | 231 | #### 缺少分号 232 | const_declaration ---> const_declaration error IDENTIFIER '=' const_value 233 |
234 | program test(input,output); 235 | const a=1 b=a; 236 | begin 237 | 238 | end. 239 |240 | 241 | #### 缺少等号 242 | const_declaration ---> const_declaration ';' IDENTIFIER error const_value 243 |
244 | program test(input,output); 245 | const a=1;b 2; 246 | begin 247 | 248 | end. 249 |250 | 251 | const_declaration ---> IDENTIFIER error const_value 252 |
253 | program test(input,output); 254 | const a 1; 255 | begin 256 | 257 | end. 258 |259 | 260 | 261 | ### var_declarations 262 | var_declarations ---> VAR var_declaration ';' | empty 263 | #### 变量定义出现错误 264 | var_declarations ---> VAR error ';' 265 |
266 | program test(input,output); 267 | var ; 268 | begin 269 | 270 | end. 271 |272 | 273 |
274 | program test(input,output); 275 | var x; 276 | begin 277 | 278 | end. 279 |280 | 281 | #### 缺少分号 282 | var_declarations ---> VAR var_declaration error 283 |
284 | program test(input,output); 285 | var x:integer; y:real 286 | begin 287 | 288 | end. 289 |290 | 291 | ### var_declaration 292 | var_declaration ---> var_declaration ';' idlist ':' type | idlist ':' type 293 | #### 缺少分号 294 | var_declaration ---> var_declaration error idlist ':' type 295 |
296 | program test(input,output); 297 | var x:integer y:real; 298 | begin 299 | 300 | end. 301 |302 | 303 | #### 缺少冒号 304 | var_declaration ---> idlist error type 305 |
306 | program test(input,output); 307 | var b real; 308 | procedure pro; 309 | begin 310 | end; 311 | begin 312 | 313 | end. 314 |315 | 316 | var_declaration ---> var_declaration ';' idlist error type 317 |
318 | program test(input,output); 319 | var x:integer;y real; 320 | begin 321 | 322 | end. 323 |324 | 325 | #### type识别失败 326 | var_declaration ---> var_declaration ';' idlist ':' error 327 |
328 | program test(input,output); 329 | var x:integer;y:; 330 | begin 331 | 332 | end. 333 |334 | 335 |
336 | program test(input,output); 337 | var x:integer;y:abc; 338 | begin 339 | 340 | end. 341 |342 | 343 | var_declaration ---> idlist ':' error 344 |
345 | program test(input,output); 346 | var x:; 347 | begin 348 | 349 | end. 350 |351 | 352 |
353 | program test(input,output); 354 | var x:123; 355 | begin 356 | 357 | end. 358 |359 | 360 | ### type 361 | //删除了缺少右中括号的产生式、数组维数识别失败 362 | type ---> TYPE | ARRAY '[' period ']' OF TYPE 363 | 364 | #### 缺少左中括号 365 | type ---> ARRAY error period ']' OF TYPE 366 |
367 | program test(input,output); 368 | var a: array 1..3] of integer; 369 | begin 370 | 371 | end. 372 |373 | 374 | #### 缺少OF关键字 375 | type ---> ARRAY '[' period ']' error TYPE 376 |
377 | program test(input,output); 378 | var a: array[1..3] integer; 379 | begin 380 | 381 | end. 382 |383 | 384 | #### 数组元素类型识别失败 385 | type ---> ARRAY '[' period ']' OF error 386 |
387 | program test(input,output); 388 | var a: array[1..2] of ; 389 | begin 390 | 391 | end. 392 |393 | 394 |
395 | program test(input,output); 396 | var a: array[1..2] of 123; 397 | begin 398 | 399 | end. 400 |401 | 402 | #### 不完整的数组类型 403 | type ---> ARRAY error 404 |
405 | program test(input,output); 406 | var a: array; 407 | begin 408 | 409 | end. 410 |411 | 412 |
413 | program test(input,output); 414 | var a: array 123; 415 | begin 416 | 417 | end. 418 |419 | 420 | type ---> ARRAY '[' error 421 |
422 | program test(input,output); 423 | var a: array [a; 424 | begin 425 | 426 | end. 427 |428 | 429 | type ---> ARRAY '[' period error 430 |
431 | program test(input,output); 432 | var a: array [1..3,4..6,7..9; 433 | begin 434 | 435 | end. 436 |437 | 438 | ### period 439 | period ---> period ',' UINUM RANGEDOT UINUM | UINUM RANGEDOT UINUM 440 | 441 | #### 缺少逗号 442 | period ---> period error UINUM RANGEDOT UINUM 443 |
444 | program test(input,output); 445 | var a: array [1..3 4..6 7..9]; 446 | begin 447 | 448 | end. 449 |450 | 451 | #### 缺少双点号 452 | period ---> period ',' UINUM error UINUM 453 |
454 | program test(input,output); 455 | var a: array [1..3,4 6,7 9]; 456 | begin 457 | 458 | end. 459 |460 | 461 | 462 | ### subprogram_declarations 463 | subprogram_declarations ---> subprogram_declarations subprogram ';' | empty 464 | 465 | #### 缺少分号 466 | subprogram_declarations ---> subprogram_declarations subprogram error 467 |
468 | program test(input,output); 469 | var b:real; 470 | procedure pro; 471 | begin 472 | end 473 | begin 474 | 475 | end. 476 |477 | 478 | ### subprogram 479 | subprogram ---> subprogram_head ';' subprogram_body 480 | 481 | #### 缺少分号 482 | subprogram ---> subprogram_head error subprogram_body 483 |
484 | program test(input,output); 485 | var b:real; 486 | procedure pro 487 | begin 488 | end; 489 | begin 490 | 491 | end. 492 |493 | 494 | ### subprogram_head 495 | subprogram_head ---> PROCEDURE IDENTIFIER formal_parameter | FUNCTION IDENTIFIER formal_parameter ':' TYPE 496 | 497 | #### 函数名缺失 498 | subprogram_head ---> FUNCTION error formal_parameter ':' TYPE 499 |
500 | program test(input,output); 501 | var b:real; 502 | function :integer; 503 | begin 504 | end; 505 | begin 506 | 507 | end. 508 |509 | 510 |
511 | program test(input,output); 512 | var b:real; 513 | function (a:integer):integer; 514 | begin 515 | end; 516 | begin 517 | 518 | end. 519 |520 | 521 | #### 缺少冒号 522 | subprogram_head ---> FUNCTION IDENTIFIER formal_parameter error TYPE 523 |
524 | program test(input,output); 525 | var b:real; 526 | function fun(a:integer)integer; 527 | begin 528 | end; 529 | begin 530 | 531 | end. 532 |533 | 534 | #### 缺少基本类型关键字 535 | subprogram_head ---> FUNCTION IDENTIFIER formal_parameter ':' error 536 |
537 | program test(input,output); 538 | var b:real; 539 | function fun; 540 | begin 541 | end; 542 | begin 543 | 544 | end. 545 |546 | 547 | subprogram_head ---> FUNCTION IDENTIFIER formal_parameter error 548 |
549 | program test(input,output); 550 | var b:real; 551 | function fun(a:integer); 552 | begin 553 | end; 554 | begin 555 | 556 | end. 557 |558 | 559 | #### 不完整的函数头 560 | subprogram_head ---> FUNCTION error 561 |
562 | program test(input,output); 563 | var b:real; 564 | function; 565 | begin 566 | end; 567 | begin 568 | 569 | end. 570 |571 | 572 | subprogram_head ---> FUNCTION IDENTIFIER error 573 |
574 | program test(input,output); 575 | var b:real; 576 | function fun; 577 | begin 578 | end; 579 | begin 580 | 581 | end. 582 |583 | 584 | #### 不完整的过程头 585 | subprogram_head ---> PROCEDURE error 586 |
587 | program test(input,output); 588 | var b:real; 589 | procedure; 590 | begin 591 | end; 592 | begin 593 | 594 | end. 595 |596 | 597 |
598 | program test(input,output); 599 | var b:real; 600 | procedure (a:integer); 601 | begin 602 | end; 603 | begin 604 | 605 | end. 606 |607 | 608 | ### formal_parameter 609 | formal_parameter ---> '(' parameter_list ')' | empty 610 | 611 | #### 不完整的形参列表 612 | formal_parameter ---> '(' error 613 |
614 | program test(input,output); 615 | var b:real; 616 | procedure pro(); 617 | begin 618 | end; 619 | begin 620 | 621 | end. 622 |623 | 624 |
625 | program test(input,output); 626 | var b:real; 627 | procedure pro(123); 628 | begin 629 | end; 630 | begin 631 | 632 | end. 633 |634 | 635 |
636 | program test(input,output); 637 | var b:real; 638 | procedure pro(; 639 | begin 640 | end; 641 | begin 642 | 643 | end. 644 |645 | 646 | #### 右括号缺失 647 | formal_parameter ---> '(' parameter_list error 648 |
649 | program test(input,output); 650 | var b:real; 651 | procedure pro(a:integer; 652 | begin 653 | end; 654 | begin 655 | 656 | end. 657 |658 | 659 | ### parameter_list 660 | parameter_list ---> parameter_list ';' parameter | parameter 661 | 662 | #### 缺少分号 663 | parameter_list ---> parameter_list error parameter 664 |
665 | program test(input,output); 666 | var b:real; 667 | procedure pro(var a:integer b:real); 668 | begin 669 | end; 670 | begin 671 | 672 | end. 673 |674 | 675 | ### var_parameter 676 | var_parameter ---> VAR value_parameter 677 | 678 | #### 不完整的引用参数列表 679 | var_parameter ---> VAR error 680 |
681 | program test(input,output); 682 | var b:real; 683 | procedure pro(var ); 684 | begin 685 | end; 686 | begin 687 | 688 | end. 689 |690 | 691 |
692 | program test(input,output); 693 | var b:real; 694 | procedure pro(var 123); 695 | begin 696 | end; 697 | begin 698 | 699 | end. 700 |701 | 702 | ### value_parameter 703 | value_parameter ---> idlist ':' TYPE 704 | 705 | #### 缺少分号 706 | value_parameter ---> idlist ':' error 707 |
708 | program test(input,output); 709 | var b:real; 710 | procedure pro(a integer); 711 | begin 712 | end; 713 | begin 714 | 715 | end. 716 |717 | 718 | #### 缺少基本类型关键字 719 | value_parameter ---> idlist ':' error 720 |
721 | program test(input,output); 722 | var b:real; 723 | procedure pro(a:); 724 | begin 725 | end; 726 | begin 727 | 728 | end. 729 |730 | 731 | value_parameter ---> idlist error 732 |
733 | program test(input,output); 734 | var b:real; 735 | procedure pro(var a); 736 | begin 737 | end; 738 | begin 739 | 740 | end. 741 |742 | 743 | ### compound_statement 744 | compound_statement ---> _BEGIN statement_list END 745 | 746 | #### 缺少end关键字 747 | compound_statement ---> _BEGIN statement_list error 748 |
749 | program test(input,output); 750 | var b:real; 751 | begin 752 | 753 | . 754 |755 | 756 | ### statement_list 757 | statement_list ---> statement_list ';' statement | statement 758 | 759 | #### 缺少分号 760 | statement_list ---> statement_list error statement 761 |
762 | program test(input,output); 763 | var b:real; 764 | procedure pro; 765 | var a:integer; 766 | begin 767 | b:=b; 768 | b:=b 769 | b:=b 770 | end; 771 | begin 772 | 773 | end. 774 |775 | 776 | ### statement 777 | statement ---> variable ASSIGNOP expression | procedure_call | 778 | compound_statement | IF expression THEN statement else_part | 779 | FOR IDENTIFIER ASSIGNOP expression TO expression DO statement | 780 | WHILE expression DO statement | REPEAT statement UNTIL expression | empty 781 | 782 | #### IF语句缺少then关键字 783 | statement ---> IF expression error statement else_part 784 |
785 | program test(input,output); 786 | var b:real; 787 | procedure pro; 788 | var a:integer; 789 | begin 790 | if a>b 791 | b:=1; 792 | end; 793 | begin 794 | 795 | end. 796 |797 | 798 | #### FOR语句缺少赋值号 799 | statement ---> FOR IDENTIFIER error expression TO expression DO statement 800 |
801 | program test(input,output); 802 | var b:real; 803 | procedure pro; 804 | var a:integer; 805 | begin 806 | for a 1 to 2 do 807 | b:=1; 808 | end; 809 | begin 810 | 811 | end. 812 |813 | 814 | #### FOR语句缺少关键字to 815 | statement ---> FOR IDENTIFIER ASSIGNOP expression error expression DO statement 816 |
817 | program test(input,output); 818 | var b:real; 819 | procedure pro; 820 | var a:integer; 821 | begin 822 | for a:=1 2 do 823 | b:=1; 824 | end; 825 | begin 826 | 827 | end. 828 |829 | 830 | #### FOR语句缺少关键字do 831 | statement ---> FOR IDENTIFIER ASSIGNOP expression TO expression error statement 832 |
833 | program test(input,output); 834 | var b:real; 835 | procedure pro; 836 | var a:integer; 837 | begin 838 | for a:=1 to 2 839 | b:=1; 840 | end; 841 | begin 842 | 843 | end. 844 |845 | 846 | #### WHILE语句缺少关键字do 847 | statement ---> WHILE expression error statement 848 |
849 | program test(input,output); 850 | var b:real; 851 | procedure pro; 852 | var a:integer; 853 | begin 854 | while a=1 855 | b:=1; 856 | end; 857 | begin 858 | 859 | end. 860 |861 | 862 | #### REPEAT语句缺少关键字until 863 | statement ---> REPEAT statement error expression 864 |
865 | program test(input,output); 866 | var b:real; 867 | procedure pro; 868 | var a:integer; 869 | begin 870 | repeat 871 | b:=1 872 | a=1; 873 | end; 874 | begin 875 | 876 | end. 877 |878 | 879 | ### id_varpart 880 | id_varpart ---> '[' expression_list ']' | empty 881 | 882 | #### 缺少右中括号 883 | id_varpart ---> '[' expression_list error 884 |
885 | program test(input,output); 886 | var b:real; 887 | c:array[1..5,6..10] of integer; 888 | procedure pro; 889 | var a:integer; 890 | begin 891 | repeat 892 | c[1,6:=100 893 | until a=1; 894 | end; 895 | begin 896 | 897 | end. 898 |899 | 900 | #### 不完整的数组下标列表 901 | id_varpart ---> '[' error 902 |
903 | program test(input,output); 904 | var b:real; 905 | c:array[1..5,6..10] of integer; 906 | procedure pro; 907 | var a:integer; 908 | begin 909 | repeat 910 | c[:=100 911 | until a=1; 912 | end; 913 | begin 914 | 915 | end. 916 |917 | 918 |
919 | program test(input,output); 920 | var b:real; 921 | c:array[1..5,6..10] of integer; 922 | procedure pro; 923 | var a:integer; 924 | begin 925 | repeat 926 | c[]:=100 927 | until a=1; 928 | end; 929 | begin 930 | 931 | end. 932 |933 | 934 | ### procedure_call 935 | procedure_call ---> IDENTIFIER | IDENTIFIER '(' expression_list ')' 936 | 937 | #### 缺少右括号 938 | procedure_call ---> IDENTIFIER '(' expression_list error 939 |
940 | program test(input,output); 941 | var b:real; 942 | c:array[1..5,6..10] of integer; 943 | procedure pro; 944 | var a:integer; 945 | begin 946 | pro(a; 947 | end; 948 | begin 949 | 950 | end. 951 |952 | 953 | ### expression_list 954 | expression_list ---> expression_list ',' expression | expression 955 | 956 | #### 缺少逗号 957 | expression_list ---> expression_list error expression 958 |
959 | program test(input,output); 960 | var b:real; 961 | c:array[1..5,6..10] of integer; 962 | procedure pro; 963 | var a:integer; 964 | begin 965 | c[a+b a*b]:=1; 966 | end; 967 | begin 968 | 969 | end. 970 |971 | 972 | ### factor 973 | factor ---> UINUM | UFNUM | variable | IDENTIFIER '(' expression_list ')' | '(' expression ')' | NOT factor | '-' factor | CHAR 974 | 975 | #### 缺少右括号 976 | factor ---> IDENTIFIER '(' expression_list error 977 |
978 | program test(input,output); 979 | var b:real; 980 | c:array[1..5,6..10] of integer; 981 | function fun(d,e:integer):integer; 982 | begin 983 | fun:=d+e; 984 | end; 985 | begin 986 | c[3,8]:=fun(b; 987 | end. 988 |989 | 990 | factor ---> '(' expression error 991 |
992 | program test(input,output); 993 | var b:real; 994 | c:array[1..5,6..10] of integer; 995 | function fun(d,e:integer):integer; 996 | begin 997 | fun:=d+e; 998 | end; 999 | begin 1000 | c[3,8]:=(b+c; 1001 | end. 1002 |1003 | 1004 | #### 函数调用表达式列表缺失 1005 | factor ---> IDENTIFIER '(' error 1006 |
1007 | program test(input,output); 1008 | var b:real; 1009 | c:array[1..5,6..10] of integer; 1010 | function fun(d,e:integer):integer; 1011 | begin 1012 | fun:=d+e; 1013 | end; 1014 | begin 1015 | c[3,8]:=fun(; 1016 | end. 1017 |1018 | 1019 | ### 整体黑盒测试 1020 | quick_sort 1021 |
1022 | 1023 | program quicksort(input,output); 1024 | var 1025 | n,i:integer; 1026 | a:array[0..100000] of integer; 1027 | b:char; 1028 | 1029 | procedure kp(l,r:integer); 1030 | var 1031 | i,j,mid:integer; 1032 | begin 1033 | b:='a'; 1034 | if l>=r then exit; 1035 | i:=l;j:=r;mid:=a[(l+r) div 2]; 1036 | repeat 1037 | begin 1038 | while a[i]1060 | -------------------------------------------------------------------------------- /各模块测试文档/代码生成 - 测试文档.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorange0/pascal2c-compiler/8687b1bf36819a74f57e4764d7f7c78dadfafafc/各模块测试文档/代码生成 - 测试文档.docx -------------------------------------------------------------------------------- /各模块测试文档/整体设计 - 测试文档.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorange0/pascal2c-compiler/8687b1bf36819a74f57e4764d7f7c78dadfafafc/各模块测试文档/整体设计 - 测试文档.docx -------------------------------------------------------------------------------- /各模块测试文档/词法分析 - 测试文档.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorange0/pascal2c-compiler/8687b1bf36819a74f57e4764d7f7c78dadfafafc/各模块测试文档/词法分析 - 测试文档.docx -------------------------------------------------------------------------------- /各模块测试文档/语义分析 - 测试文档.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorange0/pascal2c-compiler/8687b1bf36819a74f57e4764d7f7c78dadfafafc/各模块测试文档/语义分析 - 测试文档.docx -------------------------------------------------------------------------------- /各模块测试文档/语法分析 - 测试文档 - 不带调试输出.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorange0/pascal2c-compiler/8687b1bf36819a74f57e4764d7f7c78dadfafafc/各模块测试文档/语法分析 - 测试文档 - 不带调试输出.docx -------------------------------------------------------------------------------- /各模块详细设计/代码生成 - 详细设计.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorange0/pascal2c-compiler/8687b1bf36819a74f57e4764d7f7c78dadfafafc/各模块详细设计/代码生成 - 详细设计.docx -------------------------------------------------------------------------------- /各模块详细设计/整体设计 - 详细设计.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorange0/pascal2c-compiler/8687b1bf36819a74f57e4764d7f7c78dadfafafc/各模块详细设计/整体设计 - 详细设计.docx -------------------------------------------------------------------------------- /各模块详细设计/词法分析 - 详细设计.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorange0/pascal2c-compiler/8687b1bf36819a74f57e4764d7f7c78dadfafafc/各模块详细设计/词法分析 - 详细设计.docx -------------------------------------------------------------------------------- /各模块详细设计/语义分析 - 详细设计.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorange0/pascal2c-compiler/8687b1bf36819a74f57e4764d7f7c78dadfafafc/各模块详细设计/语义分析 - 详细设计.docx -------------------------------------------------------------------------------- /各模块详细设计/语法分析 - 详细设计.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorange0/pascal2c-compiler/8687b1bf36819a74f57e4764d7f7c78dadfafafc/各模块详细设计/语法分析 - 详细设计.docx --------------------------------------------------------------------------------mid do dec(j); 1040 | if i<=j then 1041 | begin 1042 | a[0]:=a[i];a[i]:=a[j];a[j]:=a[0]; 1043 | inc(i);dec(j); 1044 | end 1045 | end 1046 | until i>j; 1047 | kp(l,j); 1048 | kp(i,r) 1049 | end; 1050 | 1051 | begin 1052 | readln(n); 1053 | for i:=1 to n do 1054 | read(a[i]); 1055 | kp(1,n); 1056 | for i:=1 to n do 1057 | write(a[i]); 1058 | end. 1059 |