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




