编译原理课程设计报告学生用表.docx

上传人:b****9 文档编号:25543190 上传时间:2023-06-09 格式:DOCX 页数:14 大小:26.67KB
下载 相关 举报
编译原理课程设计报告学生用表.docx_第1页
第1页 / 共14页
编译原理课程设计报告学生用表.docx_第2页
第2页 / 共14页
编译原理课程设计报告学生用表.docx_第3页
第3页 / 共14页
编译原理课程设计报告学生用表.docx_第4页
第4页 / 共14页
编译原理课程设计报告学生用表.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

编译原理课程设计报告学生用表.docx

《编译原理课程设计报告学生用表.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计报告学生用表.docx(14页珍藏版)》请在冰豆网上搜索。

编译原理课程设计报告学生用表.docx

编译原理课程设计报告学生用表

课程设计报告

课程:

编译原理

学号:

姓名:

班级:

教师:

时间:

计算机科学与技术系

 

设计名称:

简单计算器的实现

设计内容、目的与要求:

计算器的功能要求如下:

可以支持加(+)、减(-)、乘(*)、除(/)运算,如3+4-5*2/2;支持括号运算,如(4+5)*5/8;判断用户输入的表达式是否正确,如3+-*3是一个错误的表达式,在计算时将提示错误;用户输入表达式后,按下等号按钮执行计算。

计划与进度安排:

 

设计过程、步骤(可加页):

一、需求分析

1.1总述

1.2功能要求

要求:

实现具有加、减、乘、除、括号等运算的简单计算器,输入表达式,输出该表达式的值。

二、概要设计

2.1开发环境

2.2总体设计

2.2.1模块结构图

图1.程序模块图

2.2.2模块说明

计算器分为三个功能模块:

(1)词法分析模块:

对输入的表达式从左到右扫描,识别出表达式中的单词(包括运算符和运算数),若单词的构成不符合词法规则(运算符和运算数的构成规则),则报错并停止计算。

(2)语法分析模块:

将单词分解为各类语法短语,若存在不符合规则的语法短语,则报错并停止计算。

(3)计算模块:

对符合语法规则的语法短语进行计算,若计算不能进行,则报错并停止计算。

计算器的三个功能模块中语法分析模块起到了核心作用,如图1所示。

2.2.3界面设计

 

3.详细设计

3.1词法分析模块:

其词法分析器调用接口为lex()

3.1.1词法分析简介:

词法分析是编译原理程序的第一阶段,其任务是:

从左至右逐个字符地对源程序扫描和分解,识别出一个个的单词(如标志符、常量、运算符、界符等),并判断单词的构成是否符合词法规则。

可以使用上下文无关文法来描述词法规则,使用有限自动机来识别单词。

3.1.2词法分析模块的设计及实现

lex工具的基本使用方法和工作原理:

Lex工具是一种词法分析程序生成器,它可以根据词法规则说明书的要求来生成单词识

别程序,由该程序识别出输入文本中的各个单词。

一般可以分为<定义部分><规则部

分><用户子程序部分>。

其中规则部分是必须的,定义和用户子程序部分是任选的。

(1)定义部分

定义部分起始于%{符号,终止于%}符号,其间可以是包括include语句、声明语句

在内的C语句。

这部分跟普通C程序开头没什么区别。

%{

#include"stdio.h"

intlinenum;

%}

(2)规则部分

规则部分起始于"%%"符号,终止于"%%"符号,其间则是词法规则。

词法规则由模式和

动作两部分组成。

模式部分可以由任意的正则表达式组成,动作部分是由C语言语句组

成,这些语句用来对所匹配的模式进行相应处理。

需要注意的是,lex将识别出来的单

词存放在yytext[]字符数据中,因此该数组的内容就代表了所识别出来的单词的内容。

类似yytext这些预定义的变量函数会随着后面内容展开一一介绍。

动作部分如果有多

行执行语句,也可以用{}括起来。

%%

title                showtitle();

[\n]                 linenum++;

[0-9]+               printf("Int    :

%s\n",yytext);

[0-9]*\.[0-9]+       printf("Float  :

%s\n",yytext);

[a-zA-Z][a-zA-Z0-9]*printf("Var    :

%s\n",yytext);

[\+\-\*\/\%]         printf("Op     :

%s\n",yytext);

.                    printf("Unknown:

%c\n",yytext[0]);

%%

A.规则部分的正则表达式

规则部分是Lex描述文件中最为复杂的一部分,下面列出一些模式部分的正则表达式字

符含义:

A-Z,0-9,a-z        构成模式部分的字符和数字。

-                    指定范围。

例如:

a-z指从a到z之间的所有字符。

\                    转义元字符。

用来覆盖字符在此表达式中定义的特殊意义,

                     只取字符的本身。

                     

[]                   表示一个字符集合。

匹配括号内的任意字符。

如果第一个字

                     符是^那么它表示否定模式。

例如:

[abC]匹配a,b,和C

                     的任何一个。

                     

^                    表示否定。

*                    匹配0个或者多个上述模式。

+                    匹配1个或者多个上述模式。

?

                    匹配0个或1个上述模式。

$                    作为模式的最后一个字符时匹配一行的结尾。

{}                  表示一个模式可能出现的次数。

例如:

A{1,3}表示A可

                    能出现1次或3次。

[a-z]{5}表示长度为5的,由a-z组成的

                    字符。

此外,还可以表示预定义的变量。

                    

.                    匹配任意字符,除了\n。

()                  将一系列常规表达式分组。

如:

{Letter}({Letter}|{Digit})*

|                    表达式间的逻辑或。

"一些符号"           字符的字面含义。

元字符具有。

如:

"*"相当于[\*]。

/                    向前匹配。

如果在匹配的模式中的"/"后跟有后续表达式,

                     只匹配模版中"/"前面的部分。

如:

模式为ABC/D输入ABCD,

                     时ABC会匹配ABC/D,而D会匹配相应的模式。

输入ABCE的话,

                     ABCE就不会去匹配ABC/D。

B.规则部分的优先级

规则部分具有优先级的概念,先举个简单的例子:

%{

#include"stdio.h"

%}

%%

[\n]                 ;

A                    {printf("ONE\n");};

AA                   {printf("TWO\n");};

AAAA                 {printf("THREE\n");};

%%

此时,如果输入内容:

[root@localhostliweitest]#catfile1.txt

AAAAAAA

[root@localhostliweitest]#./parser

THREE

TWO

ONE

Lex分析词法时,是逐个字符进行读取,自上而下进行规则匹配的,读取到第一个A字符

时,遍历后发现三个规则皆匹配成功,Lex会继续分析下去,读至第五个字符时,发现

"AAAA"只有一个规则可用,即按行为进行处理,以此类推。

可见Lex会选择最长的字符

匹配规则。

如果将规则

AAAA                 {printf("THREE\n");};

改为

AAAAA                {printf("THREE\n");};

./parser

THREE

TWO

(3)用户子程序部分

最后一个%%后面的内容是用户子程序部分,可以包含用C语言编写的子程序,而这些子

程序可以用在前面的动作中,这样就可以达到简化编程的目的。

这里需要注意的是,

当编译时不带-ll选项时,是必须加入main函数和yywrap(yywrap将下后面说明)。

如:

...

%%

showtitle()

{

printf("-----LexExample-----\n");

}

intmain()

{

linenum=0;

yylex();/*进行Lex分析*/

printf("\nLineCount:

%d\n",linenum);

return0;

}

intyywrap()

{

return1;

}

 

1.1.语法分析模块

1.1.1.语法分析简介

语法分析的任务是:

在词法分析的基础上,根据语言的语法规则,把单词串分解成各类语法短语(如句子、程序、表达式等),从而确定整个输入串的结构是否正确。

可使用上下文无法文法描述语法规则,算符优先分析法是一种语法分析方法,它特别适合分析各类表达式。

1.1.2.语法分析器的实现

(1)产生式:

(0)S’→E

(1)E→E+T

(2)E→T

(3)T→T*F

(4)T→F

(5)F→(E)

(6)F→i

(7)E→E-T

(8)T→T/F

 

(2)得出LR分析表:

状态

ACTION

GOTO

i

+

-

*

/

#

E

T

F

0

S5

S4

1

2

3

1

S6

S7

ACC

2

r2

r2

S8

S9

r2

r2

3

r4

r4

r4

r4

r4

r4

4

S5

S4

10

2

3

5

r6

r6

r6

r6

r6

r6

6

S5

S4

11

3

7

S5

S4

12

3

8

S5

S4

13

9

S5

S4

14

10

S6

S7

S15

11

r1

r1

S8

S9

r1

r1

12

r7

r7

S8

S9

r7

r7

13

r3

r3

r3

r3

r3

r3

14

r8

r8

r8

r8

r8

r8

15

r5

r5

r5

r5

r5

r5

(3)代码实现:

/*以下变量用于语法分析*/

//终结符符号表

Vvt[]={

"i",$INT,

"+",$PLUS,

"-",$MINUS,

"*",$MUL,

"/",$DIV,

"(",$LPAR,

")",$RPAR,

"#",$END

};

//非终结符符号表

Vvn[]={

"E",$E,

"T",$T,

"F",$F

};

//文法的产生式集合

Ppset[]={

1,$E,{$E,$PLUS,$T,0},//E->E+T

2,$E,{$E,$MINUS,$T,0},

3,$E,{$T,0,0,0},

4,$T,{$T,$MUL,$F,0},

5,$T,{$T,$DIV,$F,0},

6,$T,{$F,0,0,0},

7,$F,{$LPAR,$E,$RPAR,0},

8,$F,{$INT,0,0,0},

0,0,0

};

//action表

intaction[16][8]={

//i,+,-,*,/,(,),#

S+5,BLANK,BLANK,BLANK,BLANK,S+4,BLANK,BLANK,

BLANK,S+6,S+7,BLANK,BLANK,BLANK,BLANK,ACC,

BLANK,R+3,R+3,S+8,S+9,BLANK,R+3,R+3,

BLANK,R+6,R+6,R+6,R+6,BLANK,R+6,R+6,

S+5,BLANK,BLANK,BLANK,BLANK,S+4,BLANK,BLANK,

BLANK,R+8,R+8,R+8,R+8,BLANK,R+8,R+8,

S+5,BLANK,BLANK,BLANK,BLANK,S+4,BLANK,BLANK,

S+5,BLANK,BLANK,BLANK,BLANK,S+4,BLANK,BLANK,

S+5,BLANK,BLANK,BLANK,BLANK,S+4,BLANK,BLANK,

S+5,BLANK,BLANK,BLANK,BLANK,S+4,BLANK,BLANK,

BLANK,S+6,S+7,BLANK,BLANK,BLANK,S+15,BLANK,

BLANK,R+1,R+1,S+8,S+9,BLANK,R+1,R+1,

BLANK,R+2,R+2,S+8,S+9,BLANK,R+2,R+2,

BLANK,R+4,R+4,R+4,R+4,BLANK,R+4,R+4,

BLANK,R+5,R+5,R+5,R+5,BLANK,R+5,R+5,

BLANK,R+7,R+7,R+7,R+7,BLANK,R+7,R+7

};

//Goto表

intgo[16][3]={

//E,T,F

1,2,3,

BLANK,BLANK,BLANK,

BLANK,BLANK,BLANK,

BLANK,BLANK,BLANK,

10,2,3,

BLANK,BLANK,BLANK,

BLANK,11,3,

BLANK,12,3,

BLANK,BLANK,13,

BLANK,BLANK,14,

BLANK,BLANK,BLANK,

BLANK,BLANK,BLANK,

BLANK,BLANK,BLANK,

BLANK,BLANK,BLANK,

BLANK,BLANK,BLANK,

BLANK,BLANK,BLANK

};

intSLR1()//SLR1分析表入口

{

inttoken;//输入符号

ints,e;//状态栈顶、符号栈顶元素

int*pr,pl;//产生式右部、左部

intact;//动作

//分析栈

rstackslrstack(256);

slrstack.push(0,$END);

token=Lex();

while(true)

{

if(token==$UNKNOWN)

{

ProcError();

returnFAIL;

}

else

{

act=action[slrstack.top(s,e)][token-1];

if(act==BLANK)

{

ProcError();

returnFAIL;

}

elseif(act==ACC)

{

printf("接受!

");

returnSUCCESS;

}

elseif(act

{

//移入

printf("移入%s\n",vt[token-1].name);

slrstack.push(act-S,token);

token=Lex();

}

else

{

//规约

pr=pset[act-R-1].right;

pl=pset[act-R-1].left;

printf("规约产生式:

%s->",vn[pl-100].name);

while(*pr!

=0)

{

if(*pr>=100)

printf("%s",vn[*pr-100].name);

else

printf("%s",vt[*pr-1].name);

slrstack.pop(s,e);

pr++;

}

printf("\n");

s=go[slrstack.top(s,e)][pl-100];

slrstack.push(s,pl);

}//if(act==BLANK)

}//if(token==$UNKNOWN)

}//while

}

3.3文法分析

1.1.1文法分析器生成工具yacc

简单来说,yacc(YetAnotherCompiler-Compiler)就是编译器的编译器。

Yacc是一个通用的工具,能够根据用户指定的规则,生成一个词法分析程序。

yacc能识别LALR

(1)且无歧义的文法,它的输入是词法分析器的输出。

我们知道,生成词法分析器是lex分内的事,因此lex和yacc常常珠联璧合。

先让我们看一下yacc文件的格式。

和前面介绍的lex的格式类似:

declarations

%%

rules

%%

programs

声明

%%

规则

%%

其它程序

其中声明段声明一些符号常量,可以为空。

同lex一样,声明段中可以有出现在目标C程序中的代码,放在%{…%}中;还有一些yacc关键词可以指示出token的结合顺序:

%left

左结合

%right

右结合

%nonassoc

不结合

%token

声明token

俗话说“没有规矩,不成方圆”。

规则段描述规则,自然是重中之重了。

规则段的结构是如下,

A:

BODY;

A表示非终结符名,BODY表示产生式和动作。

产生式包括非终结符和终结符,终结符用’’引用。

一些转义字符,比如’\r’,’\n’等,和C里面的表示是一样的。

动作(action)则是在输入被当前规则识别出来时而执行的。

动作实际上就是C的代码,写在{}中。

为了沟通词法分析器和动作,yacc引入了形式变量,以$开头。

如果希望获得词法分析器和前面的动作返回的值,我们可以使用$1,$2,…。

$i表示一条规则右侧第i个单元的值。

比如有这样的一条规则,

A:

BCD;

C的返回值为$2,D为$3。

依此类推。

程序段放一些其它的程序,也可以省略,连%%都可以不要。

连接时需要指定连接库,gcc的参数为-ly。

 

结果与分析(可以加页):

设计体会与建议:

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 成人教育 > 自考

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1