自上而下语法分析
一实验题目
自上而下语法分析
二实验目的
1.给出PL/0文法规范,要求编写PL/0语言的语法分析程序。
2.通过设计、编制、调试一个典型的自上而下语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。
3.选择最有代表性的语法分析方法,如递归下降分析法、预测分析法;选择对各种常见程序语言都具备的语法结构,如赋值语句,特别是表达式,作为分析对象。
三实验环境
Ubuntu16.04、C++语言、g++工具链
四实验内容
已给PL/0语言文法,构造表达式部分的语法分析器。
分析对象(算术表达式)的BNF定义如下:
<表达式>::=[-|+]<项>{<加法运算符><项>}
<项>::=<因子>{<乘法运算符><因子>}
<因子>::=<标识符>|<无符号整数>|‘(’<表达式>‘)’
<加法运算符>::=+|-
<乘法运算符>::=*|/
<关系运算符>::==|#|<|<=|>|>=
五实验要求
- 将实验一的“词法分析”的输出结果,作为表达式语法分析器的输入,进行语法解析,对于语法正确的表达式,报告“语法正确”;对于语法错误的表达式,报告“语法错误”,指出错误原因。
- 把语法分析器设计成一个独立的一遍的过程。
- 采用递归下降分析法或采用预测分析法实现语法分析。
六设计思想
我采用递归下降分析法,首先写出表达式的上下文无关文法,根据文法写出程序,其中每一个非终结符对应一个递归子程序。
四实验步骤
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
词法分析产生的文件:

最终结果:

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

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

浙公网安备 33010602011771号