当前位置:网站首页>Compilation principle first set follow set select set prediction analysis table to judge whether the symbol string conforms to the grammar definition (with source code!!!)

Compilation principle first set follow set select set prediction analysis table to judge whether the symbol string conforms to the grammar definition (with source code!!!)

2022-04-23 17:41:00 Hui Gan Wang

Compiler principle

The original

   I want to compile here into a new series , Mainly related to my course , But it has nothing to do with homework .

   Only speak Lexical analysis and Grammar analysis . Because most colleges and universities focus on learning here , According to the class hours for compilation , What I mentioned later is just a pass .

   This series has Explain , note , Source code , exercises , It can be regarded as a quick course .

 

 

Experiment two ( Construction of syntax analysis program based on predictive analysis method )

 

1. Experimental content

 

2. Experimental instruction

 

 

 

 

 

 

 

 

3. Code implementation

  1 #include <iostream>
  2 #include <iomanip>
  3 #include <string>
  4 #include <vector>
  5 #include <set>
  6 #include<stdlib.h>
  7 #include<string.h>
  8 #define maxsize 100
  9 
 10 using namespace std;
 11 
 12 struct node {  //  Production data structure 
 13     char left;
 14     string right;
 15 };
 16 
 17 class Base {
 18     protected:
 19         int T;                            //  Number of production 
 20         node production[maxsize];         //  Production set 
 21     
 22         set<char> firstSet[maxsize];      // First Set 
 23         set<char> followSet[maxsize];      // Follow Set 
 24         vector<char> terminalNoEmpty;     //  Go to $( empty ) Terminator for 
 25         vector<char> terminal;          //  Terminator 
 26         vector<char> nonterminal;          //  non-terminal 
 27     
 28         bool isNonterminal(char c);
 29         int getIndex(char target);      //  get target Subscript in Terminator set 
 30         int getNIndex(char target);      //  get target Subscript in non terminator set 
 31         void getFirst(char target);      //  obtain First(target)
 32         void getFollow(char target);      //  obtain Follow(target)
 33     
 34     public:
 35         Base() {};
 36     
 37         void inputAndSolve();  //  Process and find First and Follow Set 
 38         void displayFirstAndFollow();  //  Output First and Follow Set 
 39 
 40 };
 41 
 42 bool Base::isNonterminal(char c) { //  Judge c Whether it is a non Terminator 
 43     if (c >= 'A' && c <= 'Z')
 44         return true;
 45     return false;
 46 }
 47 int Base::getNIndex(char target) {  //  get target Subscript in non terminator set 
 48     for (int i = 0; i<nonterminal.size(); i++) {
 49         if (target == nonterminal[i])
 50             return i;
 51     }
 52     return -1;
 53 }
 54 int Base::getIndex(char target) {  //  get target Subscript in Terminator set 
 55     for (int i = 0; i<terminalNoEmpty.size(); i++) {
 56         if (target == terminalNoEmpty[i])
 57             return i;
 58     }
 59     return -1;
 60 }
 61 
 62 void Base::getFirst(char target) {  //  seek FIRST(target)
 63     int isEmpty = 0;
 64     int targetIndex = getNIndex(target);  // Find the non terminator subscript  
 65     for (int i = 0; i < T; i++) { // Traverse every production  
 66         if (production[i].left == target) {  //  Match the left part of the production 
 67             if (!isNonterminal(production[i].right[0])) {  //  For terminators , Directly to join first
 68                 firstSet[targetIndex].insert(production[i].right[0]);  // Store the Terminator  ( The first 1)
 69             }
 70             else {
 71                 char Yj = production[i].right[0];
 72                 getFirst(Yj);// Yj Yes no terminator , recursive   Find out first FIRST(Yj)
 73                 
 74                 set<char>::iterator it;
 75                 int YjIndex = getNIndex(Yj);  // Find the non terminator subscript  
 76                 for (it = firstSet[YjIndex].begin(); it != firstSet[YjIndex].end(); it++) {  
 77                     if (*it == '$') {  //  Traversal view FIRST(Yj) Whether contains '$'( Can produce empty )
 78                         isEmpty = 1;
 79                         firstSet[getNIndex(target)].insert('$');
 80                     }
 81                     else
 82                         firstSet[targetIndex].insert(*it); // take FIRST(Yj) Middle Africa $ join FIRST(X)
 83                 }
 84             }
 85         }
 86     }
 87 }
 88 
 89 void Base::getFollow(char target) {  //  seek FOLLOW(target)
 90     int targetIndex = getNIndex(target);
 91     for (int i = 0; i < T; i++) { // Every production  
 92         int index = -1;
 93         int len = production[i].right.length();
 94         for (int j = 0; j < len; j++) {  //  seek target Position in production index
 95             if (production[i].right[j] == target) {
 96                 index = j;  // Horizontal coordinates  
 97                 break;
 98             }
 99         }
100         if (index != -1 && index < len - 1) {  //  find target Position in production index    It means there's something behind it  
101                                                //  There is A->αBβ,  take FIRST(β) In addition to empty $ All other than FOLLOW(B) in 
102                                                //  here B Corresponding target, β Corresponding nxt
103             char nxt = production[i].right[index + 1];  // Extract the following symbol  
104             if (!isNonterminal(nxt)) {  // β It's the terminator  FIRST(β)=β, Directly inserted into the β
105                 followSet[targetIndex].insert(nxt);
106             }
107             else {  // β Yes no terminator 
108                 int hasEmpty = 0;
109                 set<char>::iterator it;
110                 int nxtIndex = getNIndex(nxt);  //  Insert FIRST(β) In addition to empty $ All but     Find non terminator location  
111                 for (it = firstSet[nxtIndex].begin(); it != firstSet[nxtIndex].end(); it++) {
112                     if (*it == '$')
113                         hasEmpty = 1;
114                     else
115                         followSet[targetIndex].insert(*it);
116                 }
117 
118                 if (hasEmpty && production[i].left != target) { //  There is A->αBβ And FIRST(β)->$
119                                                              // FOLLOW(A) Put it in FOLLOW(B) in 
120                     getFollow(production[i].left);
121                     set<char>::iterator it;
122                     char tmp = production[i].left;
123                     int tmpIndex = getNIndex(tmp);
124                     for (it = followSet[tmpIndex].begin(); it != followSet[tmpIndex].end(); it++)
125                         followSet[targetIndex].insert(*it);
126                 }
127             }
128         }
129         else if (index != -1 && index == len - 1 && target != production[i].left) {  //  There is no... After the description   There is A->αB ,FOLLOW(A) Put it in FOLLOW(B) in 
130             getFollow(production[i].left);
131             set<char>::iterator it;
132             char tmp = production[i].left;
133             int tmpIndex = getNIndex(tmp);
134             for (it = followSet[tmpIndex].begin(); it != followSet[tmpIndex].end(); it++)
135                 followSet[targetIndex].insert(*it);
136         }
137     }
138 }
139 
140 void Base::inputAndSolve() {  //  Process and find First and Follow Set 
141     string s;
142     int i=0;
143     cout << " The number of production expressions entered :" << endl;
144     cin >> T;
145     cout << " Input production :" << endl;
146     for (int index = 0; index < T; index++) {  //  Process every production 
147         cin >> s;
148         production[index].left = s[0];  //  The left part of production 
149         for ( i = 3; i < s.length(); i++) //  The right part of production 
150             production[index].right += s[i];
151 
152         for (i = 0; i < s.length(); i++) {      //  Store all terminators and non terminators 
153             if (i == 1 || i == 2) 
154                 continue;      //  Skip generating symbols ->
155             if (isNonterminal(s[i])) {  // Insert a non Terminator 
156                 int flag = 0;  //  Whether to find the character  ( If you have it, you won't press it into the stack ) 
157                 for (int j = 0; j < nonterminal.size(); j++) {
158                     if (nonterminal[j] == s[i]) {
159                         flag = 1;
160                         break;
161                     }
162                 }
163                 if (!flag) nonterminal.push_back(s[i]);
164             }
165             else {                       // Insert a Terminator 
166                 int flag = 0;
167                 for (int j = 0; j < terminal.size(); j++) {
168                     if (terminal[j] == s[i]) {
169                         flag = 1;
170                         break;
171                     }
172                 }
173                 if (!flag) terminal.push_back(s[i]);
174             }
175         }
176     }
177     terminal.push_back('#');
178 
179     for ( i = 0; i < terminal.size(); i++) { //  No storage $ Terminator of symbol 
180         if (terminal[i] != '$')
181             terminalNoEmpty.push_back(terminal[i]);
182     }
183 
184     //  get first Set 
185     for ( i = 0; i < nonterminal.size(); i++) {
186         getFirst(nonterminal[i]);
187     }
188 
189     //  get follow Set 
190     for ( i = 0; i < nonterminal.size(); i++) {
191         if (i == 0)  //  Start symbol ,  First add the ending symbol 
192             followSet[0].insert('#');
193         getFollow(nonterminal[i]);
194     }
195 }
196 
197 void Base::displayFirstAndFollow() {  //  Output First and Follow Set 
198     int i=0;
199     cout << "FIRST aggregate " << endl;
200     for (i = 0; i<nonterminal.size(); i++) {
201         cout << nonterminal[i] << ": ";
202         set<char>::iterator it;
203         for (it = firstSet[i].begin(); it != firstSet[i].end(); it++)
204             cout << *it << "  ";
205         cout << endl;
206     }
207     cout << endl;
208 
209     cout << "FOLLOW aggregate " << endl;
210     for (i = 0; i<nonterminal.size(); i++) {
211         cout << nonterminal[i] << ": ";
212         set<char>::iterator it;
213         for (it = followSet[i].begin(); it != followSet[i].end(); it++)
214             cout << *it << "  ";
215         cout << endl;
216     }
217     cout << endl;
218 }
219 
220 class LL1 : public Base {
221 private:
222     vector<char> analyStack; //  Analysis of the stack 
223     vector<char> leftExpr;  //  Remaining input string 
224     int tableMap[100][100];  //  Forecast table 
225 
226 public:
227     LL1();
228 
229     void getTable(); //  Generate forecast table 
230     void printPredictTable();  //  Output forecast table 
231     void analyExpression(string s);  //  Analyze input statements s
232     void getResult(); //  Comprehensive treatment 
233 };
234 LL1::LL1() {
235     memset(tableMap, -1, sizeof(tableMap));
236 }
237 
238 void LL1::getTable() {   // Get the forecast table  
239     for (int index = 0; index < T; index++) {//   Ergodic production      For each production ( Number index):A->α
240         int row = getNIndex(production[index].left);  //  Left   Subscript  
241         int emptyCount = 0;
242         char tmp = production[index].right[0];  
243         if (!isNonterminal(tmp)) { // tmp It's the terminator 
244             if (tmp != '$')
245                 tableMap[row][getIndex(tmp)] = index;
246             if (tmp == '$')
247                 emptyCount++;
248         }
249         else {  // tmp Yes no terminator 
250             set<char>::iterator it;
251             int tmpIndex = getNIndex(tmp);  // Find non terminator subscript  
252             //  Yes FIRST(tmp) Every terminator in a, take i Join in (A, a) in 
253             for (it = firstSet[tmpIndex].begin(); it != firstSet[tmpIndex].end(); it++) {
254                 tableMap[row][getIndex(*it)] = index;
255             }
256             if (firstSet[tmpIndex].count('$') != 0)     // 2)  If empty $ stay FIRST(tmp) in , Continue to look at α The next symbol in 
257                 emptyCount++;
258         }
259 
260         // 2)  If empty $ stay FIRST(α) in , Yes FOLLOW(A) Each terminator or in the b, take i Join in (A,b) in 
261         if (emptyCount == production[index].right.size()) {  //  The right part of production is empty  
262             set<char>::iterator  it;
263             for (it = followSet[row].begin(); it != followSet[row].end(); it++) {
264                 tableMap[row][getIndex(*it)] = index;       // Put the left follow Put it in the forecast table  
265             }
266         }
267     }
268 }
269 
270 void LL1::analyExpression(string s) {
271     int i=0;
272     for (i = 0; i < s.size(); i++)
273         leftExpr.push_back(s[i]);    //  Stack the remaining string  
274     leftExpr.push_back('#');   // Pressure # 
275 
276     analyStack.push_back('#');
277     analyStack.push_back(nonterminal[0]);  //  Add the start symbol 
278 
279     while (analyStack.size() > 0) {   //  There are values in the analysis stack  
280         //cout<<" Analysis of the stack :";
281         string outs = "";
282         for (i = 0; i < analyStack.size(); i++)
283             outs += analyStack[i];
284         cout << setw(30) << outs;
285 
286         //cout<<" Remaining input string :";
287         outs = "";
288         for (i = 0; i < leftExpr.size(); i++)
289             outs += leftExpr[i];
290         cout << setw(30) << outs;
291 
292         //  matching 
293         char char1 = analyStack.back();
294         char char2 = leftExpr.front();
295         if (char1 == char2 && char1 == '#') {
296             cout << setw(15) << "Accepted!" << endl;   
297             return;
298         }
299         if (char1 == char2) {
300             analyStack.pop_back();
301             leftExpr.erase(leftExpr.begin());
302             cout << setw(15) << " matching :" << char1 << endl;
303         }
304         else if (tableMap[getNIndex(char1)][getIndex(char2)] != -1) {  //  There is a push down item in the forecast table , It can be deduced 
305             int tg = tableMap[getNIndex(char1)][getIndex(char2)];
306             analyStack.pop_back();
307 
308             if (production[tg].right != "$") {
309                 for ( i = production[tg].right.length() - 1; i >= 0; i--) //  Note that this is the reverse stack  
310                     analyStack.push_back(production[tg].right[i]);
311             }
312 
313             cout << setw(15) << " deduction :" << production[tg].left << "->" << production[tg].right << endl;
314         }
315         else {  //  error 
316             cout << setw(15) << "error!" << endl;
317             return;
318         }
319     }
320 }
321 
322 void LL1::printPredictTable() {
323     int i=0;
324     //  Header 
325     for (i = 0; i < terminalNoEmpty.size(); i++) {   
326         cout << setw(10) << terminalNoEmpty[i];   // Space  
327     }
328     cout << endl;
329     for (i = 0; i < nonterminal.size(); i++) {
330         cout << nonterminal[i] << ": ";
331         for (int j = 0; j < terminalNoEmpty.size(); j++) {
332             if (tableMap[i][j] == -1)
333                 cout << setw(10) << "   ";
334             else
335                 cout << setw(10) << production[tableMap[i][j]].right;
336         }
337         cout << endl;
338     }
339     cout << endl;
340 }
341 
342 void LL1::getResult() {  // Get the results  
343     //int a = 0;
344     inputAndSolve();
345     displayFirstAndFollow();
346     getTable();
347     printPredictTable();
348     // Stack matching 
349     string ss;
350     cout << " Please enter the symbol string :" << endl;
351     cin >> ss;
352     cout <<setw(30) << " Analysis of the stack " << setw(30) << " Remaining input string " << setw(16) << " The derived type " << endl;
353     analyExpression(ss);
354 
355 }
356 
357 
358 int main() {
359     // $ Said empty , # To terminate 
360     LL1 res;
361     res.getResult();
362     system("pause");
363     return 0;
364 }
365 
366 /*
367 E->TA
368 A->+TA
369 A->$
370 T->FB
371 B->*FB
372 B->$
373 F->i
374 F->(E)
375 */
376 //  i+i*i

 

4. test result

 

 

 

 

 

  

版权声明
本文为[Hui Gan Wang]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231740108376.html