C++实现一个简单的语言解释器
描述: 实现一个简单的语言解释器,支持以下指令
指令格式 | 描述 |
---|---|
mov a v | 把数v赋值给a,其中a是变量名称,由不超过10个小写字母组成,v是变量名或者常数 |
inc a | 变量a加1 |
dec a | 变量a减1 |
jnz a v | 如果变量a的值不是0,则相对跳转v条指令。比如-2,向上跳转两个指令 |
输入保证最多有100个变量,100条语句;执行inc, dec和jnz之前,相应变量一定已经用mov赋值过。
输入: mov bx 2 mov ax 5 inc bx dec ax jnz ax -2 dec ax 输出: ax -1 bx
代码实现
#include <iostream> #include <vector> #include <string> #include <list> #include <regex> #include <unordered_map> #include <math.h> #include <memory> static std::regex movRegex("\\s*mov\\s[a-z]{1,10}\\s((-?[1-9][0-9]{0,4})|([1-9][0-9]{0,4}))\\s*"); static std::regex jnzRegex("\\s*jnz\\s[a-z]{1,10}\\s((-?[1-9][0-9]{0,4})|([1-9][0-9]{0,4}))\\s*"); static std::regex incRegex("\\s*inc\\s[a-z]{1,10}\\s*"); static std::regex decRegex("\\s*dec\\s[a-z]{1,10}\\s*"); class SimpleInterpreter { public: SimpleInterpreter() { m_counter = 0; } std::unordered_map<std::string, int> calculation(std::vector<std::string> vctInstructions) { std::unordered_map<std::string, int> mapRst; bool flag = true; int numeric = 0; std::string split; setCounter(vctInstructions.size()); while (flag) { int lineIdx = std::abs((int)vctInstructions.size() - getCounter()); if (lineIdx > (int)vctInstructions.size() - 1) { break; } std::string strInstruction = vctInstructions[lineIdx]; if (std::regex_match(strInstruction, movRegex)) { if (!getSlipt(strInstruction, split, numeric)) { break; } mapRst.insert(std::make_pair(split, numeric)); setCounterPlus(); } else if (std::regex_match(strInstruction, incRegex)) { if (!getSlipt(strInstruction, split)) { break; } auto itr = mapRst.find(split); if (itr != mapRst.end()) { numeric = itr->second; mapRst[split] = numeric + 1; setCounterPlus(); } } else if (std::regex_match(strInstruction, decRegex)) { if (!getSlipt(strInstruction, split)) { break; } auto itr = mapRst.find(split); if (itr != mapRst.end()) { numeric = itr->second; mapRst[split] = numeric - 1; setCounterPlus(); } } else if (std::regex_match(strInstruction, jnzRegex)) { if (!getSlipt(strInstruction, split, numeric)) { break; } auto itr = mapRst.find(split); if (itr == mapRst.end()) { break; } int value = itr->second; if (value != 0) { int counter = getCounter(); setCounter(counter - numeric); } else { setCounterPlus(); } } if (getCounter() <= 0) { flag = false; } } return mapRst; } bool getSlipt(const std::string& instruction, std::string& split, int& numeric) { int posSpace1 = instruction.find(' '); int posSpace2 = instruction.find_last_of(' '); if (posSpace1 == std::string::npos || posSpace2 == std::string::npos) { return false; } int count = posSpace2 - posSpace1 - 1; split = instruction.substr(posSpace1 + 1, count); int length = instruction.length(); count = length - 1 - posSpace2; std::string split2 = instruction.substr(posSpace2 + 1, count); numeric = atoi(split2.c_str()); return true; } bool getSlipt(const std::string& instruction, std::string& split) { int posSpace = instruction.find(' '); if (posSpace == std::string::npos) { return false; } int length = instruction.length(); int count = length - 1 - posSpace; split = instruction.substr(posSpace + 1, count); return true; } int getCounter() { return m_counter; } void setCounter(int counter) { m_counter = counter; } void setCounterPlus() { m_counter--; } private: int m_counter; }; bool isValidInput(std::string& str) { if (std::regex_match(str, movRegex) || std::regex_match(str, jnzRegex) || std::regex_match(str, incRegex) || std::regex_match(str, decRegex)) { return true; } return false; } int main() { std::cout << "请输入您的指令集. 提示:输入finish会停止输入,且最多能输入100条" << std::endl; std::vector<std::string> vctInstructions; std::string line; int count = 0; while (std::getline(std::cin, line)) { count++; if (isValidInput(line)) { vctInstructions.push_back(std::move(line)); } else if (line.compare("finish") == 0 || count > 100) { std::cout << "输入完成" << std::endl; break; } else { std::string strError = "您输入的指令:"; strError.append(line); strError.append("格式错误请重新输入"); std::cout << strError << std::endl; } } std::shared_ptr<SimpleInterpreter> cal(new SimpleInterpreter); std::unordered_map<std::string, int> mapCalculation = cal->calculation(vctInstructions); for (auto itr = mapCalculation.begin(); itr != mapCalculation.end(); ++itr) { std::cout << itr->first << " " << itr->second << std::endl; } return 0; }
关于正则表达式,可以参考:
https://www.runoob.com/regexp/regexp-metachar.html