void N8Compiler::Compile(String asm_file, String hex_out_file, bool verbose)
{
	StringList asm_file_lines;
	N8HexFile hex_file(_parameters.ProgramMemorySize);

	char line[512];
	std::ifstream asmfilestream(asm_file.c_str());
	if (!asmfilestream)
	{
		if (verbose)
			std::cout << "ASM Sourcefile not found" << std::endl;
		return;
	}

	while (!asmfilestream.eof())
	{
		asmfilestream.getline(line,512);
		asm_file_lines.push_back(String(line));
	}
	asmfilestream.close();	

	InstructionSet::iterator iseti;
	unsigned int line_ctr = 0;
	bool compilation_successful = true;

	for (StringList::iterator i=asm_file_lines.begin();i!=asm_file_lines.end();i++)
	{
		line_ctr++;
		//Not enough chars or a comment, dont parse
		if (i->size()<3 || i->c_str()[0]=='#')
			continue;

		bool no_err = false;

		if (*i->begin()=='[')
		{
			//Directive case
			StringList dir_tokens = string_tokenizer(*i);
			if (dir_tokens[0]==String("[ORG]") && dir_tokens.size()==2)
			{
				String str=dir_tokens[1];
				bool correct_format = true;
				bool hexformat = false;
				int pos = 0;
				for (String::iterator i=str.begin();i!=str.end();i++)
				{
					if (pos==1 && *i=='x')
						hexformat = true;
					else if (!(isdigit(*i)||(*i>='A'&&*i<='F')))
						correct_format = false;
					pos++;
				}
				
				if (correct_format)
				{
					unsigned int i;
					if (hexformat)
						sscanf(str.c_str(),"%x",&i);
					else
						sscanf(str.c_str(),"%u",&i);				
					hex_file.Goto(i);
				}

				no_err = true;
				continue;
			}				
			
		} else
		{
			//Instruction case
			for (iseti=_instruction_set.begin();iseti!=_instruction_set.end();iseti++)
			{
				String binarycode = iseti->ParseAsmInstruction(*i);
				if (binarycode.size()!=0)
				{	
					compilation_successful = true;
					no_err=true;
					try
					{
						hex_file.Write(str32_to_bin(binarycode));
					} catch (std::exception e)
					{
						std::cout << e.what() << std::endl;
						no_err = false;
						compilation_successful = false;
					}				
					break;
				} else
					compilation_successful = false;
			}
		}
		if (!no_err && verbose)
		{
			std::cout << "Error at line " << line_ctr << std::endl;
			std::cout << "     -> " << *i << std::endl;
		}
	}

	if (compilation_successful)
	{
		std::cout << "Writing HEX..." << std::endl;
		hex_file.SaveAsHex(hex_out_file);
		std::cout << "Compilation successful" << std::endl;
	}

}
int lexical_analysis(FILE* file, token_list** list, symbols_table** s_table)
{
	/* Declare variables */
	int res;
	uint32_t code_count;
	uint32_t inst_count;
	char line[MAX_LINE_LEN];	
	
	string_list* line_tokens;
	token *first_token, *cur_token, *next_token;
	token_list *cur_list, *next_list;
	symbols_table *cur_symbol, *next_symbol;
	
	/* Initialize variables */
	code_count = 1;
	inst_count = FIRST_INST_ADD;
	
	flag_enclosed = 0;
	
	first_token = NULL;
	*list = NULL;
	*s_table = NULL;
	
	/* Read a whole line */
	while ( fgets ( line, sizeof line, file ) != NULL ){
		
		/* Divide it in a list of strings */
		line_tokens = string_tokenizer(line, (char*)delim, (char*)opr);
		
		/* For each string verify, clasify it an generate a token */
		while(line_tokens != NULL){
			
			/* Firstly, decode special operators */
			/* Colon - If the previous token was a symbol, make it a label, 
				otherwise an error is generated */
			if(*(line_tokens->string) == ':'){
				if(cur_token == NULL)
					print_error_msg(code_count, ERR_MISP_COLON);
				else{
					if(cur_token->type == TK_SYMBOL){
						cur_token->type = TK_LABEL;
						
						next_symbol = (symbols_table*)malloc(sizeof(symbols_table));
						next_symbol->symbol = malloc(strlen(cur_token->value_s)+1);
						strcpy(next_symbol->symbol, cur_token->value_s);
						next_symbol->index = inst_count;
						next_symbol->code_line = code_count;
						if(*s_table == NULL)
							*s_table = next_symbol;
						else
							cur_symbol->next = next_symbol;
						cur_symbol = next_symbol;
					}
					else
						print_error_msg(code_count, ERR_MISP_COLON);
				}
			}
			
			/* Opening bracket - Check if there is a matching closing bracket. 
				If yes, remove the closing bracket from the string list and set
				the 'encapsulated' flag */
			else if(*(line_tokens->string) == '('){
				if(line_tokens->next == NULL) 
					print_error_msg(code_count, ERR_MISA_BRACKET);
				if(line_tokens->next->next == NULL) 
					print_error_msg(code_count, ERR_MISA_BRACKET);
				if(*(line_tokens->next->next->string) == ')'){
					if(*(line_tokens->next->string) == '$'){
						line_tokens->next->next = line_tokens->next->next->next;
						flag_enclosed = 1;
					}
					else
						print_error_msg(code_count, ERR_MISP_BRACKET);
				}
				else
					print_error_msg(code_count, ERR_MISA_BRACKET);
			}
			
			/* Isolated closing bracket - error */
			else if(*(line_tokens->string) == ')'){
				print_error_msg(code_count, ERR_MISA_BRACKET);
			}
			
			/* Sharp sign - comments */
			else if(*(line_tokens->string) == '#'){
				break;
			}
			
			/* Normal strings */
			else{				
				/* Generate a new token */
				next_token = (token*)malloc(sizeof(token));
				
				/* Analyze the string and fill token information */
				if((res = classify_token(line_tokens->string, next_token)) != ERR_NO_ERROR)
					
					/* In case of error, print the error message on screen
						OBS: It also therminates the whole process */
					print_error_msg(code_count, res);
				
				/* Adding the first token of the line */
				if(first_token == NULL)
					first_token = next_token;
				
				/* Connecting the token to the last one added */
				else
					cur_token->next = next_token;
				cur_token = next_token;
			}
			
			/* Take next string */
			line_tokens = line_tokens->next;
		}
		
		/* If the line is not empty, add it to the lines list */
		if(first_token != NULL){
			next_list = (token_list*)malloc(sizeof(token_list));
			next_list->index = inst_count;
			next_list->code_line = code_count;
			next_list->first_token = first_token;
			
			/* If the line has only one token inst_count is not updated since
			it should be an isolated label token */
			if(first_token->next != NULL)
				inst_count += 4;
			
			/* Adding the first line of the list */
			if(*list == NULL)
				*list = next_list;
			
			/* Connecting the line to the last one added */
			else
				cur_list->next = next_list;
			
			cur_list = next_list;
			first_token = NULL;			
		}		
		code_count++;
	}
	return 0;
}