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; }