实现一个简单的 Decaf LSP

背景 编译原理课程在做 Decaf 的 PA ,之前做了一些比较简单的尝试,包括在线 Decaf、在线 TAC VM 等等,都是套一个前端,然后整个编译到 wasm 跑前端就可以了。如果要做 LSP 的话,工作量会稍微大一些,不过也更加实用。 然后有一天,助教 @equation314 写了 decaf-vscode 一个 VSCode 对 Decaf 的语法高亮插件,我就 Fork 了一份到 jiegec/decaf-vscode,然后添加了 LSP 的支持,让它有了一些更高级的功能。 实现 LSP 服务端一般是一个命令行程序,通过 JSONRPC 进行消息通讯,然后就上午找有没有现成的框架。比较重要的是 lsp-types 和 tower-lsp ,前者封装了 LSP 协议的各个结构体,后者提供了服务端的大概实现。不过由于后者做的不大全,所以我自己 fork 了一份添加了一些。 实际实现的时候,需要实现几个函数,分别相应客户端的请求,比如在 initialize 的时候告诉客户端我都实现了哪些东西,然后相应地提供各种信息,如 symbol,hover,folding,definition等等。为了实现简单,我要求客户端每次修改的时候都把完整的文件传过来,虽然不是很高效,但是很简单,目前也没有啥很长的 Decaf 程序嘛。 每次拿到 Decaf 程序之后,就按照 decaf-rs 的方法,Lex 然后 Parse ,然后遍历 AST ,分别把需要的各个信息都存下来,当客户端在请求的时候,直接返回即可。然后就会在 VSCode 中出现,比如实现了 document symbol ,在左边的 Outline 中就会出现相应的结构;实现了 hover ,当移动到一些地方的时候,客户端发出请求,服务端就把相应的 hover 信息返回给客户端。整个协议并不复杂,后面实际实现其实才是比较复杂的地方。 实现的功能中,symbols hovers ranges definition 都是在得到 AST 后一次遍历都计算好,然后返回,同时在遇到错误的时候,也通过 diagnostic 的形式把检查出来的错误汇报给用户。由于 VSCode 的良好支持,基本不需要写 TypeScript 代码。

Read More

每周分享第 50 期

时间过得真快,忽然就 50 期了。。 CLion 的 C++20 Concept 支持 https://blog.jetbrains.com/clion/2019/11/cpp20-concepts-in-clion/ TypeScript 一些工具 https://github.com/pirix-gh/ts-toolbelt Rust 编写的 SystemVerilog Parser https://github.com/dalance/sv-parser MacBookPro 16英寸 发布 用 Rust 写 eBPF 程序 https://blog.redsift.com/labs/putting-rust-in-the-kernel-with-ebpf/ 终端里玩蜘蛛纸牌 https://github.com/chrisbouchard/klondike-rs Rust 的 coverage 工具 https://github.com/mozilla/grcov 在 Menu Bar 或者 Touch Bar 控制 AirPods Pro 模式 https://github.com/insidegui/NoiseBuddy Demangle Rust 符号的工具 https://github.com/luser/rustfilt

Read More

用 Rust Procedure Macro 实现 GLL Parser

背景 在编译原理课上,PA 框架采用的是 MashPlant/lalr1 ,是一个比较好用的 Lexer + Parser 的工具,它的大概语法见 一个完整的例子 。然后之前看到了 GLL Parser ,想着可不可以照着类似的语法也写一个 GLL 的 Parser Generator ,也是用 Rust Procedure Macro 的方法,就开始了研究。 尝试 首先是阅读 GLL 的论文,它并不长,大概的意思就是,LL(1) 文法需要考虑 PS 冲突的情况,而 GLL 的解决方法就是“都试一下”,然后为了效率,用了 GSS 表示解析过程和 SPPF 表示解析结果。然后就开始照着论文手写了不同版本的实现,见 jiegec/gll-test 。 第一种就是按照论文里第一段实现直接抄过来,每个可能性作为一个 Continuation 存下来,它有自己的栈和执行位置(Label)。这样 Work 以后呢,我又想到了 async/await ,用类似的方法又写了一遍,相对要简洁一些,也是很平常的递归下降的写法,而不是 Loop + Label 的形式。但这些都不能做到合并栈的目的,所以遇到十分有歧义的文法的时候会很糟糕。 然后开始按照论文中的 GSS 进行编写,基本还是按照论文进行翻译,然后一步一步做,做好以后把 GSS 画出来,和论文的图可以对的上;然后照着 GLL parse-tree generation 的论文把 SPPF 实现了,这时候就可以从 recongizer 变成一个 parser 了。 宏 得到一份可行的代码以后,就要扩展到通用的情况上。学习了一下 MashPlant/lalr1 的实现,实现了一个 proc macro,它读取了用户的程序,从一个模板文件开始,往里面插入一些生成的代码,丢给编译器去编译。这时候就涉及到编译期和运行时的不同了,我把运行时一些通用的结构放到了 gll-pg-core 中,把编译期的代码放到了 gll-pg-macros 。

Read More

每周分享第 49 期

libuv wrapper in C++ https://github.com/skypjack/uvw Visual Studio Online https://visualstudio.microsoft.com/zh-hans/services/visual-studio-online/ OpenSSH 的 U2F 支持 https://readhacker.news/s/4carE Rust 1.39 Rust 1.39 Released With Async-Await Support, Attributes On Function Parameters Windows 也在用 Rust https://msrc-blog.microsoft.com/2019/11/07/using-rust-in-windows/ 用 Chrome Dev Tools 调试 Rust https://twitter.com/ChromeDevTools/status/1192803818024710145 C++20 的新 Thread 类型 https://medium.com/@vgasparyan1995/a-new-thread-in-c-20-jthread-ebd121ae8906

Read More

每周分享第 48 期

一个特殊的用于显示数字的字体 https://blog.janestreet.com/commas-in-big-numbers-everywhere/ Intel 的 SPMD 编译器 https://ispc.github.io/ 基于 Scala 的 notebook https://polynote.org/ 解析登机牌信息 https://github.com/georgesmith46/bcbp 常用的 React Hooks 库 https://github.com/streamich/react-use jwt 工具 https://github.com/mike-engel/jwt-cli 用过程宏实现的 delegation in Rust https://github.com/chancancode/rust-delegate

Read More

每周分享第 47 期

CLion 完善了 Rust 调试支持 https://blog.jetbrains.com/clion/2019/10/debugging-rust-code-in-clion/ Nginx HTTP3 的 docker 镜像 https://github.com/RanadeepPolavarapu/docker-nginx-http3 手算 Ed25519 https://dang.fan/zh-Hans/posts/25519 Rust 的 QuickCheck https://github.com/BurntSushi/quickcheck Rust 另一个类似 QuickCheck 的测试框架 https://github.com/AltSysrq/proptest Cookie 策略要改了 https://readhacker.news/s/4bvGG

Read More

每周分享第 46 期

LibC++ 正式支持 WASI https://releases.llvm.org/9.0.0/projects/libcxx/docs/ReleaseNotes.html 从文本反推 regex https://github.com/pemistahl/grex KDE 5.17 发布 https://www.omgubuntu.co.uk/2019/10/kde-plasma-5-17-features IDA 7.4 发布 支持 Py3 https://www.hex-rays.com/products/ida/7.4/index.shtml 新的 CPU Bug https://www.phoronix.com/scan.php?page=news_item&px=Chrome-Geminilake-Bug WAST -> WASM in Rust https://docs.rs/wast/

Read More

为 Cisco WLC 配置 Telegraf

最近想到可以给 Cisco WLC 也配置一下监控,查了一下,果然有一些方法。大概研究了一下,找到了方法: 把 https://github.com/haad/net-snmp/tree/master/mibs 和 https://github.com/zampat/neteye4/tree/master/monitoring/monitoring-plugins/wireless/cisco/mibs 目录下的所有 .txt 文件放到 /usr/share/snmp/mibs 目录下。 然后把 https://github.com/zampat/neteye4/blob/master/monitoring/monitoring-plugins/wireless/cisco/telegraf.conf 下面 snmp 的配置复制到 telegraf 配置中,然后修改一下 IP 地址。 确保 Cisco WLC 的 SNMP 的 Public Community 已经配置好,然后就可以拿到数据了。 目前可以拿到 WLC 自身的一些运行˙状态信息、AP 的信息、SSID 的信息和 Client 的信息,基本满足了我们的需求。 参考:https://www.neteye-blog.com/2019/08/monitoring-a-cisco-wireless-controller/

Read More

每周分享第 45 期

Android ARM32/64 环境模拟 https://github.com/zhkl0228/unidbg Calibre 4.0 https://readhacker.news/s/4aukk Rust 的 gRPC 实现 https://github.com/hyperium/tonic JAVA API 历史 https://github.com/marchof/java-almanac Elm 开发 dev server https://github.com/wking-io/elm-live 另一个静态网站生成器 https://github.com/getzola/zola Catalina 发布 Notarization 的相关情况 https://eclecticlight.co/2019/06/07/notarization-in-mojave-and-catalina/ https://eclecticlight.co/2019/05/31/can-you-tell-whether-code-has-been-notarized/ 椭圆曲线加密算法 https://fangpenlin.com/posts/2019/10/07/elliptic-curve-cryptography-explained/ Travis CI 添加 ARM 支持 https://blog.travis-ci.com/2019-10-07-multi-cpu-architecture-support CD 上的结构 https://readhacker.news/s/4aDHB 在线 TAC 的虚拟机 https://jiege.ch/online_tac_vm/ 在线 Decaf 编译和运行 https://jiege.ch/online_decaf/

Read More

每周分享第 44 期

Modern Script Loading https://jasonformat.com/modern-script-loading/ 如何实现 closure http://craftinginterpreters.com/closures.html 加速 uniform_int_distribution 实现 https://lemire.me/blog/2019/09/28/doubling-the-speed-of-stduniform_int_distribution-in-the-gnu-c-library/ 在 FPGA 上运行 Rocket Chip 教程 https://github.com/cnrv/fpga-rocket-chip Xilinx Bitstream 逆向 https://prjxray.readthedocs.io/en/latest/ JVM 利用 SIGSEGV 进行 null 检测 https://jcdav.is/2015/10/06/SIGSEGV-as-control-flow/ Async/Await 进入 Rust Beta https://blog.rust-lang.org/2019/09/30/Async-await-hits-beta.html 在 Rust 里实现 Plugin http://adventures.michaelfbryan.com/posts/plugins-in-rust/

Read More