课程设计 C语言子集的词法分析程序Word文档下载推荐.docx
《课程设计 C语言子集的词法分析程序Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《课程设计 C语言子集的词法分析程序Word文档下载推荐.docx(26页珍藏版)》请在冰点文库上搜索。
![课程设计 C语言子集的词法分析程序Word文档下载推荐.docx](https://file1.bingdoc.com/fileroot1/2023-4/29/97aac6d3-34a0-4ba5-ac0e-9b45e771e8cc/97aac6d3-34a0-4ba5-ac0e-9b45e771e8cc1.gif)
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<
stdio.h>
ctype.h>
string.h>
conio.h>
stdlib.h>
#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=='
/'
switch(ch)
case'
}while(!
(ch=='
\n'
||flg==false));
//注释一直到行尾或文件结束
Retract();
//归还换行
break;
*'
tmpc=ch;
//为了保证出错处理程序能正确定位出错位置保留注释中的换行
if(tmpc=='
tmp[tmpp++]=tmpc;
//归还一个字符
}while(flg&
!
(flg&
tmpc=='
&
ch=='
));
if(!
flg)
ProcError(5);
}
default:
//不是任何一种注释
GetChar();
tmp[tmpp++]=ch;
else
}while(flg);
tmp[tmpp]='
\0'
strcpy(proBuffer,tmp);
//错误
voidProcError(intid)
printf("
\nError:
第%d行,%s\n"
errorLine,errorTab[id]);
//获得一个字符
boolGetChar()
if(point<
PRO_MAX_LEN&
proBuffer[point]!
='
{//如果当前下标合法且当前字符为结束标记则取字符增游标
ch=proBuffer[point++];
if(ch=='
errorLine++;
returntrue;
ch='
returnfalse;
}
//获得一个非空白字符
boolGetBC()
if(!
GetChar())//获取字符失败
}while(isspace(ch));
//直到获得一个非空白字符
//将ch连接到str后
voidConcat(char*str)
inti;
for(i=0;
str[i];
++i);
str[i]=ch;
str[i+1]='
//对str字符串查找保留字表若是一个保留字-返回其编码否则返回0
intReserve(char*str)
i<
KEYWORD_LEN;
++i)//从保留字表中查找str串
if(0==strcmp(kwTab[i],str))
returni+1;
//注意,这里加一原因是0值被错误标记占用
return0;
//将搜索指示器回调一个字符位置
voidRetract()///char*ch
{
if(proBuffer[point]=='
errorLine>
0)
errorLine--;
point--;
intInsertId(char*str)
i<
pointSTB;
++i)
if(0==strcmp(signTab[i],str))
returni;
strcpy(signTab[pointSTB++],str);
return(pointSTB-1);
//将str串以常数插入常量表,并返回常数表指针
intInsertConst(char*str)
pointCTB;
if(0==strcmp(constTab[i],str))
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)
while(isalnum(ch)||ch=='
{//标识符
wordget[i++]=ch;
wordget[i]='
//回退一个字符
code=Reserve(wordget);
if(code==0)
value=InsertId(wordget);
pDu->
kind=ID;
value=value;
kind=code;
value=-1;
while(isdigit(ch))
value=InsertConst(wordget);
kind=CONST;
value=value;
//( ) [ ] . , !
= ~ sizeof <
<
= >
>
= = == &
&
= | || |= ?
+ ++ +=
// - ->
-- -= * *= / /= % %= >
= <
= ^ ^=
'
//字符串常量
}while(ch!
ch!
);
%s"
wordget);
ProcError(3);
kind=ERROR;
value=0;
//字符常量
\'
//'
\\'
)//'
{//如果是转义字符则要多接收一个字符
//ch='
if(ch!
{//'
\b'
ProcError
(2);
('
)'
['
]'
.'
'
~'
{'
}'
#'
kind=DIVIDE;
//界符
//!
if(ch=='
='
)wordget[i++]=ch;
elseRetract();
wordget[i]='
//<
<
||ch=='
//>
>
//==
//&
|'
//|||=
+'
//+++=
-'
//---=->
//***=
///=
%'
//%=
^'
//^=
ProcError
(1);
kind=OPERAT;
intmain()
Dualistictmp;
pDualisticptmp=&
tmp;
FILE*fin,*fout;
charc;
charfilename[20];
源代码读入\n"
//scanf("
filename);
//将源程序读入缓冲区
if((fin=fopen("
Test.txt"
"
r"
))==NULL)
Cannotopeninfile\n"
i=0;
//c=fgetc(fin);
while((c=fgetc(fin))!
=EOF)
if(i>
=PRO_MAX_LEN-1)
\n程序代码太长,无法处理\a"
proBuffer[i++]=c;
fclose(fin);
//关闭文件
proBuffer[i++]='
\n***************************\n源代码读入成功,源代码如下:
\n%s"
proBuffer);
\n按任意键继续\n"
getch();
\n预处理\n"
pretreatment();
\n***************************\n预处