编译原理一:编译器工作流

news2024/11/24 8:28:52

文章目录

  • 1. 编译器工作流
    • 1.1. 解析(Parsing)
    • 1.2. 遍历(Traversal)
    • 1.3 转换(Transformation)
    • 1.4 代码生成(Code Generation)

1. 编译器工作流

编译器是将一种语言转化为另一种语言的程序。在编译器工作流中,通常可以分为以下几个步骤:

  1. 解析(Parsing):解析是将最初原始的代码转换为一种更加抽象的表示(即AST)
  2. 转换(Transformation):转换将对这个抽象的表示做一些处理。让它能做到编译器期望它做到的事情
  3. 代码生成(Code Generation):接收处理之后的代码表示,然后把它转换成新的代码

1.1. 解析(Parsing)

  • 解析一般分为两个阶段:词法分析(Lexical Analysis)语法分析(Syntactic Analysis)
    • 词法分析:将源代码分解为一系列词法单元,如标识符关键字运算符等。这可以被称为Token,Token 是一个数组,由一些代码语句的碎片组成,它们可以是数字、标签、标点符号、运算符或者其它任何东西。
    • 语法分析:将词法单元(Token)转化为语法树,检查代码是否符合语法规则。抽象语法树是一个嵌套程度很深的对象,用一种更容易处理的方式代表了代码本身,也能给我们更多信息。

示例一:
原始js代码:

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

Token示例:

[
    { 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: '>' }
  ]

抽象语法树(AST):
将上面的js放到astexplorer中可以生成以下结构:

{
    "type": "Program",
    "body": [
        {
            "type": "ExpressionStatement",
            "expression": {
                "type": "JSXElement",
                "openingElement": {
                    "type": "JSXOpeningElement",
                    "name": {
                        "type": "JSXIdentifier",
                        "name": "h1"
                    },
                    "attributes": [
                        {
                            "type": "JSXAttribute",
                            "name": {
                                "type": "JSXIdentifier",
                                "name": "id"
                            },
                            "value": {
                                "type": "Literal",
                                "value": "title"
                            }
                        }
                    ]
                },
                "children": [
                    {
                        "type": "JSXElement",
                        "openingElement": {
                            "type": "JSXOpeningElement",
                            "name": {
                                "type": "JSXIdentifier",
                                "name": "span"
                            }
                            "attributes": []
                        },
                        "children": [
                            {
                                "type": "JSXText",
                                "value": "hello"
                            }
                        ],
                        "closingElement": {
                            "type": "JSXClosingElement",
                            "name": {
                                "type": "JSXIdentifier",
                                "name": "span"
                            }
                        }
                    },
                    {
                        "type": "JSXText",
                        "value": "world"
                    }
                ],
                "closingElement": {
                    "type": "JSXClosingElement",
                    "name": {
                        "type": "JSXIdentifier",
                        "name": "h1"
                    }
                }
            }
        }
    ]
}

在这里插入图片描述
在这里插入图片描述
以上就是解析的基本过程。

示例二:利于exprima实现ast
1.新建一个package.json文件

npm init 

2.安装 esparima

npm install esprima 

3.导入 esparima

let esprima = require("esprima");

4.执行以下代码
vscode安装Code Runner

let esprima = require("esprima");
let sourceCode = `<h1 id="title"><span>hello</span>world</h1>`;
// jsx: true表示支持jsx;tokens: true表示打印tokens,默认不打印
let ast = esprima.parseModule(sourceCode, { jsx: true, tokens: true }); 
console.log(ast);

在这里插入图片描述
esorima 内部要得到抽象语法树,需经过两个步骤:
1.把源代码进行分词,得到一个tokens的数组
2.把tokens数组转成一个抽象语法树

1.2. 遍历(Traversal)

  • 将jsx转换成抽象语法树之后,为了能处理所有的节点,需要采用深度优先遍历

1.安装 estraverse

npm install estraverse-fb

2.导入 estraverse

let estraverse = require("estraverse-fb");

3.执行以下代码

let esprima = require("esprima"); //把JS源代码转成AST语法树
let estraverse = require("estraverse-fb"); //遍历语法树,修改树上的节点
let sourceCode = `<h1 id="title"><span>hello</span>world</h1>`;
// jsx: true表示支持jsx;tokens: true表示打印tokens,默认不打印
let ast = esprima.parseModule(sourceCode, { jsx: true, tokens: true });
// console.log(ast);

// 间距
let tab = 0;
function padding() {
  return " ".repeat(tab);
}
estraverse.traverse(ast, {
  enter(node) {
    // 进入
    console.log(padding() + node.type + "进入");
    tab += 2;
  },
  leave(node) {
    // 离开
    console.log(padding() + node.type + "离开");
    tab -= 2;
  },
});

在这里插入图片描述

1.3 转换(Transformation)

  • 编译器的下一步就是转换,它只是把 AST 拿过来然后对它做一些修改。它可以在同种语言下操作 AST也可以把 AST 翻译成全新的语言(如vue转换成react,java转换成js等等)。
  • 你或许注意到了我们的 AST 中有很多相似的元素,这些元素都有type 属性,它们被称为 AST结点。这些结点含有若干属性,可以用于描述AST的部分信息
  • 当转换 AST 的时候我们可以添加移动替代这些结点,也可以根据现有的 AST 生成一个全新的 AST
  • 既然我们编译器的目标是把输入的代码转换为一种新的语言,所以我们将会着重于产生一个针对新语言的全新的 AST。

1.4 代码生成(Code Generation)

  • 编译器的最后一个阶段是代码生成,这个阶段做的事情有时候会和转换(transformation)重叠,但是代码生成最主要的部分还是根据 AST 来输出代码
  • 代码生成有几种不同的工作方式,有些编译器将会重用之前生成的 token,有些会创建独立的代码表示,以便于线性地输出代码。但是接下来我们还是着重于使用之前生成好的 AST
  • 我们的代码生成器需要知道如何打印AST 中所有类型的结点,然后它会递归地调用自身直到所有代码都被打印到一个很长的字符串中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/685310.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

git上传云效codeup

为了标识身份&#xff0c;建议先完成 Git 全局设置 git config --global user.name "xxx" git config --global user.email "xxxxxxqq.com" 1.删除本地 .git文件夹 2.云效上 添加库-新建代码库 3.在 git bash 里 按照 建好的代码库 下方的 命令行指引-…

chatgpt赋能python:Python编译成二进制文件:优化代码执行效率

Python编译成二进制文件&#xff1a;优化代码执行效率 介绍 随着Python编程的不断普及&#xff0c;越来越多的开发者选择Python作为开发工具。然而&#xff0c;Python解释器需要读取并解释源代码&#xff0c;这种解释方式在执行效率上存在瓶颈。为了提高执行效率&#xff0c;…

io.netty学习(十三)Netty 解码器

目录 前言 编解码概述 编解码器概述 Netty 内嵌的编码器 解码器 ByteToMessageDecoder 抽象类 ReplayingDecoder 抽象类 MessageToMessageDecoder 抽象类 总结 前言 编码和解码&#xff1a;数据从一种特定协议格式到另一种格式的转换。 处理编码和解码的程序通常被称…

【VulnHub系列】BrokenGallery

因为是从PDF转换过来偶尔可能会出现内容缺少&#xff0c;可以看原版PDF&#xff1a;有道云笔记 实验信息 Broken&#xff1a;192.168.10.111 Kali&#xff1a;192.168.10.106 实验过程 sudo arp-scan --interface eth0 192.168.10.1/24 然后对靶机进行端口探测 nmap -sT -…

定积分的应用—所围图形的面积、绕轴旋转所围成立体的体积、旋转曲面的面积、弧长

本篇本章&#xff0c;将从几个简单的例子带大家分析总结定积分的应用中常用的方法和思想&#xff0c;一起学习进入定积分的世界&#x1f61c;&#x1f61c; 一、求所围图形的面积 1.求由抛物线 y x 2 与 y 2 − x 2 所 围 图 形 的 面 积 yx^2与y2-x^2所围图形的面积 yx2与y2…

Windows下Android studio 搭建 android NDK 搭建 OLLVM 踩坑记录

1. 编译 ollvm-9.0.1 下载源码进行编译 https://github.com/heroims/obfuscator/tree/llvm-9.0.1 编译 这里有坑要注意 不能使用最新的 mingw 8.0.1 编译会报错 报错内容如下: PS D:\OLLVM\obfuscator-llvm-9.0.1\build> cmake -G "MinGW Makefiles" -DCMA…

浏览器 HTTPS 协议的相关知识点有哪些?

&#x1f482; 个人网站:【海拥】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 前言HTTPS协议的概念HT…

腾讯云私有云平台运维面试

文章目录 概述JD 岗位描述一面二面三面HR面 概述 根据会议将面试问题进行总结&#xff0c;很多问题感觉当时没回答好&#xff0c;这是为啥呢&#xff1f;应该还是不熟练吧&#xff0c;或者不善于表达。将次经历分享出来&#xff0c;大家多练练。 JD 岗位描述 私有云平台运维…

io.netty学习(十四)Netty 编码器

目录 前言 MessageToByteEncoder 抽象类 MessageToMessageEncoder 抽象类 总结 前言 上一篇我们讲解了解码器的相关知识&#xff0c;其中也提到了编码器的定义。 编码器就是用来把出站&#xff08;针对本身来讲&#xff0c;发送都是出站&#xff0c;接收都是入站&#xf…

TIA博途_字符转换为字符串以及截取字符串有效字符的具体方法示例

TIA博途_字符转换为字符串以及截取字符串有效字符的具体方法示例 情景再现: 在做某些通信相关的项目时,可能会遇到通信接收到的字符串是以字节的形式传送过来的字符,此时就需要我们对接收到的这些字符进行处理,从而获取我们实际需要的字符或字符串。 如下图所示,打开博途…

一文了解什么是Dubbo

Dubbo学习 Dubbo应用架构的演变RPC&#xff08;远程过程调用&#xff09;RPC介绍RPC组件RPC调用 Apache Dubbo概述Dubbo简介Dubbo的架构 服务注册中心ZookeeperZookeeper介绍运行zookeeper Dubbo的快速开发Dubbo管理控制台治理中心 Dubbo Dubbo是一个分布式服务框架&#xff0…

基于Servlet+JDBC实现的基础博客系统>>系列3 -- Servlet后端服务器搭建

目录 前言 1. 前期准备 2. Model层 2.1 数据库的设计 2.2 数据库表对应的实体类实现 User类 Blog类 2.3 JDBC 工具类实现 2.4 UserDao 的实现 2.5 BlogDao 的实现 3. Controller 层实现 3.1 博客列表页 3.1.1 约定前后端交互接口 3.1.2 编写后端代码 3.1.3 编写…

【Shell1】shell语法,ssh/build/scp/upgrade,环境变量

文章目录 1.shell语法&#xff1a;shell是用C语言编写的程序&#xff0c;是用户使用Linux的桥梁&#xff0c;硬件>内核(os)>shell>文件系统1.1 变量&#xff1a;readonly定义只读变量&#xff0c;unset删除变量1.2 函数&#xff1a;shell脚本传递的参数中包含空格&…

聊天GPT如何运作?| 景联文科技

什么是聊天 GPT&#xff1f; Chat GPT 被定义为一种生成语言模型。在实践中&#xff0c;它被理解为经过训练和设计以进行自然对话的人工智能聊天。 聊天 GPT 的用途是什么&#xff1f; 1.借助 GPT&#xff0c;您可以生成各种风格、主题和语言的连贯且写得很好的文本。此外&a…

【比赛writeup】2023省赛-Reverse-Re2

2023省赛-Reverse-Re2 一、概要 1、标题&#xff1a;Re2 2、关键字&#xff1a;换表BASE64 3、比赛&#xff1a;2023省赛 4、工具&#xff1a;IDAx64、python 二、开始 1、题目分析 逆向的题目&#xff0c;找到关键字符串&#xff0c;找到关键函数&#xff0c;分析函数逻辑…

ISO15765-2 网络层,通俗易懂,最佳入门

I. 简介 ISO15765-2协议网络 ISO15765-2协议网络是一种用于汽车电子系统中的通信协议。它定义了在控制区域网络&#xff08;CAN&#xff09;上使用的诊断通信的协议规范&#xff0c;包括物理层、数据链路层、网络层和传输层。该协议的主要目的是使汽车制造商和维修技术人员能够…

Vue2,Vue3 computed计算属性用法

计算属性就是当依赖的属性的值发生变化的时候&#xff0c;才会触发他的更改&#xff0c;如果依赖的值&#xff0c;不发生变化的时候&#xff0c;使用的是缓存中的属性值。 computed购物车案例 1.Vue2版 <template><div><div><input v-model"keywo…

linux系统Nginx网站服务

文章目录 一、Nginx简介二、Nginx 相对于 Apache 的优点三、nginx 应用场景1.同步与异步2.阻塞与非阻塞 四、Nginx安装及运行控制1、编译安装2、访问控制1、访问状态统计2、基于授权的访问控制3、基于客户端的访问控制4、基于域名的 Nginx 虚拟主机5、基于IP 的 Nginx 虚拟主机…

2.3ORBSLAM3之相机模型与畸变模型

1.简介 主要内容&#xff1a; 1. 对SLAM中常见的相机模型进行介绍&#xff0c;包括针孔相机模型和鱼眼相机模型 2. 对每种相机模型的畸变模型进行介绍 3. 对VSLAM中常见的几种去畸变方法进行介绍 4. 对常见的几种相机标定方法进行总结对于VSLAM来说关于相机投影模型和畸变模型…