作业十二

一、实验目的:

利用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 <iostream>
#include <ext/hash_map>
#include <string.h>
#include<map>
using std::map;
using namespace __gnu_cxx;
using namespace std;
map<string, string> m;
string str="begin if a>9 then a:=4 end #";
vector<string> str_list;
vector<string> strnum;
int select=0;
int kk=0;

void test();
void E();
void E1();
void T();
void T1();
void F();
void lrparser();
void yucu();
void statement();
void condition();
void expression();
void term();
void factor();

void test(){
    select++;
    cout<<select<<"   "<<strnum[select]<<endl;
}

void init(){
     m["begin"]="1";
     m["if"]="2";
     m["then"]="3";
     m["while"]="4";
     m["do"]="5";
     m["end"]="6";
     m["+"]="13";
     m["-"]="14";
     m["*"]="15";
     m["/"]="16";
     m[":"]="17";
     m[":="]="18";
     m["<"]="20";
     m["<="]="21";
     m["<>"]="22";
     m[">"]="23";
     m[">="]="24";
     m["="]="25";
     m[";"]="26";
     m["("]="27";
     m[")"]="28";
     m["#"]="0";
} 

//字符串切割函数 
vector<string> split(const string& str, const string& delim) {  
    vector<string> res;  
    if("" == str) return res;  
    //先将要切割的字符串从string类型转换为char*类型  
    char * strs = new char[str.length() + 1] ; 
    strcpy(strs, str.c_str());   
 
    char * d = new char[delim.length() + 1];  
    strcpy(d, delim.c_str());  
 
    char *p = strtok(strs, d);  
    while(p) {  
        string s = p; //分割得到的字符串转换为string类型  
        res.push_back(s); //存入结果数组  
        p = strtok(NULL, d);  
    }  
 
    return res;  
}

//辨别字符串是否为纯数字 
bool AllisNum(string str)  
 {  
     for (int i = 0; i < str.size(); i++)
     {
         int tmp = (int)str[i];
         if (tmp >= 48 && tmp <= 57)
         {
             continue;
         }
         else
         {
             return false;
         }
     } 
     return true;
}



void scanner() {
    int chock=0;
    int row=1;
    init();
     //string str="begin a/*:=bc/:()d>=eas;dasd";
     
//     string str;
//     string s;
//     cout<<"请输入字符串:"<<endl; 
//     do{
//         getline(cin,s);
//         str+=s;
//         if(str[str.size()-1]=='#'){
//             break;
//         }
//        str+="\n";
//     }while(1);
     
     //插入空格 
     for(int i=0;i<str.size();i++){
        switch(str[i]){
            case '+':
                   str.insert(i," ");
                i++;
                str.insert(i+1," ");
                   break;
               
               case '-':
                   str.insert(i," ");
                i++;
                str.insert(i+1," ");
                   break;
               
               case '*':
                   str.insert(i," ");
                i++;
                str.insert(i+1," ");
                   break;
               /**/
               case '/':
                   
                   if(str[i+1]=='*'){
                       
                       for(int k=i;k<str.size();k++){
                           if(str[k]=='/' && str[k-1]=='*'){
                               cout<<"成功进入"<<endl; 
                               str.erase(i,k-i+1);
                               str.insert(i," ");
                               chock=1;
                            break;    
                        }
                    }
                    
                    if(chock==0){
                        chock=0;
                        cout<<"注释方式错误不完整,错误位置第"<<row<<""<<endl ;
                        exit(0); 
                    }
                }
                else{
                       str.insert(i," ");
                    i++;
                    str.insert(i+1," ");
                }
                   break;
               
               case ':':
                   str.insert(i," ");
                if(str[i+2]=='=')i=i+2;else i++;
                str.insert(i+1," ");
                   break;
                   
               case '<':
                   str.insert(i," ");
                if(str[i+2]=='=' || str[i+2]=='>')i=i+2;else i++;
                str.insert(i+1," ");
                   break;
                   
               case '>':
                   str.insert(i," ");
                if(str[i+2]=='=')i=i+2;else i++;
                str.insert(i+1," ");
                   break;
               
               case '=':
                   str.insert(i," ");
                i++;
                str.insert(i+1," ");
                   break;
               
               case ';':
                   str.insert(i," ");
                i++;
                str.insert(i+1," ");
                   break;
                   
               case '(':
                   str.insert(i," ");
                i++;
                str.insert(i+1," ");
                   break;
               
               case ')':
                   str.insert(i," ");
                i++;
                str.insert(i+1," ");
                   break;
                   
               case '#':
                   str.insert(i," ");
                i++;
                str.insert(i+1," ");
                   break;
                   
               case '\n':
                   str.insert(i," ");
                i++;
                row++;
                str.insert(i+1," ");
                   break;
       }         
     }
     
     for(int i=0;i<str.size();i++){
         cout<<str[i];
     }
     cout<<endl;
    
    //切割空格 
     
    str_list=split(str," ");
    
    //输出对应序列 
    for(int i = 0; i < str_list.size(); i++)
    {

        if (m.find(str_list[i]) != m.end()){
            cout<<"\t< "<<str_list[i] <<","<<m[str_list[i]]<<" >"<<endl;
            strnum.push_back(m[str_list[i]]);
        }    
        else if(AllisNum(str_list[i])){        
            cout<<"\t< "<<str_list[i] <<","<<11<<" >"<<endl;
            strnum.push_back("11");
        }
        else {
            cout<<"\t< "<<str_list[i] <<","<<10<<" >"<<endl; 
            strnum.push_back("10");
        }

    }
    
    for(int i = 0; i < strnum.size(); i++){
        cout<<strnum[i]<<"  ";
    }

}

//void E(){
//    if(select==strnum.size())return;
//    T();
//    E1();                                                               
//}
//
//void E1(){
//    if(select==strnum.size())return;
//    if(strnum[select]=="13"){
//        select++;
//        T();
//        E1();
//    }
//    else if(strnum[select]=="0" || strnum[select]=="28"){
//
//    }
//    else cout<<"error : "<<select;     
//     
//}
//
//void T(){
//    if(select==strnum.size())return;
//    F();
//    T1();
//}
//
//void T1(){
//    if(select==strnum.size())return;
//    if(strnum[select]=="15"){
//        select++;
//        F();
//        T1();
//    }
//    else if(strnum[select]=="0" || strnum[select]=="13" || strnum[select]=="28"){
//
//    }
//    else cout<<"error : "<<select;     
//
//}
//
//void F(){
//    if(select==strnum.size())return;
//    if(strnum[select]=="27"){
//        select++;
//        E();
//        if(strnum[select]=="28"){}
//        else cout<<"error : "<<select;     
//    }
//    else if(strnum[select]=="10"){ 
//        select++;
//    }
//    else cout<<"error : "<<select;         
//}

//程序,判断是否以begin开始,end #结束 
void lrparser(){
    if (strnum[select]=="1") { //begin
        test();
        yucu();
        if (strnum[select]=="6") { //end
            test();
            if (strnum[select]=="0" && kk==0){
                printf("success \n");
            } 
        } 
        else {
            printf("error,lose 'end' ! \n");
            kk=1;
            exit(0);
        }
    } 
    else {
        printf("error,lose 'begin' ! \n");
        kk=1;
        exit(0);
    }
    return;
}

//语句串 
void yucu() {
    statement();
    while(strnum[select]=="26") { 
        test();
        statement();
    }
    return;
}

//语句 
void statement(){
    if (strnum[select]=="10") { //为标识符
        test();
        if (strnum[select]=="18") { //为 :=
            test();
            expression();
        } 
        else {
            printf("error!");
            kk=1;
            exit(0);
        }
    }
    else if(strnum[select]=="2"){  //为if 
        test();
        condition();
        if(strnum[select]=="3"){
            test();
            statement(); 
        }
        else{
            printf("error,lose 'then' ! \n");
            kk=1;
            exit(0);
        }
    }
    else {
        printf("error!");
        kk=1;
        exit(0);
    }
    
    return;
}
//条件
void condition(){
    expression();
    if(strnum[select]=="25"||strnum[select]=="0"||strnum[select]=="20"||strnum[select]=="21"||strnum[select]=="23"||strnum[select]=="24"){
        
        test(); 
    }
    else{
        printf("error! \n");
        kk=1;
        exit(0);
    }
    expression();
    return;
} 
//表达式 
void expression(){
    term();
    while(strnum[select]=="13" || strnum[select]=="14") {
        test();
        term();
    }
    return;
}
//
void term(){
    factor();
    while(strnum[select]=="15" || strnum[select]=="16") {
        test();
        factor();
    }
    return;
}
//因子 
void factor(){
    if(strnum[select]=="10" || strnum[select]=="11"){
        test(); //为标识符或整常数时,读下一个单词符号
    }
    else if(strnum[select]=="27") {
        test();
        expression();
        if(strnum[select]=="28"){
            test();
        }
        else {
            printf(" ')' 错误\n");
            kk=1;
            exit(0);
        }
    } else {
        cout<<select<<"  asdsada"<<endl;
        printf("表达式错误\n");
        kk=1;
        exit(0);
    }
    return;
}
int main(){
    scanner();
    cout<<endl;
    lrparser();
    
}

测试

 

猜你喜欢

转载自www.cnblogs.com/renshenbenzuig/p/11958725.html