• 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 "conio.h"
    
    char prog[100],token[8],ch;
    char *rwtab[6]={"begin","if","then","while","do","end"};
    int syn,p,m,n,sum;
    int kk;
     
    void factor(void);
    void expression(void);
    void yucu(void);
    void term(void);
    void statement(void);
    void lrparser(void);
    void scaner(void);
    
    int main(void)
    {
        p=kk=0;
        printf("
    请输入字符串并以#结束: 
    ");
      
        do
        {
            scanf("%c",&ch);
            prog[p++]=ch;
        }while(ch!='#');
      
        p=0;
        scaner();
        lrparser();
        getch();
    }
      
    void lrparser(void)
    {
        if(syn==1)
        { 
            scaner();       /*读下一个单词符号*/
            yucu();     /*调用yucu()函数;*/
      
            if(syn==6)
            {
                scaner();
                if((syn==0)&&(kk==0))
                printf("success!
    ");
            }
            else
            {
                if(kk!=1) printf("error!
    ");
                kk=1;
            }
        }
        else
        { 
            printf("error!
    ");
            kk=1;
        }
          
        return;
    }
      
    void yucu(void)
    { 
        statement();         /*调用函数statement();*/
      
        while(syn==26)
        {
            scaner();          /*读下一个单词符号*/
            if(syn!=6) 
                statement();         /*调用函数statement();*/
        } 
          
        return;
    }
      
    void statement(void)
    {
        if(syn==10)
        {
            scaner();        /*读下一个单词符号*/
            if(syn==18)
            {
                scaner();      /*读下一个单词符号*/
                expression();      /*调用函数statement();*/
            }
            else
            {
                printf("the sing ':=' is wrong!
    ");
                kk=1;
            }
        }
        else
        { 
            printf("wrong sentence!
    ");
            kk=1;
        }
          
        return;
    }
      
    void expression(void)
    {
        term();
      
        while((syn==13)||(syn==14))
        {
            scaner();             /*读下一个单词符号*/
            term();               /*调用函数term();*/
        }
          
        return;
    }
      
    void term(void)
    { 
        factor();
      
        while((syn==15)||(syn==16))
        { 
            scaner();             /*读下一个单词符号*/
            factor();              /*调用函数factor(); */
        }
          
        return;
    }
      
    void factor(void)
    { 
        if((syn==10)||(syn==11))
        {
            scaner();
        }
        else if(syn==27)
        { 
            scaner();           /*读下一个单词符号*/
            expression();        /*调用函数statement();*/
      
            if(syn==28)
            {
                scaner();          /*读下一个单词符号*/
            }
            else 
            {
                printf("the error on '('
    ");
                kk=1;
            }
        }
        else
        { 
            printf("the expression error!
    ");
            kk=1;
        }
          
        return;
    }
    void scaner(void)
    {
        sum=0;
      
        for(m=0;m<8;m++)
            token[m++]=NULL;
          
        m=0;
        ch=prog[p++];
          
        while(ch==' ')
            ch=prog[p++];
          
        if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))
        { 
            while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9')))
            {
                token[m++]=ch;
                ch=prog[p++];
            }
            p--;
            syn=10;
            token[m++]='';
            for(n=0;n<6;n++)
            if(strcmp(token,rwtab[n])==0)
            {
                syn=n+1;
                break;
            }
        }
        else if((ch>='0')&&(ch<='9'))
        {
            while((ch>='0')&&(ch<='9'))
            { 
                sum=sum*10+ch-'0';
                ch=prog[p++];
            }
            p--;
            syn=11;
        }
        else
        switch(ch)
        {
            case '<':
                m=0;
                ch=prog[p++];
                if(ch=='>')
                { 
                    syn=21;
                }
                else if(ch=='=')
                { 
                    syn=22;
                }
                else
                { 
                    syn=20;
                    p--;
                }
            break;
              
            case '>':
                m=0;
                ch=prog[p++];
                if(ch=='=')
                { 
                    syn=24;
                }
                else
                {
                    syn=23;
                    p--;
                }
            break;
              
            case ':':
                m=0;
                ch=prog[p++];
                if(ch=='=')
                {
                    syn=18;
                }
                else
                {
                    syn=17;
                    p--;
                }
                break;
                  
            case '+':
                syn=13;
            break;
              
            case '-': 
                syn=14;
            break;
              
            case '*':
                syn=15;
            break;
              
            case '/': 
                syn=16;
            break;
              
            case '(': 
                syn=27;
            break;
              
            case ')': 
                syn=28;
            break;
              
            case '=':
                syn=25;
            break;
              
            case ';': 
                syn=26;
            break;
              
            case '#':
                syn=0;
            break;
              
            default:
                syn=-1;
            break;
        }
    }
    --------------------------------------------------------------------------------
     实验截图

  • 相关阅读:
    认识js运动
    BOM下的属性和方法---上
    BOM下的属性和方法---下
    鼠标跟随提示框
    [置顶] 关于CSDN2013博客之星的一些看法
    JSP内置对象---application
    C#中foreach语句的迭代器实现机制
    EBS动态创建账户组合实现
    稀里糊涂地被评为博客之星的候选人了,那就麻烦大家帮忙投个票吧~
    UNIX/Linux进程间通信IPC---管道--全总结(实例入门)
  • 原文地址:https://www.cnblogs.com/dyun3/p/11959262.html
Copyright © 2020-2023  润新知