#include #include #include #include #include #include #include // Comp map const std::map compMap = { {"0", "0101010"}, {"1", "0111111"}, {"-1", "0111010"}, {"D", "0001100"}, {"A", "0110000"}, {"!D", "0001101"}, {"!A", "0110001"}, {"-D", "0001111"}, {"-A", "0110011"}, {"D+1", "0011111"}, {"A+1", "0110111"}, {"D-1", "0001110"}, {"A-1", "0110010"}, {"D+A", "0000010"}, {"A+D", "0000010"}, {"D-A", "0010011"}, {"A-D", "0000111"}, {"D&A", "0000000"}, {"A&D", "0000000"}, {"D|A", "0010101"}, {"A|D", "0010101"}, {"M", "1110000"}, {"!M", "1110001"}, {"-M", "1110011"}, {"M+1", "1110111"}, {"M-1", "1110010"}, {"D+M", "1000010"}, {"D+M", "1000010"}, {"D-M", "1010011"}, {"M-D", "1000111"}, {"D&M", "1000000"}, {"M&D", "1000000"}, {"D|M", "1010101"}, {"M|D", "1010101"} }; // dest Map const std::map destMap = { {"null", "000"}, {"M", "001"}, {"D", "010"}, {"MD", "011"}, {"DM", "011"}, {"A", "100"}, {"AM", "101"}, {"MA", "101"}, {"AD", "110"}, {"DA", "110"}, {"ADM", "111"}, {"AMD", "111"}, {"DAM", "111"}, {"DMA", "111"}, {"MDA", "111"}, {"MAD", "111"} }; // jump Map const std::map jumpMap = { {"null", "000"}, {"JGT", "001"}, {"JEQ", "010"}, {"JGE", "011"}, {"JLT", "100"}, {"JNE", "101"}, {"JLE", "110"}, {"JMP", "111"} }; static inline std::string trim(const std::string &s) { size_t a = s.find_first_not_of(" \t\n\r"); if (a == std::string::npos) return ""; size_t b = s.find_last_not_of(" \t\n\r"); return s.substr(a, b - a + 1); } static inline std::string strip(const std::string &s) { std::string result; for (char c : s) { if (!std::isspace(static_cast(c))) { result += c; } } return result; } using symbolsMap = std::map; using labelsMap = std::map; int find_available_address(const symbolsMap &symbols) { int address = 16; // Start from 16 for variables while (true) { bool found = false; for (const auto &pair : symbols) { if (pair.second == address) { found = true; break; } } if (!found) return address; ++address; } } int main() { // Load predefined symbols std::ifstream file("./symbols.json"); nlohmann::json symbols_json = nlohmann::json::parse(file); symbolsMap symbols_map = {}; labelsMap labels_map = symbols_json.get(); std::string line; int line_number = 0; std::vector lines; while (std::getline(std::cin, line)) { // Store lines for first pass line = trim(line); if (line.empty()) continue; // skip comments if (line[0] == '#' || (line.size() > 1 && line[0] == '/' && line[1] == '/')) continue; lines.push_back(line); } auto line_it = lines.begin(); while (line_it != lines.end()) { // First pass to handle labels if ((*line_it)[0] == '(' && line_it->back() == ')') { std::string label = line_it->substr(1, line_it->size() - 2); labels_map[label] = line_number; line_it = lines.erase(line_it); // Remove label lines } else { ++line_it; ++line_number; // Only count non-label lines } } for (const std::string &line : lines) { // Second pass to handle variables if (line[0] == '@') { if (std::isalpha(line[1]) || line[1] == '_') { std::string symbol = line.substr(1); if (labels_map.find(symbol) != labels_map.end()) { continue; // Skip labels, they are already handled } auto it = symbols_map.find(symbol); if (it == symbols_map.end()) { int address = find_available_address(symbols_map); symbols_map[symbol] = address; } } } } for (const std::string &line : lines) { // Second pass to generate // A-instruction if (line[0] == '@') { // Check if it's a symbol or a number if (std::isalpha(line[1]) || line[1] == '_') { std::string symbol = line.substr(1); int address; // search labels first auto labelIt = labels_map.find(symbol); if (labelIt != labels_map.end()) { address = labelIt->second; } else { // Search variables. auto it = symbols_map.find(symbol); if (it != symbols_map.end()) { address = it->second; } } std::bitset<16> binaryValue(address); std::cout << binaryValue.to_string() << '\n'; } else { std::string value = line.substr(1); if (value.empty()) continue; try { int intValue = std::stoi(value); std::bitset<16> binaryValue(intValue); std::cout << binaryValue.to_string() << '\n'; } catch (...) { continue; } } } else { // C-instruction std::string instruction = "111"; size_t eqPos = line.find('='); size_t scPos = line.find(';'); // comp std::string comp; if (eqPos != std::string::npos) { comp = line.substr(eqPos + 1, scPos - eqPos - 1); } else if (scPos != std::string::npos) { comp = line.substr(0, scPos); } else { comp = line; } comp = strip(comp); auto compIt = compMap.find(comp); if (compIt == compMap.end()) continue; instruction += compIt->second; // dest use use destMap "null" key if not found std::string dest = (eqPos != std::string::npos) ? line.substr(0, eqPos) : "null"; dest = strip(dest); auto destIt = destMap.find(dest); instruction += (destIt != destMap.end()) ? destIt->second : destMap.at("null"); // jump std::string jump = (scPos != std::string::npos) ? line.substr(scPos + 1) : "null"; jump = strip(jump); auto jumpIt = jumpMap.find(jump); instruction += (jumpIt != jumpMap.end()) ? jumpIt->second : jumpMap.at("null"); std::cout << instruction << '\n'; line_number++; } } return 0; }