编译原理思路学习

63 阅读2分钟

之前因为工作需求,需要把一段java格式对象数据代码转换成javascript的数据业务任务。 我提出打算用AST语法树编译器解决的(前端只要会吹技术方案就行,管什么业务,天塌下来有大哥顶着)。

image.png

结果,方案被鸡比了,大佬通过现象看出本质:这tm就是个字符串切割问题,你小子想摸鱼!

大佬提出切割思路,我去写业务代码,干了一星期搞好(痛失摸鱼机会)。

后来到现在,我开始整捞比编译器原理学习了。

众所周知, 编译原理每次鞭尸的代码 就是jsx 编译前

<h1 id='title'><span>hello</span>world</h1> 

编译后

React.createElement('h1',{
id:'title'
},Rect.createElement('span',null,'hello'),'world')

转换用的开源小网站(给开源哥磕头orz) astexplorer.net/

image.png

进去随便点点,反正英文我是看不懂

众所周知,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

image.png

形成这样的深度遍历树附加上加减乘除的权重 遍历成一个嵌套对象之类


  {
    type:"+",
    child:[
        {type:1},
        {type:'*',child:[...]}
      ]
      
  }


在这个嵌套对象里修改删除添加自己需要的对象属性,根据自己的业务因地适宜。

总结一下如果ast实现之前的业务代码效果兼容性更好, 但是干活就是要考虑效率。