前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >编译原理学习笔记-基于less实践探究(一)

编译原理学习笔记-基于less实践探究(一)

作者头像
吴文周
发布2022-03-09 15:13:45
5280
发布2022-03-09 15:13:45
举报
文章被收录于专栏:吴文周的专栏吴文周的专栏

场景

  • 编译原理这本书不用多说,别名龙书是程序员的圣经宝典。我一年之前就看过一点,也就是单纯的看过,现在可以说是基本毫无印象,一是没有做读书笔记,二是没有去实践,还是那句话纸上得来终觉浅,绝知此事要躬行。
  • 为什么又想起来去重读龙书呢?还是项目痛点,项目跑起来实在是太卡了,随着工程扩大,启动项目变成一个极其漫长的事情!我在想为什么一定要用node作为前端的工程基础呢?为什么不用其他语言呢?为什么不用golang去做呢?用golang可以啊,怎么编译呢?看龙书!
  • 突发奇想一个理想的前端工程应该是怎么样的?一个高效的编译开发体验,一个简单文件目录就包含一个可执行文件加前端代码资源,一个容器化磨平差异不用担心windows,mac平台不同。

思路起源

esbuild从去年过年后刚知道的时候,就用它来跑react项目虽然结果失败了,但使用go作为编译工具却在我脑海中埋下了种子。

go真的比nodejs快吗?事实胜于雄辩,脚本语言慢真的是天生的。下面是nodejs和go做做100000以内的求和实验

语言

执行时间

nodejs

13.074ms

nodejs

15.89ms

nodejs

14.844ms

nodejs

13.337ms

nodejs

13.316ms

平均耗时

14.1448ms

语言

执行时间

golang

67.087µs

golang

66.343µs

golang

73.034µs

golang

71.219µs

golang

68.233µs

平均耗时

69.1832µs

  • 这还用比吗?单位都不是一个单位,nodejs时间单位是ms而go是µs。
  • 衍生一下,golang 并发一定比顺序执行快吗?留下一个小疑问!

编译原理学习分享-进入正题

学习方法论

  • 本来已经写了一部分类似读书笔记的博客,自己看了可能都是昏昏欲睡那种!都是书本中核心概念的记录,最终决定还是留下几个关键图。
  1. 编译器是一个程序它可以阅读某一种语言并把改程序转换成另一种语言的程序。

编译器主要任务之一就是报告它在翻译过程中的错误

如果目标程序是可执行的机器语言程序,他可以被调用,处理输入并产生输出

  1. 解析器不通过翻译的方式生成目标程序。直接利用用提供的输入执行源程序的指定的操作
  1. 编译器产生的机器语言目标程序通常比解释器快,解释器的错误诊断效果比编译器好,解释器逐个语句执行源程序
  2. 编译构成流程顺序:

学习总结

  • 看了一波上面的图,可能有些不耐烦了,理论很重要就是在于它的指导意义和思想,如果没有这些上去就是干,后面维护性阅读性一定会很差。
  1. 关键知识点输入一段字符,输出另一段可以被机器执行的机器码(例如将less转为css)
  2. 不仅需要实现文本的转换,中间代码的规范提示告警也是必不可少的(例如将width写成了widdth需要提示)
  3. 编译流程如下 :读取字符且去除无效空格,以及无效符号例如";",生成token对象,对token列表进行遍历生成ast对象,将ast对象进行深度优先遍历生成目标机器码

代码实践与理论穿插

代码实践-读取文件

  • 一个库的设计远远没有这么简单,当前只是简单实现,真正库需要配置项和插件机制,还有业务述求例如sourcemap等等。

代码实践-定义结构体

代码实践-生成token

理论-生成token

  • 去空:读取文件一行结果其实是像" width : 100px;"这样的字符串, 我们可以看到在width字符之前或者 : 符合 前后都存在一定数量的空格,这是需要删除的
  • 去除无效符号:在编译过程中例如";"这样的符号,并没有什么实际意义可以删除(只是在less场景下举例)
  • 终止符号:在读取文件时例如"}"这个符号,就是一个明确的终止符号,可以帮助我们解析token处理ast的逻辑
  • Map表:在less中例如@big这样的字符,是一个变量引用,在下面的解析中需要把@big替换成100px,我们就需要一个这样的缓存空间去缓存这样的数据

代码实践-生成ast

理论-生成ast

  • 符号表:例如在less中 #body{ #child{width:100px}} 有这样层级嵌套的场景,需要把上一层的选择器带到下一层,因为生成的结果其实是 #body #child{width:100px},正如我们看到的 #body #child 是随着层级的变深不断叠加的,形成这样body->parent->child->grandson这样一个树形链路。在上面的代码中我是用characterList这样的数组去实现的,如果出现新的层级就向数组中添加。
  • 递归:由于子层级的出现就需要我们使用递归的方式将所有的子节点遍历处理
  • 结束体:使用递归必然关注结束,在less中显然"}"这个符号,是我们天然的结束标志

代码实践-写入文件

理论-写入文件

  • 抽象语法树:见名知意很明显我们需要把这棵树,使用深度遍历优先的方法,生成每一行css代码
  • 写入效率:bufio的使用可以提升写入效率

总结

  • 当前的代码只是简单的逻辑,还没触及编译原理的核心思想。例如less中的计算等等场景,理论里面的状态机,文法分析,中间代码等等完全没有写,这也是我下一阶段的学习目标与实践场景。
  • 代办事项:场景补齐正在能实现less转css,编译效率提升,使用更好的算法和设计模式
  • go并发是否一定能提升效率,答案是否定的,在场景上我们是不是需要顺序执行,极小携程,有耗时操作,电脑核数等等这些角度去考虑。看个代码示例
  • 由此可见并发在流程上面需要更精细的设计方案才能提升他的性能,单纯的并发并不会提升反而把执行效率降低。
  • 一定要拥抱变化,前端jsp我经历过,三大框架盛行加入nodejs的脚手架我也经历过,前后端分离经历过,nodejs中间层经历过,每一个阶段都需要人去勇于尝试,nodejs是贴近前端,从性能的角度而言nodejs是不是一个合理的选择呢?不管是工具链还是中间服务,还有有人会说生态,nodejs生态难道兴起了很久吗?
  • 关注底层库,关注核心库,提高性能,提升开发体验--加油
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/08/01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 场景
  • 思路起源
  • 编译原理学习分享-进入正题
    • 学习方法论
      • 学习总结
        • 代码实践与理论穿插
          • 代码实践-读取文件
          • 代码实践-定义结构体
          • 代码实践-生成token
          • 理论-生成token
          • 代码实践-生成ast
          • 理论-生成ast
          • 代码实践-写入文件
          • 理论-写入文件
      • 总结
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档