【编译原理实验】递归下降子程序设计


实验内容

给定CP语言中简单算术表达式文法G[E]:

E→TE’

E’→ATE’|ε

T→FT’

T’→MFT’ |ε

F→(E) | i

A → + | -

M → * | /

根据该文法,编写递归下降分析子程序。

【说明】:终结符号i为用户定义的简单变量,即专题1中标识符的定义。

 

实验要求

(1)为每个非终结符号写一个函数,选择合适的数据结构来存储产生式规则。

(2)输入:是词法分析输出的二元组序列,即任意简单算术表达式经过专题1程序输出后得到的结果。

(3)输出:判定输入串是否为该文法定义的合法算术表达式。

(4)测试数据至少包含3组正确输入和2组错误输入。

 

设计思路

先将上篇词法分析器的二元组输出作为输入读入到二维字符数组中,再将每个二元组的单词和编号提取出来存入结构体中(这里记录编号是为了能实现将题意中的i识别为任意的标识符)。根据题目给出的产生式规则为每个非终结符号编写递归下降分析函数,使用变量p标记当前的单词并开始逐步分析,若分析过程中出错则直接停止。若执行完所有的函数后p指向了结构体的末尾,则该输入串是该文法的合法算数表达式。

 

程序结构

(1)主要数据结构:

二维字符数组ch:用于读入输入的二元组。

结构体struct node{string str;string code;}:记录二元组中的单词及其编号。

 

(2)函数定义:

void E():非终结符E的函数,输出E的产生式规则,并向下进行T()和E1()。

void E1():非终结符E’的函数,若此时的单词为“+”或“-”,则输出E’->ATE’这条产生式,并依次向下进行A()、T()和E1(),否则直接输出E’->ε。

void T():非终结符T的函数,输出T的产生式规则,并向下进行F()和T1()。

void T1():非终结符T’的函数,若此时的单词为“*”或“/”,则输出T’->MFT’这条产生式,并依次向下进行M()、F()和T1(),否则直接输出T’->ε。

void F():非终结符F的函数,若此时单词的编号为28(标识符编号),则输出F产生该标识符,变量p指向后一个单词;否则,若此时单词为“(”,变量p指向后一个单词,向下进行E()后,若此时单词为“)”,则输出F->(E),否则输出错误并停止;否则,输出错误并停止。

void A():非终结符A的函数,若此时的单词为“+”或“-”,则输出A->+或A->-,变量p指向后一个单词;否则,输出错误并停止。

void M():非终结符M的函数,若此时的单词为“*”或“/”,则输出M->*或M->/,变量p指向后一个单词;否则,输出错误并停止。

 

实现代码

#include<bits/stdc++.h>
using namespace std;
char ch[100][20];
struct node
{
    string str;
    string code;
}a[100];

int p=0;
void E();
void E1();
void T();
void T1();
void F();
void A();
void M();

void E(){
    printf("E->TE'\n");
    T();
    E1();
}

void E1(){
    if(a[p].str=="+"||a[p].str=="-")
    {
        printf("E'->ATE'\n");
        A();
        T();
        E1();
    }
    else
        printf("E'->ε\n");
}

void T(){
    printf("T->FT'\n");
    F();
    T1();
}

void T1(){
    if(a[p].str=="*"||a[p].str=="/")
    {
        printf("T'->MFT'\n");
        M();
        F();
        T1();
    }
    else
        printf("T'->ε\n");
}

void F(){
    
    if(a[p].code=="28")
    {
        cout<<"F->"<<a[p].str<<endl;
        p++;
    }
    else if(a[p].str=="(")
    {
        p++;
        E();
        if(a[p].str==")")
        {
            printf("F->(E)\n");
            p++;
        }
        else{
            printf("error!\n");
            exit(0);
        }
    }
    else{
        printf("error!\n");
        exit(0);
    }
    
}

void A(){
    if(a[p].str=="+"){
        printf("A->+\n");
        p++;
    }
    else if(a[p].str=="-"){
        printf("A->-\n");
        p++;
    }
    else{
        printf("error!\n");
        exit(0);
    }
}

void M(){
    if(a[p].str=="*"){
        printf("M->*\n");
        p++;
    }
    else if(a[p].str=="/"){
        printf("M->/ \n");
        p++;
    }
    else{
        printf("error!\n");
        exit(0);
    }
}

int main(){
    FILE *fp;
    fp=fopen("result2.txt","r");
    if(fp==NULL)
    {
        cout<<"Open Error";
        exit(1);
    }
    int len=0;
    while(fscanf(fp,"%s",ch[len])!=EOF) len++;
    fclose(fp);
    
    for(int i=0;i<len;i++)//输入转换 
    {
        string temp="";
        int j;
        for(j=1;ch[i][j]!=',';j++)
        {
            temp+=ch[i][j];
        }
        a[i].str=temp;
        j++;
        temp="";
        for(j;ch[i][j]!='>';j++)
        {
            temp+=ch[i][j];
        }
        a[i].code=temp;
    }
    
    E();
    
    if(p==len) printf("succeed\n");
    else printf("failed\n");
    
    return 0;
}

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM