日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2023/12/2 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java简单编译器源代码_25行代码实现一个简单的编译器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

起因

《25行JavaScript語(yǔ)句實(shí)現(xiàn)一個(gè)簡(jiǎn)單的編譯器》實(shí)現(xiàn)的是一個(gè)簡(jiǎn)單到不能再簡(jiǎn)單的玩具的玩具,他的魔法是函數(shù)式編程簡(jiǎn)化了js代碼。java 8提供了函數(shù)式編程的支持,昨晚腦子抽風(fēng)突然興趣java也可以實(shí)現(xiàn)一個(gè)如此簡(jiǎn)單的編譯器!

java和js語(yǔ)言差異

java相對(duì)js這類膠水語(yǔ)言來(lái)說(shuō)還是相對(duì)啰嗦的,一些動(dòng)態(tài)語(yǔ)言的特性在java里并不具備。《25行JavaScript語(yǔ)句實(shí)現(xiàn)一個(gè)簡(jiǎn)單的編譯器》的作者是個(gè)js高手js用得溜溜的,下面說(shuō)說(shuō)他用到j(luò)s里有而java沒(méi)有的功能。

js 字符串模板

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

js內(nèi)置 map和簡(jiǎn)單的賦值語(yǔ)法 const node = { val: consume(), type: Op, expr: [] };

其他膠水語(yǔ)言的話對(duì)應(yīng)的是tuple,java要實(shí)現(xiàn)的話還真啰嗦不少。

模式匹配(實(shí)際這是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還木有模式匹配。

沒(méi)有這幾個(gè)js功能,但我們還是可以通過(guò)各種方法繞一下的。怎么繞?請(qǐng)看下文!

java實(shí)現(xiàn)

廢話不啰嗦上代碼,代碼風(fēng)格學(xué)他的也緊促點(diǎn)湊合著看吧!

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實(shí)現(xiàn)lex和transpile用了23行代碼。沒(méi)有tuple java實(shí)現(xiàn)node多花了9行代碼,加起來(lái)用了25行。不過(guò)他加eval功能的代碼行(33行)比我這(29行)可是多的。代碼行數(shù)多少是其次,函數(shù)式編程寫(xiě)代碼還真精簡(jiǎn)不少,寫(xiě)的爽看得也不累。

寫(xiě)在后

最后還是想說(shuō)這個(gè)玩具的玩具。之所以說(shuō)這個(gè)是玩具呢。

首先,他定的語(yǔ)法規(guī)則是非常簡(jiǎn)單的。

其次,表面是一個(gè)乘除加減語(yǔ)言,但是沒(méi)有算術(shù)優(yōu)先級(jí)。

最后,這跟什么編譯器沒(méi)啥多大的關(guān)聯(lián)(詞法分析器用空格直接分割也只能是玩泥沙),如果想寫(xiě)個(gè)簡(jiǎn)單解析器之類的可以參考我的《練手寫(xiě)了個(gè)SQLite解析器》和《一個(gè)android sqlite CRUD代碼生成小工具》

本文源碼下載移步github《tiny-compiler-java》

總結(jié)

以上是生活随笔為你收集整理的java简单编译器源代码_25行代码实现一个简单的编译器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。