\documentclass[../main.tex]{subfiles} \begin{document} \section{需求分析} % 包括:数据流图、功能及数据说明等 % 开发环境 \subsection{开发环境} 在本次课程设计中,我们没有使用编译原理课程设计的传统工具:flex和bison,而是决定自行手动实现词法分析和语法分析。因此,我们在进行开发环境选型是就具有较高的灵活性,不必拘泥于C++语言。在综合了小组人员的开发经验和各个不同语言的优劣之后,我们决定选择.NET平台的C\#语言作为我们的开发语言。使用C\#语言作为开发语言所给我们带来的好处有: \begin{itemize} \item C\#是一门面向对象的新式类型安全语言,具有自动垃圾回收的功能。 \item .NET平台提供了多种不同的部署方式。可以直接AOT(Ahead of time)编译到单个可执行程序,亦可以使用JIT(Just in time)编译的方式使用运行时进行运行。因此在共享同样的核心库时,我们可以提供编译到单个可执行文件的编译器程序,也可以基于.NET强大的Web开发能力提供在线编译器。 \item C\#在全平台上提供了统一的开发和运行体验,适用于我们小组中需要兼容多个平台开发的需求。 \end{itemize} 此外,为了提高开发效率和代码的可维护性,我们还选用了一些辅助工具和库: \begin{itemize} \item \textbf{Gitea}:我们通过使用自行搭建的Gitea服务器进行版本控制,这样可以确保团队成员之间的代码同步和变更记录。 \item \textbf{Gitea Actions}:我们依托Gitea提供的丰富持续集成、自动部署的功能,编写了一系列的自动化脚本,在每次提交新代码和合并到主线代码时运行单元测试和集成测试。 \end{itemize} 为了撰写开发文档和实验报告,我们利用了Overleaf和飞书的在线文档协作功能。这使得文档的共享和协作变得更加高效和便捷,尤其是在团队分布在不同地点时。 \subsection{功能分析} 在需求文档中提供的Pascal-S语法基础上,我们希望我们的编译器支持如下的Pascal语法和功能: \begin{enumerate} \item 支持Pascal-S语法中的常见数据类型,包括整数、浮点数、字符值和布尔值。 \item 支持Pascal-S语法中的常见流程控制语句,包括分支语句,循环语句(While循环和For循环) \item 支持Pascal-S语法中的流程定义和函数定义 \item 支持Pascal-S标准库中的输入输出函数(write, writeln, read) \end{enumerate} 基于上述语法和功能,我们基于Pascal-S语法设计了如下的Pascal语法。 \subsubsection{支持的Pascal语法}\label{pascal_grammar} \begin{lstlisting}[ style=grammar, caption={Pascal-S语法}, ] ProgramStart -> ProgramStruct ProgramStruct -> ProgramHead ; ProgramBody . ProgramHead -> program id (IdList) | program id ProgramBody -> ConstDeclarations VarDeclarations SubprogramDeclarations CompoundStatement IdList -> , id IdList | : Type ConstDeclarations -> $\epsilon$ | const ConstDeclaration ; ConstDeclaration -> id = ConstValue | ConstDeclaration ; id = ConstValue ConstValue -> +num | -num | num | 'letter' | true | false VarDeclarations -> | var VarDeclaration ; VarDeclaration -> id IdList | VarDeclaration ; id IdList Type -> BasicType | array [ Period ] of BasicType BasicType -> integer | real | boolean | char Period -> digits .. digits | Period , digits .. digits SubprogramDeclarations -> $\epsilon$ | SubprogramDeclarations Subprogram ; Subprogram -> SubprogramHead ; SubprogramBody SubprogramHead -> procedure id FormalParameter | function id FormalParameter : BasicType FormalParameter -> $\epsilon$ | () | ( ParameterList ) ParameterList -> Parameter | ParameterList ; Parameter Parameter -> VarParameter | ValueParameter VarParameter -> var ValueParameter ValueParameter -> id IdList SubprogramBody -> ConstDeclarations VarDeclarations CompoundStatement CompoundStatement -> begin StatementList end StatementList -> Statement | StatementList ; Statement Statement -> $\epsilon$ | Variable assignOp Expression | ProcedureCall | CompoundStatement | if Expression then Statement ElsePart | for id assignOp Expression to Expression do Statement | while Expression do Statement Variable -> id IdVarPart IdVarPart -> $\epsilon$ | [ ExpressionList ] ProcedureCall -> id | id () | id ( ExpressionList ) ElsePart -> $\epsilon$ | else Statement ExpressionList -> Expression | ExpressionList , Expression Expression -> SimpleExpression | SimpleExpression RelationOperator SimpleExpression SimpleExpression -> Term | SimpleExpression AddOperator Term Term -> Factor | Term MultiplyOperator Factor Factor -> num | true | false | Variable | ( Expression ) | id () | id ( ExpressionList ) | not Factor | - Factor | + Factor AddOperator -> + | - | or MultiplyOperator -> * | / | div | mod | and RelationOperator -> = | <> | < | <= | > | >= \end{lstlisting} \paragraph{对语法的调整} 相较于需求中给定的Pascal-S语法,我们在开发和实践的过程中对于语法做出了如下的调整和扩充。 \begin{itemize} \item 消除文法中存在的部分左递归,例如VarDeclaration。消除左递归使得我们可以使用S-属性的翻译方案进行类型检查和代码生成。 \item 将ProcedureCall中添加空括号的产生式。支持在调用无参的过程或者是函数时添加一对空括号。 \item 删除Statment中产生funcid的产生式。因为Pascal中的函数返回语句只是一个合法的赋值语句,在实际上并不会终止函数的执行。因此删除该产生式,并在类型检查和代码生成的阶段进行进一步的处理。 \item 添加Factor中对于加号的支持。支持在运算的过程中使用显式注明的整数,即$ 1 ++ 1$类型的表达式。 \item 调整对于Factor中对于ProcedureCall的定义为Id() | Id (ExpressionList)。支持调用没有参数的函数。 \item 在FormalParameter中添加一对空括号。支持在定义无参的过程和函数时添加一对空括号。 \item 增加while-do语句的支持。 \end{itemize} \paragraph{冲突的处理} 在实现使用LR(1)分析技术的语法分析器时,我们发现在需求分析中给出的Pascal-S语法中存在着一处移进-归约冲突,即语法中的ElsePart非终结符:在对含有多个嵌套的If语句进行处理时,ElsePart既可以直接从空产生式中归约出来,也继续可以继续移进。但是在语法层面上,Else语句应该和最近的一个If语句相结合。因此,在语法分析器中做如下处理:(1) 在构建分析表出添加一个特殊判断,如果是检测到ElsePart的移进-归约冲突,则不报错继续处理;(2) 在按照分析表进行分析时,首先进行移进操作,然后再进行归约操作,这样就能保证ElsePart会优先和最近和If语句进行结合。 \end{document}