Advertisement
fooker

slr parser

Feb 25th, 2025
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.24 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. #include <pthread.h>
  3. #include <mutex>
  4. using namespace std;
  5.  
  6. #define F first
  7. #define S second
  8.  
  9. mutex mtx;
  10. struct Rule {
  11.     char lhs;
  12.     string rhs;
  13.     int id, ptr;
  14.    
  15.     Rule() {
  16.         lhs = '\0';
  17.         rhs = "";
  18.         ptr = 0;
  19.         id = -1;
  20.     }
  21.    
  22.     Rule( char _l, string _r, int _id ): lhs(_l), rhs(_r), id(_id), ptr(0) {}
  23.    
  24.     bool operator<( const Rule &a ) const {
  25.         string p(1,lhs);
  26.         p += rhs;
  27.         p.insert( ptr+1, "." );
  28.         string q(1,a.lhs);
  29.         q += a.rhs;
  30.         q.insert( a.ptr+1, "." );
  31.         return ( p < q );
  32.     }
  33.        
  34.     void print() {
  35.         string q = rhs;
  36.         q.insert( ptr, "." );
  37.         cout << lhs << "->" << q << " :" << ptr << '\n';
  38.     }
  39. };
  40.  
  41. set<char> nonTerm, Term, lit;
  42. set<Rule> RuleSet;
  43. map< char, set<Rule> > LHS;
  44. map< pair<int,char>, pair<char,int> > ACTION;
  45. map<string,int> HASH;
  46. map<int,bool> explored;
  47. map< char, set<char> > _FIRST, _FOLLOW;
  48. map< int, Rule > RuleList;
  49. int statecount = 0, rules = 0;
  50. char start;
  51.  
  52. int getHash( set<Rule> p ) {
  53.     string str;
  54.     for( Rule r : p ) {
  55.         str.push_back(';');
  56.         string rule;
  57.         rule.push_back(r.lhs);
  58.         rule += "->" + r.rhs;
  59.         rule.insert( r.ptr+3, "." );
  60.         str += rule;
  61.     }
  62.     if( HASH.find(str) == HASH.end() )
  63.         HASH[str] = statecount++;
  64.     return HASH[str];
  65. }
  66.  
  67. void escape( string &s ) {
  68.     string str;
  69.     for( char c : s )
  70.         if( c != ' ' )
  71.             str.push_back(c);
  72.     s = str;
  73. }
  74.  
  75. set<Rule> getProductionRules( string s ) {
  76.     escape(s);
  77.     set<Rule> v;
  78.     string l;
  79.    
  80.     for( int i = 3; i <= (int)s.size(); i++ ) {
  81.         if( i == (int)s.size() || s[i] == '|' ) {
  82.             v.insert( Rule( s[0], l, rules ) );
  83.             RuleList[rules] = Rule( s[0], l, rules );
  84.             rules++;
  85.             l.clear();
  86.         }
  87.         else {
  88.             if( isupper(s[i]) )
  89.                 nonTerm.insert(s[i]);
  90.             else
  91.                 Term.insert(s[i]);
  92.             lit.insert(s[i]);
  93.             l.push_back(s[i]);
  94.         }
  95.     }
  96.     return v;
  97. }
  98.  
  99. void FIRST( Rule r ) {
  100.     if( nonTerm.count(r.rhs[0]) )
  101.         _FIRST[r.lhs].insert(r.rhs[0]);
  102.     else {
  103.         for( Rule p : LHS[r.rhs[0]] )
  104.         if( p.lhs != r.lhs ) {
  105.             FIRST(p);
  106.             for( char c : _FIRST[p.lhs] )
  107.             _FIRST[r.lhs].insert(c);
  108.         }
  109.     }
  110. }
  111.  
  112. void FOLLOW( Rule r ) {
  113.     for( int i = 0; i < (int)r.rhs.size(); i++ )
  114.         if( nonTerm.count(r.rhs[i]) ) {
  115.             if( i+1 >= (int)r.rhs.size() && r.lhs != r.rhs[i+1] ) {
  116.                 for( char c : _FOLLOW[r.lhs] )
  117.                 _FOLLOW[r.rhs[i]].insert(c);
  118.             }
  119.             else if( i+1 < (int)r.rhs.size() && Term.count(r.rhs[i+1]) )
  120.                 _FOLLOW[r.rhs[i]].insert(r.rhs[i+1]);
  121.             else if( i+1 < (int)r.rhs.size() && nonTerm.count(r.rhs[i+1]) ) {
  122.                 for( char c : _FOLLOW[r.rhs[i+1]] )
  123.                 _FOLLOW[r.rhs[i]].insert(c);
  124.             }
  125.         }
  126. }
  127.  
  128. struct thread_data {
  129.     set<Rule> sR;
  130.     char ch;
  131.    
  132.     thread_data() {
  133.     }
  134.     thread_data( set<Rule> _sR, char _ch ) {
  135.         sR = _sR;
  136.         ch = _ch;
  137.     }
  138. };
  139.  
  140. void *rec(void *param) {
  141.     thread_data *data = (thread_data*)param;
  142.    
  143.     set<Rule> v = data->sR;
  144.     char c = data->ch;
  145.    
  146.     set<Rule> idx;
  147.        
  148.     for( Rule r : v ) {
  149.         if( r.rhs[r.ptr] == c ) {
  150.         Rule copy = r;
  151.         copy.ptr++;
  152.         idx.insert(copy);
  153.         }
  154.     }
  155.    
  156.     int initsize = 0;
  157.     while( initsize != (int)idx.size() ) {
  158.         initsize = idx.size();
  159.         set<Rule> toadd;
  160.         for( Rule r : idx )
  161.         if( r.ptr < (int)r.rhs.size() && nonTerm.count(r.rhs[r.ptr]) )
  162.             for( Rule p : LHS[r.rhs[r.ptr]] )
  163.             toadd.insert(p);
  164.         for( Rule r : toadd )
  165.             idx.insert(r);
  166.     }
  167.        
  168.     if( idx.empty() )
  169.         return 0;
  170.    
  171.     mtx.lock();
  172.    
  173.     for( Rule r : idx )
  174.         if( r.ptr >= (int)r.rhs.size() ) {
  175.         for( char c : _FOLLOW[r.lhs] )
  176.             ACTION[{getHash(idx),c}] = {'R', r.id};
  177.         }
  178.        
  179.     if( Term.count(c) )
  180.         ACTION[{getHash(v),c}] = {'S',getHash(idx)};
  181.     if( nonTerm.count(c) )
  182.         ACTION[{getHash(v),c}] = {'G',getHash(idx)};
  183.    
  184.     if( explored[getHash(idx)] ) {
  185.         mtx.unlock();
  186.         return 0;
  187.     }
  188.    
  189.     explored[getHash(idx)] = 1;
  190.    
  191.     mtx.unlock();
  192.    
  193.     pthread_attr_t attr;
  194.     void *status;
  195.  
  196.     pthread_attr_init(&attr);
  197.     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  198.  
  199.    
  200.     pthread_t threads[lit.size()];
  201.     thread_data td[lit.size()];
  202.     int cur = 0;
  203.     for( char t : lit ) {
  204.         td[cur] = thread_data(idx,t);
  205.         pthread_create(&threads[cur], &attr, rec, (void *)&td[cur]);
  206.         cur++;
  207.     }
  208.    
  209.     pthread_attr_destroy(&attr);
  210.    
  211.     for( int i = 0; i < cur; i++ ) {
  212.         int rc = pthread_join(threads[i], &status);
  213.         if (rc) {
  214.         cerr << "Error: unable to join, " << rc << endl;
  215.         exit(-1);
  216.         }
  217.     }
  218.  
  219.     return 0;
  220. }
  221.  
  222. struct ParseTreeNode {
  223.     string symbol;
  224.     vector<ParseTreeNode*> children;
  225.     ParseTreeNode(string sym) : symbol(sym) {}
  226. };
  227.  
  228. void printParseTree(ParseTreeNode* node, int level = 0);
  229. void deleteParseTree(ParseTreeNode* node);
  230.  
  231. void printParseTree(ParseTreeNode* node, int level) {
  232.     if (!node) return;
  233.     for (int i = 0; i < level; i++)
  234.         cout << "  ";
  235.     cout << node->symbol << endl;
  236.     for (ParseTreeNode* child : node->children) {
  237.         printParseTree(child, level + 1);
  238.     }
  239. }
  240.  
  241. void deleteParseTree(ParseTreeNode* node) {
  242.     if (!node) return;
  243.     for (ParseTreeNode* child : node->children) {
  244.         deleteParseTree(child);
  245.     }
  246.     delete node;
  247. }
  248.  
  249. void validate(string s) {
  250.     string backup = s;
  251.     if (s.back() != '$')
  252.         s.push_back('$');
  253.     escape(s);
  254.  
  255.     cout << "\n[STATE BUFFER ACTION]\n";
  256.     stack<pair<string, int>> st;
  257.     st.push({"STATE", 0});
  258.     stack<ParseTreeNode*> parseStack;
  259.  
  260.     while (true) {
  261.         int state = st.top().S;
  262.         char c = *s.begin();
  263.  
  264.         cout << setw(backup.size() + 2) << s << ":  ";
  265.  
  266.         cout << "State: " << state << ", Input: " << c << " -> ";
  267.  
  268.         if (ACTION.find({state, c}) == ACTION.end()) {
  269.             cout << backup << " - not accepted (no action found).\n";
  270.  
  271.             while (!parseStack.empty()) {
  272.                 deleteParseTree(parseStack.top());
  273.                 parseStack.pop();
  274.             }
  275.             return;
  276.         }
  277.  
  278.         auto act = ACTION[{state, c}];
  279.  
  280.         if (act.F == 'S') {
  281.             cout << "Shift to state " << act.S << "\n";
  282.             st.push({"TOKEN", c});
  283.             st.push({"STATE", act.S});
  284.             s.erase(s.begin());
  285.  
  286.             ParseTreeNode* node = new ParseTreeNode(string(1, c));
  287.             parseStack.push(node);
  288.         } else if (act.F == 'R') {
  289.             int id = act.S;
  290.             Rule r = RuleList[id];
  291.             cout << "Reduce using rule " << r.lhs << " -> " << r.rhs << "\n";
  292.             for (int i = 0; i < 2 * (int)r.rhs.size(); i++)
  293.                 st.pop();
  294.             vector<ParseTreeNode*> children;
  295.             for (int i = 0; i < (int)r.rhs.size(); i++) {
  296.                 if (parseStack.empty()) {
  297.                     cout << backup << " - parse error (underflow).\n";
  298.                     return;
  299.                 }
  300.                 ParseTreeNode* child = parseStack.top();
  301.                 parseStack.pop();
  302.                 children.push_back(child);
  303.             }
  304.             reverse(children.begin(), children.end());
  305.             ParseTreeNode* newNode = new ParseTreeNode(string(1, r.lhs));
  306.             newNode->children = children;
  307.             parseStack.push(newNode);
  308.  
  309.             int top = st.top().S;
  310.             st.push({"NT", r.lhs});
  311.  
  312.             if (ACTION.find({top, r.lhs}) == ACTION.end()) {
  313.                 cout << backup << " ~ not accepted (no GOTO found).\n";
  314.                 while (!parseStack.empty()) {
  315.                     deleteParseTree(parseStack.top());
  316.                     parseStack.pop();
  317.                 }
  318.                 return;
  319.             }
  320.  
  321.             auto now = ACTION[{top, r.lhs}];
  322.             st.push({"STATE", now.S});
  323.         }
  324.  
  325.         cout << "Stack: ";
  326.         auto prev = st;
  327.         while (!prev.empty()) {
  328.             if (prev.top().F != "STATE") {
  329.                 cout << (char)prev.top().S;
  330.             } else {
  331.                 cout << prev.top().S;
  332.             }
  333.             prev.pop();
  334.         }
  335.         cout << '\n';
  336.  
  337.         if (s == "$" && st.top().S == ACTION[{0, start}].S) {
  338.             cout << backup << " ACCEPTED\n";
  339.             if (!parseStack.empty()) {
  340.                 ParseTreeNode* root = parseStack.top();
  341.                 cout << "\nParse Tree:\n";
  342.                 printParseTree(root);
  343.                 deleteParseTree(root);
  344.                 parseStack.pop();
  345.             }
  346.             return;
  347.         }
  348.  
  349.         static int loopCounter = 0;
  350.         if (++loopCounter > 1000) {
  351.             cout << backup << " - parser stuck in a loop. Aborting.\n";
  352.             while (!parseStack.empty()) {
  353.                 deleteParseTree(parseStack.top());
  354.                 parseStack.pop();
  355.             }
  356.             return;
  357.         }
  358.     }
  359. }
  360.  
  361. int main() {
  362.     int n;
  363.     cout << "Enter the number of Production Rules: ";
  364.     cin >> n;
  365.     cin.ignore();
  366.    
  367.     cout << "Enter the start symbol: ";
  368.     cin >> start;
  369.     cin.ignore();
  370.    
  371.     cout << "Enter the Production Rules:\n";
  372.     for( int i = 0; i < n; i++ ) {
  373.         string s; getline(cin,s);
  374.         set<Rule> a = getProductionRules(s);
  375.         for( Rule r : a ) {
  376.             LHS[r.lhs].insert(r);
  377.             RuleSet.insert(r);
  378.             FIRST(r);
  379.         }
  380.     }
  381.    
  382.     _FOLLOW[start].insert('$');
  383.     for( Rule r : RuleSet ) FOLLOW(r);
  384.     for( Rule r : RuleSet ) FOLLOW(r);
  385.    
  386.     char _S;
  387.     for( char i = 'A'; i <= 'Z'; i++ ) {
  388.         if( nonTerm.count(i) == 0 ) {
  389.             _S = i;
  390.             break;
  391.         }
  392.     }
  393.        
  394.     set<Rule> G = RuleSet;
  395.     G.insert( Rule( _S, string(1,start)+"$", -1 ) );
  396.    
  397.     explored[getHash(G)] = 1;
  398.    
  399.     pthread_attr_t attr;
  400.     void *status;
  401.  
  402.     pthread_attr_init(&attr);
  403.     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  404.  
  405.     pthread_t threads[lit.size()];
  406.     thread_data td[lit.size()];
  407.     int cur = 0;
  408.    
  409.     for( char c : lit ) {
  410.         td[cur] = thread_data(G,c);
  411.         pthread_create(&threads[cur], &attr, rec, (void *)&td[cur]);
  412.         cur++;
  413.     }
  414.    
  415.     pthread_attr_destroy(&attr);
  416.    
  417.     for( int i = 0; i < cur; i++ ) {
  418.         int rc = pthread_join(threads[i], &status);
  419.         if (rc) {
  420.         cerr << "Error: unable to join, " << rc << endl;
  421.         exit(-1);
  422.         }
  423.     }
  424.    
  425.     cout << "\n[PARSING TABLE]\n\n";
  426.     for( auto p : ACTION ) {
  427.         cout << "GOTO(I" << p.F.F << "," << p.F.S << ") = " << p.S.F << p.S.S << '\n';
  428.     }
  429.     cout << "Total Table Entries: " << ACTION.size() << "\n\n";
  430.    
  431.     while(1) {
  432.         cout << "\nEnter string to validate: ";
  433.         string s; cin >> s;
  434.         validate(s);  
  435.     }
  436. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement