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


[实验目的]:

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

#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;
}

修改版本1:

#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语言解释程序:

#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;
}

答辩时的程序:

#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;
}

发表评论