深入浅出理解编译器:前端视角
一、编译器究竟是什么?
在前端开发的世界里,我们经常会听到 “编译器” 这个词。就拿 Babel 来说,在它的官网上,最显眼的一句话就是:“Babel is a JavaScript compiler”。那什么是 JavaScript 编译器呢?又该如何去学习和理解编译器呢?让我们一起来揭开它的神秘面纱。
编译器,简单来说,就是一种电脑程序,它的主要工作就是把用某种编程语言写的源代码,转换成另一种编程语言。比如说,Babel 就可以把 ES6、ES7 或者 JSX 这些新的语法转换成 ES5 或者其他指定版本,就像是给代码做了一次 “变形记”。
其实,在我们日常的前端开发中,有很多工具都用到了编译器的技术,比如 Less/Saas 用于处理样式,TypeScript/coffeeScript 用于处理脚本,还有 Eslint 用于代码检查等等。正是因为有了这些工具,前端工程化才能发展得越来越好。
二、编译器的基本思路
(一)词法分析 (Lexical Analysis)
目的
词法分析的主要任务就是把我们写的文本代码分割成一个个小小的 “token”,就像是把一句话拆分成一个个的单词。比如说,“init、main、x、;、=、3” 这些都可以是 token。同时,它还会把那些注释、空格、回车等对代码运行没有实际作用的字符去掉,让代码变得更加 “纯粹”。
生成方式
生成 token 主要有两种办法:
- 正则表达式:这种方法需要写大量的正则表达式,而且这些正则之间还可能会有冲突,维护起来比较麻烦,性能也不是很高。所以,正则表达式一般只适合一些简单的模板语法,对于真正复杂的语言就不太合适了。而且有些语言可能还没有自带的正则引擎呢。
- 自动机:自动机就像是一个智能的小机器,可以很好地生成 token。其中,有穷状态自动机(finite state machine)是一个很重要的概念。它在有限个输入的情况下,会在不同的状态之间转移,最终达到一个终止状态。有穷状态自动机又可以分为 “确定有穷状态自动机”(DFA - Deterministic finite automaton)和 “非确定有穷自动机”(NFA - Non-deterministic finite automaton)。DFA 在输入一个状态时,只会得到一个固定的状态,可以认为是一种特殊的 NFA;而 NFA 当输入一个字符或者条件时,会得到一个状态机的集合。JavaScript 正则采用的就是 NFA 引擎。
(二)语法分析 (Syntactic Analysis)
我们平时说的编译原理,其实就是把一种语言转换为另一种语言。编译原理研究的是形式语言,这种语言不需要知道太多的背景知识,而且没有歧义。和自然语言不一样,自然语言很难处理,因为很难分清哪些是名词、动词、形容词。比如说 “进口汽车”,这里的 “进口” 到底是动词还是形容词呢?所以,我们要解析一门语言,前提是这门语言有严格的语法规定。
在 1956 年,乔姆斯基把文法按照规范的严格性分成了 0 型、1 型、2 型和 3 型共 4 种。一般的计算机语言用的是 2 型文法,也叫上下文无关文法(CFG)。因为 0 型和 1 型文法定义太宽松,会增加解析的难度,降低效率;而 3 型文法限制又太多,不利于语言设计的灵活性。
语法分析的目的就是把词法分析得到的 token 流,结合文法规则,通过一定的算法生成一颗抽象语法树(AST)。AST 在前端领域非常重要,比如说 Babel 插件的原理就是:es6 代码通过 Babylon.parse 生成 AST,然后用 babel-traverse 处理得到新的 AST,最后再生成 es5 代码。
从生成 AST 的效率和实现难度来看,主要有两种解析算法:自顶向下的分析方法和自底向上的分析方法。自底向上算法可以分析的文法范围比较广,但是实现起来比较难;自顶向下算法实现相对简单,能解析的文法范围也不错,所以一般的编译器都会采用深度优先索引的方式。
(三)代码转换(Transformation)
当我们得到 AST 之后,通常会先把它转换成另一种 AST,这样可以生成更符合我们预期的 AST,这个过程就叫做代码转换。代码转换有很多优势:
- 易移植:它和具体的机器没有关系,所以可以作为中间语言,为生成多种不同型号的目标机器码服务。
- 机器无关优化:可以对中间码进行优化,提高代码的质量。
- 层次清晰:把 AST 先映射成中间代码,再映射成目标代码,这样可以让编译算法更加清晰。
对于一个编译器来说,在转换阶段通常有两种形式:
同语言的 AST 转换和 AST 转换为新语言的 AST。
一般的做法是,对之前的 AST 从上至下进行解析(称为 traversal),然后有一个映射表(称为 visitor),把对应的类型做相应的转换。
(四)代码生成 (Code Generation)
在实际处理代码的过程中,我们可能会递归地分析最终生成的 AST,对于每种 type 都有一个对应的函数来处理。最终,我们的目标代码就会在这一步输出。在前端领域,我们的目标代码可能就是 HTML 了。
三、完整链路 (Compiler)
一个完整的编译器过程可以用下面的代码来表示:
input => tokenizer => tokens; // 词法分析
tokens => parser => ast; // 语法分析,生成 AST
ast => transformer => newAst; // 中间层代码转换
newAst => generator => output; // 生成目标代码

相关文章:
深入浅出理解编译器:前端视角
一、编译器究竟是什么? 在前端开发的世界里,我们经常会听到 “编译器” 这个词。就拿 Babel 来说,在它的官网上,最显眼的一句话就是:“Babel is a JavaScript compiler”。那什么是 JavaScript 编译器呢?又…...
Minio搭建并在SpringBoot中使用完成用户头像的上传
Minio使用搭建并上传用户头像到服务器操作,学习笔记 Minio介绍 minio官网 MinIO是一个开源的分布式对象存储服务器,支持S3协议并且可以在多节点上实现数据的高可用和容错。它采用Go语言开发,拥有轻量级、高性能、易部署等特点,并且可以自由…...
Ubuntu系统上部署Node.js项目的完整流程
以下是在Ubuntu系统上部署Node.js项目的完整流程,分为系统初始化、环境配置、项目部署三个部分: 一、系统初始化 & 环境准备 bash # 1. 更新系统软件包 sudo apt update && sudo apt upgrade -y# 2. 安装基础工具 sudo apt install -y buil…...
DeepSeek效应初现:Grok-3补刀ChatGPT,OpenAI已在ICU?
嘿,技术小伙伴们!今天咱们聊聊最近在AI界引发轰动的新闻——DeepSeek和xAI相继用R1和Grok-3证明了预训练Scaling Law并非OpenAI的护城河。这意味着什么呢?让我们一探究竟! 开场白 首先,让我们看看最新的“全能冠军”…...
【知识】torchrun 与 torch.multiprocessing.spawn 的对比
转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 来自ChatGPT、DeepSeek 有点干,可仅做了解。 torchrun 和 torch.multiprocessing.spawn 都是在 PyTorch 中用于并行化和分布式训练的工具&a…...
深入了解 K-Means 聚类算法:原理与应用
引言 在数据科学和机器学习的世界中,聚类是一项非常重要的技术,它帮助我们根据数据的相似性将数据划分为不同的组或簇。聚类算法在许多领域中得到了广泛的应用,如图像处理、市场细分、基因研究等。K-Means 聚类算法作为最常见的无监督学习算…...
Rust ~ Collect
背景 Transforms an iterator into a collection 将一个迭代器转换为一个集合 collect() 可以处理任何可迭代的对象,并将其转换为相关的集合 collect() 最基本模式是将一个集合转换为另一个集合: 先获取一个集合,对其调用 iter 方法&#x…...
C# 类型转换
C# 类型转换 引言 在C#编程语言中,类型转换是一种将一个数据类型的变量转换成另一个数据类型的操作。类型转换是编程中常见的操作,特别是在处理不同数据类型的变量时。本文将详细探讨C#中的类型转换,包括隐式转换和显式转换,以及…...
[IP] DDR_FIFO(DDR3 用户FIFO接口)
IP(DDR_FIFO)将DDR3 IP的用户侧复杂接口修改为简易的FIFO接口,用户侧更加简易例化使用MIG 核 IP介绍 c0_xx (连接DDR app接口) 此IP 仅需根据MIG配置进行有限修改,即可使用! 关于IP详细使用说明,参考IP datasheet! 示…...
第三百七十二节 JavaFX教程 - JavaFX HTMLEditor
JavaFX教程 - JavaFX HTMLEditor HTMLEditor控件是一个富文本编辑器,具有以下功能。 粗体斜体下划线删除线字体系列字体大小前景色背景颜色缩进项目符号列表编号列表对齐水平线复制文本片段粘贴文本片段 HTMLEditor类返回HTML字符串中的编辑内容。 创建HTML编辑器…...
蓝桥杯试题:DFS回溯
一、题目要求 输入一个数组n,输出1到n的全排列 二、代码展示 import java.util.*;public class ikun {static List<List<Integer>> list new ArrayList<>();public static void main(String[] args) { Scanner sc new Scanner(System.in);…...
Lua | 每日一练 (4)
💢欢迎来到张胤尘的技术站 💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Lua | 每日一练 (4)题目参考答案线程和协程调度方式上…...
每日一题——接雨水
接雨水问题详解 问题描述 给定一个非负整数数组 height,表示每个宽度为 1 的柱子的高度图。计算按此排列的柱子,下雨之后能接多少雨水。 示例 示例 1: 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释&#…...
java常见面试01
为什么重写 equals 还要重写 hashcode 🌈 核心原因: 当两个对象通过equals()判断为相等时,它们的hashCode()必须返回相同的整数值!这是Java世界的交通规则哦~(交警曼波敬礼.jpg) 🧩 具体场景…...
算法-二叉树篇27-把二叉搜索树转换为累加树
把二叉搜索树转换为累加树 力扣题目链接 题目描述 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提…...
C语言:51单片机 基础知识
一、单片机概述 单片机的组成及其特点 单片机是指在一块芯片上集成了CPU、ROM、RAM、定时器/计数器和多种I/O接口电路等,具有一定规模的微型计算机。 特点: 1、单片机的存储器以ROM、RAM严格分工。 2、采用面向控制的指令系统。 3、单片机的I/O口引脚通…...
olmOCR:使用VLM解析PDF
在PDF解析中,目前主流的开源工具包括Minuer、GOT OCR等。主要都是通过飞桨等OCR套件组装的一套pipeline,或者直接通过VLM解析图像。 #一、 olmOCR是使用VLM进行的端到端的PDF文档解析 二、document-anchoring 与上述的不同在于,olmOCR使用…...
数据结构(初阶)(七)----树和二叉树(堆,堆排序)
八,树与二叉树 树 概念与结构 树是⼀种⾮线性的数据结构,它是由 n(n>0) 个有限结点组成⼀个具有层次关系的集合。把它叫做树是因为它看起来像⼀棵倒挂的树,也就是说它是根朝上,⽽叶朝下的。 • 有⼀…...
图像分类项目1:基于卷积神经网络的动物图像分类
一、选题背景及动机 在现代社会中,图像分类是计算机视觉领域的一个重要任务。动物图像分类具有广泛的应用,例如生态学研究、动物保护、农业监测等。通过对动物图像进行自动分类,可以帮助人们更好地了解动物种类、数量和分布情况,…...
Kali Linux 2024.4版本全局代理(wide Proxy)配置,适用于浏览器、命令行
1. 网络拓扑介绍(不使用虚拟机直接跳到2) 虚拟机:VMware 17 Pro,为本机开启桥接模式。 我的究极套娃网络:手机V2rayNG代理端口为10808,开热点 -> 电脑连接wifi -> 虚拟机中运行kali 2. kali 配置…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
