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

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 }


 

 


 

 

posted @ 2011-01-01 17:04  open source  阅读(1426)  评论(0编辑  收藏