• 编译原理实验(算符优先文法)


    work.h
     1 #include<iostream>
     2 #include<stdlib.h>
     3 #include<stdio.h>
     4 #include<string.h>
     5 
     6 /*************STRUCT*************/
     7 #ifndef keyword
     8 #define keyword
     9 /*
    10  * 关键字结构,用于work2.cpp
    11  */
    12 struct KEYWORD_NODE{
    13     char val[100];
    14 };
    15 
    16 /*
    17  * 非终结符结构,用于work3.cpp
    18  */
    19 struct N_NODE{//非终结符
    20     char val;//
    21     int cnt;//产生式数目
    22     char ARR[30][30];
    23 };
    24 #endif
    25 
    26 /************FUNCTION************/
    27 void init();
    28 bool isLetter(char ch);
    29 void dealSourceCode();
    30 void morphologyAnalysis();
    31 void dealOperatorPrecedenceGrammar();
    32 using namespace std;



    init.cpp
     1 /***************************************************************\
     2  *Author:Hu Wenbiao
     3  *Created Time: Mon 15 Nov 2010 09:12:44 PM CST
     4  *File Name: init.cpp
     5  *Description:执行各文件所需的初始化操作
     6 \***************************************************************/
     7 //*========================*Head File*========================*\\
     8 
     9 #include"work.h"
    10 /*----------------------*Global Variable*----------------------*/
    11 //work2.cpp
    12 extern KEYWORD_NODE KEYWORD[30];
    13 //work3.cpp
    14 extern bool F[30][30],L[30][30];
    15 extern N_NODE N_ARRAY[30];
    16 extern char T_ARRAY[30];
    17 extern char PRECEDENCETABLE[30][30];
    18 //*=======================*Main Program*=======================*//
    19 
    20 /*
    21  * 设置关键字,用于work2.cpp的初始化
    22  */
    23 void setKeyword(int pos,string str){
    24     int p=0;
    25     while(str[p]){
    26         KEYWORD[pos].val[p]=str[p];
    27         p++;
    28     }
    29 }
    30 
    31 /*
    32  * 各文件的初始化
    33  */
    34 void init(){
    35 
    36     /*
    37      * work2.cpp
    38      */
    39     memset(KEYWORD,0,sizeof(KEYWORD));
    40     setKeyword(1,"const");
    41     setKeyword(2,"var");
    42     setKeyword(3,"procedure");
    43     setKeyword(4,"call");
    44     setKeyword(5,"begin");
    45     setKeyword(6,"end");
    46     setKeyword(7,"if");
    47     setKeyword(8,"then");
    48     setKeyword(9,"while");
    49     setKeyword(10,"do");
    50     setKeyword(11,"odd");
    51     setKeyword(12,"+");
    52     setKeyword(13,"-");
    53     setKeyword(14,"*");
    54     setKeyword(15,"/");
    55     setKeyword(16,">");
    56     setKeyword(17,">=");
    57     setKeyword(18,"<");
    58     setKeyword(19,"<=");
    59     setKeyword(20,"=");
    60     setKeyword(21,"<>");
    61     setKeyword(22,".");
    62     setKeyword(23,"(");
    63     setKeyword(24,")");
    64     setKeyword(25,",");
    65     setKeyword(26,";");
    66     setKeyword(27,":=");
    67 
    68     /*
    69      * work3.cpp
    70      */
    71     memset(N_ARRAY,0,sizeof(N_ARRAY));
    72     memset(T_ARRAY,0,sizeof(T_ARRAY));
    73     memset(F,0,sizeof(F));
    74     memset(L,0,sizeof(F));
    75     memset(PRECEDENCETABLE,0,sizeof(PRECEDENCETABLE));
    76 }
    work1.cpp
      1 /***************************************************************\ * Author: Hu Wenbiao
      2  * Created Time: Wed 06 Oct 2010 09:29:56 AM CST
      3  * File Name: work1.cpp
      4  * Description: 处理源代码格式,将多余空格去掉,换行,跳格改成空格
      5  * 去掉注释。
      6 \***************************************************************/
      7 //*========================*Head File*========================*\\
      8 
      9 #include "work.h"
     10 /*----------------------*Global Variable*----------------------*/
     11 
     12 //*=======================*Main Program*=======================*//
     13 
     14 /*
     15  * 处理空格和注释
     16  */
     17 void dealSourceCode(){
     18     bool space=false,multiply=false,slash=false,quote=false;
     19     char ch;
     20     int slash_multiply=0;
     21     while(scanf("%c",&ch)!=EOF){
     22 
     23         if(ch=='\\'){//转义符
     24             printf("\\");
     25             scanf("%c",&ch);
     26             printf("%c",ch);
     27             continue;
     28         }
     29 
     30         if(quote){//有引号
     31             //有printf("\"")这种情况
     32             //有printf("\\")这种情况
     33             //有printf("")这种情况
     34 
     35             if(ch=='\"'){//第三种情况
     36                 printf("\"");
     37                 quote=false;
     38                 continue;
     39             }
     40 
     41              /* 处理前两种情况*/
     42             char buf[10000];
     43             int p=0;
     44             buf[p++]=ch;
     45             while(scanf("%c",&buf[p])!=EOF&&(buf[p]!='\"'||(buf[p-1]=='\\'&&(p==1||buf[p-2]!='\\'))))p++;
     46             buf[p+1]='\0';
     47             printf("%s",buf);
     48             quote=false;
     49             continue;
     50         }
     51 
     52         if(ch==' '||ch=='\n'||ch=='\t'){//空格处理
     53             if(!space){
     54                 printf(" ");
     55                 space=true;
     56             }
     57             while(scanf("%c",&ch)!=EOF&&(ch==' '||ch=='\n'||ch=='\t'));
     58         }
     59 
     60         if(ch=='/'){//有可能是注释,注释处理
     61             scanf("%c",&ch);
     62 
     63             if(ch=='/'){//单行注释
     64                 while(scanf("%c",&ch)!=EOF&&ch!='\n');
     65             }
     66             else if(ch=='*'){//多行注释
     67                 slash_multiply=1;
     68                 slash=multiply=false;
     69                 while(slash_multiply){
     70                     if(scanf("%c",&ch)==EOF)break;//输入源文件语法错误
     71                     if(ch=='/'){
     72                         if(multiply){
     73                             slash_multiply--;
     74                             multiply=slash=false;
     75                         }
     76                         else
     77                           slash=true;
     78                     }
     79                     else if(ch=='*'){
     80                         if(slash){
     81                             slash_multiply++;
     82                             multiply=slash=false;
     83                         }
     84                         else
     85                           multiply=true;
     86                     }
     87                 }
     88             }
     89             else{//不是注释
     90                 printf("/");
     91                 if(ch==' '||ch=='\n'||ch=='\t')
     92                   space=true;
     93                 printf("%c",ch);
     94             }
     95         }
     96         else if(ch=='\"'){//发现第一个引号"\""
     97             printf("\"");
     98             quote=true;
     99         }
    100         else{//普通字符
    101             printf("%c",ch);
    102             space=false;
    103         }
    104     }
    105 }
    106 /*
    107 int main(){
    108     freopen("input.txt","r",stdin);
    109     freopen("output.txt","w",stdout);
    110     dealSourceCode();
    111     return 0;
    112 }
    113 */
    work2.cpp
    /***************************************************************\
     *Author:Hu Wenbiao
     *Created Time: Mon 15 Nov 2010 07:09:54 PM CST
     *File Name: work2.cpp
     *Description:词法分析器
    \**************************************************************
    */
    //*========================*Head File*========================*\\

    #include
    "work.h"
    /*----------------------*Global Variable*----------------------*/

    KEYWORD_NODE KEYWORD[
    30];
    //*=======================*Main Program*=======================*//

    bool isLetter(char ch){//判断是否是字母
        return (ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9');
    }

    bool isNumber(char ch){//判断是否是数字
        return ch>='0'&&ch<='9';
    }

    /*
     *判断是否是关键字,是则返回编码,否则返回28(标识符)
     
    */
    int getKeywordId(char* str,int s,int t){
        
    int i,p;
        
    for(i=0;i<12;i++){
            p
    =0;
            
    while (KEYWORD[i].val[p] && s+p<=&& 
                        KEYWORD[i].val[p]
    ==str[s+p]){
                p
    ++;
            }

            
    if(KEYWORD[i].val[p]=='\0' && s+p>t)
              
    return i;
        }
        
    return 28;//id
    }

    /*
     *判断是否是分隔符或操作符,是则返回编码,否则返回0(Error)
     
    */
    int getSepOrOprId(char* str,int s,int t){
        
    int i,p;
        
    for(i=12;i<28;i++){
            p
    =0;
            
    while (KEYWORD[i].val[p] && s<=&& 
                        KEYWORD[i].val[p]
    ==str[s]){
                p
    ++,s++;
            }

            
    if(KEYWORD[i].val[p]=='\0' && s>t)
              
    return i;
        }
        
    return 0;//Error
    }

    /*
     * 按要求的格式输出
     
    */
    void printOut(int id,char* str,int s,int t){
        printf(
    "%d: ",id);
        
    for(;s<=t;s++)
          printf(
    "%c",str[s]);
        printf(
    "\n");
    }

    /*
     * 是否是分隔符或操作符组成元素
     
    */
    bool isSepOrOpr(char ch){
        
    return ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='>'||ch=='<'||ch=='='
            
    ||ch=='.'||ch=='('||ch==')'||ch==','||ch==';'||ch==':';
    }

    /*
     * 对字符串str进行分析
     
    */
    void dealMorphology(char* str){
        
    int p=0,s,t;
        
    while(str[p]){
            s
    =t=p;
            
    if(isNumber(str[p])){//整型
                while(str[p]&&isNumber(str[p])) p++;
                t
    =p-1;
                
    if(isLetter(str[p])){//整型中有字母,错误
                    printOut(0,str,s,t);
                }
                
    else{//整型
                    printOut(29,str,s,t);
                }
            }
            
    else if(isLetter(str[p])){//标识符
                while(str[p]&&(isLetter(str[p])||isNumber(str[p]))) p++;
                t
    =p-1;
                printOut(getKeywordId(str,s,t),str,s,t);
            }
            
    else if(isSepOrOpr(str[p])){//分隔符或操作符
                while(str[p] && isSepOrOpr(str[p])) p++;
                t
    =p-1;
                printOut(getSepOrOprId(str,s,t),str,s,t);
            }
            
    else if(s==t&&str[s]=='\n'){
                p
    ++;
                
    continue;
            }
            
    else{
                printf(
    "ERROR:\n");
                p
    ++;
            }
        }
    }

    /*
     * 将dealSourceCode()处理后代码按空格进行分成若干字符串进行分别处理
     
    */
    void morphologyAnalysis(){
        
    char str[1000]; int p; bool flag=true;
        
    while(flag){
            p
    =0;
            
    while((flag=(scanf("%c",&str[p])!=EOF))&&str[p]!=' ') p++;
            str[p]
    =0;
            dealMorphology(str);
        }
    }
    work3.cpp
      1 /***************************************************************\
      2  *Author:Hu Wenbiao
      3  *Created Time: Tue 16 Nov 2010 05:11:20 PM CST
      4  *File Name: work3.cpp
      5  *Description:算符优先文法
      6  * 1.非终结符和终结符的编号(id)都是它们在数组中的下标
      7  * 2.算法只能处理单字符的非终结符和终结符(大写字母为非终结符,
      8  * 其他为终结符)
      9  * 3.处理的表达式必须含有:=且其左边不能含有运算符,否则会被作为
     10  * 标识符的一部分处理
     11  * 4.表达式的标识符可以是字符串如:aa=bb+cc+dd*eef
     12  * 5.处理表达式时先将标识符转化为i(因为文法中只用i表示标识符),
     13  * 标识符的名称在NAME中记录,另外产生的中间标识符(如T1、E2)
     14  * 的名称也在NAME中记录,名称的id为其下标,NAME[0]记录等号“:=”
     15  * 左边的那个标识符,对于其他的标识符若id为0表示出错
     16 \***************************************************************/
     17 //*========================*Head File*========================*\\
     18 
     19 #include<stack>
     20 #include"work.h"
     21 
     22 /*----------------------*Global Variable*----------------------*/
     23 
     24 N_NODE N_ARRAY[30];//非终端符数组(下标从1开始)
     25 char T_ARRAY[30];//终端符数组(下标从1开始)
     26 bool F[30][30],L[30][30];//F[i][j]表示id为j的终结符是否属于
     27                         //id为i的非终结符的FIRSTVT,L相同。
     28 stack<pair<int,int> > S;//用于求FIRSTVT和LASTVT
     29 char PRECEDENCETABLE[30][30];//算符优先关系表
     30 char NAME[100][10];//用来存放标识符名称,NAME[i]表示id为i的标识符
     31 int name_foot[100];//分配中间标识符的下标,如T1中的1
     32 //*=======================*Main Program*=======================*//
     33 
     34 int getTnodeId(char ch){//返回终端符编码(下标),不存在返回0
     35     int p=1;
     36     while(T_ARRAY[p]&&T_ARRAY[p]!=ch) p++;
     37     if(T_ARRAY[p])
     38         return p;
     39     else
     40         return 0;
     41 }
     42 
     43 int getNnodeId(char ch){//返回非终端符编码(下标),不存在返回0
     44     int pos=1;
     45     while(N_ARRAY[pos].val && N_ARRAY[pos].val!=ch) pos++;
     46     if(N_ARRAY[pos].val)
     47       return pos;
     48     else
     49       return 0;
     50 }
     51 
     52 int getNameId(char* str,int s,int t){//给str[s]~str[t]分配位置,并返回id
     53     int ptr=0;
     54     while(NAME[ptr][0])ptr++;
     55 
     56     for(int i=0;s+i<=t;i++)
     57       NAME[ptr][i]=str[s+i];
     58 
     59     return ptr;
     60 }
     61 
     62 int getNameId(char ch){//同上,重载
     63     name_foot[ch]++;
     64     int ptr=0;
     65     while(NAME[ptr][0])ptr++;
     66 
     67     NAME[ptr][0]=ch;
     68     NAME[ptr][1]=char(name_foot[ch]+'0');
     69 
     70     return ptr;
     71 }
     72 
     73 void insertN_ARRAY(char val,char* str,int s,int t){//增加非终结符
     74     int pos=1;
     75     while(N_ARRAY[pos].val&&N_ARRAY[pos].val!=val) pos++;
     76     N_ARRAY[pos].val=val;
     77     int cnt=N_ARRAY[pos].cnt,p=0;
     78     for(;s<=t;p++,s++){
     79         N_ARRAY[pos].ARR[cnt][p]=str[s];
     80     }
     81     N_ARRAY[pos].cnt++;
     82 }
     83 
     84 void insertT_ARRAY(char ch){//增加终结符
     85     int p=1;
     86     while(T_ARRAY[p]) p++;
     87     T_ARRAY[p]=ch;
     88 }
     89 
     90 bool isNnode(char ch){//判断是否是非终结符
     91     return ch>='A'&&ch<='Z';
     92 }
     93 
     94 /*
     95  * 求解所有非终结符的FIRSTVT
     96  */
     97 
     98 void getFIRSTVT(){
     99     pair<int,int> cur;//cur.first是非终结符的id,cur.second是终结符的id
    100     int nr_Nnode=1;
    101     while(N_ARRAY[nr_Nnode].val) nr_Nnode++;//其实nr_Nnode=(nr of Nnode)+1
    102     for(int i=1;i<nr_Nnode;i++){//每个非终结符
    103         for(int j=0;j<N_ARRAY[i].cnt;j++){//每个产生式
    104             if(!isNnode(N_ARRAY[i].ARR[j][0])){//N_ARRAY[i].ARR[j][0]是终结符
    105                 int id_Tnode=getTnodeId(N_ARRAY[i].ARR[j][0]);
    106                 if(F[i][id_Tnode])continue;
    107                 F[i][id_Tnode]=true;
    108                 S.push(pair<int,int>(i,id_Tnode));
    109             }
    110             //N_ARRAY[i].ARR[j][1]是终结符
    111             else if(N_ARRAY[i].ARR[j][1&& !isNnode(N_ARRAY[i].ARR[j][1])){
    112                 int id_Tnode=getTnodeId(N_ARRAY[i].ARR[j][1]);
    113                 if(F[i][id_Tnode])continue;
    114                 F[i][id_Tnode]=true;
    115                 S.push(pair<int,int>(i,id_Tnode));
    116             }
    117         }
    118     }
    119     while(!S.empty()){
    120         cur=S.top(),S.pop();
    121         char curNnodeVal=N_ARRAY[cur.first].val;
    122 
    123         for(int i=1;i<nr_Nnode;i++){
    124             if(F[i][cur.second])continue;//cur.second已经属于FIRSTVT(i)
    125             for(int j=0;j<N_ARRAY[i].cnt;j++){//查找哪个产生式右边以curNnodeVal为首
    126                 if(N_ARRAY[i].ARR[j][0]==curNnodeVal){
    127                     F[i][cur.second]=true;
    128                     S.push(pair<int,int>(i,cur.second));
    129                     break;
    130                 }
    131             }
    132         }
    133     }
    134     /*输出FIRSTVT*/
    135     for(int i=1;i<nr_Nnode;i++){
    136         for(int j=1;j<30;j++){
    137             if(F[i][j]){
    138                 printf("FIRSTVT(%c): {",N_ARRAY[i].val);
    139                 while(j<30){
    140                     if(F[i][j])
    141                       printf("%c ",T_ARRAY[j]);
    142                     j++;
    143                 }
    144                 printf("}\n");
    145             }
    146         }
    147     }
    148     printf("\n");
    149     /**/
    150 }
    151 
    152 /*
    153  * 求解所有非终结符的LASTVT
    154  */
    155 
    156 void getLASTVT(){
    157     pair<int,int> cur;
    158     int nr_Nnode=1;
    159     while(N_ARRAY[nr_Nnode].val) nr_Nnode++;
    160     for(int i=1;i<nr_Nnode;i++){
    161         for(int j=0;j<N_ARRAY[i].cnt;j++){
    162             int ptr=0;
    163             while(N_ARRAY[i].ARR[j][ptr]) ptr++;
    164             ptr--;
    165             if(!isNnode(N_ARRAY[i].ARR[j][ptr])){
    166                 int id_Tnode=getTnodeId(N_ARRAY[i].ARR[j][ptr]);
    167                 if(L[i][id_Tnode])continue;
    168                 L[i][id_Tnode]=true;
    169                 S.push(pair<int,int>(i,id_Tnode));
    170             }
    171             else if(ptr>0&&!isNnode(N_ARRAY[i].ARR[j][ptr-1])){
    172                 int id_Tnode=getTnodeId(N_ARRAY[i].ARR[j][ptr-1]);
    173                 if(L[i][id_Tnode])continue;
    174                 L[i][id_Tnode]=true;
    175                 S.push(pair<int,int>(i,id_Tnode));
    176             }
    177         }
    178     }
    179     while(!S.empty()){
    180         cur=S.top(),S.pop();
    181         char curNnodeVal=N_ARRAY[cur.first].val;
    182 
    183         for(int i=1;i<nr_Nnode;i++){
    184             for(int j=0;j<N_ARRAY[i].cnt;j++){
    185                 int ptr=0;
    186                 while(N_ARRAY[i].ARR[j][ptr]) ptr++;
    187                 ptr--;
    188                 if(N_ARRAY[i].ARR[j][ptr]==curNnodeVal &&
    189                         !L[i][cur.second]){
    190                     L[i][cur.second]=true;
    191                     S.push(pair<int,int>(i,cur.second));
    192                     break;
    193                 }
    194             }
    195         }
    196     }
    197     /*输出LASTVT*/
    198     for(int i=1;i<nr_Nnode;i++){
    199         for(int j=1;j<30;j++){
    200             if(L[i][j]){
    201                 printf("LASTVT(%c): {",N_ARRAY[i].val);
    202                 while(j<30){
    203                     if(L[i][j])
    204                       printf("%c ",T_ARRAY[j]);
    205                     j++;
    206                 }
    207                 printf("}\n");
    208             }
    209         }
    210     }
    211     printf("\n");
    212     /**/
    213 }
    214 
    215 /*
    216  * 求算符优先表
    217  */
    218 
    219 void getPrecedenceTable(){
    220     int nr_Nnode=1,nr_Tnode=1;
    221     while(N_ARRAY[nr_Nnode].val) nr_Nnode++;
    222     while(T_ARRAY[nr_Tnode]) nr_Tnode++;
    223 
    224     /**关于#的比较**/
    225     int id_sharp=getTnodeId('#');
    226     for(int j=1;j<nr_Tnode;j++){
    227         if(F[1][j]){
    228             PRECEDENCETABLE[id_sharp][j]='<';
    229         }
    230         if(L[1][j]){
    231             PRECEDENCETABLE[j][id_sharp]='>';
    232         }
    233     }
    234 
    235     /***************/
    236 
    237     for(int i=1;i<nr_Nnode;i++){//每个非终结符
    238         for(int j=0;j<N_ARRAY[i].cnt;j++){//每个产生式
    239             int tail=0;
    240             while(N_ARRAY[i].ARR[j][tail]) tail++;
    241             tail--;//最后一位(非零)
    242             for(int p=0;p<tail;p++){
    243                 //tt
    244                 if(!isNnode(N_ARRAY[i].ARR[j][p]) && 
    245                             !isNnode(N_ARRAY[i].ARR[j][p+1])){
    246                     int id1=getTnodeId(N_ARRAY[i].ARR[j][p]);
    247                     int id2=getTnodeId(N_ARRAY[i].ARR[j][p+1]);
    248                     if(PRECEDENCETABLE[id1][id2]){
    249                         printf("ERROR:不是算符优先文法!");
    250                         exit(EXIT_FAILURE);
    251                     }
    252                     PRECEDENCETABLE[id1][id2]='=';
    253                 }
    254                 //tNt
    255                 if(p<=tail-2&&!isNnode(N_ARRAY[i].ARR[j][p])&&
    256                             isNnode(N_ARRAY[i].ARR[j][p+1])&&
    257                             !isNnode(N_ARRAY[i].ARR[j][p+2])){
    258                     int id1=getTnodeId(N_ARRAY[i].ARR[j][p]);
    259                     int id2=getTnodeId(N_ARRAY[i].ARR[j][p+2]);
    260                     if(PRECEDENCETABLE[id1][id2]){
    261                         printf("ERROR:不是算符优先文法!");
    262                         exit(EXIT_FAILURE);
    263                     }
    264                     PRECEDENCETABLE[id1][id2]='=';
    265                 }
    266                 //tN
    267                 if(!isNnode(N_ARRAY[i].ARR[j][p]) &&
    268                             isNnode(N_ARRAY[i].ARR[j][p+1])){
    269                     int id1=getTnodeId(N_ARRAY[i].ARR[j][p]);
    270                     int id_Nnode=getNnodeId(N_ARRAY[i].ARR[j][p+1]);
    271                     int id2=1;
    272                     while(T_ARRAY[id2]){
    273                         if(F[id_Nnode][id2]){
    274                             if(PRECEDENCETABLE[id1][id2]){
    275                                 printf("ERROR:不是算符优先文法!");
    276                                 exit(EXIT_FAILURE);
    277                             }
    278                             PRECEDENCETABLE[id1][id2]='<';
    279                         }
    280                         id2 ++;
    281                     }
    282                 }
    283                 //Nt
    284                 if(isNnode(N_ARRAY[i].ARR[j][p]) &&
    285                                 !isNnode(N_ARRAY[i].ARR[j][p+1])){
    286                     int id_Nnode=getNnodeId(N_ARRAY[i].ARR[j][p]);
    287                     int id2=getTnodeId(N_ARRAY[i].ARR[j][p+1]);
    288                     int id1=1;
    289                     while(T_ARRAY[id1]){
    290                         if(L[id_Nnode][id1]){
    291                             if(PRECEDENCETABLE[id1][id2]){
    292                                 printf("ERROR:不是算符优先方法!");
    293                                 exit(EXIT_FAILURE);
    294                             }
    295                             PRECEDENCETABLE[id1][id2]='>';
    296                         }
    297                         id1++;
    298                     }
    299                 }
    300             }
    301         }
    302     }
    303     //////输出优先表////////
    304     cout<<"  ";
    305     for(int i=1;i<nr_Tnode;i++){
    306         cout<<T_ARRAY[i]<<" ";
    307     }
    308     cout<<endl;
    309     for(int i=1;i<nr_Tnode;i++){
    310         cout<<T_ARRAY[i]<<" ";
    311         for(int j=1;j<nr_Tnode;j++){
    312             if(PRECEDENCETABLE[i][j])
    313               cout<<PRECEDENCETABLE[i][j]<<" ";
    314             else
    315               cout<<"  ";
    316         }
    317         cout<<endl;
    318     }
    319     cout<<endl;
    320     //////////////////////
    321 }
    322 
    323 /*
    324  * 比较ARR[s]~ARR[t]中的id和str中的符号是否匹配
    325  * 其中非终结符的id是取负值的,比较时也不比较非
    326  * 终结符是否相同,只要求终结符相同,非终结符相
    327  * 对应就返回true
    328  */
    329 
    330 bool cmpIdNodeVal(pair<int,int>* ARR,int s,int t,char* str){
    331     int ptr=0,id;
    332     while(s<=&& str[ptr]){
    333         if(isNnode(str[ptr])){//非终结符
    334             if(ARR[s].first>0)
    335               return false;
    336         }
    337         else if(ARR[s].first!=getTnodeId(str[ptr]))
    338           return false;
    339         ptr++;
    340         s++;
    341     }
    342     if(s<=|| str[ptr])
    343       return false;
    344     return true;
    345 }
    346 
    347 /*
    348  * 将STACK[s]~STACK[t]归约,返回归约后的非终结符的值,
    349  * 分配并由name返回非终结符的名称id
    350  */
    351 
    352 char reduction(pair<int,int>* STACK,int s,int t,int& name){
    353     int i=1;
    354     while(N_ARRAY[i].val){
    355         for(int j=0;j<N_ARRAY[i].cnt;j++){
    356             if(cmpIdNodeVal(STACK,s,t,N_ARRAY[i].ARR[j])){//查找成功
    357 
    358 
    359                 ///输出///
    360 
    361                 if(s==t&&STACK[s].first>0){// 1
    362                     name=STACK[s].second;
    363                 }
    364 
    365                 if(s+1==t){// 2
    366                         name=getNameId(N_ARRAY[i].val);
    367                     if(STACK[s].first>0){
    368                         printf("(%c,_,%s,%s)\n",
    369                                     T_ARRAY[STACK[s].first],NAME[STACK[t].second],NAME[name]);
    370                     }
    371                     else{
    372                         printf("(%c,%s,_,%s)\n",
    373                                     T_ARRAY[STACK[t].first],NAME[STACK[s].second],NAME[name]);
    374                     }
    375                 }
    376                 if(s+2==t){// 3
    377                     if(STACK[s].first>0&&STACK[t].first>0){//(T)这种情况
    378                         name=STACK[s+1].second;
    379                     }
    380                     else{
    381                         name=getNameId(N_ARRAY[i].val);
    382                         printf("(%c,%s,%s,%s)\n",T_ARRAY[STACK[s+1].first],
    383                                 NAME[STACK[s].second],NAME[STACK[t].second],NAME[name]);
    384                     }
    385                 }
    386 
    387                 //////////
    388 
    389                 return N_ARRAY[i].val;
    390             }
    391         }
    392         i++;
    393     }
    394     return 0;
    395 }
    396 
    397 /*
    398  * 核心函数,处理传入的单句表达式,要求表达式必须为
    399  * abc:=x*y+zuv 的形式,即必须有:=号且其左边不能有运
    400  * 算符,否则会被当作标识符的一部分处理
    401  */
    402 
    403 void operatorPrecedenceParser(char* str0){
    404     ///将空格去掉///
    405     int s=0,t=0,p;
    406     while(str0[t]){
    407         if(str0[t]!=' '){
    408             str0[s]=str0[t];
    409             s++;
    410         }
    411         t++;
    412     }
    413     str0[s]=0;
    414 
    415     ///将str0转换成str,由文法符号表示///
    416     char str[1000];
    417     int str_name[1000];//str_name[i]是str[i]的名称,当str[i]为操作符时无意义
    418 
    419     memset(NAME,0,sizeof(NAME));
    420     memset(name_foot,0,sizeof(name_foot));
    421 
    422     s=0;
    423     while(str0[s]&&str0[s]!=':')s++;
    424     if(str0[s]==0){
    425         printf("ERROR:表达式不合法\n");
    426         return;
    427     }
    428     getNameId(str0,0,s-1);//放在NAME[0],在下面进行归约时标识符id为0时表示出错
    429     s+=2;// :=右边首字符
    430     p=0;
    431     while(str0[s]){
    432         if(isLetter(str0[s])){//标识符
    433             t=s;
    434             while(str0[t]&&isLetter(str0[t]))t++;
    435             str[p]='i';
    436             str_name[p]=getNameId(str0,s,t-1);
    437             s=t,p++;
    438         }
    439         else{//操作符
    440             str[p]=str0[s];
    441             s++,p++;
    442         }
    443     }
    444     str[p]='#';//结束符
    445     str[p+1]=0;
    446     //////////////
    447     
    448     pair<int,int> STACK[1000];//STACK[i].first保存id,正数是Tnode,负数是Nnode
    449                               //STACK[i].second保存标识符id 
    450     int k=0,j;STACK[k].first=getTnodeId('#');//STACK[k]栈顶
    451     p=0;//str[p]当前字符
    452     int q,cid;
    453 
    454     while(str[p]){
    455         cid=getTnodeId(str[p]);//当前字符id
    456 
    457         if(STACK[k].first>0) j=k;
    458         else j=k-1;
    459 
    460         while(PRECEDENCETABLE[STACK[j].first][cid]=='>'){
    461             do{
    462                 q=STACK[j].first;
    463                 j=STACK[j-1].first>0?j-1:j-2;
    464             }while(PRECEDENCETABLE[STACK[j].first][q]=='=');
    465 
    466             int tmp_name=0;
    467             char tmp=reduction(STACK,j+1,k,tmp_name);//归约
    468             k=j+1;
    469             STACK[k].first=-getNnodeId(tmp);
    470             if(tmp_name)
    471               STACK[k].second=tmp_name;
    472             else // name为0表示错误
    473               printf("ERROR:tmp_name,when reduction");
    474         }
    475         if(PRECEDENCETABLE[STACK[j].first][cid]=='<' ||
    476                     PRECEDENCETABLE[STACK[j].first][cid]=='='){
    477             k++;
    478             STACK[k].first=cid,STACK[k].second=str_name[p];
    479             p++;
    480         }
    481         else{
    482             if(str[p]=='#'&&j==0){
    483 
    484                 //给:=左边的符号赋值
    485                 printf("(:=,%s,_,%s)\n",NAME[STACK[1].second],NAME[0]);
    486 
    487                 printf("Done!\n");
    488                 return;
    489             }
    490             else{
    491                 printf("ERROR:归约时出错!");
    492                 exit(-1);
    493             }
    494         }
    495     }
    496     
    497 }
    498 
    499 /*
    500  * 读入文法
    501  */
    502 
    503 void readGrammar(){
    504     char str[30];
    505     
    506     while(scanf("%[^\n]%*c",str)!=EOF){
    507         ///将空格去掉///
    508         int s=0,t=0;
    509         while(str[t]){
    510             if(str[t]!=' '){
    511                 str[s]=str[t];
    512                 s++;
    513             }
    514             t++;
    515         }
    516         str[s]=0;
    517         //////////////
    518 
    519         if(str[0]<'A'||str[0]>'Z'){//检查首字母是否大写
    520             printf("ERROR:首字母不是非终结符\n");
    521             continue;
    522         }
    523         int p=0;
    524         while(str[p]&&(str[p]!='-'||str[p+1]!='>')) p++;//检查是否有符号"->"
    525         if(!str[p]){
    526             printf("ERROR:不是产生式\n");
    527             continue;
    528         }
    529         p+=2;
    530         ///找终结符///
    531         t=p;
    532         while(str[t]){
    533             if(!isNnode(str[t])&&str[t]!='|')
    534               insertT_ARRAY(str[t]);
    535             t++;
    536         }
    537         //////////////
    538 
    539         ///找产生式///
    540         while(str[p]){
    541             s=t=p; 
    542             while(str[p]&&str[p]!='|') p++;
    543             if(str[p]){
    544                 t=p-1,p++;
    545             }
    546             else
    547                 t=p;
    548 
    549             insertN_ARRAY(str[0],str,s,t);
    550         }
    551         //////////////
    552     }
    553     insertT_ARRAY('#');//加入终结符'#'
    554 }
    555 
    556 /*
    557  * 算符优先文法主函数
    558  */
    559 
    560 void dealOperatorPrecedenceGrammar(){
    561     freopen("input31","r",stdin);
    562     freopen("output3","w",stdout);
    563     readGrammar();
    564     getFIRSTVT();
    565     getLASTVT();
    566     getPrecedenceTable();
    567 
    568     freopen("input32","r",stdin);
    569     char str[100];
    570     while(scanf("%[^\n]%*c",str)!=EOF){
    571         operatorPrecedenceParser(str);
    572     }
    573 }
    work.cpp
     1 /***************************************************************\
     2  *Author:Hu Wenbiao
     3  *Created Time: Mon 15 Nov 2010 09:58:46 PM CST
     4  *File Name: work.cpp
     5  *Description:主函数
     6 \***************************************************************/
     7 //*========================*Head File*========================*\\
     8 
     9 #include"work.h"
    10 /*----------------------*Global Variable*----------------------*/
    11 
    12 //*=======================*Main Program*=======================*//
    13 
    14 int main(){
    15     init();
    16     freopen("input1","r",stdin);
    17     freopen("output1","w",stdout);
    18     dealSourceCode();
    19     freopen("output1","r",stdin);
    20     freopen("output2","w",stdout);
    21     morphologyAnalysis();
    22 
    23     dealOperatorPrecedenceGrammar();//输入的设置在该函数中
    24 }


     


  • 相关阅读:
    Java实体书写规范
    Mybatis配置中遇到的问题和问题分析
    Ubuntu下eclipse的Extjs提示插件安装
    Ubuntu中root用户和user用户的相互切换
    ubuntu下启动和关闭tomcat的简单方法
    Ubuntu上安装Maven Eclipse以及配置
    IE8兼容<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
    心情
    更改Eclipse下Tomcat的部署目录
    Tomcat:IOException while loading persisted sessions: java.io.EOFException 解决
  • 原文地址:https://www.cnblogs.com/Open_Source/p/1923797.html
Copyright © 2020-2023  润新知