std::string Parser::symbol() const { // PRE: current_line_ has commandType == A_COMMAND or L_COMMAND // POST: dest in upper. Empty string if null. assert(commandType() == A_COMMAND || commandType() == L_COMMAND); std::string s = current_line_; s.erase(0,1); // Erasing '@' or '(' size_t p = s.find(")"); if (p != std::string::npos) // Looking for the ')'. s.erase(p, std::string::npos); std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s; }
string Parser::symbol() { if (commandType() == HasmCommandType::A_COMMAND) return command.substr(1); return command.substr(1, command.size() - 2); }
std::string Parser::jump() const { // PRE: current_line_ has commandType == C_COMMAND // POST: jmp in UPPERCASE. Empty string if none. assert(commandType() == C_COMMAND); std::string s = current_line_; size_t p = s.find(";"); if (p != std::string::npos) { s.erase(0, p+1); std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s; } // No jmp mnemonic. return ""; }
std::string Parser::dest() const { // PRE: current_line_ has commandType == C_COMMAND // POST: dest in UPPERCASE. Empty string if null. assert(commandType() == C_COMMAND); std::string s = current_line_; size_t e = s.find("="); if (e == std::string::npos) s = ""; // Dest = null. else { s.erase(s.find("="), std::string::npos); } std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s; }
std::string Parser::comp() const { // PRE: current_line_ has commandType == C_COMMAND // POST: comp in UPPERCASE. (Empty string if none.) assert(commandType() == C_COMMAND); std::string s = current_line_; size_t p = s.find(";"); if (p != std::string::npos) s.erase(p+1, std::string::npos); p = s.find("="); if (p != std::string::npos) s.erase(0, p+1); size_t end = s.find_last_not_of(";"); std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s.substr(0, end+1); }
/* Put in string the first argument of the current command, if it is a arithmetic command string = currentCommand */ void arg1(char string[LENGTH_MAX]) { /* If the command is a C_ARITHMETIC command, string = the currentCommand */ if(commandType() == C_ARITHMETIC) strcpy(string, currentCommand); /* Else, string = first argument of the command */ else { int indexCommand; int indexString; for(indexCommand = 0; currentCommand[indexCommand] != ' '; ++indexCommand) ; ++indexCommand; for(indexString = 0; isalpha(currentCommand[indexCommand]) || isdigit(currentCommand[indexCommand]) || currentCommand[indexCommand] == '_' || currentCommand[indexCommand] == '.' || currentCommand[indexCommand] == ':' ; ++indexCommand, ++indexString) string[indexString] = currentCommand[indexCommand]; string[indexString] = '\0'; } }
void firstPass(void) { int ROMaddress; ROMaddress = 0; /* First pass */ while(hasMoreCommands()) { /* Read the current command */ advance(); /* If there is a current command */ if(currentCommand[0] != '\0') { int returnCommandType; /* Get the type of the command */ returnCommandType = commandType(); /* If it is a A_COMMAND or C_COMMAND */ if(returnCommandType == A_COMMAND || returnCommandType == C_COMMAND) ++ROMaddress; /* Else if it is a L_COMMAND */ else if(returnCommandType == L_COMMAND) { char string[LENGTH_MAX]; /* Get the symbol */ symbol(string); /* Add the symbol into the symbol table associating the ROMaddress variable */ addEntry(string, ROMaddress); } } } }
void secondPass(void) { /* Second pass */ /* While there is a command */ while(hasMoreCommands()) { /* Read the current command */ advance(); /* If there is a current command */ if(currentCommand[0] != '\0') { char string[LENGTH_MAX]; int returnCommandType; int bits[16]; int stringAddress; int indexBit; /* Get the type of the command */ returnCommandType = commandType(); /* If it is a A_COMMAND */ if(returnCommandType == A_COMMAND) { /* Get the symbol */ symbol(string); /* If the symbol is not a number */ if(isalpha(string[0])) { /* If string is already in the symbol table */ if(contains(string)) /* Get string's address */ stringAddress = getAddress(string); /* Else it is a new symbol */ else { /* Get the address */ stringAddress = RAMaddress; /* Add string to the symbol table */ addEntry(string, RAMaddress); /* Increment the next available RAM address */ ++RAMaddress; } } /* Else it is a number */ else /* Get string's address */ stringAddress = atoi(string); /* Transform it into binairy */ symbolBinary(stringAddress, bits); /* Put it into the hack file */ for(indexBit = 0; indexBit < 16; ++indexBit) fprintf(hackFile, "%d", bits[indexBit]); fprintf(hackFile, "\n"); } /* Else if it is a C_COMMAND */ else if(returnCommandType == C_COMMAND) { /* Put the 3 first bits to 1 in the hack file */ for(indexBit = 0; indexBit < 3; ++indexBit) fprintf(hackFile, "1"); /* Get the comp part */ compParser(string); /* Get the binairy */ comp(string, bits); /* Write the comp part into the hack file */ for(indexBit = 0; indexBit < 7; ++indexBit) fprintf(hackFile, "%d", bits[indexBit]); /* Get the dest part */ destParser(string); /* Get the binairy */ dest(string, bits); /* Write the dest part into the hack file */ for(indexBit = 0; indexBit < 3; ++indexBit) fprintf(hackFile, "%d", bits[indexBit]); /* Get the jump part */ jumpParser(string); /* Get the binairy */ jump(string, bits); /* Write the jump part into the hack file */ for(indexBit = 0; indexBit < 3; ++indexBit) fprintf(hackFile, "%d", bits[indexBit]); fprintf(hackFile, "\n"); } } } }
void parseInput() { while (currentToken().type != TT_EOF) { Token tok1 = currentToken(); if (tok1.type == TT_EOL) { nextToken(); } else if (tok1.type == TT_SEMICOLON) { while(nextToken().type != TT_EOL); nextToken(); } else if (tok1.type == TT_WORD) { Token tok2 = nextToken(); if (tok2.type == TT_COLON) { addLabel(tok1.value.str, commandsCount); nextToken(); } else { Command cmd; cmd.type = commandType(tok1.value.str); FREE(tok1.value.str); switch (cmd.type) { case CT_MOV: case CT_ADD: case CT_SUB: case CT_MUL: case CT_MOD: case CT_DIV: cmd.args.arg1 = parseCommandArg(1); cmd.args.arg2 = parseCommandArg(1); break; case CT_JE: case CT_JNE: case CT_JL: case CT_JNL: case CT_JG: case CT_JNG: cmd.args.arg1 = parseCommandArg(1); cmd.args.arg2 = parseCommandArg(1); if (cmd.args.arg2.type != AT_LABEL) { error(ET_UNEXPECTED_TOKEN); } break; case CT_JMP: cmd.args.arg1 = parseCommandArg(1); if (cmd.args.arg1.type != AT_LABEL) { error(ET_UNEXPECTED_TOKEN); } break; case CT_HLT: cmd.args.arg1 = parseCommandArg(1); break; } addCommand(cmd); } } else { error(ET_UNEXPECTED_TOKEN); } } }