当前位置: 首页 > news >正文

深入浅出理解编译器:前端视角

一、编译器究竟是什么?

在前端开发的世界里,我们经常会听到 “编译器” 这个词。就拿 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&#xff0c;输出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)

&#x1f4a2;欢迎来到张胤尘的技术站 &#x1f4a5;技术如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 Lua | 每日一练 (4)题目参考答案线程和协程调度方式上…...

每日一题——接雨水

接雨水问题详解 问题描述 给定一个非负整数数组 height&#xff0c;表示每个宽度为 1 的柱子的高度图。计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#…...

java常见面试01

为什么重写 equals 还要重写 hashcode &#x1f308; 核心原因&#xff1a; 当两个对象通过equals()判断为相等时&#xff0c;它们的hashCode()必须返回相同的整数值&#xff01;这是Java世界的交通规则哦~&#xff08;交警曼波敬礼.jpg&#xff09; &#x1f9e9; 具体场景…...

算法-二叉树篇27-把二叉搜索树转换为累加树

把二叉搜索树转换为累加树 力扣题目链接 题目描述 给出二叉 搜索 树的根节点&#xff0c;该树的节点值各不相同&#xff0c;请你将其转换为累加树&#xff08;Greater Sum Tree&#xff09;&#xff0c;使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提…...

C语言:51单片机 基础知识

一、单片机概述 单片机的组成及其特点 单片机是指在一块芯片上集成了CPU、ROM、RAM、定时器/计数器和多种I/O接口电路等&#xff0c;具有一定规模的微型计算机。 特点&#xff1a; 1、单片机的存储器以ROM、RAM严格分工。 2、采用面向控制的指令系统。 3、单片机的I/O口引脚通…...

olmOCR:使用VLM解析PDF

在PDF解析中&#xff0c;目前主流的开源工具包括Minuer、GOT OCR等。主要都是通过飞桨等OCR套件组装的一套pipeline&#xff0c;或者直接通过VLM解析图像。 #一、 olmOCR是使用VLM进行的端到端的PDF文档解析 二、document-anchoring 与上述的不同在于&#xff0c;olmOCR使用…...

数据结构(初阶)(七)----树和二叉树(堆,堆排序)

八&#xff0c;树与二叉树 树 概念与结构 树是⼀种⾮线性的数据结构&#xff0c;它是由 n&#xff08;n>0&#xff09; 个有限结点组成⼀个具有层次关系的集合。把它叫做树是因为它看起来像⼀棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;⽽叶朝下的。 • 有⼀…...

图像分类项目1:基于卷积神经网络的动物图像分类

一、选题背景及动机 在现代社会中&#xff0c;图像分类是计算机视觉领域的一个重要任务。动物图像分类具有广泛的应用&#xff0c;例如生态学研究、动物保护、农业监测等。通过对动物图像进行自动分类&#xff0c;可以帮助人们更好地了解动物种类、数量和分布情况&#xff0c;…...

Kali Linux 2024.4版本全局代理(wide Proxy)配置,适用于浏览器、命令行

1. 网络拓扑介绍&#xff08;不使用虚拟机直接跳到2&#xff09; 虚拟机&#xff1a;VMware 17 Pro&#xff0c;为本机开启桥接模式。 我的究极套娃网络&#xff1a;手机V2rayNG代理端口为10808&#xff0c;开热点 -> 电脑连接wifi -> 虚拟机中运行kali 2. kali 配置…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

云安全与网络安全:核心区别与协同作用解析

在数字化转型的浪潮中&#xff0c;云安全与网络安全作为信息安全的两大支柱&#xff0c;常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异&#xff0c;并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全&#xff1a;聚焦于保…...