之前因为工作需求,需要把一段java格式对象数据代码转换成javascript的数据业务任务。 我提出打算用AST语法树编译器解决的(前端只要会吹技术方案就行,管什么业务,天塌下来有大哥顶着)。
结果,方案被鸡比了,大佬通过现象看出本质:这tm就是个字符串切割问题,你小子想摸鱼!
大佬提出切割思路,我去写业务代码,干了一星期搞好(痛失摸鱼机会)。
后来到现在,我开始整捞比编译器原理学习了。
众所周知, 编译原理每次鞭尸的代码 就是jsx 编译前
<h1 id='title'><span>hello</span>world</h1>
编译后
React.createElement('h1',{
id:'title'
},Rect.createElement('span',null,'hello'),'world')
转换用的开源小网站(给开源哥磕头orz) astexplorer.net/
进去随便点点,反正英文我是看不懂
众所周知,http传的文件就是文本流,https就是加了个密,所以如果平时拿到html的文件就是文本流<h1 id='title'><span>hello</span>world</h1>
上esprima翻译代码
let esprima=require('esprima')
let sourceCode=`<h1 id='title'><span>hello</span>world</h1>`
let ast=esprima.pareseModule(sourceCode,{jsx:true,tokens:true})
console.log(ast)
会得出
[
{ type: 'Punctuator', value: '<' },
{ type: 'JSXIdentifier', value: 'h1' },
{ type: 'JSXIdentifier', value: 'id' },
{ type: 'Punctuator', value: '=' },
{ type: 'String', value: '"title"' },
{ type: 'Punctuator', value: '>' },
{ type: 'Punctuator', value: '<' },
{ type: 'JSXIdentifier', value: 'span' },
{ type: 'Punctuator', value: '>' },
{ type: 'JSXText', value: 'hello' },
{ type: 'Punctuator', value: '<' },
{ type: 'Punctuator', value: '/' },
{ type: 'JSXIdentifier', value: 'span' },
{ type: 'Punctuator', value: '>' },
{ type: 'JSXText', value: 'world' },
{ type: 'Punctuator', value: '<' },
{ type: 'Punctuator', value: '/' },
{ type: 'JSXIdentifier', value: 'h1' },
{ type: 'Punctuator', value: '>' }
]
果真是字符串切割啊
后来看到引用了estraverse-fb的库进去深度遍历
说白了就是把字符串进行切割,然后进行深度遍历形成一个树结构举个加减乘除例子
1+2*3-5
形成这样的深度遍历树附加上加减乘除的权重 遍历成一个嵌套对象之类
{
type:"+",
child:[
{type:1},
{type:'*',child:[...]}
]
}
在这个嵌套对象里修改删除添加自己需要的对象属性,根据自己的业务因地适宜。
总结一下如果ast实现之前的业务代码效果兼容性更好, 但是干活就是要考虑效率。