[编译原理]实验一 词法分析程序设计


[实验目的]:

1.了解词法分析的主要任务。

2. 熟悉编译程序的编制。

[实验内容]:根据某文法,构造一基本词法分析程序。找出该语言的关键字、标识符、整数以及其他一些特殊符号,给出单词的种类和值。

[实验要求]:

  1. 构造一个小语言的文法,例如,Pascal语言子集的文法:

G[<程序>]:

<程序>→<程序首部>;<分程序>.

<程序首部>→program<标识符>

<分程序>→<常量说明部分> <变量说明部分> <复合语句>

<常量说明部分>→CONST <常量定义表>

<常量定义表>→<常量定义><常量定义表> |<常量定义>

<常量定义>→<标识符>=<无符号整数>;

<变量说明部分>→VAR <变量定义表>

<变量定义表>→<变量定义><变量定义表>|<变量定义>

<变量定义>→<标识符表>:<类型>;

<标识符表>→<标识符>,<标识符表>|<标识符>

<类型>→integer|real|boolean|char

<分程序>→<复合语句>

<复合语句>→begin<语句序列>end

<语句序列>→<语句>|<语句序列>;<语句>

<语句>→<赋值语句>|<复合语句>|<条件语句>

<赋值语句>→<标识符>:=<表达式>

<条件语句>→if <布尔表达式> then <语句> else <语句>

<表达式>→<表达式>+<项>|<表达式>-<项>|<项>

<项>→<项>*<因式>|<项>/<因式>|<因式>

<因式>→<标识符>|<无符号整数>|(<表达式>)

<布尔表达式>→<表达式><关系运算符><表达式>

<关系运算符>→ =|<|<=|>|>=|<>

<标识符>→<字母>|<标识符><字母>|<标识符><数字>

<无符号整数>→<数字>|<无符号整数><数字>

<字母>→a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z

<数字>→0|1|2|3|4|5|6|7|8|9

  1. 设计单词的输出形式,单词的种类和值的表示方法,例如:

keyword  program

digit      1

……

  1. 编写词法分析程序cffx.c

实现基本的词法分析器,能够分析关键字、标识符、数字、运算符(需要有“==”或“:=”之类需要超前搜索的运算符)以及其他一些符号。实验报告中要说明分析使用的方法。

  1. 生成并输出单词符号表

1 keyword program

……

[实验步骤]:

  1. 写出一个小语言的文法,根据情况自由选择C语言或Pascal语言。
  2. 写出该小语言的单词分类情况表。
  3. 编写词法分析程序。
  4. 调试运行程序。
  5. 结果分析。
  6. 撰写实验报告。

[实验报告]:

  1. 写出实现的算法。
  2. 画出流程图。
  3. 实验设计过程中出现的问题及解决的方法。
  4. 实验设计过程中的体会。
  5. 给出程序清单。
  6. 给出测试结果。

原版Code
[c]
#include "stdio.h"
#include "conio.h"
#include "string.h"
#include "ctype.h"
#include "windows.h"
char save[20];/*定义暂存函数*/
char *p;
char count[200];
int total;
char *sum[5]={"begin","end","integer","program","var"};/*定义5个关键字*/

char alpha()/*分析标识符*/
{
int i,j;
char *opp;
i=0;
j=0;/*j=0是标识符,j=1是关键字*/

while(isalpha(*p))//检查是否是字母
{
save[i]=*p;
p++;i++;
}

while(isalnum(*p))/*检查是字母还是数字,如果是字母返回1,是数字返回2*/
{
save[i]=*p;
p++;
i++;
}
opp=save;
for(i=0;i<5;i++)/*把字母与关键字表核对,如果是关键字就设置j=1*/
if(!(strcmp(opp,sum[i])))/*比较两个字符串*/
{
printf(" %d keyword %sn",total,opp); /*识别关键字*/
j=1;
}
if(j==0)
printf(" %d captionsign %sn",total,opp); /*识别标识符*/
p–; /*回退多读进的字符*/
return 0;
}

char digit()/*分析数字*/
{
int i;
i=0;
while(isdigit(*p))/*检查是否数字(0-9)*/
{
save[i]=*p;
i++;
p++;
}
printf(" %d digit %sn",total,save);
p–;
return 0;
}

main()
{
//int i,j;
total=1;/*计数器等于一*/
memset(count,0,200);/*把count所指内存区域的前200个字节设置成字符0*/
system("cls");
strcpy(count,"program test;nvar i,j:integer;nbegin i:=j+1;end.");
printf("The source program is:n");
puts(count);
printf("n");
p=count;
while(*p!=’�’)/*检查源程序是否结束*/
{
memset(save,0,20);
while(*p==’ ‘||*p==’n’||*p==’t’) p++;/*检查是否是空白字符,如果是直接跳过*/
if(isalpha(*p)) alpha();/*识别关键字或标识符*/
else if(*p==’;’)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’,’)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’:’)
{
p++;
if(*p==’=’)
printf(" %d airthmeticsign %sn",total,":=");/*识别赋值号*/
else
{
printf(" %d airthmeticsign %sn",total,":");/*识别冒号*/
p–; /*回退多读进字符*/
}
}
else if(*p==’+’)
printf(" %d arithmeticsign %cn",total,*p);
else if(*p==’.’)
printf(" %d boundarysign %cn",total,*p);
else if(*p=='(‘)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’)’)
printf(" %d boundarysign %cn",total,*p);
else if(isdigit(*p))/*识别整数*/
digit();
total=total+1;p++; /*准备识别下一个单词*/
}
printf("npress any key to return");
getch();
return 0;
}

[/c]
修改版本1:
[c]
#include "stdio.h"
#include "conio.h"
#include "string.h"
#include "ctype.h"
#include "windows.h"
char save[20];/*定义暂存函数*/
char *p;
char count[200];
int total;
char *sum[5]={"begin","end","integer","program","var"};/*定义5个关键字*/

char alpha()/*分析标识符*/
{
int i=0,j=0;/*j=0是标识符,j=1是关键字*/
char *opp;
while(isalpha(*p))/*检查是否是字母*/
{
save[i]=*p;
p++;
i++;
}
while(isalnum(*p))/*检查是字母还是数字,如果是字母返回1,是数字返回2*/
{
save[i]=*p;
p++;
i++;
}
opp=save;
for(i=0;i<5;i++)/*把字母与关键字表核对,如果是关键字就设置j=1*/
{
if(!(strcmp(opp,sum[i])))/*比较两个字符串*/
{
printf(" %d keyword %sn",total,opp); /*识别关键字*/
j=1;
}
}
if(j==0)
printf(" %d captionsign %sn",total,opp); /*识别标识符*/
p–; /*回退多读进的字符*/
return 0;
}

char digit()/*分析数字*/
{
int i=0;
while(isdigit(*p))/*检查是否数字(0-9)*/
{
save[i]=*p;
i++;
p++;
}
printf(" %d digit %sn",total,save);
p–;
return 0;
}

int main()
{
total=1;/*计数器等于一*/
memset(count,0,200);/*把count所指内存区域的前200个字节设置成字符0*/
system("cls");/*清屏*/
strcpy(count,"program test;nvar i,j:integer;nbegin i:=j/#1;nend.");
printf("The source program is:n");
printf("———————-n");
puts(count);
printf("———————-n");
p=count;
while(*p!=’�’)/*检查源程序是否结束*/
{
memset(save,0,20);
while(*p==’ ‘||*p==’n’||*p==’t’) p++;/*检查是否是空白字符,如果是直接跳过*/
if(isalpha(*p)) alpha();/*识别关键字或标识符*/
else if(*p==’;’)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’,’)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’:’)
{
p++;
if(*p==’=’)
printf(" %d airthmeticsign %sn",total,":=");/*识别赋值号*/
else
{
printf(" %d airthmeticsign %sn",total,":");/*识别冒号*/
p–; /*回退多读进字符*/
}
}
else if(*p==’+’ || *p==’-‘ || *p==’*’ || *p==’/’)//此处修改,增加-*/三个符号
printf(" %d arithmeticsign %cn",total,*p);
else if(*p==’.’)
printf(" %d boundarysign %cn",total,*p);
else if(*p=='(‘)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’)’)
printf(" %d boundarysign %cn",total,*p);
else if(isdigit(*p))/*识别整数*/
digit();
else
printf(" %d error %cn",total,*p);
total=total+1;
p++; /*准备识别下一个单词*/
}
printf("npress any key to return");
getch();
return 0;
}

[/c]
根据模板自己改写的C语言解释程序:
[c]
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>

#define KEYWORDS 10
#define TEMPHANSHU 20

int total;
char *p;
char count[200];
char save[TEMPHANSHU]; //定义暂存函数
char *sum[KEYWORDS]={"include","stdio.h","main","void","int","float","double","scanf","printf","return"}; //定义关键字

char alpha() //分析标识符
{
int i=0,j=0;//j=0是标识符,j=1是关键字
char *opp;
while(isalnum(*p))//检查是字母还是数字,字母返回1,数字返回2
{
save[i]=*p;
p++;
i++;
}
opp=save;
for(i=0;i<keywords;i++)/*把字母与关键字表核对,如果是关键字就设置j=1*/
if(!(strcmp(opp,sum[i])))/*比较两个字符串*/
{
printf(" %d keyword %sn",total,opp); /*识别关键字*/
j=1;
}
if(j==0)
printf(" %d captionsign %sn",total,opp); /*识别标识符*/
p–; /*回退多读进的字符*/
return 0;
}

char digit()/*分析数字*/
{
int i;
i=0;
while(isdigit(*p))/*检查是否数字(0-9)*/
{
save[i]=*p;
i++;
p++;
}
printf(" %d digit %sn",total,save);
p–;
return 0;
}

int main()
{
total=1;/*计数器等于一*/
memset(count,0,200);/*把count所指内存区域的前200个字节设置成字符0*/
strcpy(count,"#include <stdio.h>nint main()n{ntint i,j,sum;ntscanf("%d %d",&i,&j);ntsum=i+j;ntprintf("%d",sum);ntreturn 0;n}");
printf("The source program is:n");
printf("———————-n");
puts(count);
printf("———————-n");
p=count;
while(*p!=’�’)/*检查源程序是否结束*/
{
memset(save,0,20);
while(*p==’ ‘||*p==’n’||*p==’t’) p++;/*检查是否是空白字符,如果是直接跳过*/
if(isalpha(*p)) alpha();/*识别关键字或标识符*/
else if(*p==’#’)
printf(" %d boundarysign %cn",total,*p);
else if(*p=='<‘ || *p==’>’)
printf(" %d boundarysign %cn",total,*p);
else if(*p=='{‘ || *p==’}’)
printf(" %d boundarysign %cn",total,*p);
else if(*p=='(‘ || *p==’)’)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’+’ || *p==’-‘ || *p==’*’ || *p==’/’)
printf(" %d arithmeticsign %cn",total,*p);
else if(*p==’,’)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’=’)
printf(" %d airthmeticsign %cn",total,*p);
else if(*p==’.’)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’&’)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’;’)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’"’)
printf(" %d boundarysign %cn",total,*p);
else if(*p==’%’)
{
p++;
if(*p==’d’)
printf(" %d airthmeticsign %sn",total,"%d");/*识别属性符号*/
else
{
printf(" %d airthmeticsign %sn",total,"%");/*识别百分号*/
p–; /*回退多读进字符*/
}
}
else if(isdigit(*p))/*识别整数*/
digit();
else
printf(" %d error %cn",total,*p);
total=total+1;
p++; /*准备识别下一个单词*/
}
getch();
return 0;
}
[/c]
答辩时的程序:
[c]
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>

#define KEYWORDS 10
#define TEMPHANSHU 20

int count;
char *p;
char str[200];
char save[TEMPHANSHU]; //定义暂存函数
char *sum[KEYWORDS]={"include","stdio.h","main","void","int","float","double","scanf","printf","return"}; //定义关键字

char isAlpha() //分析标识符
{
int i=0,j=0;//j=0是标识符,j=1是关键字
char *opp;
while(isalnum(*p))//检查是字母还是数字,字母返回1,数字返回2
{
save[i]=*p;
p++;
i++;
}
opp=save;
for(i=0;i<keywords;i++)//把字母与关键字表核对,如果是关键字就设置j=1
if(!(strcmp(opp,sum[i])))//比较两个字符串
{
printf("%2d 关键字 %sn",count,opp); //识别关键字
j=1;
}
if(j==0)
printf("%2d 标识符 %sn",count,opp); //识别标识符
p–; //回退多读进的字符
return 0;
}

char isDigit()//分析数字
{
int i;
i=0;
while(isdigit(*p))//检查是否数字
{
save[i]=*p;
i++;
p++;
}
printf("%2d 数字 %sn",count,save);
p–;
return 0;
}

int main()
{
count=1;//计数器
memset(str,0,200);//把str所指内存区域的前200个字节设置成字符0
strcpy(str,"#include <stdio.h>nint main()n{ntint i,j,sum;ntscanf("%d %d",&i,&j);ntsum=i+j;ntprintf("%d",sum);ntreturn 0;n}");
printf("The source program is:n");
printf("———————-n");
puts(str);
printf("———————-n");
p=str;
while(*p!=’�’)//检查源程序是否结束
{
memset(save,0,20);
while(*p==’ ‘||*p==’n’||*p==’t’) p++;//检查是否是空白字符,如果是直接跳过
if(isalpha(*p)) isAlpha();//识别关键字或标识符
else if(*p==’#’)
printf("%2d 界符 %cn",count,*p);
else if(*p=='<‘ || *p==’>’)
printf("%2d 界符 %cn",count,*p);
else if(*p=='{‘ || *p==’}’)
printf("%2d 界符 %cn",count,*p);
else if(*p=='(‘ || *p==’)’)
printf("%2d 界符 %cn",count,*p);
else if(*p==’+’ || *p==’-‘ || *p==’*’ || *p==’/’)
printf("%2d 运算符 %cn",count,*p);
else if(*p==’,’)
printf("%2d 界符 %cn",count,*p);
else if(*p==’=’)
printf("%2d 运算符 %cn",count,*p);
else if(*p==’.’)
printf("%2d 界符 %cn",count,*p);
else if(*p==’&’)
printf("%2d 界符 %cn",count,*p);
else if(*p==’;’)
printf("%2d 界符 %cn",count,*p);
else if(*p==’"’)
printf("%2d 界符 %cn",count,*p);
else if(*p==’%’)
{
p++;
if(*p==’d’)
printf("%2d 标识符 %sn",count,"%d");//识别属性符号
else
{
printf("%2d 运算符 %sn",count,"%");//识别百分号
p–; //回退多读进字符
}
}
else if(isdigit(*p))//识别整数
isDigit();
else
printf("%2d ERROR %cn",count,*p);
count++;
p++; //识别下一个单词
}
getch();
return 0;
}

[/c]

发表评论