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

    以下是我用c语言写的一个递归下降分析程序(该程序是基于我的上一篇博文词法分析程序的设计与实现中的词法分析程序改造出来的):

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    void readString();
    void lrparser();
    void yucu();
    void statement();
    void expression();
    void term();
    void factor();
    
    typedef struct {
        int key;
        char *value;
    }HASH;
    HASH hash[100];
    char str[1000];//存储输入语句数组 
    char ch;//存储源程序段 
    int j=0;// hash[100] 的下标
    int Long=0;//str[]的下标 
    char word[10];//存储单词的容器 
    char num[10];//存储数字的容器 
    int start=0;//读取str[i]的for循环用的下标 
    
    int kk=0;
    int pp;
    
    void readString(){
        int i,p;//循环用的下标 
        int k=0;// word[10] 的下标
        int h=0;// num[10] 的下标
        bool flag=false;//数字串标签 
        bool flag2=false;//字母串标签 
        bool iflag=false;//i循环结束标签 
        for(i=start;i<Long;i++){
            
            if(str[i]>='a'&&str[i]<='z'){
                word[k]=str[i];//if(1==1){printf("aaa");}else{printf("bbb");} # 
                k++;
                flag2=true; 
            }else if(flag2){
                if(strcmp(word,"begin")==0){
                    hash[j].key=1; hash[j].value="begin";j++;
                }else if(strcmp(word,"if")==0){
                    hash[j].key=2; hash[j].value="if";j++;
                }else if(strcmp(word,"then")==0){
                    hash[j].key=3; hash[j].value="then";j++;
                }else if(strcmp(word,"while")==0){
                    hash[j].key=4; hash[j].value="while";j++;
                }else if(strcmp(word,"do")==0){
                    hash[j].key=5; hash[j].value="do";j++;
                }else if(strcmp(word,"end")==0){
                    hash[j].key=6; hash[j].value="end";j++;
                }else if(word[0]>='a'&&str[i]<=word[0]){
                    hash[j].key=10; hash[j].value="字母串";j++;
                } 
                flag2=false;
                k=0;
                for(p=0;p<10;p++){
                    word[p]='';
                }
                start=i;
                break;
            }
            if(str[i]>='0'&&str[i]<='9'){
                num[h]=str[i];
                h++;
                flag=true;
            }else if(flag){
    //                hash[j].key=11; hash[j].value=num;j++;
                hash[j].key=11; hash[j].value="数字串";j++;
                h=0;
                num[10]=NULL;
                flag=false;
                start=i;
                break;
            }
            switch(str[i]){
                case '+': hash[j].key=13; hash[j].value="+";j++;iflag=true;break;
                case '-': hash[j].key=14; hash[j].value="-";j++;iflag=true;break;
                case '*': hash[j].key=15; hash[j].value="*";j++;iflag=true;break;
                case '/': hash[j].key=16; hash[j].value="/";j++;iflag=true;break;
                case ':': 
                    if(str[++i]=='='){
                        hash[j].key=18; hash[j].value=":=";j++;
                    }else{
                        hash[j].key=17; hash[j].value=":";j++;
                        i--;
                    }
                    iflag=true;
                    break;
                case '<': 
                    if(str[++i]=='='){
                        hash[j].key=21; hash[j].value="<=";j++;
                    }else if(str[i]=='>'){
                        hash[j].key=22; hash[j].value="<>";j++;
                    }else{
                        hash[j].key=20; hash[j].value="<";j++;
                        i--;
                    }
                    iflag=true;
                    break;
                case '>': 
                    if(str[++i]=='='){
                        hash[j].key=24; hash[j].value=">=";j++;
                    }else{
                        hash[j].key=23; hash[j].value=">";j++;
                        i--;
                    }
                    iflag=true;
                    break;
                case '=': hash[j].key=25; hash[j].value="=";j++;iflag=true;break;
                case ';': hash[j].key=26; hash[j].value=";";j++;iflag=true;break;
                case '(': hash[j].key=27; hash[j].value="(";j++;iflag=true;break;
                case ')': hash[j].key=28; hash[j].value=")";j++;iflag=true;break;
                case '#': hash[j].key=0; hash[j].value="#";j++;iflag=true;break;
            }
            if(iflag) {
                start=i+1;
                break;
            }
        }
    }
    
    
    void lrparser() {
        if (hash[j-1].key==1) { //识别begin的种别码
            readString();
            yucu();
            if (hash[j-1].key==6) { //识别end的种别码 
                readString();
                if (hash[j-1].key==0 && kk==0)
                    printf("success 
    ");
            } else {
                if(kk!=1) 
                    printf("error,lose 'end' ! 
    ");
                kk=1;
            }
        } else {
            printf("error,lose 'begin' ! 
    ");
            kk=1;
        }
        return;
    }
     
    void yucu() {
        statement();
        while(hash[j-1].key==26) { 
            readString();
            statement();
        }
        return;
    }
     
    void statement() {
        if (hash[j-1].key==10) { //是否为字母
            readString();
            if (hash[j-1].key==18) { //为 :=
                readString();
                expression();
            } else {
                printf("error! 1 ");
                kk=1;
            }
        } else {
            printf("error! 2 ");
            kk=1;
        }
        return;
    }
     
     
    void expression() {
        term();
        while(hash[j-1].key==13 || hash[j-1].key==14) {
            readString();
            term();
        }
        return;
    }
     
     
    void term() {
        factor();
        while(hash[j-1].key==15 || hash[j-1].key==16) {
            readString();
            factor();
        }
        return;
    }
     
     
    void factor() {
        if(hash[j-1].key==10 || hash[j-1].key==11)
            readString(); //为标识符或整常数时,读下一个单词符号
        else if(hash[j-1].key==27) {
            readString();
            expression();
            if(hash[j-1].key==28)
                readString();
            else {
                printf(" ')' 错误
    ");
                kk=1;
            }
        } else {
            printf("表达式错误
    ");
            kk=1;
        }
        return;
    }
     
     
    int main() {
        printf("==========递归下降分析程序===========
    ");
        printf("请输入源程序段:
    ");
        do{
            ch=getchar();
            str[Long++]=ch;
        } while(ch!='#');
        readString();
        lrparser();
        printf("语法分析结束!
    ");
        //输出识别出来的语法,可供调试使用 
        printf("识别出来的语法:
    ");
        int k=0;
        while(hash[k].key!=0){
            printf("
    <%d,%s>",hash[k].key,hash[k].value);
            k++;
        }
    }

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

    得到的运行结果为

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

    得到的运行结果为

  • 相关阅读:
    Flask11 Session、CSRF、注销session、利用端点自动跳转
    python学习笔记4-时间函数
    python学习笔记3-循环1
    python学习笔记2-条件语句
    python学习笔记1-基础语法
    sprintf系列函数
    sscanf非常的重要
    c++中.c_str和.c_data
    c++Map用法
    c语言sscanf总结
  • 原文地址:https://www.cnblogs.com/mogong/p/11955123.html
Copyright © 2011-2022 走看看