起因

《25行JavaScript语句实现一个简单的编译器》实现的是一个简单到不能再简单的玩具的玩具,他的魔法是函数式编程简化了js代码。java 8提供了函数式编程的支持,昨晚脑子抽风突然兴趣java也可以实现一个如此简单的编译器!

java和js语言差异

java相对js这类胶水语言来说还是相对啰嗦的,一些动态语言的特性在java里并不具备。《25行JavaScript语句实现一个简单的编译器》的作者是个js高手js用得溜溜的,下面说说他用到js里有而java没有的功能。

js 字符串模板

他在Transpiler中使用ES2015新增的模板字符串功能。 `(${ast.expr.map(transpileNode).join(' ' + opMap[ast.val] + ' ')})`;

js内置 map和简单的赋值语法 const node = { val: consume(), type: Op, expr: [] };

其他胶水语言的话对应的是tuple,java要实现的话还真啰嗦不少。

模式匹配(实际这是js的map啊啊啊) const opAcMap = {

'sum': args => args.reduce((a, b) => a + b, 0),

'sub': args => args.reduce((a, b) => a - b),

'div': args => args.reduce((a, b) => a / b),

'mul': args => args.reduce((a, b) => a * b, 1)

};

java还木有模式匹配。

没有这几个js功能,但我们还是可以通过各种方法绕一下的。怎么绕?请看下文!

java实现

废话不啰嗦上代码,代码风格学他的也紧促点凑合着看吧!

static final int OP = 0, NUM = 1;

private static List lexer(String input){return Stream.of(input.split(" ")).map(String::trim).filter(s -> s.length() > 0).collect(Collectors.toList());}

private static class Parser {

Iterator lex;

String next=null;

public Parser(List lex) { this.lex=lex.iterator(); }

private Node parseOp(String str) {

Node n = new Node(str, OP);

while (lex.hasNext())n.addLast(parse());

return n;

}

public Node parse() { return (next=lex.next()).matches("\\d+") ? new Node(Integer.parseInt(next), NUM) : parseOp(next); }

}

final static Map opMap = new HashMap(4) {{ put("sum", "+"); put("sub", "-"); put("div", "/"); put("mul", "*");}};

private static String codeGenerator (Node ast) { return ast.type == NUM ? String.valueOf(ast.val) : genOp(ast); }

private static String genOp(Node node) { return "(" + node.stream().map(n -> codeGenerator(n)) .collect(Collectors.joining(" " + opMap.get(node.val) + " ")) + ")"; }

private static class Node extends ArrayDeque{

Object val;

int type;

public Node(Object val, int type) {

super();

this.val = val;

this.type = type;

}

}

private static int eval(Node ast) { return (int) (ast.type == NUM ? ast.val : ast.stream().reduce(evalOps.get(ast.val)).get().val); }

final static Map> evalOps=new HashMap>(4) {{

put("sum", (a, b) -> new Node(eval(a) + eval(b), NUM)); put("sub", (a, b) -> new Node(eval(a) - eval(b), NUM));

put("div", (a, b) -> new Node(eval(a) / eval(b), NUM)); put("mul", (a, b) -> new Node(eval(a) * eval(b), NUM));}};

js实现lex和transpile用了23行代码。没有tuple java实现node多花了9行代码,加起来用了25行。不过他加eval功能的代码行(33行)比我这(29行)可是多的。代码行数多少是其次,函数式编程写代码还真精简不少,写的爽看得也不累。

写在后

最后还是想说这个玩具的玩具。之所以说这个是玩具呢。

首先,他定的语法规则是非常简单的。

其次,表面是一个乘除加减语言,但是没有算术优先级。

最后,这跟什么编译器没啥多大的关联(词法分析器用空格直接分割也只能是玩泥沙),如果想写个简单解析器之类的可以参考我的《练手写了个SQLite解析器》和《一个android sqlite CRUD代码生成小工具》

本文源码下载移步github《tiny-compiler-java》

java简单编译器源代码_25行代码实现一个简单的编译器相关推荐

  1. 35 行代码实现一个简单的 shell

    先上代码 shell.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include & ...

  2. 【Unity3D】10行代码实现一个简单的角色移动旋转脚本

    一.前言 今天分享一个简单的角色移动脚本,主要用到碰撞器和刚体组件,代码简单易懂,复用性.扩展性较强,跟我一起来看看吧. 二.效果图 三.代码 using UnityEngine;public cla ...

  3. python文本处理入门:44行代码写一个简单的藏头诗生成器

    想必最近大家家庭群里最近都会看到这么一张图: 一惊,这什么玩意儿???后来一搜会发现里面不同的诗句来自于不同的古诗,嘛,这不是很好玩的一件事情吗?这次我们使用Github的唐诗宋词dataset:ht ...

  4. 37行代码实现一个简单的打游戏AI

    不废话,直接上码,跟神经网络一点关系都没有,这37行代码只能保证电脑的对敌牺牲率是1:10左右,如果想手动操控,注释掉autopilot后边的代码即可. 哪个大神有兴趣可以用tensorflow或者s ...

  5. 用python60行代码写一个简单的笔趣阁爬虫!三分一章?

    前言 利用python写一个简单的笔趣阁爬虫,根据输入的小说网址爬取整个小说并保存到txt文件.爬虫用到了BeautifulSoup库的select方法 结果如图所示: 本文只用于学习爬虫 一.网页解 ...

  6. python编写程序输出诗句_Python文本处理简介:44行代码编写一个简单的隐藏诗生成器,python,入门,藏头诗...

    想必最近大家家庭群里最近都会看到这么一张图: 一惊,这什么玩意儿???后来一搜会发现里面不同的诗句来自于不同的古诗,嘛,这不是很好玩的一件事情吗?这次我们使用Github的唐诗宋词dataset:ht ...

  7. 基于Java和Bytemd用120行代码实现一个桌面版Markdown编辑器

    前提 某一天点开掘金的写作界面的时候,发现了内置Markdown编辑器有一个Github的图标,点进去就是一个开源的Markdown编辑器项目bytemd(https://github.com/byt ...

  8. 200 行代码实现一个简单的区块链应用1

    区块链的基础概念很简单:一个分布式数据库,存储一个不断加长的 list,list 中包含着许多有序的记录.然而,在通常情况下,当我们谈到区块链的时候也会谈起使用区块链来解决的问题,这两者很容易混淆.像 ...

  9. 200 行代码实现一个简单的区块链

    英文原文:Lauri Hartikka 区块链的基础概念很简单:一个分布式数据库,存储一个不断加长的 list,list 中包含着许多有序的记录.然而,在通常情况下,当我们谈到区块链的时候也会谈起使用 ...

最新文章

  1. BeanShell中的Java指令和表达式
  2. linux下查看服务器性能,linux命令查看服务器性能
  3. ACM模板--邻接矩阵 有向图 搜索算法
  4. hadoop balance failed
  5. SAP ui5 单元测试框架 - OPA
  6. vue利用级联选择器实现全国省市区乡村五级菜单联动
  7. 后台开发常用mysql语句_v1.0
  8. 虚拟化部署的四大安全问题
  9. 判定两个点是否在一条直线的同一侧_计算几何01-判定两条线段是否相交
  10. java实现线性填充空值_为什么我的Java字符串用空值填充?
  11. 关于清除丢失贴图与IES文件
  12. 安卓原生系统_你没有用过的安卓系统:原生安卓桌面体验
  13. 电瓶升级问题:在本节最后一个electric_car.py版本中,给Battery类添加一个名为upgrade_battery()的方法。这个方法检查电瓶容量,如果它不是85,就将它设置为85。
  14. D3基础 | 条形图
  15. Python脚本调用谷歌浏览器的谷歌翻译
  16. 同星T1014在线回放设置
  17. php万圣节源码,如何使用纯CSS实现万圣节的toggle控件(附源码)
  18. 解决CUDA error: no kernel image is available for execution on the device
  19. Microbime:微生物组学领域的标准制定
  20. EPON OLT光模块RSSI问题分析报告

热门文章

  1. rowspan不显示 wpf_wpf的datagrid绑定datatable列不自动更新解决方案
  2. Ubuntu16U盘没有不能新建粘贴文件[sdf] Write cache: disabled, read cache: enabled, doesn‘t support DPO or FUA
  3. Ubuntu将python2.7默认更改为python3.X版本
  4. 【渝粤教育】国家开放大学2018年春季 0507-21T非线性编辑 参考试题
  5. [渝粤教育] 西南科技大学 程序设计语言VB 在线考试复习资料(1)
  6. 【渝粤题库】广东开放大学 电子商务安全与支付 形成性考核
  7. android tag定义快捷键,Android Studio快捷键生成TAG、Log.x日志输出介绍
  8. ckfinder php 配置,php – 在Laravel 5中为CKEditor设置路径以使用CKFinder
  9. 无穷级数求和7个公式_大家看,用反证法判别级数敛散性(送微积分同学)!...
  10. 【自适应(盲)均衡5】分数间隔均衡器基本原理及应用(更正数字通信翻译版中公式错误)