课程设计 C语言子集的词法分析程序.docx

上传人:b****2 文档编号:19000722 上传时间:2023-04-24 格式:DOCX 页数:26 大小:76.33KB
下载 相关 举报
课程设计 C语言子集的词法分析程序.docx_第1页
第1页 / 共26页
课程设计 C语言子集的词法分析程序.docx_第2页
第2页 / 共26页
课程设计 C语言子集的词法分析程序.docx_第3页
第3页 / 共26页
课程设计 C语言子集的词法分析程序.docx_第4页
第4页 / 共26页
课程设计 C语言子集的词法分析程序.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

课程设计 C语言子集的词法分析程序.docx

《课程设计 C语言子集的词法分析程序.docx》由会员分享,可在线阅读,更多相关《课程设计 C语言子集的词法分析程序.docx(26页珍藏版)》请在冰豆网上搜索。

课程设计 C语言子集的词法分析程序.docx

课程设计C语言子集的词法分析程序

**大学

计算机科学与技术学院

实验报告

(2007~2008学年度第1学期)

课程名称

编译原理

实验名称

C语言子集的词法分析程序

 

姓名

学号

专业

班级

地点

教师

一.实验目的及要求

1、目的:

通过设计、编制、调试一个具体的词法分析程序,加深对词法分析原理的理解,并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法.

2、软、硬件环境:

windowsxp,MicrosoftvisualC++.

二.实验步骤

1、原理分析,单词符号一般分为关键字、标识符、常数、运算符、界符号五种。

对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是以上五种中之一,那么就以单词的二元式形式输出。

每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。

  各类单词的二元式表述均具有相同的结构与长度,形式如下:

(单词种别t,单词自身的值i)

t是单词种别,而单词种别共分为五类且每类对应一张表格.

所以整个的词法分析过程就是从源程序中获得一个个的单词符号,将这些符号分别填入五张类表中,并且有一个二元式序列构成一个索引,这个索引为以后的语法分析提供处理上的方便.

为了方便期间本程序中引用了Const.txt常量表Sign.txt标识符(32个)表。

在这里将主要的保留字及标识符作一个列举(放在一个表中)。

Keyform

单词种别t

单词符号i

单词种别t

单词符号i

单词种别t

单词符号i

1

auto

21

short

41

{

2

break

22

sizeof

42

}

3

case

23

static

43

[

4

char

24

struct

44

]

5

const

25

switch

45

?

6

continue

26

union

46

:

7

default

27

unsigned

47

‘’

8

do

28

void

48

“”

9

double

29

while

49

;

10

else

30

typedef

50

.

11

enum

31

volatile

51

!

12

extern

32

signed

52

#

13

float

33

+

53

<

14

for

34

-

54

>

15

goto

35

=

55

|

16

if

36

*

56

&&

17

int

37

%

57

==

18

long

38

58

<=

19

register

39

59

-=

20

return

40

\

60

!

=

 

2、编写源程序代码。

本程序用c语言实现。

此程序采用一缓冲方式读入程序源码,首先进行预处理去掉注释和无效空格。

然后再进行详细的词法分析,为了便于后续处理,程序设置了几个表:

符号表和常数表。

3、调试程序。

三.实验内容

1、流程图

2、程序

#include

#include

#include

#include

#include

#defineKEYWORD_LEN32//保留字个数

#defineSTR_MAX_LEN300//标识符最大长度

#definePRO_MAX_LEN20480//源程序最大长度

#defineSTB_MAX_LEN1000//符号表最大容量

#defineCTB_MAX_LEN1000//常数表最大容量

#defineERROR0//错误

#defineID(KEYWORD_LEN+1)//标识符

#defineCONST(KEYWORD_LEN+2)//常量

#defineOPERAT(KEYWORD_LEN+3)//运算符

#defineDIVIDE(KEYWORD_LEN+4)//界符

interrorLine=0;

charproBuffer[PRO_MAX_LEN]="";//存储程序代码的全局缓冲区

charch;//读出来的当前字符

charwordget[STR_MAX_LEN];//标识符或常量

intpoint=0;//源程序当前位置指针

charsignTab[STB_MAX_LEN][STR_MAX_LEN];//符号表

intpointSTB=0;//符号表指针

charconstTab[CTB_MAX_LEN][STR_MAX_LEN];//常量表

intpointCTB=0;//常数表指针

charkwTab[KEYWORD_LEN][10]={//保留字表C语言一共有32个保留字[关键字]

"auto","break","case","char","const",

"continue","default","do","double","else",

"enum","extern","float","for","goto",

"if","int","long","register","return",

"short","signed","sizeof","static","struct",

"switch","typedef","union","unsigned","void",

"volatile","while"};

charerrorTab[][50]={//错误代码表

/*0*/"未知错误",/*1*/"非法的字符",/*2*/"不正确的字符常量表达",

/*3*/"不正确的字符串表达",/*4*/"不正确的数字表达",/*5*/"注释丢失'*/'"};

typedefstructsignDuality

{

intkind;

intvalue;

}*pDualistic,Dualistic;

voidpretreatment();//预处理

voidProcError(intid);//错误

boolGetChar();//获得一个字符不包括结束标记

boolGetBC();//获得一个非空白字符

voidConcat(char*str);//将ch连接到str后

intReserve(char*str);//对str字符串查找保留字表若是一个保留字-返回其编码否则返回0

voidRetract();//将搜索指示器回调一个字符位置

intInsertId(char*str);//将str串以标识符插入符号表,并返回符号表指针

intInsertConst(char*str);//将str串以常数插入符号表,并返回常数表指针

boolwordAnalyse(pDualisticpDu);//词法分析true正常

 

//预处理将缓冲区内的源代码去掉注释和无效空格

voidpretreatment()

{intlines=0;

chartmp[PRO_MAX_LEN];//先将处理结果保存到临时空间

inttmpp=0;//这个临时空间的末尾指针

boolflg;

chartmpc;

//去掉注释先

//注释有两种一种是//另一种是/**/

point=0;

do

{

flg=GetChar();

if(ch=='/')

{

flg=GetChar();

switch(ch)

{

case'/':

do

{

flg=GetChar();

}while(!

(ch=='\n'||flg==false));//注释一直到行尾或文件结束

if(ch=='\n')

Retract();//归还换行

break;

case'*':

do

{

flg=GetChar();

tmpc=ch;

//为了保证出错处理程序能正确定位出错位置保留注释中的换行

if(tmpc=='\n')

tmp[tmpp++]=tmpc;

flg=GetChar();

Retract();//归还一个字符

}while(flg&&!

(flg&&tmpc=='*'&&ch=='/'));

flg=GetChar();

if(!

flg)

{

ProcError(5);

}

break;

default:

//不是任何一种注释

Retract();

Retract();

GetChar();

tmp[tmpp++]=ch;

flg=GetChar();

tmp[tmpp++]=ch;

}

}

else

{

tmp[tmpp++]=ch;

}

}while(flg);

tmp[tmpp]='\0';

strcpy(proBuffer,tmp);

}

//错误

voidProcError(intid)

{

printf("\nError:

第%d行,%s\n",errorLine,errorTab[id]);

}

//获得一个字符

boolGetChar()

{

if(point

='\0')

{//如果当前下标合法且当前字符为结束标记则取字符增游标

ch=proBuffer[point++];

if(ch=='\n')

errorLine++;

returntrue;

}

ch='\0';

returnfalse;

}

//获得一个非空白字符

boolGetBC()

{

do

{

if(!

GetChar())//获取字符失败

{

ch='\0';

returnfalse;

}

}while(isspace(ch));//直到获得一个非空白字符

returntrue;

}

//将ch连接到str后

voidConcat(char*str)

{

inti;

for(i=0;str[i];++i);

str[i]=ch;

str[i+1]='\0';

}

//对str字符串查找保留字表若是一个保留字-返回其编码否则返回0

intReserve(char*str)

{

inti;

for(i=0;i

{

if(0==strcmp(kwTab[i],str))

returni+1;//注意,这里加一原因是0值被错误标记占用

}

return0;

}

//将搜索指示器回调一个字符位置

voidRetract()///char*ch

{

if(proBuffer[point]=='\n'&&errorLine>0)

errorLine--;

point--;

}

//将str串以标识符插入符号表,并返回符号表指针

intInsertId(char*str)

{

inti;

for(i=0;i

if(0==strcmp(signTab[i],str))

returni;

strcpy(signTab[pointSTB++],str);

return(pointSTB-1);

}

//将str串以常数插入常量表,并返回常数表指针

intInsertConst(char*str)

{

inti;

for(i=0;i

if(0==strcmp(constTab[i],str))

returni;

strcpy(constTab[pointCTB++],str);

return(pointCTB-1);

}

//词法分析false--分析结束

boolwordAnalyse(pDualisticpDu)

{

intcode,value;

charjudge;//这里有个技巧借用此变量巧妙的运用SWITCH结构

inti=0;//辅助

GetBC();

judge=ch;

if(isalpha(ch)||ch=='_')judge='L';

if(isdigit(ch))judge='D';

switch(judge)

{

case'L':

while(isalnum(ch)||ch=='_')

{//标识符

wordget[i++]=ch;

GetChar();

}

wordget[i]='\0';

Retract();//回退一个字符

code=Reserve(wordget);

if(code==0)

{

value=InsertId(wordget);

pDu->kind=ID;

pDu->value=value;

}

else

{

pDu->kind=code;

pDu->value=-1;

}

returntrue;

case'D':

while(isdigit(ch))

{

wordget[i++]=ch;

GetChar();

}

wordget[i]='\0';

Retract();

value=InsertConst(wordget);

pDu->kind=CONST;

pDu->value=value;

returntrue;

//( ) [ ] . , !

!

= ~ sizeof < << <= > >> >= = ==  & && &= | || |= ?

:

 + ++ +=

// - -> -- -= * *= / /= % %= >>= <<= ^ ^=

case'"':

//字符串常量

do

{

wordget[i++]=ch;

GetChar();

}while(ch!

='"'&&ch!

='\0');

wordget[i++]=ch;wordget[i]='\0';

if(ch=='\0')

{

printf("%s",wordget);

ProcError(3);

pDu->kind=ERROR;

pDu->value=0;

}

else

{

value=InsertConst(wordget);

pDu->kind=CONST;

pDu->value=value;

}

returntrue;

//字符常量

case'\'':

wordget[i++]=ch;//'

GetChar();

wordget[i++]=ch;

if(ch=='\\')//'\n'

{//如果是转义字符则要多接收一个字符

GetChar();//ch='

wordget[i++]=ch;

}

GetChar();

wordget[i++]=ch;

wordget[i]='\0';

if(ch!

='\'')

{//'\b'

printf("%s",wordget);

ProcError

(2);

pDu->kind=ERROR;

pDu->value=0;

}

else

{

value=InsertConst(wordget);

pDu->kind=CONST;

pDu->value=value;

}

returntrue;

case'(':

case')':

case'[':

case']':

case'.':

case',':

case'~':

case'?

':

case':

':

case';':

case'{':

case'}':

case'#':

wordget[i++]=ch;wordget[i]='\0';

pDu->kind=DIVIDE;//界符

pDu->value=-1;

returntrue;

case'!

':

//!

=

wordget[i++]=ch;

GetChar();

if(ch=='=')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'<':

//<<<=

wordget[i++]=ch;

GetChar();

if(ch=='<'||ch=='=')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'>':

//>>>=

wordget[i++]=ch;

GetChar();

if(ch=='>'||ch=='=')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'=':

//==

wordget[i++]=ch;

GetChar();

if(ch=='=')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'&':

//&&&=

wordget[i++]=ch;

GetChar();

if(ch=='&'||ch=='=')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'|':

//|||=

wordget[i++]=ch;

GetChar();

if(ch=='|'||ch=='=')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'+':

//+++=

wordget[i++]=ch;

GetChar();

if(ch=='+'||ch=='=')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'-':

//---=->

wordget[i++]=ch;

GetChar();

if(ch=='-'||ch=='='||ch=='>')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'*':

//***=

wordget[i++]=ch;

GetChar();

if(ch=='*'||ch=='=')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'/':

///=

wordget[i++]=ch;

GetChar();

if(ch=='=')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'%':

//%=

wordget[i++]=ch;

GetChar();

if(ch=='=')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'^':

//^=

wordget[i++]=ch;

GetChar();

if(ch=='=')wordget[i++]=ch;

elseRetract();

wordget[i]='\0';

break;

case'\0':

returnfalse;

default:

ProcError

(1);

returnfalse;

}

pDu->kind=OPERAT;

returntrue;

}

intmain()

{

Dualistictmp;

pDualisticptmp=&tmp;

FILE*fin,*fout;

inti;

charc;

charfilename[20];

printf("源代码读入\n");

//scanf("%s",filename);

//将源程序读入缓冲区

if((fin=fopen("Test.txt","r"))==NULL)

{

printf("Cannotopeninfile\n");

return0;

}

i=0;

//c=fgetc(fin);

while((c=fgetc(fin))!

=EOF)

{

if(i>=PRO_MAX_LEN-1)

{

printf("\n程序代码太长,无法处理\a");

return0;

}

proBuffer[i++]=c;

}

fclose(fin);//关闭文件

proBuffer[i++]='\0';

printf("\n***************************\n源代码读入成功,源代码如下:

\n%s",proBuffer);

printf("\n按任意键继续\n");

getch();

//预处理

printf("\n预处理\n");

pretreatment();

printf("\n***************************\n预处

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

当前位置:首页 > IT计算机 > 计算机硬件及网络

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

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