源码下载:https://files.cnblogs.com/files/heyang78/basicInterpreter102-20200531-2.rar

输入:

  1. for x= to
  2. print(x)
  3. next
  4.  
  5. print("")
  6.  
  7. for y= to
  8. print(y)
  9. next
  10.  
  11. print("程序结束")

输出:

  1. 原文= for x= to print(x) next print("") for y= to print(y) next print("程序结束")
  2. Index Type No Text Type Desc
  3. ------------------------------------------------------------------------------------
  4. for for
  5. x Variable
  6. = =
  7. Number
  8. to to
  9. Number
  10. print Function
  11. ( (
  12. x Variable
  13. ) )
  14. next next
  15. print Function
  16. ( (
  17. "" String
  18. ) )
  19. for for
  20. y Variable
  21. = =
  22. Number
  23. to to
  24. Number
  25. print Function
  26. ( (
  27. y Variable
  28. ) )
  29. next next
  30. print Function
  31. ( (
  32. "程序结束" String
  33. ) )
  34.  
  35. 执行结果:
  36.  
  37. ""
  38.  
  39. "程序结束"

以下是核心类:

Token类:

  1. package com.heyang;
  2.  
  3. public class Token {
  4. public static final int TYPE_OPEN_PARENTHESIS=0; // (
  5. public static final int TYPE_CLOSE_PARENTHESIS=1; // (
  6. public static final int TYPE_ASSIGN=2; // =
  7. public static final int TYPE_NUMBER=4; // \d+
  8. public static final int TYPE_STRING=5; // \w+
  9. public static final int TYPE_VARIABLE=6; // Variable
  10. public static final int TYPE_FUNCTION=7; // Function
  11. public static final int TYPE_EQUAL=8; // ==
  12. public static final int TYPE_IF=9; // if
  13. public static final int TYPE_THEN=10; // then
  14. public static final int TYPE_LESSTHAN=10; // <
  15. public static final int TYPE_BIGGERTHAN=11; // >
  16. public static final int TYPE_FOR=12; // For
  17. public static final int TYPE_TO=13; // To
  18. public static final int TYPE_NEXT=14; // Next
  19.  
  20. private int type;
  21. private String text;
  22. private int index;// Used to remember location
  23.  
  24. public Token(char c,int type) {
  25. this.text=String.valueOf(c);
  26. this.type=type;
  27. }
  28.  
  29. public Token(String word,int type) {
  30. this.text=word;
  31. this.type=type;
  32. }
  33.  
  34. public String toString() {
  35. return String.format("token(text=%s,type=%s,index=%d)", text,getTypeStr(),index);
  36. }
  37.  
  38. public String getTypeStr() {
  39. if(type==TYPE_OPEN_PARENTHESIS) {
  40. return "(";
  41. }else if(type==TYPE_CLOSE_PARENTHESIS) {
  42. return ")";
  43. }else if(type==TYPE_ASSIGN) {
  44. return "=";
  45. }else if(type==TYPE_NUMBER) {
  46. return "Number";
  47. }else if(type==TYPE_STRING) {
  48. return "String";
  49. }else if(type==TYPE_VARIABLE) {
  50. return "Variable";
  51. }else if(type==TYPE_FUNCTION) {
  52. return "Function";
  53. }else if(type==TYPE_EQUAL) {
  54. return "==";
  55. }else if(type==TYPE_IF) {
  56. return "if";
  57. }else if(type==TYPE_THEN) {
  58. return "then";
  59. }else if(type==TYPE_LESSTHAN) {
  60. return "<";
  61. }else if(type==TYPE_BIGGERTHAN) {
  62. return ">";
  63. }else if(type==TYPE_FOR) {
  64. return "for";
  65. }else if(type==TYPE_TO) {
  66. return "to";
  67. }else if(type==TYPE_NEXT) {
  68. return "next";
  69. }
  70.  
  71. return null;
  72. }
  73.  
  74. public int getType() {
  75. return type;
  76. }
  77.  
  78. public void setType(int type) {
  79. this.type = type;
  80. }
  81.  
  82. public String getText() {
  83. return text;
  84. }
  85.  
  86. public void setText(String text) {
  87. this.text = text;
  88. }
  89.  
  90. public int getIndex() {
  91. return index;
  92. }
  93.  
  94. public void setIndex(int index) {
  95. this.index = index;
  96. }
  97. }

Lexer类:

  1. package com.heyang;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.Collections;
  5. import java.util.List;
  6. import java.util.regex.Pattern;
  7.  
  8. /**
  9. * Parse json string to tokens
  10. * @author Heyang
  11. *
  12. */
  13. public class Lexer {
  14. private List<Token> tokens;
  15.  
  16. public Lexer(String text) {
  17. tokens = new ArrayList<Token>();
  18.  
  19. String swallowed = "";
  20. for (int i = 0; i < text.length(); i++) {
  21. char c = text.charAt(i);
  22.  
  23. if (Character.isWhitespace(c)) {
  24. addTextToList(swallowed);
  25. swallowed="";
  26. continue;
  27. } else if (c == '(') {
  28. addTextToList(swallowed);
  29. swallowed="";
  30.  
  31. tokens.add(new Token(c, Token.TYPE_OPEN_PARENTHESIS));
  32. } else if (c == ')') {
  33. addTextToList(swallowed);
  34. swallowed="";
  35.  
  36. tokens.add(new Token(c, Token.TYPE_CLOSE_PARENTHESIS));
  37. }else if (c == '>') {
  38. addTextToList(swallowed);
  39. swallowed="";
  40.  
  41. tokens.add(new Token(c, Token.TYPE_BIGGERTHAN));
  42. }else if (c == '<') {
  43. addTextToList(swallowed);
  44. swallowed="";
  45.  
  46. tokens.add(new Token(c, Token.TYPE_LESSTHAN));
  47. } else if (c == '=') {
  48. int next=i+1;
  49. if(next<text.length() && text.charAt(next)=='=') {
  50. // ==
  51. addTextToList(swallowed);
  52. swallowed="";
  53. tokens.add(new Token("==",Token.TYPE_EQUAL));
  54. i++;
  55. }else {
  56. // =
  57. addTextToList(swallowed);
  58. swallowed="";
  59. tokens.add(new Token(c, Token.TYPE_ASSIGN));
  60. }
  61. } else if(c == '\"') {
  62. addTextToList(swallowed);
  63. swallowed="";
  64.  
  65. int idx=i+1;
  66.  
  67. while(idx<text.length()) {
  68. char cEnd = text.charAt(idx);
  69.  
  70. if (cEnd == '\"') {
  71. break;
  72. }
  73.  
  74. idx++;
  75. }
  76.  
  77. String sub=text.substring(i, idx+1);
  78. tokens.add(new Token(sub, Token.TYPE_STRING));
  79. i=idx;
  80. } else {
  81. swallowed += c;
  82. }
  83. }
  84.  
  85. setTokenIndexes();
  86. }
  87.  
  88. private void addTextToList(String text) {
  89. if("if".equalsIgnoreCase(text)) {
  90. tokens.add(new Token(text, Token.TYPE_IF));
  91. }else if("then".equalsIgnoreCase(text)) {
  92. tokens.add(new Token(text, Token.TYPE_THEN));
  93. }else if("for".equalsIgnoreCase(text)) {
  94. tokens.add(new Token(text, Token.TYPE_FOR));
  95. }else if("to".equalsIgnoreCase(text)) {
  96. tokens.add(new Token(text, Token.TYPE_TO));
  97. }else if("next".equalsIgnoreCase(text)) {
  98. tokens.add(new Token(text, Token.TYPE_NEXT));
  99. }else if(isFunction(text)) {
  100. tokens.add(new Token(text, Token.TYPE_FUNCTION));
  101. }else if(isNumber(text)) {
  102. tokens.add(new Token(text, Token.TYPE_NUMBER));
  103. }else if(isVarable(text)) {
  104. tokens.add(new Token(text, Token.TYPE_VARIABLE));
  105. }
  106. }
  107.  
  108. private boolean isFunction(String text) {
  109. if("print".equalsIgnoreCase(text)) {
  110. return true;
  111. }
  112.  
  113. return false;
  114. }
  115.  
  116. private boolean isNumber(String code) {
  117. final String patternStr = "\\d+";
  118. return Pattern.matches(patternStr, code);
  119. }
  120.  
  121. private boolean isVarable(String code) {
  122. final String patternStr = "([a-zA-Z_])\\w*";
  123. return Pattern.matches(patternStr, code);
  124. }
  125.  
  126. public void printTokens() {
  127. final String continuousStar = createRepeatedStr("-", 84);
  128. final String layout = "%-20s %-20s %-20s %-20s %s";
  129. StringBuilder sb = new StringBuilder();
  130.  
  131. sb.append(String.format(layout, "Index", "Type No","Text","Type Desc","\n"));
  132. sb.append(continuousStar + "\n");
  133. int index=0;
  134. for(Token token:tokens) {
  135. sb.append(String.format(layout, String.valueOf(index),String.valueOf(token.getType()), token.getText(),token.getTypeStr(),"\n"));
  136. index++;
  137. }
  138.  
  139. System.out.println(sb.toString());
  140. }
  141.  
  142. private static String createRepeatedStr(String seed, int n) {
  143. return String.join("", Collections.nCopies(n, seed));
  144. }
  145.  
  146. public void setTokenIndexes() {
  147. int idx = 0;
  148. for (Token t : tokens) {
  149. idx++;
  150. t.setIndex(idx);
  151. }
  152. }
  153.  
  154. public String getCompactJsonTxt() {
  155. StringBuilder sb=new StringBuilder();
  156.  
  157. for (Token t : tokens) {
  158. sb.append(t.getText());
  159. }
  160.  
  161. return sb.toString();
  162. }
  163.  
  164. public List<Token> getTokenList() {
  165. return tokens;
  166. }
  167. }

Interpreter类:

  1. package com.heyang;
  2.  
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. import java.util.Stack;
  7.  
  8. class LoopInfo{
  9. public LoopInfo(String loopValueName,int limit,int startLocation) {
  10. this.loopValueName=loopValueName;
  11. this.limit=limit;
  12. this.startLocation=startLocation;
  13. }
  14.  
  15. String loopValueName;
  16. int limit;
  17. int startLocation;
  18. }
  19. public class Interpreter {
  20. private List<Token> tokens;
  21. private int tokenIdx;
  22. private Map<String,Integer> varmap;
  23. private Stack<LoopInfo> loopStack;
  24.  
  25. public Interpreter(List<Token> tokens) throws Exception{
  26. this.tokens=tokens;
  27. this.tokenIdx=0;
  28. varmap=new HashMap<String,Integer>();
  29. loopStack=new Stack<LoopInfo>();
  30.  
  31. execute();
  32. }
  33.  
  34. private void execute() throws Exception{
  35.  
  36. Token token;
  37. for(;;) {
  38. token=fetchToken();
  39. if(token==null) {
  40. return;
  41. }
  42.  
  43. if(token.getType()==Token.TYPE_VARIABLE) {
  44. String varibleName=token.getText();
  45.  
  46. token=fetchToken();
  47. if(token.getType()==Token.TYPE_ASSIGN) {
  48. token=fetchToken();
  49.  
  50. if(token.getType()==Token.TYPE_NUMBER) {
  51. int variableValue=Integer.parseInt(token.getText());
  52.  
  53. // 赋值核心语句
  54. varmap.put(varibleName, variableValue);
  55. }
  56. }else {
  57. throw new Exception("Expected:'=' actual:"+token.getText()+" "+token);
  58. }
  59. }else if(token.getType()==Token.TYPE_FUNCTION) {
  60. String functionName=token.getText();
  61.  
  62. if("print".equalsIgnoreCase(functionName)) {
  63. token=fetchToken();
  64. if(token.getType()!=Token.TYPE_OPEN_PARENTHESIS) {
  65. throw new Exception("Expected:'(' actual:"+token.getText()+" "+token);
  66. }
  67.  
  68. token=fetchToken();
  69. if(token.getType()==Token.TYPE_STRING) {
  70. // 打印字符串
  71. String str=token.getText();
  72. System.out.println(str);
  73. }else if(token.getType()==Token.TYPE_VARIABLE) {
  74. String varibleName=token.getText();
  75.  
  76. // 打印变量
  77. if(varmap.containsKey(varibleName)) {
  78. int value=varmap.get(varibleName);
  79. System.out.println(value);
  80. }else {
  81. System.out.println("Variable:'"+varibleName+"' was not assigned.");
  82. }
  83. }
  84. }
  85. }else if(token.getType()==Token.TYPE_IF) {
  86. int vLeft,vRight;
  87. String oprand;
  88.  
  89. // get left value
  90. token=fetchToken();
  91. if(token.getType()==Token.TYPE_VARIABLE) {
  92. String varibleName=token.getText();
  93.  
  94. if(varmap.containsKey(varibleName)) {
  95. vLeft=varmap.get(varibleName);
  96. }else {
  97. throw new Exception("Variable:'"+varibleName+"' was not assigned.");
  98. }
  99. }else if(token.getType()==Token.TYPE_NUMBER) {
  100. vLeft=Integer.parseInt(token.getText());
  101. }else {
  102. throw new Exception("Expected:number/variable actual:"+token.getText()+" "+token);
  103. }
  104.  
  105. // get ==,<,>
  106. token=fetchToken();
  107. if(token.getType()!=Token.TYPE_EQUAL && token.getType()!=Token.TYPE_LESSTHAN && token.getType()!=Token.TYPE_BIGGERTHAN) {
  108. throw new Exception("Expected:'== or > or <' actual:"+token.getText()+" "+token);
  109. }
  110. oprand=token.getText();
  111.  
  112. // get right
  113. token=fetchToken();
  114. if(token.getType()==Token.TYPE_VARIABLE) {
  115. String varibleName=token.getText();
  116.  
  117. if(varmap.containsKey(varibleName)) {
  118. vRight=varmap.get(varibleName);
  119. }else {
  120. throw new Exception("Variable:'"+varibleName+"' was not assigned.");
  121. }
  122. }else if(token.getType()==Token.TYPE_NUMBER) {
  123. vRight=Integer.parseInt(token.getText());
  124. }else {
  125. throw new Exception("Expected:number/variable actual:"+token.getText()+" "+token);
  126. }
  127.  
  128. // Compare
  129. if(compare(vLeft,oprand,vRight)) {
  130. // get then
  131. token=fetchToken();
  132. if(token.getType()!=Token.TYPE_THEN) {
  133. throw new Exception("Expected:'then' actual:"+token.getText()+" "+token);
  134. }
  135. }else {
  136. // 跳过两个token(then及后面的dosth)
  137. fetchToken();
  138. fetchToken();
  139. }
  140. }
  141. else if(token.getType()==Token.TYPE_FOR) {
  142. token=fetchToken();
  143. if(token.getType()!=Token.TYPE_VARIABLE) {
  144. throw new Exception("Expected:variable actual:"+token.getText()+" "+token);
  145. }
  146. String varibleName=token.getText();
  147.  
  148. token=fetchToken();
  149. if(token.getType()==Token.TYPE_ASSIGN) {
  150. token=fetchToken();
  151.  
  152. if(token.getType()==Token.TYPE_NUMBER) {
  153. int variableValue=Integer.parseInt(token.getText());
  154.  
  155. // 赋值核心语句
  156. varmap.put(varibleName, variableValue);
  157. }
  158. }else {
  159. throw new Exception("Expected:'=' actual:"+token.getText()+" "+token);
  160. }
  161.  
  162. token=fetchToken();
  163. if(token.getType()!=Token.TYPE_TO) {
  164. throw new Exception("Expected:to actual:"+token.getText()+" "+token);
  165. }
  166.  
  167. token=fetchToken();
  168. if(token.getType()!=Token.TYPE_NUMBER) {
  169. throw new Exception("Expected:number actual:"+token.getText()+" "+token);
  170. }
  171.  
  172. int limit=Integer.parseInt(token.getText());
  173. int variableValue=varmap.get(varibleName);
  174.  
  175. if(variableValue<=limit) {
  176. loopStack.push(new LoopInfo(varibleName,limit,tokenIdx));
  177. }else {
  178. fetchToken();
  179. }
  180.  
  181. }
  182. else if(token.getType()==Token.TYPE_NEXT) {
  183. doNext();
  184. }
  185. }
  186. }
  187.  
  188. private void doNext() {
  189. LoopInfo info=loopStack.pop();
  190. int variableValue=varmap.get(info.loopValueName)+1;
  191. varmap.put(info.loopValueName, variableValue);
  192.  
  193. if(variableValue>info.limit) {
  194. //
  195. }else {
  196. loopStack.push(info);
  197. tokenIdx=info.startLocation;
  198. }
  199. }
  200.  
  201. private boolean compare(int vLeft,String oprand,int vRight) throws Exception{
  202. if("==".equals(oprand)) {
  203. return vLeft==vRight;
  204. }else if(">".equals(oprand)) {
  205. return vLeft>vRight;
  206. }else if("<".equals(oprand)) {
  207. return vLeft<vRight;
  208. }else {
  209. throw new Exception("oprand should be == or > or < but not.");
  210. }
  211. }
  212.  
  213. private Token fetchToken() {
  214. if(tokenIdx>=tokens.size()) {
  215. return null;
  216. }else {
  217. Token t=tokens.get(tokenIdx);
  218. tokenIdx++;
  219. return t;
  220. }
  221. }
  222.  
  223. private void returnToken() {
  224. if(tokenIdx>0) {
  225. tokenIdx--;
  226. }
  227. }
  228. }

入口类:

  1. package com.heyang;
  2.  
  3. import com.heyang.util.BracketChecker;
  4. import com.heyang.util.CommonUtil;
  5. import com.heyang.util.Renderer;
  6.  
  7. public class EntryPoint {
  8. public static void main(String[] args) {
  9. try {
  10. // Read context from file
  11. String text=CommonUtil.readTextFromFile("C:\\hy\\files\\basic\\05.basic");
  12. System.out.println("原文="+text);
  13.  
  14. // Is brackets balanced
  15. BracketChecker checker=new BracketChecker();
  16. boolean isBalanced=checker.isBalanced(text);
  17. if(isBalanced==false) {
  18. System.out.println(Renderer.paintBrown(checker.getErrMsg()));
  19. return;
  20. }
  21.  
  22. // lex text to tokens
  23. Lexer lex=new Lexer(text);
  24. lex.printTokens();
  25.  
  26. // Execute
  27. System.out.println("执行结果:\n");
  28. new Interpreter(lex.getTokenList());
  29. }catch(Exception ex) {
  30. System.out.println(Renderer.paintBrown(ex.getMessage()));
  31. ex.printStackTrace();
  32. }
  33. }
  34. }

--2020年5月31日--

basicInterpreter1.02 增加对for循环的支持的更多相关文章

  1. MWeb 1.3.7 发布!增加发布到 Wordpress 等支持 MetaWeblog API 的服务,如:Wordpress 博客、新浪博客、cnblogs、oschina。

    MWeb 1.3.7 版的新功能 增加发布到 Wordpress 等支持 Metaweblog API 的服务,目前经测试过的有: Wordpress 博客.新浪博客.cnblogs.oschina. ...

  2. AndroidInject项目使用动态代理增加对网络请求的支持

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3540427.html AndroidInject项目是我写的一 ...

  3. 在内核中增加对yaffs文件系统的支持

    自己最近在搞一些内核以及根文件系统的移植,就涉及到了需要在内核中增加对yaffs文件系统的支持.在网上找了一些文档后,自己将具体的操作过程做了一个总结,方便以后查询使用: 1.获取yaffs源码 YA ...

  4. NGINX 加载动态模块(NGINX 1.9.11开始增加加载动态模块支持)

    NGINX 1.9.11开始增加加载动态模块支持,从此不再需要替换nginx文件即可增加第三方扩展.目前官方只有几个模块支持动态加载,第三方模块需要升级支持才可编译成模块. tinywan@tinyw ...

  5. dubbo/dubbox 增加原生thrift及avro支持

    (facebook) thrift / (hadoop) avro / (google) probuf(grpc)是近几年来比较抢眼的高效序列化/rpc框架,dubbo框架虽然有thrift的支持,但 ...

  6. cocos2d-x编译到android平台后,增加返回键和菜单键支持

    在头文件中增加函数 virtual void keyBackClicked();//android返回键 virtual void keyMenuClicked();//android菜单键 在ini ...

  7. subilme增加对markdown的高亮支持

    sublime2对markdown原生主题支持都没有, 需要通过插件补充 1.插件安装 通过Package Control安装下列插件: Markdown Extended Monokai Exten ...

  8. Touch Punch在移动设备上面增加jQuery UI的触摸支持|Jquery UI 支持移动端 触摸滑动等

    jQuery UI是我们前台开发常用的UI前端类库,但是目前的jQuery UI用户界面类库在互动和widget上并不支持touch事件.这意味着你在桌面上设计的优雅的UI可能在触摸设备,例如,ipa ...

  9. 增加响应header让ajax支持跨域

    ajax请求数据步骤 发送请求--->浏览器接受响应--->判断是否是同域下 是的话,就把响应数据返回给ajax.不是的话就提醒禁止跨域请求. 现在可以在响应头重增加 header(&qu ...

随机推荐

  1. DotNet Core

    安装 dotnet add package Pomelo.EntityFrameworkCore.MySql 使用 MySQL 作为后端     在继承 DbContext 类中重写 OnConfig ...

  2. 【Spring Security】1.快速入门

    1 导入Spring Security的相关依赖 <dependency> <groupId>org.springframework.boot</groupId> ...

  3. C#LeetCode刷题之#88-合并两个有序数组(Merge Sorted Array)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3686 访问. 给定两个有序整数数组 nums1 和 nums2, ...

  4. Homekit_温湿度传感器

    本款产品为Homekit相关产品需要使用苹果手机进行操作,有兴趣的可以去以下链接购买: https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-112 ...

  5. oracle正则表达式语法介绍及实现手机号码匹配方法

    Oracle10g提供了在查询中使用正则表达的功能,它是通过各种支持正则表达式的函数在where子句中实现的.本文将简单的介绍oracle正则表达式常用语法,并通过一个手机特号匹配的例子演示正则表达式 ...

  6. 一文看懂 Netty 架构设计

    本文重点分析 Netty 的逻辑架构及关键的架构质量属性,希望有助于大家从 Netty 的架构设计中汲取营养,设计出高性能.高可靠性和可扩展的程序. Netty 的三层架构设计 Netty 采用了典型 ...

  7. day1 计算机的组成

    1.计算机,是用于高速计算的电子机器,具有数值计算, 逻辑判断,储存记忆的功能. 2.计算机由硬件系统和软件系统组成构成. 3.计算机中所有的运行程序都是在内存中进行的,暂时存放在CPU中的运算数据 ...

  8. PYTHON-错误-函数有返回值未接收导致替换不成功

    #1.有返回值,没有赋值,替换不成功 cxj = 'guapi' cxj.replace(cxj,'2b') print(cxj) #2.有返回值,赋值,替换成功 cxj = 'guapi' cxj ...

  9. 真正从底层理解 Synchronized 实现原理

    实现synchronized的基础有两个:Java 对象头和 Monitor. 在虚拟机规范中定义了对象在内存中的布局,主要由以下 3 部分组成: 对象头 实例数据 对齐填充 而synchronize ...

  10. unsigned char printf 如何输出

    参考链接:https://blog.csdn.net/m0_37362454/article/details/88639668 #include <stdio.h> int main() ...