zoukankan      html  css  js  c++  java
  • 编译原理第五次作业

    词法分析程序(Lexical Analyzer)要求:

    - 从左至右扫描构成源程序的字符流

    -  识别出有词法意义的单词(Lexemes

    -  返回单词记录(单词类别,单词本身)

    -  滤掉空格

    -  跳过注释

    -  发现词法错误

    程序结构:

    输入:字符流(什么输入方式,什么数据结构保存)

    处理:

    –遍历(什么遍历方式)

    –词法规则

    输出:单词流(什么输出形式)

    –二元组

    单词类别:

    1.标识符(10)

    2.无符号数(11)

    3.保留字(一词一码)

    4.运算符(一词一码)

    5.界符(一词一码)

    单词符号

    种别码

    单词符号

    种别码

    begin

    1

    :

    17

    if

    2

    :=

    18

    then

    3

    <

    20

    while

    4

    <=

    21

    do

    5

    <>

    22

    end

    6

    >

    23

    l(l|d)*

    10

    >=

    24

    dd*

    11

    =

    25

    +

    13

    ;

    26

    -

    14

    (

    27

    *

    15

    )

    28

    /

    16

    #

    0

      

      首先先说下我的思路,先建立map<string, string> m;存储符号及其种别码

    map<string, string> m;
    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";
    } 

      而后进行字符串录入以#作为结束录入的标志。在c++中,cin用于string类型录入时会将空格作为结束符从而导致空格后的内容无法录入,故采用getline()函数来进行字符串的录入。

    string str;
         string s;
         cout<<"请输入字符串:"<<endl; 
         do{
             getline(cin,s);
             str+=s;
             if(str[str.size()-1]=='#'){
                 break;
             }
            str+="
    ";
         }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 '
    ':
                       str.insert(i," ");
                    i++;
                    row++;
                    str.insert(i+1," ");
                       break;
             }         
          }

      之后再将处理过的字符串用空格相隔开,不比c#,c++没有字符串切割函数只能直接编写

    //字符串切割函数 
    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;  
    }

      而后得到的vector<string>遍历从map中找出对应值即可。

        //输出对应序列 
        for(int i = 0; i < str_list.size(); i++)
        {
    
            if (m.find(str_list[i]) != m.end())
                cout<<"	< "<<str_list[i] <<","<<m[str_list[i]]<<" >"<<endl;
            else if(AllisNum(str_list[i]))cout<<"	< "<<str_list[i] <<","<<11<<" >"<<endl;
            else cout<<"	< "<<str_list[i] <<","<<10<<" >"<<endl; 
    
    
        }

       最后附上完整代码

    #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;
    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;
    }
    
    
    
    int main() {
        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+="
    ";
         }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 '
    ':
                       str.insert(i," ");
                    i++;
                    row++;
                    str.insert(i+1," ");
                       break;
           }         
         }
         
         for(int i=0;i<str.size();i++){
             cout<<str[i];
         }
         cout<<endl;
        
        //切割空格 
         
        vector<string> str_list=split(str," ");
        
        //输出对应序列 
        for(int i = 0; i < str_list.size(); i++)
        {
    
            if (m.find(str_list[i]) != m.end())
                cout<<"	< "<<str_list[i] <<","<<m[str_list[i]]<<" >"<<endl;
            else if(AllisNum(str_list[i]))cout<<"	< "<<str_list[i] <<","<<11<<" >"<<endl;
            else cout<<"	< "<<str_list[i] <<","<<10<<" >"<<endl; 
    
    
        }
    
        return 0;
    }

     附上实验截图

  • 相关阅读:
    与众不同 LibreOJ
    清点人数 LibreOJ
    数星星 Stars LibreOJ
    树状数组 1 :单点修改,区间查询 Gym
    DDL与DML
    605. 种花问题
    Minimum Spanning Tree Gym
    最小生成树动态演示
    ssm框架添加分页
    ssm框架下的文件自动生成模板(简单方便)
  • 原文地址:https://www.cnblogs.com/renshenbenzuig/p/11656677.html
Copyright © 2011-2022 走看看