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