编译原理词法分析程序实现实验报告

实验一词法分析程序实现

一、实验内容

选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。

输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。

二、设计部分

因为需要选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来,而其中的关键则为无符号数的识别,它不仅包括了一般情况下的整数和小数,还有以E为底数的指数运算,其中关于词法分析的无符号数的识别过程流程图如下:

编译原理词法分析程序实现实验报告

编译原理词法分析程序实现实验报告

GOTO 1:

编译原理词法分析程序实现实验报告

GOTO 2:

编译原理词法分析程序实现实验报告

三、源程序代码部分

#include

#include

#include

#define MAX 100

#define UNSIGNEDNUMBER 1

#define PLUS 2

#define SUBTRACT 3

#define MULTIPL Y 4

#define DIVIDE 5

#define LEFTBRACKET 6

#define RIGHTBRACKET 7

#define INEFFICACIOUSLABEL 8

#define FINISH 111

int count=0;

int Class;

void StoreType();

int Type[100];

char Store[20]={'\0'};

void ShowStrFile();//已经将要识别的字符串存在文件a中

void Output(int a,char *p1,char *p2);//字符的输出过程

int Sign(char *p);//'+''-''*''/'整体识别过程

int UnsignedNum(char *p);//是否适合合法的正整数0~9

int LegalCharacter(char *p);//是否是合法的字符:Sign(p)||UnsignedNum(p)||'E'||'.' void DistinguishSign(char *p);//'+''-''*''/'具体识别过程

void TypyDistinguish();//字符的识别过程

void ShowType();//将类别码存储在Type[100]中,为语法分析做准备

void ShowStrFile()//已经将要识别的字符串存在文件a中

{

FILE *fp_s;

char ch;

if((fp_s=fopen("a.txt","r"))==NULL)

{printf("The FILE cannot open!");

exit(0);

}

else

ch=fgetc(fp_s);

while(ch!=EOF)

{

putchar(ch);

ch=fgetc(fp_s);

}

printf("\n");

}

void StoreStr()//将文件中的字符串存储到数组Store[i] {

FILE *fp=fopen("a.txt","r");

char str;

int i=0;

while(!feof(fp))

{

fscanf(fp,"%c",&str);

if(str=='?')

{

Store[i]='\0';

break;

}

Store[i]=str;

i++;

}

Store[i]='\0';

}

void ShowStore()

{int i;

for (i=0;Store[i]!='\0';i++)

printf("%c",Store[i]);

printf("\n");

}

void Output(int a,char *p1,char *p2)

{

printf("%3s\t%d\t%s\t","CLASS",a,"VALUE");

while(p1<=p2)

{

printf("%c",*p1);

p1++;

}

printf("\n");

}

int Sign(char *p)

{

char ch=*p;

if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')')

return 1;

else

return 0;

}

int UnsignedNum(char *p)

{

char ch=*p;

if('0'<=ch&&ch<='9')

return 1;

else

return 0;

}

int LegalCharacter(char *p)

{

char ch=*p;

if(Sign(p)||UnsignedNum(p)||ch=='E'||ch=='.')

return 1;

else return 0;

}

void DistinguishSign(char *p)

{ int Class;

char ch=*p;

switch(ch)

{

case '+':

Output(PLUS,p,p);Type[count++]=PLUS;break;

case '-':

Output(SUBTRACT,p,p);Type[count++]=SUBTRACT;break;

case '*':

Output(MULTIPL Y,p,p);Type[count++]=MULTIPL Y;break;

case '/':

Output(DIVIDE,p,p);Type[count++]=DIVIDE;break;

case '(':

Output(LEFTBRACKET,p,p);Type[count++]=LEFTBRACKET;break;

case ')':

Output(RIGHTBRACKET,p,p);Type[count++]=RIGHTBRACKET;break;

default:

break;

}

}

void TypyDistinguish()

{

printf("词法开始,分析结果如下:\n");

char *p;

p=&Store[0];

while(*p!='\0')

{

if(Sign(p))

{

DistinguishSign(p++);

continue;

}

else if(UnsignedNum(p)||*p=='.')

{

char *p1=p;

if(UnsignedNum(p))

{

while(UnsignedNum(p))

p++;

if(*p=='\0')

{

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

else if(*p=='E')

{

p++;

if(UnsignedNum(p))

{

while(UnsignedNum(p))

p++;

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

else if(*p=='+'||*p=='-')

{

p++;

while(UnsignedNum(p))

p++;

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

else

{

Output(INEFFICACIOUSLABEL,p1,--p);

printf("输入的这个符号是不合法的!"); break;

Type[count++]=INEFFICACIOUSLABEL;

p++;

continue;

}

}

else if(*p=='.')

{

p++;

while(UnsignedNum(p))

p++;

if(*p=='\0')

{

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

else if(*p=='E')

{

p++;

if(UnsignedNum(p))

{

while(UnsignedNum(p))

p++;

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

else if(*p=='+'||*p=='-')

{

p++;

if(UnsignedNum(p))

{

while(UnsignedNum(p))

p++;

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

else

{

Output(INEFFICACIOUSLABEL,p1,--p);

printf("输入的这个符号是不合法的!/n");

break;

Type[count++]=INEFFICACIOUSLABEL;

p++;

continue;

}

}

else

{

Output(INEFFICACIOUSLABEL,p1,--p);

printf("输入的这个符号是不合法的!因为他的后面既不是

0~9也不是“+”或者“-…");

break;//1.5E*2这样的字符串不是无符号数

Type[count++]=INEFFICACIOUSLABEL;

p++;

continue;

}

}

else

{

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

}

else

{

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

}

if(*p=='.')

{

p++;

if(UnsignedNum(p))

{

p++;

while(UnsignedNum(p))

p++;

if(*p=='\0')

{

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

else if(*p=='E')

{

p++;

if(UnsignedNum(p))

{

while(UnsignedNum(p))

p++;

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

else if(*p=='+'||*p=='-')

{

p++;

while(UnsignedNum(p))

p++;

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

}

else

{

Output(UNSIGNEDNUMBER,p1,--p);

Type[count++]=UNSIGNEDNUMBER;

p++;

continue;

}

}

else

{

Output(INEFFICACIOUSLABEL,p1,--p);

printf("输入的这个符号是不合法的!"); b reak;

Type[count++]=INEFFICACIOUSLABEL;

p++;

continue;

}

}

}

else if(*p=='E')

{

Output(INEFFICACIOUSLABEL,p,p); break;

Type[count++]=INEFFICACIOUSLABEL;

printf("输入的这个符号是不合法的!");

p++;

continue;

}

}

printf("\n\n词法分析完毕!");

}

void ShowType()//将类别码存储在Type[100]中,为语法分析做准备{

printf("\n用类别码表示输入的字符如下:\n");

int i;

printf("\n");

for(i=0;Type[i]!=FINISH;i++)

{printf("%d",Type[i]);

}

printf("\n\n");

}

void main()

{

//词法分析部分

StoreStr();

ShowStore();

TypyDistinguish();

Type[count]=FINISH;

ShowType();

}

四、实验结果

正确的结果:

编译原理词法分析程序实现实验报告

错误的结果:

输入的字符串中有1.5E*2

因为实验是以文件的形式进行读取的所以,在读取不合法的过程中只是将存在project 中的a.txt 中的内容改变改为1.5E*2+100*555

实验结果如下:

编译原理词法分析程序实现实验报告

结果分析:

对于正确的结果,我以二元式的形式输出,包括他的值和他的类别码,其中将类别码存放在另外的一个数组中,为了在实验二中的语法识别打下基础。

对于错误的结果,我选择的是跳出这个程序,并且能过分析出错的原因。

改进设计:

(1)字符串是以文件的形式输出的,连续重复输入存在局限性

(2)能够跳过错误的字符继续识别剩下的字符

实验一扩展

李晓萌088330

一、实验内容:

试对基础实验识别的单词种类进行扩充,构造识别以下单词的词法分析程序。

语言中具有的单词包括五个有代表性的关键字begin、end、if、then、else;标识符;整型常数;六种关系运算符;一个赋值符和四个算术运算符。

二、设计部分

基础实验和扩展实验的差别在基础实验的关键在于无符号数的判断,但是,扩展实验的关键在于关键字和标识符的识别。

关于关键字的识别,通过和题目中给出的几个关键字的对比,若相同则可以确定是关键字,否则,就可自动确定为标识符

具体实现的流程图如下:

编译原理词法分析程序实现实验报告

三、源程序代码部分

#include

#include

#define BEGIN 1

#define END 2

#define IF 3

#define THEN 4

#define ELSE 5

# define ID 6

# define INT 7

# define LT 8

# define LE 9

# define EQ 10

# define NE 11

# define GT 12

# define GE 13

#define IS 14

#define PL 15

#define MI 16

#define MU 17

#define DI 18

char *KeyWord[5]={"begin","end","if","then","else"};

int i=0,j=0,k=0,t=0;//搜索指示器

char ch;//存放最新读入的原程序字符

char strToken[20];//存放构成单词符号的字符串

char * chr_form[100];//字符表

char * int_form[100];//常数表

char form[1000];

int q=0;

int temp;

void GetChar()//将下一个字符读入ch中,搜索指示器前移一字符位

{

ch=form[k];

k++;

}

void GetBC()//检查ch中的字符是否为空白,若是则调用Getchar直至ch中进入//一个非空白字符

{

while(ch==' ')

{

//k--;

GetChar();

}

}

void Concat()//将ch中的字符连接到strToken之后,

{

strToken[i]=ch;

i++;

}

bool IsLetter()//判断ch中的字符是否为字符

{

if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))

return (1);

else

return(0);

}

bool IsDigit()//判断ch中的字符是否为数字

{

//k--;

if(((ch)<='9')&&( (ch)>='0'))

return (1);

else

return (0);

}

int Reserve()//对strToken中的字符串查找保留字表,若它是一个保留字

//则返回它的编码,否则返回-1值

{

for(int q=0;q<5;q++)

if(strcmp(KeyWord[q],strToken)==0)

return q;

if(q==4)

return -1;

}

}

void Retract()//将搜索指示器回调一个字符位置,将ch置为空白字符{

k--;

ch=NULL;

}

char*InsertId()//将strToken中的标识符插入符号表,返回符号表的指针

{

chr_form[j]=strToken;

j++;

return chr_form[0];

}

char * InsertConst()//将strToken中的常数插入常数表,返回常数表指针{

int_form[t]=strToken;

t++;

return int_form[0];

}

int code;

//////////////////////////////////////////////////////////////////////

void Output(int a,char *p1,char *p2)

{

cout<<"\t类别码(CLASS):"<

while(p1<=p2)

{

cout<<*p1;

p1++;

}

cout<

}

void analyze()

{

GetChar();

GetBC();

//cout<<"此处没有错"<

if(IsLetter())

while(IsLetter()||IsDigit())

{

Concat();

GetChar();

}

//cout<<"此处没有错"<

Retract();

code=Reserve();

switch(code)

{

case 0:cout<<"需检测的的单词:"<

case 1:cout<<"需检测的的单词:"<

case 2:cout<<"需检测的的单词:"<

case 3:cout<<"需检测的的单词:"<

case 4:cout<<"需检测的的单词:"<

default:

cout<<"需检测的的单词:"<

}

}

else

{

if(IsDigit())

{

while(IsDigit()||ch=='.')

{

Concat();

GetChar();

}

Retract();

cout<<"需检测的的单词:"<

}

else

{

switch (ch)

{ case '+': cout<<"需检测的的单词:+ 类别码为:"<

case'-': cout<<"需检测的的单词:- 类别码为:"<

case'*': cout<<"需检测的的单词:* 类别码为:"<

case'/': cout<<"需检测的的单词:/ 类别码为:"<

case':':GetChar();

if(ch=='=')

{ cout<<"需检测的的单词::= 类别码为:"<

else

{

Retract();

cout<<"需检测的的单词为非法输入!"<

}

case'=':cout<<"需检测的的单词:= 类别码为:"<

case'>':GetChar();switch(ch)

{case'=':

cout<<"需检测的的单词:>= 类别码为:"<

default:Retract();

cout<<"需检测的的单词:> 类别码为:"<

}

case'<':GetChar();

switch(ch)

{case'=':cout<<"需检测的的单词:<= 类别码为:"<

case'>':cout<<"需检测的的单词:<> 类别码为:"<

default:Retract();

cout<<"需检测的的单词:< 类别码为:"<

}

}

}

}

while(k

{

for(int p=0;p<50;p++)

strToken[p]='\0';

i=0;

analyze();

}

}

void main()

{

cout<<"请输入一段程序,以#号结束:"<

form[0]=cin.get();

for( q=1;form[q-1]!='##';q++)

{

form[q]=cin.get();

if(form[q]=='#')

{

cout<<"你输入的程序段为\n";

cout.write(form,q);

break;

}

}

cout<

analyze();

}

四、实验结果:

编译原理词法分析程序实现实验报告

结果分析:

实验的程序只是完成了最基本的部分,能够把题目中给出的关键字begin、end、if、then、else;标识符;整型常数;六种关系运算符;一个赋值符和四个算术运算符顺利的识别出来,还是存在缺陷

改进设计:

(1)关键字的数目太少

(2)只是识别了整数,应该能够将基本实验中的无符号数识别出来

(3)实现多次循环输入

(4)判断出错的功能是很强大

实验二语法分析程序实现

李晓萌088330 一、实验内容:

通过设计、编制、调试典型的SLR(1)语法分析程序,实现对实验一所得词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。

二、设计部分

(1)

首先根据算术四则运算的语法定义,构造SLR(1)分析表。

无符号数的算术四则运算的语法可表示为:

S->E(自己添加的)

E->E+T| E-T|T

T->T*F| T/F|F

F->(E)|i

该表1是根据下一页的图画出来的:

编译原理词法分析程序实现实验报告

表1

编译原理词法分析程序实现实验报告

I8I9

I8I9

(2)对实验一得字符串1.5E+2+100*555进行验证:经过自己的推理所得的表2

编译原理词法分析程序实现实验报告

相关推荐
相关主题
热门推荐