zoukankan      html  css  js  c++  java
  • 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;
    }

    实验结果:

     

  • 相关阅读:
    [RxJS] ReplaySubject
    [React Fundamentals] Composable Components
    [Webpack] Use the Webpack Dashboard to Monitor Webpack Operations
    [RxJS] AsyncSubject
    [React Fundamentals] Component Lifecycle
    [React Fundamentals] Component Lifecycle
    [React Fundamentals] Component Lifecycle
    [RxJS] Subject basic
    [React Fundamentals] Using Refs to Access Components
    文档管理系统二——文档扫描与图片编辑
  • 原文地址:https://www.cnblogs.com/HvYan/p/11950967.html
Copyright © 2011-2022 走看看