1 问题描述
对于如下文法所定义的PASCAL语言子集,试编写并上机调试一个词法分析程序:
<程序>→PROGRAM<标识符>;<分程序>.
<分程序>→<变量说明>BEGIN<语句表>END
<变量说明>→VAR<变量表>:<类型>;|<空>
<变量表>→<变量表>,<变量>| <变量>
<类型>→INTEGER
<语句表>→<语句表>;<语句>| <语句>
<语句>→<赋值语句>| <条件语句> |<WHILE语句> |<复合语句> |<过程定义>
<赋值语句>→<变量>:=<算术表达式>
<条件语句>→IF<关系表达式>THEN<语句>ELSE<语句>
<WHILE语句>→WHILE<关系表达式>DO<语句>
<复合语句>→BEGIN<语句表>END
<过程定义>→PROCEDURE<标识符><参数表>;
BEGIN<语句表>END
<参数表>→(<标识符表>)|<空>
<标识符表>→<标识符表>,<标识符>| <标识符>
<算术表达式>→<算术表达式>+<项>| <项>
<项>→<项>*<初等量>| <初等量>
<初等量>→(<算术表达式>)|<变量> |<无符号数>
<关系表达式>→<算术表达式><关系符><算术表达式>
<变量>→<标识符>
<标识符>→<标识符><字母>|<标识符><数学>| <字母>
<无符号数>→<无符号数><数字>| <数字>
<关系符>→= | < |<= | > | >= |<>
<字母>→A | B | C | ··· | X | Y |Z
<数字>→0 | 1 | 2 | ··· | 8 | 9
<空>→
要求和提示:
(1) 单词的分类。
可将所有标识符归为一类;将常数归为另一类;保留字和分隔符则采取一词一类。
(2) 符号表的建立。
可事先建立一保留字表,以备在识别保留字时进行查询。变量名表及常数表则在词法分析过程中建立。
(3) 单词串的输出形式。
所输出的每一单词,均按形如(CLASS,VALUE)的二元式编码。对于变量标识符和常数,CLASS字段为相应的类别码,VALUE字段则是该标识符、常数在其符号表中登记项的序号(要求在变量名表登记项中存放该标识符的字符串,其最大长度为四个字符;常数表登记项中则存放该整数的二进制形式。)。对于保留字和分隔号,由于采用一词一类的编码方式,所以仅需在二元式的CLASS字段上放置相应的单词的类别码,VALUE字段则为“空”。不过,为便于查看由词法分析程序所输出的单词串,也可以在CLASS字段上直接放置单词符号串本身。
2 C源代码
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define num 32
char *keysign[num]={
"auto","break","case","char",
"const","continue","default","do",
"double","else","enum","extern",
"float","for","goto","if",
"int","long","regist","return",
"short","signed","sizeof","static",
"struct","switch","typedef","union",
"unsigned","void","volatile","while"};
FILE *fpin,*fpout,*outa,*outb,*outc;
char token[40];
int j=0;
int lookup()
{
inti,k=0;
for(i=0;i<=31;i++)
{
if(strcmp(token,keysign[i])==0)
{
k=1;
return(1);
}
}
if(k!=1)
return(0);
}
void cltoken()
{
j=0;
strcpy(token," ");
}
int scanner(void)
{
char ch,in[40],out[40];
char aa[40],bb[40],cc[40];
int id=0;
printf("please input the Source documentname:");
scanf("%s",in);
printf("please input the document name whichwill be saved:");
scanf("%s",out);
printf("please input the aa document name whichwill be saved:");
scanf("%s",aa);
printf("please input the bb document name whichwill be saved:");
scanf("%s",bb);
printf("please input the cc document name whichwill be saved:");
scanf("%s",cc);
if((fpin=fopen(in,"rt"))==NULL)
{
printf("\nSource document filecan't be found");
return(1);
}
fpout=fopen(out,"wt");
outa=fopen(aa,"wt");
outb=fopen(bb,"wt");
outc=fopen(cc,"wt");
ch=fgetc(fpin);
while(ch!=EOF)
{
if(isspace(ch))
ch=fgetc(fpin);
else if(isalpha(ch))
{
token[j]=ch;
for(ch=fgetc(fpin);isalnum(ch)||ch=='_';ch=fgetc(fpin))
token[++j]=ch;
token[++j]='\0';
id=lookup();
printf("%d--->%s\n",id,token);
fprintf(outa,"%d--->%s\n",id,token);
fprintf(fpout,"%d--->%s\n",id,token);
cltoken();
}
else if(isdigit(ch))
{
token[j]=ch;
for(ch=fgetc(fpin);isdigit(ch);ch=fgetc(fpin))
token[++j]=ch;
token[++j]='\0';
id=2;
printf("%d--->%s\n",id,token);
fprintf(outb,"%d--->%s\n",id,token);
fprintf(fpout,"%d--->%s\n",id,token);
cltoken();
}
else if(ch=='!' || ch=='{' ||ch=='*' || ch=='/' || ch=='%'|| ch=='}' || ch=='[' ||ch==']'||ch=='(' ||ch==')'|| ch=='?')
{
id=3;
printf("%d--->%c\n",id,ch);
fprintf(outc,"%d--->%s\n",id,ch);
fprintf(fpout,"%d--->%c\n",id,ch);