Skip to content
  • 首页
  • 留言
  • 关于

Share the joys of programming and technology

C++实现一个简单的语言解释器

C++实现一个简单的语言解释器

2022年3月20日 liyanliang Comments 0 Comment
阅读次数: 260

描述: 实现一个简单的语言解释器,支持以下指令

指令格式描述
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

相关文章

  • 通过数学方法来计算short类型的变量w的低八位x和高八位通过数学方法来计算short类型的变量w的低八位x和高八位
  • Midas XD-选筋助手开发Midas XD-选筋助手开发
  • Civil Designer开发-检测规范自动生成控制截面Civil Designer开发-检测规范自动生成控制截面
  • Civil Designer开发-公路桥梁承载能力检算评定Civil Designer开发-公路桥梁承载能力检算评定
  • Midas W-满堂支架快速建模助手开发Midas W-满堂支架快速建模助手开发
  • 土木想往土木软件开发方向发展,应该如何准备土木想往土木软件开发方向发展,应该如何准备

C++
C++

Post navigation

PREVIOUS
OpenGL-法线贴图(Normal Mapping)
NEXT
IBL计算总结

发表回复 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

近期文章

  • ANR崩溃日志查看方法
  • 通过数学方法来计算short类型的变量w的低八位x和高八位
  • 3dTiles数据解析
  • Games101和Games202脑图汇总
  • LearnOpenGL脑图汇总
  • IBL计算总结
  • C++实现一个简单的语言解释器
  • OpenGL-法线贴图(Normal Mapping)
  • OpenGL-卡通着色(Cartoon)
  • OpenGL几何着色器实现贝塞尔曲线
  • WinDbg检查内存泄漏
  • OpenGL雾化效果实现-每像素雾化
  • OpenGL实现billboard效果(CPU)
  • 算法:寻找异常数字
  • OpenGL 几何着色器的应用
  • Midas XD-构件详图开发
  • Midas XD-选筋助手开发
  • Civil Designer开发-检测规范自动生成控制截面
  • Civil Designer开发-公路桥梁承载能力检算评定
  • Midas W-满堂支架快速建模助手开发

全站热点

  • C++编写的情人节小程序 (2,083)
  • 提取最小封闭区域 (1,696)
  • Modern OpenGL绘制圆柱体 (1,607)
  • OpenGL开发环境搭建-GLFW与GLAD配置 超详细 (1,465)
  • 截面特性计算程序-附源码 (1,290)
  • OpenGL绘制旋转立方体 (1,110)
  • 判断一个点是否在闭合区域内 (1,032)
  • WordPress分页插件 – WP-PageNavi的使用(替换现有脚本) (948)
  • OpenGL实现billboard效果(CPU) (865)
  • Midas W-满堂支架快速建模助手开发 (837)
  • 从DLL中动态加载一个函数:LoadLibrary和GetProcAddress的使用 (748)
  • Midas XD [错误] 右侧挡土墙的最下端深度必须小于地基的最下端深度 (709)
  • 两跨连续梁影响线绘制-附源码 (686)
  • 土木想往土木软件开发方向发展,应该如何准备 (680)
  • OpenGL几何着色器实现贝塞尔曲线 (664)
  • 通过Spy++抓取窗口以查询对话框id (613)
  • 使用ODA数据库出现 “ODA_ASSUME”: 找不到标识符的错误 (547)
  • #pragma message 编译时提示信息 (527)
  • OpenGL雾化效果实现-每像素雾化 (508)
  • midas XD2020的开发 (476)

分类

  • C# (3)
  • C++ (19)
  • GIS (1)
  • MFC (3)
  • ObjectARX (2)
  • OpenGL (11)
  • Revit开发 (1)
  • 学习笔记 (2)
  • 岩土 (2)
  • 算法 (1)
  • 结构设计 (7)
  • 职场生涯 (1)
  • 计算几何 (3)

归档

  • 2024 年 12 月 (1)
  • 2024 年 10 月 (1)
  • 2024 年 9 月 (1)
  • 2023 年 3 月 (2)
  • 2022 年 10 月 (1)
  • 2022 年 3 月 (1)
  • 2022 年 2 月 (1)
  • 2022 年 1 月 (5)
  • 2021 年 11 月 (7)
  • 2021 年 6 月 (3)
  • 2021 年 5 月 (2)
  • 2021 年 3 月 (2)
  • 2021 年 2 月 (8)
  • 2021 年 1 月 (18)

标签

3dtiles anr Bezier Curves BillBoard C++ CDN CivilDesigner DLL EasyX fog glTF MFC Midas W Midas XD NormalMapping ObjectARX ODA OpenGL OpenXML Open XML PBR revit WinDbg 基坑设计 影响线 截面特性 桥梁 桥梁检测 桥梁设计 算法 计算几何 设计模式

书签

  • 李燕良的CSDN
  • 崔济东的博客
  • C++爱好者博客
  • 陈学伟的博客
  • 贾苏的博客
  • 陈睦锋的博客
  • 孙勇的博客

统计

  • 0
  • 204
  • 103
  • 388
  • 145
  • 268,907
  • 77,790

实时访问地域

© 2025   liyanliang.net Copyright. All Rights Reserved.