V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
qiuyk
V2EX  ›  JavaScript

我也用 js 写了个 js 解析器

  •  1
     
  •   qiuyk · 2019-03-14 15:05:00 +08:00 · 4668 次点击
    这是一个创建于 2084 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一年前看到 bramblex 大佬用 js 写了个js 解析器,觉得很好玩,于是自己也实现了一个,叫sval。一开始实现 es5 和部分 es6,本来想着写着玩一玩就算了,所以也没太上心,估摸这破玩意儿也不会有人用。结果没想到还真的有老外在用,还提了一些 issue。有人反馈了一些 bug,有人问某些特性是不是支持等等,但是大家还是希望支持 async/await

    但是刚好又到了毕业季,一直忙着写论文,就没有怎么搭理这部分 issue,主要就是修修 bug 什么的。这段时间论文差不多写完了,就寻思把后面的特性也给实现了

    可是在实现 generator 的时候卡住了,因为解析的时候都通过递归 dfs 遍历 ast 的,如果要自己保存状态给 yield 出来会十分的蛋疼。一开始想着把 ast 通过后续遍历给拍平,但在节点进行处理的时候仍然会遇到循环(for/while 等),还是得保存状态,这个就不好怕平的。最后实在没办法,把所有的节点处理函数都改成 generator,递归的时候通过 delegate 一层一层把 yield 表达式给暴露处理,然后用 typescript 给编译一下

    有了 generator,实现 async/await 的时候就方便多了,无非就是加个类似 co 的库而已。于是就能吹一波了(逃...

    • 基于 es5,支持 es5/6/7/8 所有特性(嗯,吹牛逼而已,import/export/label/with 这些是不支持的)
    • 浏览器端和 Node 端都能用,自带沙盒模式,可以避免污染外部作用域

    搭了个 PlayGround 给大家玩玩,戳这里

    后面可能会基于 sval 做热更新的库玩玩,基本思路就是服务端做解析生成 ast,直接丢给客户端用 sval 去跑更新,然后 export 出来调用,当然性能不会太好了。目前在自己笔记本上,sval 把自己“自举”一遍,大概 7000 行吧,都要 200ms 左右的时间,而且内存占用应该也不少,只是我还没去看过

    最后放上一个项目地址吧:https://github.com/Siubaak/sval,如果真有人用的话,帮忙提下 bug 吧...

    第 1 条附言  ·  2019-04-10 11:52:31 +08:00

    因为自己很喜欢玩魔方,发现小程序里居然没有一款能用的魔方计时器,然后就做了个qtimer。其中打乱公式生成的模块是通过热更新来进行加载的,将模块发布到CDN上(我这里用了Unpkg),然后小程序把代码拉下来直接用sval在worker里跑就可以了。

    说实话,性能真的不好。在xs上,7阶打乱生成,原生跑也就2ms,sval跑需要600ms,复杂度应该是O(n^3)吧。还好打乱的生成不怎么影响业务体验,但是在稳定以后,还是需要直接打包到小程序里直接跑才行。

    12 条回复    2019-03-14 19:15:24 +08:00
    misaka19000
        1
    misaka19000  
       2019-03-14 15:10:06 +08:00 via Android
    资瓷
    Exia
        2
    Exia  
       2019-03-14 15:25:27 +08:00
    厉害,支持一下
    66beta
        3
    66beta  
       2019-03-14 15:30:30 +08:00 via Android
    汝为何如此优秀
    attackonFourier
        4
    attackonFourier  
       2019-03-14 16:46:40 +08:00   ❤️ 1
    Eich 为了证明 js 的完备性 早年就实现了一个名叫 narcissus 的 js interpreter 后来贡献给了 mz
    lastpass
        5
    lastpass  
       2019-03-14 17:03:26 +08:00 via Android
    厉害了。资瓷。
    顺便安利一下 antlr
    https://github.com/antlr/grammars-v4/tree/master/javascript
    你可以直接生成 js 版 js 解析器。
    qiuyk
        6
    qiuyk  
    OP
       2019-03-14 17:43:38 +08:00 via iPhone
    @lastpass 学习了 我这里 parser 是直接用的 acorn
    qiuyk
        7
    qiuyk  
    OP
       2019-03-14 17:45:33 +08:00 via iPhone
    @lastpass 才发现表述有误了 应该是写了个 js 解释器而不是 js 解析器
    Bramblex2
        8
    Bramblex2  
       2019-03-14 18:12:45 +08:00
    喵喵喵?
    loading
        9
    loading  
       2019-03-14 18:29:00 +08:00 via Android
    我都不敢去看您的代码,这太厉害了吧。
    xcodebuild
        10
    xcodebuild  
       2019-03-14 19:01:07 +08:00
    卧槽居然已经过去一年了
    qiuyk
        11
    qiuyk  
    OP
       2019-03-14 19:03:30 +08:00 via iPhone
    @Bramblex2 哈哈哈哈 大佬出现了
    qiuyk
        12
    qiuyk  
    OP
       2019-03-14 19:15:24 +08:00 via iPhone
    @codefalling 当时我打算重新维护的时候也是这个想法 2333
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3315 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 12:36 · PVG 20:36 · LAX 04:36 · JFK 07:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.