编译原理课程设计报告

时间:2024.4.30

《编译原理》课程设计报告

                                        

      

       学院(系):  电子信息与电气工程学院计算机系  

           级:              F0603034            

       学生姓名:   徐晓峰        学号   5060309852 

       指导教师:             张冬茉                

一、       课程设计目的

   通过课程设计进一步理解高级语言在计算机中的执行过程,了解现代编译器的运作机制,加深对编译原理中重点算法和编译技术的理解,提高自己自学和理解的能力。学会如何利用已有软件JFLex、Java_cup对词法分析器及语法分析器的构造。

二、       设计概述

本tiger语言编译器的编译过程涉及到编译五个阶段中的二个,即词法分析器、语法分析器。其中语法分析后还完成了语法树的打印的构造以及类型检查。词法分析器由JFLex编译正则式生成,词法分析器编译产生式生成,语法分析器由CUP生成。结果通过GUI界面呈现在使用者面前。

编译程序需要在单词级别上来分析和翻译源程序,所以首先要识别出单词,而词法分析部分的任务是:从左至右扫描源程序的字符串,按照词法规则(正则文法规则)识别出一个个正确的单词,并转换成该单词相应的二元式(种别码、属性值)交给语法分析使用。因此,词法分析是编译的基础。执行词法分析的程序称为词法分析器。

语法分析是编译程序的核心部分,其主要任务是确定语法结构,检查语法错误,报告错误的性质和位置,并进行适当的纠错工作。

三、       设计过程

(一) 设计构思

     

程序主要完成三大功能模块:词法分析器、语法分析器、GUI人机交互界面。词法分析器由JFLex编译正则式生成,其中必须为外界提供一个获取记号流的接口,实验中定为java_cup.runtime.Symbol next_token。语法分析器是建立在词法分析器上的,故必须包含词法分析器以便获得记号流,next_token为语法分析器提供TOKEN,语法分析器的对外接口是:java_cup.runtime.Symbol debug_parse(),同时返回语法树的根节点。

GUI界面是提供人机交互的,它能够依次显示词法分析阶段分析得到的所有TOKEN的信息,语法阶段生成的语法树,另外对于词法和语法阶段出现的错误在“错误提示”文本框中一一列举出来,提供用户改进代码的信息。

流程图:

 

类及文件说明:

包Absyn                           

Print.java                    //print out the syntax tree

……                            //The abstract syntax classes for Tiger

包errormsg                       

ErrorMsg.java             //used to produce error messages with detail information

包java_cup.runtime           //Support for CUP parser

包parse                             

Grm.java                     //Parser analyser

MainInterface.java      //GUI interface

Sym.java                     //tokens' decimal representation

Yylex.java                   //Lexer analyser

包Semant

Entry.java                   //for bindings in value environment

Env.java                      //holds a value ,type environment and an error printer

ExpTy.java                  //holds the result of translating and type-checking

FunEntry.java             //for function bindings

Semant.java                //the main type-checking module

VarEntry.java              //for variable bindings

包Symbol

Symbol.java                //makes strings into unique Symbol objects

Table.java                   //does environments with Scopes

包Translate

包Types                             //describes Tiger_language types

(二) 词法分析器

    这部分的工作主要是熟悉JFLex的使用以及正确书写正则式,通过正则式的书写,生成相应的词法分析器。

1.     JFLex的使用

        修改jflex-1.4.2\bin中的jflex.bat文件中的参数,                          JAVA_HOME=%JAVA_HOME%\lib\classes.zip;

 JFLEX_HOME=%JFLEX_HOME%\lib\JFlex.jar;

运行jflex.bat 并给选择输入文件(tiger.jlex),在没有错误的情况下,它在输出目录下生成一个Yylex.java的词法分析器。

tiger.jlex文件开始部分的书写格式如下:

package parse;                  //将词法分析器打包在Parse下

import errormsg.ErrorMsg;   //导入类

%%

%cup          //支持与cup的关联

%line         //支持yyline()调用

%column       //支持yycolumn()调用

%char

%state COMMENT,STRING           //声明两个新的状态

%{                          //设置所有可能的词法错误类型

    StringBuffer str = new StringBuffer();

       private static final String errorM[] = {

            "Error: Unmatched end-of-comment punctuation.",

            "Error: Unmatched start-of-comment punctuation.",

            "Error: Unclosed string.",

           "Error: Illegal character."

    };

    private void newline() {    //保持errormsg里的行数记录变量的正确性

      errorMsg.newline(yychar);

    }                   

    private void err(String s) { …… } //通过errormsg报错

    private java_cup.runtime.Symbol tok(int kind, Object value) {

       return new java_cup.runtime.Symbol(kind, yychar, yychar+yylength(), value);      //返回所识别的TOKEN

    }

    public Yylex(java.io.FileReader s, ErrorMsg e) {

      this(s);                   //重载Yylex构造函数,方便错误输出

      errorMsg = e;

    }

    private ErrorMsg errorMsg;      // ErrorMsg对象声明

    private int comment_count = 0;  //变量,用于处理注释嵌套

%}

%eofval{     

    {      //到文件末尾时判断最后的状态是否是YYINITIAL,若不是则报相应的错误

    if(zzLexicalState!=0){

       switch(zzLexicalState){

           case 2:       {err(errorM[E_STARTCOMMENT]);

                  break;}

           case 4:       {err(errorM[E_UNCLOSEDSTR]);

                  break;}

           default:   { /*do nothing*/ }

       }

    }

    return tok(sym.EOF, null);

    }

%eofval}

   

//一些基本类型简化表达式的定义

    ALPHA=[A-Za-z]                                //字母

    DIGIT=[0-9]                                   //数字

    LINE_TERMINATOR = \r|\n|\r\n                  //换行符

    NONNEWLINE_WHITE_SPACE_CHAR=[\ \t\f\b\012]    //非换行空白符

    WHITE_SPACE_CHAR ={LINE_TERMINATOR} | NONNEWLINE_WHITE_SPACE_CHAR}

//空白符

%%

2.        正规表达式的书写

    Tiger需要识别的变量和字符有:整型常量、字符常量、操作符、括符、分隔符、关键字、标识符、COMMENT       。

   整型常量: 一个整形数字,即字母的任意组合。

字符常量: 用双引号引起来的字符,可跨行但行尾必须以\结尾,行首\开始。字符         常量中间可包含转义字符如:\r \n \t \f \” \\ \xyz x,y,z表示         0~127的整数。

   操作符:    + - * / > >= < <= = := & |

   括符:      ( ) { } [ ]

   分隔符:       ; :

   关键字:     while do for to if else then let in end type var                  array of  break nil function

   标识符:以字符开头,加上字符、数字、下划线的任意组合

   评论: 以/*开头,以*/结尾中间可嵌套任意个但必须是封闭的。

   一般的字符或者保留字只需返回它的名字就可以了,例如:在YYINITAIL的状态下识      别到最长匹配串为“array” ,则直接返回token,编号为sym.java中已经定义的数字    编号,书写的格式如下:

   <YYINITIAL> "array"     { return tok(sym.ARRAY,null); }

   下面着重谈一下对于字符串和注释的处理:

   字符串的处理

  ã 在YYINITIAL状态下遇到一个 ” 时表示识别字符常量的开始,此时就要进入先前声明的STRING 状态,先前声明的字符串str用来保存已识别的字符常量(初始化为空),代码如下:

<YYINITIAL> \" {  str.setLength(0); yybegin(STRING);}

  ã 当识别的过程中如果碰到转义字符\n \t \" \\,在str后添加相应的字符,碰到非转移字符就直接添加到str后面,忽略两个反斜杠之间的所有空白字符,代码如下:

  <STRING> [^\n\r\"\\]+ { str.append(yytext()); }

  <STRING> \\n { str.append('\n'); }

  <STRING> \\\\ { str.append('\\'); }

  <STRING> \\{WHITE_SPACE_CHAR}+\\ { /*do nothing*/}

  ã 特别是当碰到\跟上三位数字时,应该判断数值范围是否在ASCII范围中

  <STRING> \\0{DIGIT}{DIGIT}|\\1[0-1]{DIGIT}|\\12[0-7] {

str.append((char)Integer.valueOf(new     String(yytext().getBytes(),1,3)).intValue());}

 ã 当再次识别到"时标志着字符串的识别结束,此时将str中的字符串内容作为String的内容返回,同时应该返回YYINITIAL状态,继续识别其他的TOKEN

  <STRING> \" {

        yybegin(YYINITIAL);     

        return tok(sym.STRING,str.toString()); }

ã 识别到这些token以外的其他字符,则直接报错

<STRING> . {err(errorM[E_ILLEGAL]);  }

注释的处理

ã 在YYINITIAL状态下遇到一个 /* 时表示识别注释的开始,此时就要进入先前声明的COMMENT状态,同时comment_count加1,以实现注释嵌套的实现。如果在COMMENT状态下又一次识别到/*表示另一个注释嵌套的开始,此时也需要对comment_count进行加1的操作,代码如下:

  <YYINITIAL> "/*" {

      yybegin(COMMENT);

      comment_count = comment_count + 1; }

  <COMMENT> "/*" { comment_count = comment_count + 1; }

Ò 但是如果在YYINITIAL状态下遇到一个 */则是一个错误,需要报出,代码如下:

   <YYINITIAL> "*/" { err(errorM[E_ENDCOMMENT]); }

ã 在COMMENT状态下遇到*/则表示着一个嵌套中的注释结束,此时需要对comment_count进行减1的操作,如果操作之后其值为0,表示整个注释已经结束,回到YYINITIAL状态,如若不然则继续在COMMENT的状态下识别,代码如下:

  <COMMENT> "*/" {

        comment_count = comment_count - 1;

        if (comment_count == 0)

             yybegin(YYINITIAL);}

ã 识别到这些token以外的其他字符,则直接忽略

<COMMENT> . { /*do nothing*/ }

3.        词法分析器的结构   

      词法分析器实现了Lexer接口,也就是实现了Token next_token()这个方法,不断调用此方法就可以获得所有的记号流。使用词法分析器时需要指定输入流InputStream以及ErrorMsg,InputStream完成源程序的读取,ErrorMsg完成对错误信息的输出。

      至此词法分析器的构造已经基本基本结束了。

(三)  语法分析器

完成语法分析器的主要步骤是cup文件的编写,由于语法树的数据结构已给出,所以产生式的编写可以直接参考tiger语言的语法模式,当然这其中产生了许多冲突,但是可以通过设置符号的优先级来解决移进和规约的冲突。

1. CUP的使用

       CUP的使用需要在命令行的环境下进行,打开命令提示符,输入如下所示的语句,

既可以在当前目录下生成语法分析器Grm.java,Grm.cup的书写格式如下所示:

Cup开始部分的书写格式如下:

package parse;              //产生在parse包里面

import Absyn.*;

import javax.swing.*;

action code {:

    static Symbol.Symbol sym(String s) {   //将字符串转化为Symbol

       return Symbol.Symbol.symbol(s);

    }

:};

parser code {:

    Yylex lexer;

    public static Exp parseResult;     //记录语法树根节点的变量

    errormsg.ErrorMsg errorMsg;        //输出语法错误的ErrorMsg对象声明

    public void syntax_error(java_cup.runtime.Symbol current) {

       report_error("Syntax error (" + current.sym + ")", (java_cup.runtime.Symbol)current);

    }

    public void report_error(String message, java_cup.runtime.Symbol tok) {

       errorMsg.error(tok.left, message);

    }

    public Grm(errormsg.ErrorMsg err, JTextArea text) {

       this();              //语法分析器的构造

       errorMsg=err;

       textin=text;

    }

:};

init with {:      //语法分析器初始化,从界面文本框中获取输入流

     lexer = new Yylex( new java.io.StringBufferInputStream(textin.getText()),errorMsg);

:};

scan with {: java_cup.runtime.Symbol symb= lexer.debug_next_token();

       for(;(symb.sym==sym.error)&&symb.sym!=sym.EOF;)

           symb= lexer.debug_next_token();

       return symb;

    :};               //同过debug_next_token获取token并打印出token

//终结符

terminal String STRING;

terminal Integer INT;

terminal COMMA, COLON, SEMICOLON, LPAREN, RPAREN, LBRACK,                     RBRACK, LBRACE, RBRACE, DOT;

terminal PLUS, MINUS, TIMES, DIVIDE, EQ, NEQ, LT, LE, GT, GE,                 AND, OR, ASSIGN, UMINUS;

terminal ARRAY, IF, THEN, ELSE, WHILE, FOR, TO, DO, LET, IN,                   END, OF, BREAK, NIL, FUNCTION, VAR, TYPE, ID;

//终结符优先级次序

precedence right DO, ELSE, THEN;

precedence nonassoc ASSIGN;

precedence left OR;

precedence left AND;

precedence nonassoc EQ, NEQ, LT, LE, GT, GE;

precedence left PLUS, MINUS;

precedence left TIMES, DIVIDE;

precedence left UMINUS;

precedence left LBRACK;

? 关于优先级次序的说明:由于在语法分析的过程中会产生许多移进和规约的冲突,通过设置终结符的优先级可以避免一些情况的发生。将PLUS、MINUS的优先级定义在

   TIMES、DIVIDE之前即可使乘除的优先级高于加减运算的优先级。另外通过设置比较运算符的有限次序,可以避免分析时的移进--归约冲突。

   此外在实际的cup生成过程中,还会出现一些其他的冲突,例如以下两个冲突的解决:

№.1

  出现冲突  

  between lvalue ::= ID (*)

  and     lvalue ::= ID (*) LBRACK expr RBRACK

  and     expr ::= ID (*) LBRACK expr RBRACK OF expr

  under symbol LBRACK

      解决办法:把left LBRACK 设为最高优先级,这样的话当碰到是归约ID还是移进      LBRACK的冲突时,系统会自动根据优先级而去执行移进的动作。

№.2

  出现冲突

  between expr ::= IF expr THEN expr (*)

  and     expr ::= IF expr THEN expr (*) ELSE expr

  under symbol ELSE

      解决办法:把right DO,ELSE,THEN设为最低优先级,通过precedence  right

      ELSE,THEN语句;定义为右结合的then将与else结合,故先移进。

   №.3

      负号和减号识别时有冲突,解决方案是重新定义一个终结符UMINUS算数运算符中最   高优先级,负号时重新赋予UMINUS的优先级。

 2.     语法的书写

按照Tiger Manual上的语法规则,将上面的语法一一写入cup文件的后面,必要的时候定义适当的非终结符来完成语法的结构。每一条语法规则都应该返回其相应的语句类型,这些类型都已经在Absyn包中定义好了,只       要根据语句的类型按照定义返回即可。其中,要注意的是一些链表的连接,如ExpList、FieldList等,需要保证这些对象的连接正确性。

 ã 首先,在语法分析前完成非终结符的定义,定义如下:

non terminal FieldList          type_fields, type_fields_n, type_fields_ex;

non terminal FieldExpList   field_list, field_list_n, field_list_ex;

non terminal ExpList        expr_list, expr_list_n, expr_list_ex, expr_seq, expr_seq_n, expr_seq_ex;

non terminal DecList        declaration_list, declaration_list_ex;

non terminal Ty                 type;

non terminal Dec            declaration, type_declaration, variable_declaration, function_declaration;

non terminal Exp             expr, program;       //文法开始符

non terminal Var             lvalue;

 ã 其次在文法开始符的语法句的执行语句中,将第一个Exp传给先前定义的parseResul,代码如下:

start with program;

program ::= expr:e     {: parser.parseResult = e; :};

 ã 对于一些常规的语法,只需返回相应的语句类型即可,如赋值语句

    expr ::= lvalue:l ASSIGN expr:e

{: RESULT = new AssignExp(lleft, l, e); :};

 ã 对于需要连接起来的类型,如ExpList,FieldExpList,FieldList,DecList,可以通过消除左递归的方法来将多个具有向后指针的类型的语句相连,另外链表还可以为空,下面举ExpList的例子来说明处理的方法:

expr_list ::= expr_list_n:l…………………………………………………(1)

{: RESULT = l; :}

                       |  {: RESULT = null; :};

expr_list_n ::= expr:e expr_list_ex:x…………………………………(2)

                     {: RESULT = new ExpList(e, x); :};

expr_list_ex::=COMMA expr_list_n:l ……………………………………(3)

                         {: RESULT = l; :}

                       |  {: RESULT = null; :};

在(1)开始识别的时候先判断这个表达式是否为空,若空则直接返回null,否则进入(2),因为至少有一个Explist的存在,所以可以声明一个新的ExpList,并将它的tail指向下一个可能的ExpList,当然下一个ExpList可能为空,所以在处理expr_list_ex时需要判断其是否为空,如空则直接返回null,否则可以将嵌套进行下去。

3. 语法树的生成

语法分析结束后,同时会返回整棵语法树的根结点,我们可以利用这个根节点进行语法树的打印,调用Absyn\Print.Java中的prExp(par.parseResult,2),将整个语法树在屏幕上打印出来,同时还可以在Print.Java中定义一个string变量将需要的打印内容储存起来,在屏幕上打印完之后在GUI界面的文本框内显示出来。

4. 类型检查

 ã 类型检查运作思想

语法分析结束后,我们还可以对整棵语法树进行类型检查,我们可以从语法树的根结点开始对每一个分支进行扫描,根据Tiger语言所所规定的语法类型规则进行判断这一条语句运算或者返回的类型是否符合要求,如果类型不匹配立即报出类型错误。

类型检查的关键是管理好符号表。整个检查过程维护一张变量表,一张类型表,都是Table类型的。Table是按键值方式存储,关键字是Symbol类型,值是Binder类型,Binder中变量value存储具体的信息。变量表的value存储Entry类型,Entry说明变量的类型以及其它信息。类型表的value存储的是Type类型,保存类型的具体信息。Binder类是一个链表结构,也就是说一个符号可以几个类型,如本地变量覆盖全局变量,本地类型覆盖全局类型等。

类型检查所用到的类的关系可以从下图中看清:

 

文本框: Semant文本框: FunEntry 文本框: Entry        

 

每个变量或类型都有一个有效范围,在function的声明过程中,其声明的变量只在它的函数体中有效,出了函数体就失去了它的作用范围,成为了一个无效的变量。又如在in end中又嵌套了let in end 语句,则外面语句中声明的变量在里面的语句中仍然有效(重复声明会覆盖)。可以利用table中的beginscope()和endscope()来确定变量的作用范围。调用函数 beginScope() 添加一个标记,标记起始位置。当这个变量的作用域到底时用调用函数 endScope() 把先前的声明都删掉。

 ã 遇到的实际问题与思考

№.1

类型检查的过程中,还有一个递归调用的问题,如testcase6

let

function do_nothing1(a: int, b: string)=

       do_nothing2(a+1)

function do_nothing2(d: int) =

       do_nothing1(d, "str")

in

    do_nothing1(0, "str2")

End

其中do_nothing1函数的body需要调用do_nothing2,但是按照函数按顺序声明的话,此时do_nothing2还没有被声明,因而不能够被识别,会报错。

解决方法:在let语句检查declist之前将所有的dec(包括type_declaration,function_declaration)置入相应的表中,这样的话当检查上述的函数do_nothing1时就不会出现do_nothing2还未被声明的情况了。

№.2

类型检查的过程中,还有一个循环定义的问题,如testcase16

let

type a=c

type b=a

type c=d

type d=a

in

end

解决方法:在这四个类型定义中,都用到了其他一起声明的类型,存在类似a-c-d-a的类型循环定义,到最后四个四个变量的类型还是没有被实在定义,这是不允许的。解决的方法是在检查类型定义之前用bind(ExpTy)函数将新声明的类型的binding设为声明中将要被赋予的类型。这样在进入类型声明的检查中,只需通过isloop()函数判断是否是循环定义就可知道是否出错。在这样的设计之下,代码

let

type a=c

type b=a

type c=d

type d=int

in

end

就不会出现如上的错误了,a-c-d-int就会跳出检查,返回false

№.3

在Declist中的声明中要求函数和类型的声明分别必须放在一起,如

let

    function g(a:int):int = a

    type t = int

    function g(a:int):int = a

in

end

示例中说这是合法的,应为声明的时候是以类处理的,funcDec和后面的funcDec一起处理,typeDec和后面的typeDec一起处理,导致检查不出这个重复定义函数。我认为这里有点不太合理,我的想法是可以在let语句的检查中将所有的声明都放入环境变量中,这样的话既可以检查出是否重复定义,有可以使类型的前后调用不受阻碍。

即在ExpTy transExp(LetExp e)中添加如下代码:

ArrayList<String> list =new ArrayList<String>();

       for(DecList tmp=e.decs;tmp!=null;tmp=tmp.tail){

           Dec head=tmp.head;

           if(head instanceof TypeDec){       //置入新的类型

              TypeDec td=(TypeDec)head;

              if(list.contains(td.name.toString()))

                  env.errorMsg.error(td.pos,"type '"+td.name+"' has                                              been already defined");

              list.add(td.name.toString());

              env.tenv.put(td.name,new NAME(td.name));

           }

           if(head instanceof FunctionDec){          //置入新的函数变量

              FunctionDec fd=(FunctionDec)head;

              Type re=transTy(fd.result);

              RECORD rc=transTypeFields(fd.params);

              if(list.contains(fd.name.toString()))

                  env.errorMsg.error(fd.pos,"function '"+fd.name+"'                                          already defined");  

              else{

                  list.add(fd.name.toString());

                  env.venv.put(fd.name, new FunEntry(rc,re));

              }

           }

       }

       list.clear();

这样的处理过后,就会达到上述的效果,不过这只是我的个人意见,虽然与tiger语言的要求有矛盾,但我认为这不失为一种好的改进。处于这种改动,testcases中的有点不应该报错的例子,在本编译器中会出错,像上述例子就会报“重复定义”的类型错误,所以请使用者注意这一点。

(四)   GUI界面

最后介绍一下本编译器GUI界面的实现及结构。在界面中有一个工具栏和三个显示窗口和一个输入窗口,分别为:

源程序输入窗口-------用于获取需要检查的代码

语法树输出窗口-------显示语法树

云形标注: 点击logo也可实现此功能TOKEN输出窗口--------显示所识别的TOKEN

错误信息输出窗口-----显示源程序中的词法、语法和类型错误

打开-----------------从文件输入程序

检查-----------------执行编译程序,检查错误

退出-----------------退出程序

1. 文件输入

点击“打开”按钮会触发鼠标事件,会新建一个JFileChooser,选择文件并确定后,会从所选文件路径中将内容读出来并置入输入文本框。另外,还记录下本次的路径,当下一次再次打开时就以上次的路径为当前路径。

2. 树的输出

修改Absyn中的Print.Java文件,在其中定义一个String变量str,在语法树向屏幕输出的同时也将信息保存在str中,当屏幕输出完成之后,可将str传递给界面中的文本框,达到语法树的输出功能。

3. 错误输出

词法分析,语法分析、类型检查阶段错误信息都是由ErrorMsg类实现。这个类中添加了一个JtextArea的变量,在定义的时候将外部的调入,这样的话当调用error函数时就可以直接在界面的文本框内输出错误信息。

四、   总结与感想

这次编译原理课程设计主要是实现Tiger语言编译器前面一些分析阶段的功能,包括词法分析、语法分析和类型检查等。词法分析部分既词法分析器的设计,词法分析是编译的基础,词法分析器从输入流获取源程序,进行分析之后给语法分析器提供token,语法分析器从中进行语法分析,同时生成语法树,之后根据这棵语法素进行类型检查。总的来说,一个编译器的实现过程是很复杂的,但又是井井有条的。本编译器所能实现的功能只是其中的一小部分,要想完整地实现一个编译器的功能确实还有很多的工作要做。

在本次课程设计中,充分体现了上半学期编译原理课程中的一些基础的知识,对于后来的debug和设计思路都提供了很大的帮助,也达到了课程设计的目的。另外在课程设计的过程中也用到了很多java语言方面的知识和大量编程技巧,在程序的实际编写方面提供了许多的经验。可以说通过本次课程设计不仅对编译原理这一门课程也有了更加深刻的了解,同时自己的编程能力也有所提高,对于java程序的理解和运用也有所感悟和提高。同时,我也发现自己在所学知识不够全面,自己的自学和理解能力有所欠缺,以后需要在这些方面多加注意,多加完善,为今后其他的课程设计甚至今后的就业打下扎实的基础。

五、   鸣谢

对于在本次编译原理课程设计中给予我帮助的助教老师和同学表示由衷的感谢!特别感谢Herr Gu同学对我耐心的指导,以及在一些问题上给予我解决问题的思想。

参考文献

Alfred V.Aho Ravi Sethi Jeffrey D.Ullman 著 Cpmpilers Principles, Techniq1ues, and Tools 机械工业出版社出版

更多相关推荐:
编译原理课程设计报告

南京航空航天大学编译原理课程设计题目一个PASCAL语言子集PL0编译器的设计与实现专业班号学号姓名指导老师答辩日期20xx年1月1设计的题目一个PASCAL语言子集PL0编译器的设计与实现2课程设计的要求PL...

编译原理课程设计报告 编译器

《编译技术》课程设计实验报告实验名称:编译器程序姓名:学号:班级:计算机系08本一班20##年11月12日目录一、课设要求...3二、总体设计思想...4三、详细算法设计...4四、流程框图...5五、函数相关…

编译原理课程设计报告

编译原理课程设计报告实验1用Lex设计词法分析器1实验目的学会用lex设计一个词法分析器实验内容使用lex为下述文法语言写一个词法分析器实验要求输入为用该语言所写的源程序文件输出为记号序列每个记号显示为二元组记...

编译原理课设报告

北华航天工业学院编译原理课程设计课程设计题目编译程序构造作者所在系部计算机科学与工程系作者所在专业计算机科学与技术作者所在班级作者学号作者姓名指导教师姓名完成时间20xx年6月18日课程设计任务书摘要编译原理是...

广工20xx编译原理课程设计报告

课程设计课程名称编译原理题目名称PL0编译器的扩充学生学院计算机学院专业班级计算机科学与技术124学号31120xx901学生姓名柏石先指导教师李杨20xx年12月28日一实验目的与要求基本内容成绩范围中及格或...

编译原理课程设计报告

20xx20xx学年第二学期编译原理课程设计报告学院班级学生姓名成绩指导教师学号时间20xx年5月目录一课程设计的目的1二课堂实验及课程设计的内容121课堂实验内容122课程设计内容1三visualstudio...

编译原理词法分析器设计课程设计报告

盐城工学院编译原理课程设计报告设计词法分析器专业计算机科学与技术20xx年1月10日学生姓名班学级号完成日期编译原理课程设计目录1前言22报告主体221设计目的222设计内容及要求2221课程设计内容2223测...

编译原理课程设计报告——词法分析器

课程设计任务书目录引言4第一章概述511设计内容512设计要求5第二章设计的基本原理6216226第三章程序设计731总体方案设计732各模块设计8第四章程序测试941一般测试42出错处理测试第五章结论10参考...

编译原理课程设计

计算机科学系编译原理课程设计报告题目CMIUNS或简称C学生姓名付冠超学号班级专业计算机年级09级教师王艳秋成绩枣庄学院计算机科学系制1目的学生在学习编译原理课程过程中结合各章节的构造编译程序的基本理论总共用1...

编译原理课程设计报告

编译原理实验报告课程名称编译原理题目名称PL0上机作业学生学院计算机学院专业班级12级计科8班学号31120xx110学生姓名谢偲灏指导教师杨劲涛20xx年1月3日一概述目的在分析理解一个教学型编译程序如PL0...

编译原理课程设计报告

燕山大学编译原理课程设计报告题目PL0编译程序的研究与改进学院信息学院年级专业12计算机应用2班学生姓名学号指导教师设计日期20xx年12月29日一丶设计目的1研究改进或自行设计开发一个简单的编译程序或其部分功...

编译原理课程设计报告

编译技术课程设计班级计算机1201学号姓名指导老师20xx年6月目录一目的2二题目2三要求2四实验环境2五系统实现31词法分析32语法分析73中间代码84错误处理13六程序运行结果141成功用例142出错处理用...

编译原理课程设计报告(23篇)