#include <iostream>
#include <fstream>
#include <sstream>
#include <istream>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <cstdlib>
#include <limits>
#include <cerrno>
#include <regex>

using namespace std;

class DefList{
    public:
        int Definition_Count;
        vector<string> DefSymbolList;
        vector<int> Definition_Address;
};

class ProgramText{
    public:
        int ProgramText_Count;
        vector<string> IARE_List;
        vector<string> Instruction_Address;
};


void parseFile(char* argv[]); // to read to input file.
bool is_number(string& src); // to check if the string is number.
bool is_IARE(string& iare); // to check if the string is IARE type.
bool is_symbol(string& symbol); // to check if the string is symbol.
void syntaxError(int position, int errorCode); 
bool is_multipleDef(map<string , int>& FreqSymDef , string& defSym);

/* parse Defition Symbol, Use List, Program Text. Set flag: valid = 1; fail = 0 */
int parseDefList(vector<DefList>& Vector_DefList) ;
int parseUseList(vector< vector<string> >& Vector_UseList);
int parseProgramText(int& num_ProgTxt , vector<ProgramText>& Vector_Program_Text);

void SymbolTable(vector<DefList>& Vector_DefList, vector<int>& baseAdding);




/* Containers */
// to store all line;
vector<string> inputLine;


// to store all token
vector<string> tokenVector;
// to record positions of each token.
vector<int> rowVector; // to store the number of row on each token
vector<int> columnVector; // to store the number of vector on each token
//
map<string , int> FreqSymDef; // frequency of defining a symbol <symbol token , frequency>
map<string , int> Count_Sym_Module; // log the position where the symbol is <symbol token , modulePos>
map<string , int> DictSymAddress; // Dictionary for {Symbol : Address}




void parseFile(char* argv[]);

// Index Area
int token_index = 0; // token index when parsing
int num_token; // numbers of token in the file

/* Main Function */
int main (int argc , char* argv[]){
    
    if (argc != 2){
        cout << "The format of input file is invalid." << endl;
        exit(0);    
                
    }
    
    parseFile(argv);

    return 0;
}

/* Read File and Parse it */
void parseFile(char* argv[]){
    // Stream the input file
    string text;
    ifstream inputFile (argv[1], ios::binary);
    if (inputFile.is_open()) {
        text.assign((std::istreambuf_iterator<char>(inputFile)) , (std::istreambuf_iterator<char>()));

        vector<int> lengthLine; // log the length of each line

        
        /* Parse the token */
        /* Log the position (row , column) */
        int row = 0; // Initialization
        int column = 0;

        string token = "";
        for (int i = 0 ; i < text.size() ; i++){
            row += 1;
            
            if (text[i] != ' ' || text[i] != '\t' || text[i] != '\n'){

                if (text[i + 1] == ' ' || text[i + 1] == '\t' || text[i + 1] == '\n'){
                    tokenVector.push_back(token);
                    token = "";
                }
                                column += 1;
                token += text[i];
            }
            else if (text[i] == ' '){
                column += 1;
                token = "";
            }
            else if (text[i] == '\t'){
                column +=1;
                token = "";
            }
            else if (text[i] == '\n'){
                column = 0;
                token = "";
            }
        }



        for (int i = 0 ; i < tokenVector.size() ; i++){
            cout<<tokenVector[i]<<endl;
        }




            
/*

// test read all line in the inputFile:
        
        cout<<inputLine.size()<<endl; // number of line

        for (int i = 0 ; i < inputLine.size() ; i++){
            for (int j = 0 ; j < inputLine[i].size() ; j++){
                cout<<"line: "<<i+1<<" offset: "<<j+1<<" token: "<<inputLine[i][j]<<endl;
            }
        }

*/




/*
        while ( getline(inputFile, line)) { 
            
            row += 1;
            lengthLine.push_back(line.length());
            stringstream input(line);
            
            // Start to Parse the Token 
            int column = -1; // Initialization: be ware of the situation like input-3
            for (string token; input >> token;){
                column = line.find(token, column + 1); // find the position of the token in the line 
                tokenVector.push_back(token);  // store up the token
                // Record the position
                rowVector.push_back(row);
                columnVector.push_back(column + 1); // reason: the end of the parsed token.
            }
        }
*/

/*

        // log the last position in the input file
        int lastRow = row; 
        int lastColumn = lengthLine.back() + 1;    
        rowVector.push_back(lastRow);
        columnVector.push_back(lastColumn);
*/

        inputFile.close();
    } 
    else {
        cout << "Failed to open the file." << endl;
    }

/* 
// test parsing
    cout<<tokenVector.size()<<endl;
    cout<<columnVector.size()<<endl;
    cout<<rowVector.size()<<endl;

    for (int i = 0 ; i < tokenVector.size() ; i++){
        cout<<tokenVector[i]<<":"<<rowVector[i]<<":"<<columnVector[i]<<endl;
    }
// end
*/

}