Robust第22期:用AST实现简易的中文编程

广告位招租
扫码页面底部二维码联系

【未经授权禁止转载】【原创内容,转载请注明出处】未经授权,禁止复制转载。

中文编程是件很有意思的事情,通过基于AS转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.netT的编译方法,可以让我们实现一种中文编程【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net语言。本期Robust主要聊一聊AST,著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net顺带把基于AST的编译实现过程,以及以中【本文受版权保护】未经授权,禁止复制转载。文编程为例子,聊一聊AST的一些用法,让著作权归作者所有,禁止商业用途转载。【本文受版权保护】你在工作中,遇到一些特殊语法时,可以快速【转载请注明来源】【原创内容,转载请注明出处】建立自己的解决方法。

未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。

勘误:本期是22期,音频中说成21期。

【关注微信公众号:wwwtangshua【作者:唐霜】未经授权,禁止复制转载。ngnet】本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】

补充:AST可用于正式线上环境,不仅限于【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。编译器阶段。比如我音频中提到,我用AST【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】完成模板渲染,就是在生产环境使用,否则就【原创不易,请尊重版权】【原创不易,请尊重版权】没有意义了。

【本文首发于唐霜的博客】【转载请注明来源】【本文受版权保护】

在线收听

网易云音乐:点击播放

转载请注明出处:www.tangshua【本文受版权保护】本文作者:唐霜,转载请注明出处。ng.net本文版权归作者所有,未经授权不得转载。

喜马拉雅:点击播放

原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。

你还可以在苹果自带的 Podcast 应【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net用中搜“Robust”找到我们的节目收听本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net

本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】

捐赠支持

求打赏🙇如果你觉得 Ro本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】bust 这样一档技术类的谈话节目还不错【原创内容,转载请注明出处】【作者:唐霜】,希望我继续做下去,不妨打赏支持。

著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】【版权所有,侵权必究】

本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.n原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】【版权所有】唐霜 www.tangshu【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。ang.net

内容大纲

如果一等于一,那么显示“成功”。
【作者:唐霜】原创内容,盗版必究。【未经授权禁止转载】
【原创不易,请尊重版权】【版权所有】唐霜 www.tangshu【未经授权禁止转载】【作者:唐霜】ang.net【原创内容,转载请注明出处】原创内容,盗版必究。
人有一双眼睛,我是人。
【版权所有】唐霜 www.tangshu著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】ang.net【版权所有,侵权必究】【本文受版权保护】【本文受版权保护】
如果我有一双眼睛,那么显示“成功”。
未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。
【本文首发于唐霜的博客】原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。
我的名字是“否子戈”。
【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.netang.net转载请注明出处:www.tangshua未经授权,禁止复制转载。未经授权,禁止复制转载。ng.net【原创内容,转载请注明出处】
我的学号是141446。
著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshu本文作者:唐霜,转载请注明出处。原创内容,盗版必究。ang.net【本文首发于唐霜的博客】【作者:唐霜】
显示“我的名字和学号分别是「我的名字」、未经授权,禁止复制转载。未经授权,禁止复制转载。「我的学号」”。
本文作者:唐霜,转载请注明出处。【转载请注明来源】未经授权,禁止复制转载。未经授权,禁止复制转载。
显示我的全部信息。
著作权归作者所有,禁止商业用途转载。【转载请注明来源】【转载请注明来源】
如果我的学号是偶数,那么显示我的名字。
本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。
本文作者:唐霜,转载请注明出处。【转载请注明来源】本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】ngnet】
【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshu【作者:唐霜】原创内容,盗版必究。ang.net原创内容,盗版必究。
1. 简易编程的共性
【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。
– 定义语句:什么是什么,什本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】么属于什么,什么有什么,什么的什么是什么
【转载请注明来源】本文版权归作者所有,未经授权不得转载。
– 条件语句:如果̷本文作者:唐霜,转载请注明出处。【作者:唐霜】0;那么
【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net【本文受版权保护】ang.net【关注微信公众号:wwwtangshua【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。ngnet】转载请注明出处:www.tangshua【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。ng.net
– 逻辑语句:不仅̷著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。0;而且,既是……又是,和,或,不是,不【本文受版权保护】【本文受版权保护】
【本文受版权保护】【关注微信公众号:wwwtangshua【原创内容,转载请注明出处】未经授权,禁止复制转载。ngnet】
– 循环语句:?从0到10依【本文首发于唐霜的博客】【原创内容,转载请注明出处】次执行,循环5次,一直循环直到我的年龄为本文作者:唐霜,转载请注明出处。【未经授权禁止转载】12
【转载请注明来源】【原创内容,转载请注明出处】【原创不易,请尊重版权】
– 运算语句:1加1,100转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。除50,2的6次方
转载请注明出处:www.tangshua未经授权,禁止复制转载。【版权所有,侵权必究】ng.net【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】【原创内容,转载请注明出处】
– 函数语句:我会唱歌:树上本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】的鸟儿成双对。我唱歌。
著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。本文作者:唐霜,转载请注明出处。
【本文首发于唐霜的博客】原创内容,盗版必究。【作者:唐霜】
2. 抽象语法树(Abstract sy【作者:唐霜】原创内容,盗版必究。ntax tree)
本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshua【作者:唐霜】【转载请注明来源】ngnet】【未经授权禁止转载】原创内容,盗版必究。
源代码的语法结构的抽象树状表示。源代码就【本文首发于唐霜的博客】【转载请注明来源】是一串字符串,该字符串是一种语法结构,既著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。然是结构,那么就可以通过某种形式进行表示【转载请注明来源】本文版权归作者所有,未经授权不得转载。,而AST就是其中的一种表示方法,它的特【本文首发于唐霜的博客】【本文首发于唐霜的博客】点是将语法结构抽象成一个树状的数据结构,【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net在js中就是一个树状的对象结构。
转载请注明出处:www.tangshua【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。ng.net【本文受版权保护】
转载请注明出处:www.tangshua【作者:唐霜】【版权所有】唐霜 www.tangshuang.netng.net【原创内容,转载请注明出处】未经授权,禁止复制转载。
3. 怎么得到AST
【访问 www.tangshuang.n【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。et 获取更多精彩内容】【本文首发于唐霜的博客】【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。
一般分为两步,第一步是通过一个token原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】izer方法,遍历原始字符串得到一个一维【未经授权禁止转载】【本文首发于唐霜的博客】数组,这个一维数组称为tokens。第二【关注微信公众号:wwwtangshuangnet】【本文受版权保护】步是通过一个parser方法,遍历tok转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。ens得到一个树状结构的对象,这个对象被未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】称为ast。
【转载请注明来源】本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】
【版权所有】唐霜 www.tangshu【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.netang.net【作者:唐霜】【原创不易,请尊重版权】未经授权,禁止复制转载。
4. tokenizer方法
【转载请注明来源】转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net原创内容,盗版必究。ng.net
本质上,就是如何去切割字符串。首先,我们未经授权,禁止复制转载。【未经授权禁止转载】要定义自己的语法,去寻找语法中的关键字。转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】比如,我们定义「如果一等于一,那么显示“【版权所有】唐霜 www.tangshuang.net【作者:唐霜】成功”。」这句话的内在逻辑,实际上是通过未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】“如果”“等于”“那么”“显示”以及双引原创内容,盗版必究。【未经授权禁止转载】号和句尾的句号表示的。每一个关键字,都有转载请注明出处:www.tangshuang.net【版权所有,侵权必究】一个自己的类型,由被拆分之后得到的字符串转载请注明出处:www.tangshuang.net【本文受版权保护】段和每个段自己的类型组成的数组,就是to原创内容,盗版必究。【转载请注明来源】kens。所以「如果一等于一,那么显示“转载请注明出处:www.tangshuang.net【未经授权禁止转载】成功”。」的tokens就是【(“条件”【版权所有】唐霜 www.tangshuang.net【转载请注明来源】,“如果”),(“数字”,“一”),(“本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】判断”,“等于”),(“数字”,“一”)原创内容,盗版必究。【转载请注明来源】,(“符号”,“,”),(“结果”,“那转载请注明出处:www.tangshuang.net【转载请注明来源】么”),(“命令”,“显示”),(“文本【转载请注明来源】【版权所有】唐霜 www.tangshuang.net”,”成功“),(”符号“,”。“)】
本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。ng.net本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。
具体怎么做呢?随便怎么都可以,只要你得到【转载请注明来源】著作权归作者所有,禁止商业用途转载。正确预期的结果就行。
【版权所有】唐霜 www.tangshu【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。ang.net转载请注明出处:www.tangshua【原创不易,请尊重版权】【本文受版权保护】ng.net
本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.netang.net
5. parser方法
转载请注明出处:www.tangshua未经授权,禁止复制转载。【本文受版权保护】ng.net未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。【转载请注明来源】
和tokenizer非常像,也是在遍历过【版权所有,侵权必究】原创内容,盗版必究。程中,逐渐生成和组合出一个树状的数据结构【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】。在遍历一开始,生成一个根节点,一般该节【本文首发于唐霜的博客】未经授权,禁止复制转载。点的类型叫Program,并用一个bod【未经授权禁止转载】转载请注明出处:www.tangshuang.nety属性存放所有内部节点。根据碰到的tok著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。en类型,创建一个节点node,或将该t【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】oken的值作为当前节点的内容之一。总而本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】言之,和tokens单纯的一个数组不同,原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】parser遍历过程中生成的ast是有嵌【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。套结构的,比如一个函数或一个语句块,它本著作权归作者所有,禁止商业用途转载。【作者:唐霜】身是一个节点,它的内容是节点的内容,而内【转载请注明来源】【作者:唐霜】容又是由多个平行节点,以及它们的子节点组本文版权归作者所有,未经授权不得转载。【转载请注明来源】成。
转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net原创内容,盗版必究。ng.net【作者:唐霜】
【关注微信公众号:wwwtangshua原创内容,盗版必究。转载请注明出处:www.tangshuang.netngnet】【转载请注明来源】
6. AST转换
原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。
得到AST之后,我们就得到了关于一段代码本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。的抽象语法结构。但是,这段抽象语法结构必【本文首发于唐霜的博客】【本文首发于唐霜的博客】须要成为可以被计算机识别的代码,才可以在【未经授权禁止转载】未经授权,禁止复制转载。计算机中运行,那具体怎么做呢?我们可以把【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】它转化为其他可以直接运行的编程语言之后,【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。再以其他编程语言直接运行,比如转化为js【本文受版权保护】【版权所有,侵权必究】语言在浏览器中直接运行,或者python原创内容,盗版必究。转载请注明出处:www.tangshuang.net在机器上运行,当然,还可以有其他选择,比本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。如直接转化为计算机指令运行,或者转化为c著作权归作者所有,禁止商业用途转载。【本文受版权保护】等语言,再编译后得到字节码运行。
转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。ng.net【版权所有,侵权必究】
怎么才能将上面的AST转化为其他语言运行【原创内容,转载请注明出处】【本文首发于唐霜的博客】呢?也分两步:AST转换,代码生成。
本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】转载请注明出处:www.tangshua【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.netng.net
AST转换就是将当前的AST转换为另外一【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。个AST。经过转换后,可以方便的生成另外原创内容,盗版必究。原创内容,盗版必究。一种编程语言。比如,上面的中文文本中的如【原创不易,请尊重版权】【作者:唐霜】果……那么结构,我们可以转化到shell本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。脚本运行,而shell中表示如果……那么【转载请注明来源】本文版权归作者所有,未经授权不得转载。的语句是 if…then&#【版权所有,侵权必究】转载请注明出处:www.tangshuang.net8230;fi 语句,所以,我们要将基于【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。中文的这个AST转换为方便生成shell【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。语句的ast。
【未经授权禁止转载】【原创不易,请尊重版权】
【版权所有】唐霜 www.tangshu【版权所有,侵权必究】【作者:唐霜】ang.net转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】ng.net本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。
7. 生成代码
著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshu【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。ang.net【作者:唐霜】
在经过AST转化之后,得到一个新ast,本文作者:唐霜,转载请注明出处。原创内容,盗版必究。而这个新ast,是比较方便新代码生成的a原创内容,盗版必究。原创内容,盗版必究。st。什么样才方便生成新代码呢?生成新代著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】码的过程,实际上也是一个遍历过程,在遍历【未经授权禁止转载】【作者:唐霜】过程中,不断组合成新代码的字符串。遍历结【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。束的时候,就是新代码字符串完成出现的时候未经授权,禁止复制转载。【本文首发于唐霜的博客】。而由于ast是一个树状结构,遍历树的方未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net法也很简单,所以,拼接字符串而已。
转载请注明出处:www.tangshua原创内容,盗版必究。本文作者:唐霜,转载请注明出处。ng.net【版权所有,侵权必究】未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。
【访问 www.tangshuang.n【本文受版权保护】【作者:唐霜】et 获取更多精彩内容】【本文首发于唐霜的博客】
8. 提供修改ast的接口
未经授权,禁止复制转载。未经授权,禁止复制转载。
基于ast的js转化工具babel,提供本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net了插件能力。它的插件主要是对已经解析好的著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】es ast进行调整。同样的道理,我们一【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。般会在这个过程中,提供一种让开发者调整a本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】st的接口。
【本文受版权保护】【本文受版权保护】转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.netng.net
通过这种调整,开发者可以控制最终输出的代【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。码。比如调整代码输出的顺序,只需要改变a本文作者:唐霜,转载请注明出处。【作者:唐霜】st中节点的顺序即可。
原创内容,盗版必究。本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。
但是你会发现,要通过babel支持新语法【本文受版权保护】未经授权,禁止复制转载。则比较麻烦。比如,我们要支持一个@@的语著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】法,非常麻烦,我们需要克隆babel的代本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。码,然后自己去修改babel解析器中的逻【原创内容,转载请注明出处】【原创内容,转载请注明出处】辑,才能完成这个语法添加。这是因为,ba【本文首发于唐霜的博客】【本文首发于唐霜的博客】bel并没有直接提供tokenizer和著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.netparser的接口。
【本文首发于唐霜的博客】【关注微信公众号:wwwtangshua著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。ngnet】本文作者:唐霜,转载请注明出处。
【本文首发于唐霜的博客】转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】ng.net【转载请注明来源】【作者:唐霜】
9. 编译器
【访问 www.tangshuang.n未经授权,禁止复制转载。未经授权,禁止复制转载。et 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】【未经授权禁止转载】
这样我们就发明了一门新编程语言,用中文来【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net编程。虽然它的能力还比较弱,只支持简单的【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】加减乘除,但是,你会发现用中文写代码,比转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】英文写代码代码量更少,且表达更准确。
本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshua【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】ng.net【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。et 获取更多精彩内容】【原创内容,转载请注明出处】
【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。
10. AST还能干什么?
【关注微信公众号:wwwtangshua未经授权,禁止复制转载。【转载请注明来源】ngnet】【本文受版权保护】
我在腾讯内完成了一个从模板到界面的功能,未经授权,禁止复制转载。原创内容,盗版必究。我让客户按照我提供的特定标识进行模板撰写【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net,而这样撰写出来的模板实际上就是有语法的【未经授权禁止转载】【作者:唐霜】文本。借助ast,这些模板被解析为特定的【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.netast,而利用这个ast,我做了3件事:本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net1)语法高亮,客户写模板时,有颜色提示;未经授权,禁止复制转载。【作者:唐霜】2)实时预览,客户写模板时,可以实时看到未经授权,禁止复制转载。【未经授权禁止转载】模板解析为表单后的界面效果;3)生成表单【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】,ast和react结合,直接生成表单。
原创内容,盗版必究。【作者:唐霜】
总而言之,AST可以帮你把一个符合某种语原创内容,盗版必究。未经授权,禁止复制转载。法的字符串,转化为计算机系统中其他任意表【转载请注明来源】【版权所有】唐霜 www.tangshuang.net现形式的目标。
原创内容,盗版必究。【未经授权禁止转载】
未经授权,禁止复制转载。【转载请注明来源】

转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】ng.net【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua【作者:唐霜】【转载请注明来源】ng.net

2020-12-20 3491

为价值买单,打赏一杯咖啡

本文价值34.91RMB