Advertisement
splash365

Compiler Assignment 2 [optimized]

Apr 21st, 2021 (edited)
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.62 KB | None | 0 0
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. class SymbolInfo{
  5.     string symbol_name, symbol_type;
  6. public:
  7.     SymbolInfo(string s_n, string s_t)
  8.     {
  9.         symbol_name = s_n;
  10.         symbol_type = s_t;
  11.     }
  12.     void printSymbol() /// for printing a SymbolInfo
  13.     {
  14.         cout << "<" << symbol_name << ", " << symbol_type << "> ";
  15.     }
  16.     bool isSame(string s_n) /// For checking if a string matches with this->symbol_name
  17.     {
  18.         return s_n == symbol_name;
  19.     }
  20. };
  21.  
  22. class SymbolTable{
  23.     ///Table is vector pointer initialized in constructor
  24.     vector<SymbolInfo> *Table;
  25.     int mod, hash_type; /// member variables
  26.  
  27.     /// these functions are private because we don't need to call it from outside of this class.
  28.  
  29.     /// it returns the index of the SymbolInfo stored in the Table based on the mod and hash type.
  30.     int get_index(string s_n)
  31.     {
  32.         int len = s_n.size();
  33.         int index;
  34.         if(hash_type == 1) /// hash_type = 1 denotes technique-1
  35.         {
  36.             if(len %2 == 0) /// for even
  37.             {
  38.                 if(len > 1) index = ((int)s_n[len - 1]) + ((int)s_n[len - 2]) * 28; ///if size is at least 2
  39.                 else index = ((int)s_n[len - 1]) * 28; /// if size is 1
  40.                 index %= mod;
  41.             }
  42.             else
  43.             {
  44.                 if(len > 1) index = ((int)s_n[0]) + ((int)s_n[1]) * 28;
  45.                 else index = ((int)s_n[0]) * 28;
  46.                 index %= mod;
  47.             }
  48.         }
  49.         else if(hash_type == 2) /// hash_type = 2 denotes technique-2
  50.         {
  51.             index = 0;
  52.             for (int i = 0; i < len; i+=2) /// Iterate through all the even position characters
  53.             {
  54.                 int x = ((int)s_n[i]) << 8; /// left shift 8 times
  55.                 index += x % mod; /// mod the value of x and add it
  56.                 index %= mod; /// mod again, because i used ((a+b) mod) = ((a mod + b mod) mod)
  57.             }
  58.         }
  59.         return index;
  60.     }
  61.     /// it returns the position of the index where the symbol name exists or returns -1 if it doesn't exist
  62.     int search(string s_n)
  63.     {
  64.         int len = s_n.size();
  65.         int index = get_index(s_n); /// find the index of given string name
  66.         for (int i = 0; i < Table[index].size(); i++) /// iterate though all elements of that index
  67.             if (Table[index][i].isSame(s_n))          /// if any element matches with given string, return it's position
  68.                 return i;
  69.         return -1; /// if no matching is found, return -1
  70.     }
  71. public:
  72.     SymbolTable(int mod, int h_type = 1) /// by default hash_type is set 1
  73.     {
  74.         this->mod = mod;
  75.         if(h_type == 2) this->hash_type = h_type; /// hash_type = 2 for technique-2
  76.         else hash_type = 1; /// otherwise hash_type = 1 for technique-1
  77.         Table = new vector<SymbolInfo>[mod]; /// allocate the memory of the table dynamically
  78.     }
  79.     void Insert(string s_n, string s_t)
  80.     {
  81.         int len = s_n.size();
  82.         int index = get_index(s_n);
  83.         int pos = search(s_n); /// search if it is already exists or not
  84.         if(pos == -1) /// if not exists, search() function will return -1
  85.         {
  86.             pos = Table[index].size(); /// pos will be right after the last element which is also the size of the vector of that index.
  87.             Table[index].push_back(SymbolInfo(s_n, s_t)); /// push the symbolInfo
  88.             Table[index][pos].printSymbol();
  89.             cout << "Inserted  at position (" << index << ", " << pos << ")\n\n";
  90.         }
  91.         else /// if pos != -1, that means it already exists!
  92.         {
  93.             Table[index][pos].printSymbol();
  94.             cout << "already exists\n\n";
  95.         }
  96.     }
  97.     void LookUp(string s_n) /// this function print the index and position of SymbolInfo
  98.     {
  99.         int len = s_n.size();
  100.         int index = get_index(s_n), pos = search(s_n);
  101.         if(pos != -1) cout << "Found at (" << index << ", " << pos << ")\n\n";
  102.         else cout << s_n << " not found!\n\n";
  103.     }
  104.     void Delete(string s_n)
  105.     {
  106.         int len = s_n.size();
  107.         int index = get_index(s_n), pos = search(s_n);
  108.         if(pos == -1)
  109.         {
  110.             cout << s_n << " not found!\n\n";
  111.             return;
  112.         }
  113.         for (int i = pos + 1; i < Table[index].size(); i++)
  114.             Table[index][i - 1] = Table[index][i]; ///left shift every element starting from pos+1
  115.         Table[index].pop_back(); /// pop_back() removes the last element
  116.         cout << "Deleted from (" << index << ", " << pos << ")\n\n";
  117.     }
  118.     void Print()
  119.     {
  120.         for (int i = 0; i < mod; i++)
  121.         {
  122.             cout << i << " -> ";
  123.             for (int j = 0; j < Table[i].size(); j++)
  124.                 Table[i][j].printSymbol();
  125.             cout << "\n";
  126.         }
  127.     }
  128.     ~SymbolTable() /// free the allocated memory here
  129.     {
  130.         delete[] Table;
  131.     }
  132. };
  133.  
  134. bool is_keyword(string s)
  135. {
  136.     vector<string> keywords = {"if", "else", "for", "while", "break", "int", "char", "float",
  137.                                "double", "void", "return"};
  138.     for(string i : keywords)
  139.         if(i == s)
  140.             return true;
  141.     return false;
  142. }
  143.  
  144. bool is_number(string s)
  145. {
  146.     for(int i = 0; i<s.size(); i++)
  147.     {
  148.         if(s[i] < '0' || s[i] > '9') return false;
  149.     }
  150.     return true;
  151. }
  152.  
  153. bool is_valid(char ch)
  154. {
  155.     if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) return true;
  156.     if(ch == '_') return true;
  157.     if(ch >= '0' && ch <= '9') return true;
  158.     return false;
  159. }
  160.  
  161. bool is_valid(string s)
  162. {
  163.     if((s[0] >= 'a' && s[0] <= 'z') || (s[0] >= 'A' && s[0] <= 'Z'))
  164.     {
  165.         for(char i : s) if(is_valid(i)) return true;
  166.     }
  167.     return false;
  168. }
  169.  
  170. bool check_ignore(string s)
  171. {
  172.     if(is_number(s)) return true;
  173.     vector<string> ignore_words = {" ", ";", "(", ")", "{", "}", "[", "]", ",", "&",".",":","\n"};
  174.     for(string i : ignore_words)
  175.         if(i == s)
  176.             return true;
  177.     return false;
  178. }
  179.  
  180. bool end_char(char ch)
  181. {
  182.     string s = " ;(){}[]+-*/%&,<>=.:\"\n";
  183.     for (char i : s)
  184.         if (i == ch)
  185.             return true;
  186.     return false;
  187. }
  188.  
  189. bool is_operator(string s)
  190. {
  191.     vector<string> operators = {"+", "-", "*", "/", "%", "<", ">", "=", "!"};
  192.     for(string i : operators)
  193.         if(i == s)
  194.             return true;
  195.     return false;
  196. }
  197.  
  198. bool is_operator(string s1, string s2)
  199. {
  200.     if(!is_operator(s2)) return false;
  201.     string s = s1 + s2;
  202.     vector<string> operators = {"++", "--", "==", "!=", ">=", "<="};
  203.     for(string i : operators)
  204.         if(i == s)
  205.             return true;
  206.     return false;
  207. }
  208.  
  209. signed main() {
  210.     int mod = 51, hash_type = 1;
  211.     SymbolTable Table(mod, hash_type);
  212.    
  213.     string s;
  214.     int line_number = 0;
  215.    
  216.     ifstream inFile ("input.txt");
  217.     ofstream outKey ("out_keyword.txt");
  218.     ofstream outId ("out_identifier.txt");
  219.     ofstream outFn ("out_function.txt");
  220.     ofstream outOpt ("out_operator.txt");
  221.  
  222.     while (getline(inFile, s))
  223.     {
  224.         line_number++;
  225.         if(s[0] == '#') continue;
  226.         vector<string> all_words; ///to store every non-empty valid substring for lexeme
  227.         int buffer_start = 0, forward = 0;
  228.         while(buffer_start < s.size())
  229.         {
  230.             if(s[buffer_start] == ' ')
  231.             {
  232.                 buffer_start++;
  233.                 continue;
  234.             }
  235.             string temp = "";
  236.             forward = buffer_start;
  237.             while (forward < s.size())
  238.             {
  239.                 temp += s[forward];
  240.                 forward++;
  241.                 if(end_char(s[forward]) || end_char(s[buffer_start])) break;
  242.             }
  243.             // cout << temp << endl;
  244.             all_words.push_back(temp);
  245.             buffer_start = forward;
  246.         }
  247.         /// Iterate each word
  248.         for (int i = 0; i < all_words.size(); i++)
  249.         {
  250.             if(check_ignore(all_words[i])) continue;
  251.  
  252.             /// Ignore Literals
  253.             if(all_words[i] == "\"")
  254.             {
  255.                 i++;
  256.                 while (i < all_words.size())
  257.                 {
  258.                     if (all_words[i] == "\"")
  259.                         break;
  260.                     i++;
  261.                 }
  262.                 continue;
  263.             }
  264.             string symbol_name, symbol_type;
  265.  
  266.             /// check keyword
  267.             if(is_keyword(all_words[i]))
  268.             {
  269.                 if(all_words[i] == "else" && i+1 < all_words[i].size())
  270.                 {
  271.                     if(i+1 < all_words.size() && all_words[i+1] == "if")
  272.                     {
  273.                         symbol_name = "else if";
  274.                         i++;
  275.                     }
  276.                     else symbol_name = all_words[i];
  277.                 }
  278.                 else symbol_name = all_words[i];
  279.                 symbol_type = "KEYWORD";
  280.                 outKey << symbol_name << "  " << line_number << "\n";
  281.             }
  282.  
  283.             /// check operator
  284.             else if(is_operator(all_words[i]))
  285.             {
  286.                 if (i + 1 < all_words.size())
  287.                 {
  288.                     if (is_operator(all_words[i], all_words[i+1]))
  289.                     {
  290.                         symbol_name = all_words[i] + all_words[i + 1];
  291.                         i++;
  292.                     }
  293.                     else symbol_name = all_words[i];
  294.                 }
  295.                 else symbol_name = all_words[i];
  296.                 symbol_type = "OPERATOR";
  297.                 outOpt << symbol_name << "  " << line_number << "\n";
  298.             }
  299.  
  300.             /// check function/identifier
  301.             else if(is_valid(all_words[i]))
  302.             {
  303.                 symbol_name = all_words[i];
  304.                 ///if next word is "(" then current word is a function, otherwise identifier
  305.                 if(i+1 < all_words.size() && all_words[i+1] == "(")
  306.                 {
  307.                     symbol_type = "FUNCTION";
  308.                     i++;
  309.                     outFn << symbol_name << "  " << line_number << "\n";
  310.                 }
  311.                 else
  312.                 {
  313.                     symbol_type = "IDENTIFIER";
  314.                     outId << symbol_name << "  " << line_number << "\n";
  315.                 }
  316.             }
  317.  
  318.             /// otherwise print error
  319.             else
  320.             {
  321.                 cout << "Lexical Error at Line: " << line_number << "\n";
  322.                 continue;
  323.             }
  324.             Table.Insert(symbol_name, symbol_type);
  325.         }
  326.     }
  327.    
  328.     inFile.close();
  329.     outId.close();
  330.     outKey.close();
  331.     outFn.close();
  332.  
  333.     cout << "\n\nSymbol Table:\n\n";
  334.     Table.Print();
  335.     return 0;
  336. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement