axyd icon

cpp_tokenizer_mine

axyd | PRO | 05/22/22 05:20:33 PM UTC | 0 ⭐ | 1453 👁️ | Never ⏰ | []
C++ |

6.77 KB

|

None

|

0 👍

/

0 👎

#include <iostream>
#include <fstream>
#include <regex>
#include <vector>
#include <string>
#include <iomanip>
using namespace std;
 
 
/*Detects and merges binary operators*/
smatch bin_ops_merger (vector<string>&, size_t);
 
/*Combines two vectors into a pair*/
template<typename T,typename U>
vector<pair<T,U>> merge_vectors (const vector<T>&, const vector<U>&);
 
/*Assigns Matching Tokens to Lexemes*/
void tokenizer (vector<string>&, vector<pair<string,string>>&);
 
 
int main(int argc, char** argv) {
    //store full source file in a string
    string file, line;
    ifstream ifs("analyzethis.file");
    
    while (getline(ifs, line, '\0')){
        file+= line;
    }
    ifs.close();
    
    /*Strip single and multi line comments*/
    regex rexComments("(//.*)|(/\\*(?:.|[\\n\\r])*?\\*/)");
 
    string result;
    regex_replace(std::back_inserter(result), file.begin(), file.end(), rexComments, " ");
    file= result;
    
    
    /* REGEX Patterns:
     *      Not alphanumeric [\\W]
     *      number: (\\d+).(\\d+)
     *      string: (\".*\")
     */
 
    regex rexPtrn("[\\W]|(\\d+).(\\d+)|(\".*\")"); 
    
    
    //only alpha numeric, reverses negation
    regex_token_iterator<string::iterator> rtiNS(file.begin(), file.end(), rexPtrn, -1);
    //only symbols
    regex_token_iterator<string::iterator> rtiS(file.begin(), file.end(), rexPtrn);
    //end of line comparison
    regex_token_iterator<string::iterator> rtiEnd;
 
    
    vector<string> vData;   //holds token
    while ((rtiNS!=rtiEnd)&&(rtiS!=rtiEnd)){        
        if((*rtiNS).length()>0)                             //if not symbol
            vData.push_back(*rtiNS);
 
        if((*rtiS).length()>0&&*rtiS!=" "&&*rtiS!="\t"&&*rtiS!="\n")
            vData.push_back(*rtiS);
 
        //advance iterators
        ++rtiNS;
        ++rtiS;
    }
 
    
    //FIND BINARY OPERATORS AND COMBINE THEM
    for (size_t ctr= 0; ctr < vData.size() - 1; ++ctr) {
        bin_ops_merger(vData, ctr);
    }
 
    
    /*Holds final matches*/
    vector<pair<string,string>> vTokenLexeme;
    tokenizer(vData, vTokenLexeme);
 
 
    //Save tokenized lexemes
    ofstream ofs("tokenized.txt");
    
    ofs<<string(30, '=')<<endl;
    ofs<<setw(17)<<right<<"Lexeme      ||"<<setw(10)<<"Token"<<endl;
    ofs<<string(30, '=')<<endl;
    
    for(auto it : vTokenLexeme){
        ofs<<setw(15)<<left<<it.first<<"||  "<<it.second<<endl;     
    }
    
    ofs.close();
    
 
//  system("PAUSE");
    return 0;   
}
 
 
/*Combines two vectors into a pair*/
template<typename T,typename U>
vector<pair<T,U>> merge_vectors (const vector<T>& v1, const vector<U>& v2) {
    vector<pair<string, string>> vOut;
    
    for(size_t i= 0; i< v1.size(); ++i){
        vOut.emplace_back(v1.at(i), v2.at(i));
    }   
    return vOut;
}
 
/*Detects and merges binary operators*/
smatch bin_ops_merger (vector<string>& vData, size_t ctr) {
    regex binaryOperatorsPattern("\\+=|-=|\\*=|/=|%=|&=|\\!=|==|\\|=|\\^="
        "|<=|>=|--|\\+\\+|<<|>>|&&|\\|\\||->");
    
    vector <string>::iterator curr, next;
    curr= vData.begin()+ctr;
    next= vData.begin()+ctr+1;
    
    string str= *curr+*next;    //run regex pattern on this string  
    smatch binOpsMatch;         //stores the matched partion
    
    if (regex_match(str, binOpsMatch, binaryOperatorsPattern)) {
        *curr= *curr + *next;                   //merge operators
        vData.erase(next);                      //delete extra element
    }
    
    return binOpsMatch; 
}
 
 
/*Assigns Matching Tokens to Lexemes*/
void tokenizer (vector<string>& vLex, vector<pair<string,string>>& vTknLex) {
    //Reserved Key Words
    vector<string> vKword;
    vKword={"string","include","auto","const","struct","unsigned","break",
        "continue","else","for","signed","switch","void","case","default",
        "enum","goto","register","sizeof","typedef","volatile","char","do",
        "extern","if","return","static","union","while","asm","dynamic_cast",
        "namespace","reinterpret_cast","try","bool","explicit","new","template",
        "static_cast","typeid","catch","false","operator","typename","public",
        "class","friend","private","this","using","const_cast","inline","throw",
        "virtual","delete","mutable","protected","true","elseif"};
 
    vector<string> vDataTypes;
    vDataTypes={"double","float","int","short","size_t","long","string"};
    
 
    //Binary Operators
    vector<string> vbotkn, vbolex;
    vbotkn={"+=", "-=", "*=", "/=", "%=", "&=", "!=", "==", "|=", "^=", "<=",
        ">=","--", "++", "<<", ">>", "&&", "||", "->",":"};
    vbolex={"ADD_ASSIGN","SUB_ASSIGN","MUL_ASSIGN","DIV_ASSIGN","MOD_ASSIGN",
        "AND_ASSIGN","LOGIC_INEQ","LOGIC_EQ","OR_ASSIGN","XOR_ASSIGN",
        "LESS_OR_EQ","MORE_OR_EQ","DECREMENT","INCREMENT","INSERTION",
        "EXTRACTION","LOGIC_AND","LOGIC_OR","MEMBER_PTR","SCOPE_RES"};
    vector<pair<string,string>> vBOpsTokens= merge_vectors(vbotkn, vbolex);
    
    //Unary Symbols
    vector<string> vsymtkn, vsymlex;
    vsymtkn={".","#",",","=","-","+","/","*","%","(",")","{","}","[","]","~",
        "^","|","&","?",":",";","!",">","<"};
    vsymlex={"MEMBER_OBJ","PREPROC","SEPARATOR","ASSIGN","SUB","ADD","DIV",
        "MUL_OR_DEREF","MOD","L_PAREN","R_PAREN","L_BRACE","R_BRACE","L_BRACKET",
        "R_BRACKET","COMPLEMENT","XOR","OR","AND","CONDITIONAL","COND_SEP",
        "SEMI_COLON","NOT","GREATER_THAN","LESS_THAN"};
    vector<pair<string,string>> vUnaryTokens= merge_vectors(vsymtkn, vsymlex);
    
    //Library Objects
    vector<string> vLibObj;
    vLibObj={"cout","cin","printf","size","sizeof","system","getline","endl",
        "to_string"};
    
    /*
     * Search lexemes for token matches
     * 
     */
    for(size_t lexItr= 0; lexItr<vLex.size(); ++lexItr){
        bool found= false;
        
        //match string
        regex rexStr("(\".*\")");
        if(regex_match(vLex[lexItr], rexStr)){
            vTknLex.emplace_back(vLex.at(lexItr), "STRING_LIT");
            found= true;
        }
        if(found) continue;
        
        //match numbers
        regex rexNum("(\\d)|(\\d+.\\d+)");
        if(regex_match(vLex[lexItr], rexNum)){
            vTknLex.emplace_back(vLex.at(lexItr), "NUMERIC");
            found= true;
        }
        if(found) continue;
        
        //match keywords
        for(auto it : vKword){
            if(vLex[lexItr]==it){
                vTknLex.emplace_back(vLex.at(lexItr), "KEYWORD");
                found= true;
                break;
            }
        }
        if(found) continue;
        
        //match data types
        for(auto it : vDataTypes){
            if(vLex[lexItr]==it){
                vTknLex.emplace_back(it, "PRIM_DTYPE");
                found= true;
                break;
            }
        }
        if(found) continue;
        
        
        //match binary operators
        for(auto it : vBOpsTokens){
            if(vLex[lexItr]==it.first){
                vTknLex.emplace_back(it.first, it.second);
                found= true;
                break;
            }
        }
        if(found) continue;
        
        //match unary operators
        for(auto it : vUnaryTokens){
            if(vLex[lexItr]==it.first){
                vTknLex.emplace_back(it.first, it.second);
                found= true;
                break;
            }
        }
        if(found) continue;
        
        //match library objects
        for(auto it : vLibObj){
            if(vLex[lexItr]==it){
                vTknLex.emplace_back(it, "LIB_OBJ");
                found= true;
                break;
            }
        }
        if(found) continue;
        
 
        
        //left overs are identifiers
        vTknLex.emplace_back(vLex.at(lexItr), "IDENTIFIER");
    }
}
 

Comments