#include <iostream>
#include <fstream>
#include <sstream>


#include "parser.h"
#include "instructions.h"
#include "parameters.h"
using namespace std;


extern bool errorOccured;

void src_file::parsing(string name,vector<instruction> &vect, table_label &labels, bool verbose) {
    table_instr table;
    f.open(name.c_str(),ios::in);
    int cline=0, cinstr=0;
    if (f) {
        string line,namevar;
		while (getline(f,line)){
            if (verbose) cout << endl;

            cline++;

            // Remove comments
            string::size_type loc;
            loc = line.find(";");
            if(loc!=string::npos)
                line = line.substr(0,loc);

            // Save labels
            loc = line.find(":");
            if (loc <= line.size()) {
                string lblname = line.substr(0,loc);
                labels.add_label(lblname,cinstr);
                if (verbose)    cout << "Label " << lblname << " memorized on instruction " << cinstr << endl;
                line = line.substr(loc + 1);
            }

            istringstream aliasline (line,istringstream::in);

            namevar="";
            aliasline >> namevar;
            if(namevar=="")continue;
		    instruction instr(namevar, cline, &table);
            if (verbose)    cout << "Analyzing instruction n° "<< cinstr << " on line " << cline << " : " << instr.name << endl << "\t Reading arguments : ";

		    int max = instr.nb_int_arg;
            int aint; string astring; int i;
            for (i=0;i<max;i++) {
                while(!aliasline.eof() && isspace(aliasline.peek()))aliasline.get();
                if (aliasline.eof()) {
                    if (instr.type == jump && i==1) {
                        // Jump with only one argument
                        instr.arg[1] = 0;
                        instr.arg[0] = instr.arg[0];
                        instr.exn -= 8;
                    }
                    else     instr.error("missing int argument");
                }else{
                    if(aliasline.get()!='W')aliasline.unget();
                    aliasline >> aint; instr.arg[i] = aint;
                    if (verbose)    cout << "(" << i << ") " << aint << "\t";
                }
            }
            if(instr.type == jump){
                // invert two arguments !
                int tmp=instr.arg[0];
                instr.arg[0] = instr.arg[1];
                instr.arg[1] = tmp;
            }
            for (i=max;i<3;i++)     instr.arg[i] = 0;
            aliasline >> astring; instr.s_arg = astring;
                        if (verbose && astring != "")    cout << "(s) " << astring << "\t";
            if (instr.name=="la" && astring == "")   instr.error("missing string argument");

            if(!aliasline.eof())instr.error("too many arguments or bad type.");

            if(verbose) cout << endl;

            // handling of multilined pseudoinstructions so that labels have correct adresses.
            if(instr.type==pseudo && instr.exn < 0){
                cinstr += -instr.exn;
            }else{
                cinstr ++;
            }
            vect.push_back (instr);
		}
    }else{
        cerr << "ERROR : reading input file";
        errorOccured = true;
    }
}
