一、实验目的
根据某一文法编制调试自顶向下语法分析器(递归下降分析程序、 LL ( 1 )分析程序),以便对任意输入的符号串进行自顶向下的语法分析。本次实验的目的主要是加深对自顶向下的语法分析法的理解。
1. 递归下降分析器
实验设计思想:利用函数之间的递归调用模拟语法树自上而下的构造过程。
实验算法 :
为文法 G 的每个非终结符号 U 构造一个递归过程,不妨命名为 U 。
U 的产生式的右边指出这个过程的代码结构:
(1) 若是终结符号,则和向前看符号对照,若匹配则向前进一个符号;否则出错。
(2) 若是非终结符号,则调用与此非终结符对应的过程。当 A 的右部有多个产生式时,可用选择结构实现。具体为:
( 1 )对于每个非终结符号 U → u1|u2|…|un 处理的方法如下:
U( )
{
ch= 当前符号 ;
if(ch 可能是 u1 字的开头 ) 处理 u1 的程序部分 ;
else if(ch 可能是 u2 字的开头 ) 处理 u2 的程序部分 ;
…
else error()
}
( 2 )对于每个右部 u1 → x1x2…xn 的处理架构如下:
处理 x1 的程序;
处理 x2 的程序;
…
处理 xn 的程序;
( 3 )如果右部为空,则不处理。
( 4 )对于右部中的每个符号 xi
① 如果 xi 为终结符号:
if(xi= = 当前的符号 )
{
NextChar() ;
return;
}
else
出错处理
② 如果 xi 为非终结符号,直接调用相应的过程 xi()
说明: NextChar 为前进一个字符函数。
2.LL(1) 下降分析器
实验设计思想:利用 LL ( 1 )控制程序根据显示栈栈顶内容、向前看符号以及 LL ( 1 )分析表,对输入符号串自上而下的分析。
二、实验过程和指导
程序要求
程序输入 / 输出示例:
对下列文法,用递归下降分析法 /LL(1) 分析法, 对任意输入的符号串进行分析:
( 1 ) E → TG
( 2 ) G → +TG| — TG
( 3 ) G →ε
( 4 ) T → FS
( 5 ) S → *FS|/FS
( 6 ) S →ε
( 7 ) F → (E)
( 8 ) F → i
输出的格式如下:
1. 递归下降分析程序 /LL(1) 分析程序 ,编制人:姓名,学号,班级
2. 输入一以 # 结束的符号串 ( 包括 +-*/ () i#) :在此位置输入符号串例如: i+i*i#
3. 输出结果: i+i*i# 为合法符号串
4. 输出从文法开始符到句子的推导的全过程,或输出以下的分析过程:
步骤 |
分析栈 |
剩余输入串 |
所用产生式 |
1 |
E |
i+i*i# |
E →TG |
|
|
|
|
5. 输入符号串 为非法符号串 ( 或者为合法符号串 )
输入一符号串如 i+i*# ,要求输出为“ i+i*# 为非法符号串”。
实验代码如下:
#include #include #include //用到了字符串处理函数strcat struct stack //stack堆栈用来存放推倒所用的产生式 { stack *top; char value; }; char pop(stack *pst) //堆栈的出栈操作 { char e; if(pst->top==pst) { printf("The stack is null."); return 0; } else { e=pst->top->value; pst->top--; return e; } } void push(stack *pst,char e) //堆栈的压栈操作 { pst->top++; pst->top->value=e; } void printstack(stack *pst) //显示堆栈内容 { stack *printtemp=pst->top; while(printtemp!=pst) { printf("%c",printtemp->value); printtemp--; } } int main() //主函数入口 { stack *grammar=(stack *)malloc(sizeof(stack)); //分配堆栈的内存空间,并初始化 grammar->top=grammar; grammar->top->value='#'; push(grammar,'e'); push(grammar,'T'); char str[20]={' ','/0'}; FILE *fp; FILE *op; fp=fopen("C://c.txt","a+");//文件地址在C盘 op=fopen("C://b.txt","a+");//文件地址在C盘 printf("E => "); printstack(grammar); printf("%c",'/n'); while(!feof(fp)) //开始扫描C盘文件中的字符 { char ch=fgetc(fp); char strchar[]={ch,'/0'}; if(ch!=';') { if(ch=='i') //扫描到‘i'字符的处理 { if(grammar->top->value=='T') { pop(grammar); push(grammar,'t'); push(grammar,'F'); printf(" =>%s",str); printstack(grammar); printf("%c",'/n'); pop(grammar); push(grammar,'i'); printf(" =>%s",str); printstack(grammar); printf("%c",'/n'); } else if(pop(grammar)=='*') { pop(grammar); push(grammar,'t'); push(grammar,'F'); printf(" =>%s",str); printstack(grammar); printf("%c",'/n'); pop(grammar); push(grammar,'i'); printf(" =>%s",str); printstack(grammar); printf("%c",'/n'); } strcat(str,strchar); } else if(ch=='+') //遇见字符'+'的处理 { if(pop(grammar)=='i') { pop(grammar); printf(" =>%s",str); printstack(grammar); printf("%c",'/n'); } else printf("there is wrong char near + "); push(grammar,'T'); strcat(str,strchar); printf(" =>%s",str); printstack(grammar); printf("%c",'/n'); } else if(ch=='*') //遇见字符'*'的处理 { if(pop(grammar)=='i') { push(grammar,'*'); strcat(str,strchar); } else printf("there is wrong char near * "); } } else { while(grammar->top!=grammar) { pop(grammar); printf(" =>%s",str); printstack(grammar); printf("%c",'/n'); } printf("递归向下分析完成!/n"); grammar->top=grammar; grammar->top->value='#'; push(grammar,'e'); push(grammar,'T'); printf("E => "); printstack(grammar); printf("%c",'/n'); strcpy(str," "); } } return 0; }
实验结果如下: