zoukankan      html  css  js  c++  java
  • 实验二 递归下降语法分析

    一、实验目的:

    利用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<iostream>
    
    char prog[]="begin a:=9;x:=2*3;b:=a+x #", token[20];  //程序段,单词符号 
    char ch;
    int syn,p,m,n,sum,kk=0; //单词符号类型syn,整数sum,#
    const char *rwtab[6]={"begin","if","then","while","do","end"};
    
    void scanner();
    void transfer();
    void yuju();
    void statement();
    void factor();
    void expression();
    void term(); 
    
    void scanner(){ //读取一个单词符号,类型syn('#'is 0),单词token或sum 
        for(n=0;n<20;n++){
            token[n]='';
        }
        ch=prog[p++];
        while(ch == ' '){
            ch=prog[p++];
        }
        if (ch>='a'&&ch<='z'){ //标识符 
            while(ch>='a'&&ch<='z'||ch>='0'&&ch<='9'){
                token[m++]=ch;
                ch =prog[p++];
            }
            syn=10;
            p--;
            for(n=0;n<6;n++){ //标识符是否关键词 
                if (strcmp(token,rwtab[n])==0){
                    syn=n+1;
                    break;
                } 
            }
        }
        else{
            if(ch>='0'&&ch<='9'){  // 数字 
                sum=0;
                while(ch>='0'&&ch<='9'){
                    sum=sum*10+(ch-'0');
                    ch=prog[p++];
                }
                syn=11;
                p--;
            }
            else{
                m=0;
                switch(ch){  // 表达式 
                    case '<':
                        token[m++]=ch;
                        ch=prog[p++];
                        if(ch=='>'){                  //不等于 
                            syn=21;
                            token[m++]=ch;
                        }
                        else if (ch=='='){           //小于等于 
                            syn=22;
                            token[m++]=ch;
                        }
                        else{                       //小于 
                            syn=20;
                            p--;
                        }
                        break;
                    case '>':
                        m=0;
                        token[m++]=ch;
                        ch=prog[p++];
                        if (ch=='='){               //大于等于 
                            syn=24;
                            token[m++]=ch;
                        }
                        else{                       //大于 
                            syn=23;
                            p--;
                        }
                        break;
                    case ':':
                        m=0;
                        token[m++]=ch;
                        ch=prog[p++];
                        if (ch=='='){                //  := 
                            syn=18;
                            token[m++]=ch;
                        }
                        else{                        //
                            syn=17;
                            p--;
                        }
                        break;
                    case '+':
                        syn=13;
                        token[0]=ch;
                        break;
                    case '-':
                        syn=14;
                        token[0]=ch;
                        break;
                    case '*':
                        syn=15;
                        token[0]=ch;
                        break;
                    case '/':
                        syn=16;
                        token[0]=ch;
                        break;
                    case '=':
                        syn=25;
                        token[0]=ch;
                        break;
                    case ';':
                        syn=26;
                        token[0]=ch;
                        break;
                    case '(':
                        syn=30;
                        token[0]=ch;
                        break;
                    case ')':
                        syn=31;
                        token[0]=ch;
                        break;
                    case '#':
                        syn=0;
                        token[0]=ch;
                        break;
                    default:
                        syn=1;
                        token[0]=ch;
                }
            }
        }
    }
    
    void transfer(){
        if(syn==1){ //begin
            scanner();
            yuju();
            if(syn==6){ //end
                scanner();
                if(syn==0&&kk==0){
                    printf("success
    ");
                }
            }
            else{
                if(kk!=1){
                    printf("error,lose 'end'
    ");
                    kk=1;
                }
            }
        }
        else{
            printf("error,lose 'begin'
    ");
            kk=1;
        }
    }
    void yuju(){
        statement();
        while(syn==26){
            scanner();
            statement();
        }
    }
    void statement(){
        if(syn==10){ //标识符
             scanner();
             if(syn==18){ //  :=
                 scanner();
                 expression();
             }
             else{
                 printf("error!
    ");
                 kk=1;
             }
        }
        else{
            printf("error!
    ");
            kk=1;
        }
    }
    void expression(){
        term();
        while(syn==13||syn==14){
            scanner();
            term();
        }
    }
    void term(){
        factor();
        while(syn==15||syn==16){
            scanner();
            factor();
        }
    }
    void factor(){
        if(syn==10||syn==11){ // 为标识符或整常数时,读下一个单词符号 
            scanner();
        }
        else if (syn==30){
            scanner();
            expression();
            if(syn==31){
                scanner();
            }
            else{
                printf("')' error.
    ");
                kk=1;
            }
        }
        else{
            printf("表达式错误
    ");
            kk=1;
        } 
    }
    int main(){
        scanner();
        transfer();
        printf("语法分析结束!
    ");
    
    
        return 0;
    }

  • 相关阅读:
    通过anaconda进行python多版本控制
    搭建java环境
    windows安装 Microsoft Visual c++
    更改jupyter notebook的主题颜色(theme) 包括pycharm
    linux服务器安装anaconda,然后远程使用jupyter
    根据经纬度坐标计算距离-python
    Redis相关链接
    VBA笔记-参考教程
    用sklearn计算卡方检验P值
    linux创建新用户
  • 原文地址:https://www.cnblogs.com/lxml/p/11933171.html
Copyright © 2011-2022 走看看