自上而下语法分析

 

 

一实验题目

自上而下语法分析

二实验目的

1.给出PL/0文法规范,要求编写PL/0语言的语法分析程序。

2.通过设计、编制、调试一个典型的自上而下语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。

3.选择最有代表性的语法分析方法,如递归下降分析法、预测分析法;选择对各种常见程序语言都具备的语法结构,如赋值语句,特别是表达式,作为分析对象。

三实验环境

Ubuntu16.04、C++语言、g++工具链

四实验内容

已给PL/0语言文法,构造表达式部分的语法分析器。

分析对象(算术表达式)的BNF定义如下:

<表达式>::=[-|+]<项>{<加法运算符><项>}

<项>::=<因子>{<乘法运算符><因子>}

<因子>::=<标识符>|<无符号整数>|‘(’<表达式>‘)’

<加法运算符>::=+|-

<乘法运算符>::=*|/

<关系运算符>::==|#|<|<=|>|>=

五实验要求

  1. 将实验一的“词法分析”的输出结果,作为表达式语法分析器的输入,进行语法解析,对于语法正确的表达式,报告“语法正确”;对于语法错误的表达式,报告“语法错误”,指出错误原因。
  2. 把语法分析器设计成一个独立的一遍的过程。
  3. 采用递归下降分析法或采用预测分析法实现语法分析。

六设计思想

我采用递归下降分析法,首先写出表达式的上下文无关文法,根据文法写出程序,其中每一个非终结符对应一个递归子程序。

四实验步骤

1写出表达式的文法:

文法:

EBTA|BTA

B+|-

A+T|ε

TFC

C*F|ε

FI|N|(E)

I(a|…|z|A|…|Z)( a|…|z|A|…|Z|0|…|9)*

N(1|…|9)(0|…|9)*

2修改词法分析程序:

将分析结果输出到文件中,因为表达式语法分析过程中使用到的单词编码首字母没有一样的,为了简化语法分析程序,仅仅将单词编码的首字母输出到文件中供语法分析器使用。

分析后产生的文件:

3编写语法分析程序。

五算法流程

六源程序

#include<stdio.h>
#include<unistd.h> 
#include<stdlib.h>
#define plus 1
#define minus 2
#define times 3
#define lparen 4
#define rparen 5
#define ident 6
#define number 7
#define finish 8

FILE *fp2=NULL;
int sym=0;
int err=0;

void advance();
void expression();
void factor();
void term();

int main()
{
	fp2 = fopen("result.txt","a+"); //以读写的权限打开文件(如果文件不存在则创建)
	if(fp2 == NULL)
    	{
        	perror("fopen");
        	exit(1);
    	}
	advance();
	expression();
	if(err == 0)
	{
		printf("语法正确!\n");
	}
	else 
	{
		printf("语法错误!\n");	
		printf("err=%d\n",err);
	}
	fclose(fp2); 
    	return 0;
}
//指针向后移动一个字符
void advance() {
        char ch;
	if((ch=fgetc(fp2)) == EOF)
	{
		printf("分析结束!\n");
		sym=finish;
	}
	else
	{
		if(ch == 'l')
		{
			sym=lparen;
		}
		else if(ch == 'r')
		{
			sym=rparen;
		}
		else if(ch == 't')
		{
			sym=times;
		}
		else if(ch == 'i')
		{
			sym=ident;
		}
		else if(ch == 'm')
		{
			sym=minus;
		}
		else if(ch == 'n')
		{
			sym=number;
		}
		else if(ch == 'p')
		{
			sym=plus;
		}
		else
		{
			printf("error\n");
			sym=finish;
		}
	}
}

//因子
void factor()
{
	if(sym!=ident && sym!=number && sym!=lparen)
	{
		err++;
		printf("error----Factor Needs ident or number or lparen\n");
	}
	else
	{
		if (sym == ident)
		{
			printf("5");
			advance();		
		}
		else if (sym == number)
		{
			printf("6");
			advance();
		}
		else
		{
			printf("3");
			advance();
			expression();
			if (sym == rparen)
			{
				printf("7");
				advance();
			}		
			else
			{
				err++;
				printf("error----Needs Rparen\n");
			}
		}
	}
}
//项
void term()
{
	if((sym==rparen) || (sym==times) || (sym==minus) || (sym==plus))
	{
		err++;
		printf("error----term\n");
	}
	else
	{
		printf("2");
		factor();
		while(sym == times)
		{
			printf("9");
			advance();
			factor();
		}
	}
}
//表达式
void expression()
{
	if ((sym == plus) || (sym == minus))
	{
		printf("4");
		term();
		while(sym==plus)
		{
			advance();
			term();
		}	

	}
	else if((sym==rparen) || (sym==times))
	{
		err++;
		printf("error----expresson\n");
	}
	else
	{
		printf("1");
		term();	
		while(sym==plus)
		{
			printf("8");
			advance();
			term();
		}	
	}
}

  

七调试数据及结果

调试数据:

(a+15)*b

词法分析产生的文件:

最终结果:

验证程序分析过程是否正确:

通过在各个函数和判断模块中输出数字序号,经推导分析可判断程序执行过程正确。

八实验体会

程序需要对两个文件进行操作,这时出现段错误 (核心已转储)这个错误,最终发现,在打开一个文件后,不能再打开另一个文件,必须对一个文件操作后,关闭这个文件,才能对下一个文件进行操作。

posted @ 2018-05-24 20:03  奇热行  阅读(1344)  评论(0)    收藏  举报