递归下降语法分析

一、实验目的:

利用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. 递归下降分析程序

源代码:

/* Note:Your choice is C IDE */
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

char cxd[200],dc[70]; //程序段  单词 
char ch;  //单词中的字符 
int k,p,syn,m=0,sum=0; //单词符号种别码   指针p 
char *word[6]={"begin","if","then","while","do","end"};  //保留字 
int fg=0; //判断是否有错误 

void scaner();
void lps();
void yucu();
void sm();
void ct();
void es();
void term();
void factor();

void scaner(){  //读取一个字符 
    m=0;
    //初始化数组dc 
    for(k=0;k<8;k++)
        dc[k]=NULL;
    ch=cxd[p++];
    //遇到空格指针加1 
    while(ch==' '){
        ch=cxd[p];
        p++;
    }
    //标识符 
    if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){
        m=0;
        while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){
            dc[m++]=ch;
            ch=cxd[p++];
        }
        p--;
        syn=10;
        //保留字 
        for(k=0;k<6;k++){
            if(strcmp(dc,word[k])==0){
                syn=k+1;
                break;
            }
        }
    }
    //数字 
    else if((ch>='0'&&ch<='9')){
        sum=0;
        while((ch>='0'&&ch<='9')){
            sum=sum*10+ch-'0';
            ch=cxd[p++];
        }
        p--;
        syn=11;
    }
    else{
        switch(ch){
            case '<':m=0;
                dc[m++]=ch;
                ch=cxd[p++];
                if(ch=='>'){
                    syn=22;
                    dc[m++]=ch;
                }
                else if(ch=='='){
                    syn=21;
                    dc[m++]=ch;
                }
                else{
                    syn=20;
                    p--;
                }
                break;
            case '>':m=0;
                dc[m++]=ch;
                ch=cxd[p++];
                if(ch=='='){
                    syn=24;
                    dc[m++]=ch;
                }
                else{
                    syn=23;
                    p--;
                }
                break;
            case ':':m=0;
                dc[m++]=ch;
                ch=cxd[p++];
                if(ch=='='){
                    syn=18;
                    dc[m++]=ch;
                }
                else{
                    syn=17;
                    p--;
                }
                break;
            case '*':syn=15;dc[0]=ch;break;
            case '/':syn=16;dc[0]=ch;break;
            case '+':syn=13;dc[0]=ch;break;
            case '-':syn=14;dc[0]=ch;break;
            case '=':syn=25;dc[0]=ch;break;
            case ';':syn=26;dc[0]=ch;break;
            case '(':syn=27;dc[0]=ch;break;
            case ')':syn=28;dc[0]=ch;break;
            case '#':syn=0;dc[0]=ch;break;
            case '
':syn=-2;dc[0]=ch;break;        
        }
    }
}

//程序,判断是否以begin开始,end #结束 
void lps(){
    if (syn==1) { //begin
        scaner();
        yucu();
        if (syn==6) { //end
            scaner();
            if (syn==0 && fg==0){
                printf("success! 
");
            } 
        } 
        else {
            printf("error,lose 'end' ! 
");
            fg=1;
            exit(0);
        }
    } 
    else {
        printf("error,lose 'begin' ! 
");
        fg=1;
        exit(0);
    }
    return;
}

//语句串 
void yucu() {
    sm();
    while(syn==26) { 
        scaner();
        sm();
    }
    return;
}
//语句 
void sm(){
    if (syn==10) { //为标识符
        scaner();
        if (syn==18) { //为 :=
            scaner();
            es();
        } 
        else {
            printf("error!");
            fg=1;
            exit(0);
        }
    }
    else if(syn==2){  //为if 
        ct();
        scaner();
        if(syn==3){
            sm(); 
        }
        else{
            printf("error,lose 'then' ! 
");
            fg=1;
            exit(0);
        }
    }
    else {
        printf("error!");
        fg=1;
        exit(0);
    }
    
    return;
}
//条件
void ct(){
    es();
    if(syn==25||syn==0||syn==20||syn==21||syn==23||syn==24){
        scaner(); 
    }
    else{
        printf("error! 
");
        fg=1;
        exit(0);
    }
    es();
    return;
} 
//表达式 
void es(){
    term();
    while(syn==13 || syn==14) {
        scaner();
        term();
    }
    return;
}
//
void term(){
    factor();
    while(syn==15 || syn==16) {
        scaner();
        factor();
    }
    return;
}
//因子 
void factor(){
    if(syn==10 || syn==11){
        scaner(); //为标识符或整常数时,读下一个单词符号
    }
    else if(syn==27) {
        scaner();
        es();
        if(syn==28){
            scaner();
        }
        else {
            printf(" ')' 错误
");
            fg=1;
            exit(0);
        }
    } else {
        printf("表达式错误
");
        fg=1;
        exit(0);
    }
    return;
}
int main(void){
    //指针从0开始
    p=0;

    printf("在此输入要分析的程序:
");
    do {
        scanf("%c",&ch);
        cxd[p++]=ch;
    } while(ch!='#');
    //指针从0开始 
    p=0;
    do{
        scaner();
        lps();
    }while(syn!=0);
    printf("#分析完成,任意键结束程序#
");
    
}

原文地址:https://www.cnblogs.com/crjia/p/11960500.html