12 递归下降语法分析

一、实验目的:

利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

 

二、实验原理

每个非终结符都对应一个子程序。

该子程序根据下一个输入符号(SELECT集)来确定按照哪一个产生式进行处理,再根据该产生式的右端:

  • 每遇到一个终结符,则判断当前读入的单词是否与该终结符相匹配,若匹配,再读取下一个单词继续分析;不匹配,则进行出错处理
  • 每遇到一个非终结符,则调用相应的子程序

 

三、实验要求说明

输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。

例如:

输入begin a:=9;x:=2*3;b:=a+x end #

输出success

输入x:=a+b*c  end #

输出‘end' error

 

四、实验步骤

      1.待分析的语言的语法(参考P90)

      2.将其改为文法表示,至少包含

–语句

–条件

–表达式

3. 消除其左递归

4. 提取公共左因子

5. SELECT集计算

6. LL(1)文法判断

7. 递归下降分析程序

代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void match();  //匹配的方法
void Pre();   //对语法进行预处理
void statement();  //匹配语法声明(赋值) 
void expression(); //匹配运算符 
void term();   //匹配*/运算符 
void factor();  //匹配括号 
char temp[500],test[500];
char ch;
const char *keyword[6]= {"begin","if","then","while","do","end"};   //存储保留字
int i=0,num,n,ednum=0,bnum=0;

int main() {
    printf("	
请输入程序,以#号结束:
");
    ch=getchar();
    while(ch!='#') {
        temp[i]=ch;
        ch=getchar();
        i++;
    }
    temp[i]='#';
    i++;
    temp[i]='';
    i=0;
    match();
    Pre();
}
void match() {
    ch=temp[i++];
    while(ch==' ') {
        ch=temp[i++];
    }
    if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z')) {        //保留字与标识符判断
        n=0;
        num=10;
        char a=ch;

        while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')) { //字符串数组复制
            test[n++]=ch;
            ch=temp[i++];
        }

        test[n++]='';

        for(n=0; n<6; n++) {
            if(strcmp(test,keyword[n])==0) {  //判断两个字符串是否一致
                num=n+1;
                printf("[%s,%d]
",test,num);
                if(num==1) {
                    bnum=1;
                }
                if(num==6) {
                    ednum=1;
                }
                break;
            }
        }
        i--;
        if(num==10) {
            ch=a;
            printf("[%c,%d]
",ch,num);
        }
    }

    if(ch>='0'&&ch<='9') {    //数字判断
        num=11;
        printf("[%c,%d]
",ch,num);

    } else {
        switch(ch) {    //运算符界符的判断
            case '#':
                num=0;printf("[%c,%d]
",ch,num);break;
            case '+':
                num=13;printf("[%c,%d]
",ch,num);break;
            case '-':
                num=14;printf("[%c,%d]
",ch,num);break;
            case '*':
                num=15;printf("[%c,%d]
",ch,num);break;
            case '/':
                num=16;printf("[%c,%d]
",ch,num);break;
            case ':':
                ch=temp[i++];
                if(ch=='=') {
                    num=18;
                    printf("[:%c,%d]
",ch,num);
                } else {
                    i--;
                    ch=temp[i];
                    num=17;
                    printf("[%c,%d]
",ch,num);
                }
                break;
                
            case '<':
                ch=temp[i++];
                if(ch=='=') {
                    num=21;
                    printf("[<%c,%d]
",ch,num);
                } else if(ch='>') {
                    num=22;
                    printf("[<%c,%d]
",ch,num);
                } else {
                    i--;
                    ch=temp[i];
                    num=20;
                    printf("[%c,%d]
",ch,num);
                }
                break;

            case '>':
                ch=temp[i++];
                if(ch=='=') {
                    num=24;
                    printf("[>%c,%d]
",ch,num);
                } else {
                    i--;
                    ch=temp[i];
                    num=23;
                    printf("[%c,%d]
",ch,num);
                }
                break;
            case '=':
                num=25;printf("[%c,%d]
",ch,num);break;
            case ';':
                num=26;printf("[%c,%d]
",ch,num);break;
            case '(':
                num=27;printf("[%c,%d]
",ch,num);break;
            case ')':
                num=28;printf("[%c,%d]
",ch,num);break;
        }
    }
}

void Pre() {  //对语法进行预处理,当匹配到分号时,进行一次match匹配下一个字符    
    if(bnum==1){  //当匹配到begin时,匹配下一个字符 
        match();
    } 
    statement();
    while(num==26) {
        match();
        statement();
    }
    if(bnum!=1){
        printf("【语法错误】缺失'begin'
");  //否则,提示begin缺失(不用else是为了结果美观-。-) 
    }
    return;
}
void statement() {  //匹配语法声明(赋值),当匹配到变量时,匹配声明符号 
    if (num==10) {   
        match();
        if(num==18) {
            match();
            expression();
        } else {
            printf("【语法错误】缺失符号':='
");
        }
    } else {
        if(num==0&&ednum==1&&bnum==1) printf("【Success!语法无错误!分析完成】
");  //当匹配到#且begin、end存在时,输出语法无错误 
        else if(num==0&&ednum!=1) {
            printf("【语法错误】缺失'end'
");    //匹配到#后end缺失 
        }
    }
    return;
}
void expression() {  //匹配+-运算符 
    term();
    while(num==13||num==14) {
        match();
        term();
    }
    return;
}
void term() {   //匹配*/运算符 
    factor();
    while(num==15||num==16) {
        match();
        factor();
    }
    return;
}
void factor() {  //匹配括号 
    if(num==10||num==11) {
        match();
    } else if(num==27) {
        match();
        expression();
        if(num==28) {
            match();
        } else {
            printf(" 缺失')' 错误
");
        }
    } else {
        printf("语法错误!
");
    }

    return;
}

实验结果:

 

原文地址:https://www.cnblogs.com/HvYan/p/11950967.html