深入V8引擎-AST(4)
(再声明一下,为了简单暴力的讲解AST的转换过程,这里的编译内容以"'Hello' + ' World'"作为案例)
上一篇基本上花了一整篇讲完了scanner的Init方法,接下来就是Scan了,Init的方法基本上都是在Stream类下操作,但是本节回到了scanner层级。
/**
* Scan
* 仅仅只涉及next_指针
*/
void Scanner::Scan() { Scan(next_); }
void Scanner::Scan(TokenDesc* next_desc) {
next_desc->token = ScanSingleToken();
/**
* 设置当前词法的结束位置
*/
next_desc->location.end_pos = source_pos();
}
虽然这里只有简简单单的两步(砍掉了所有的CHECK和DEBUG内容),但这个ScanSingleToken已经够讲了。从字面意思理解,就是对单个词法的解析,源码如下。
/**
* 这个ScanSingleToken方法可TM太长了
*/
V8_INLINE Token::Value Scanner::ScanSingleToken() {
Token::Value token;
do {
/**
* 设置当前词法的起始位置
*/
next().location.beg_pos = source_pos();
/**
* Ascii码是从0 ~ 127
* 简单的判断一下合法性
*/
if (V8_LIKELY(static_cast<unsigned>(c0_) <= kMaxAscii)) {
/**
* 这是一个mapping数组
* 对所有的Unicode => Ascii做了映射
*/
token = one_char_tokens[c0_];
/**
* 包含非常多的case...先不展开了
* 根据Token类型进行不同的处理
*/
switch (token) {
case Token::LPAREN:
case Token::RPAREN:
// 其他单符号...
// One character tokens.
return Select(token);
case Token::STRING:
return ScanString(); // 更多...
default:
UNREACHABLE();
}
}
/**
* 处理结束符、空格、异常符号等特殊情况
*/
// ...
} while (token == Token::WHITESPACE); return token;
}
作为一个词法解析方法,长度其实还是可以接受的,已经删掉了大部分的case判断,由于本系列专注于"'Hello' + ' World'"的编译,所以留下了STRING类型。
讲两个点,第一个是那个source_pos,位置的属性和方法是真的多,比较简单,看看就行了。
/**
* 上一篇解析了第一个字符 所以pos移动到了1
* 然而记录location需要从头开始 所以这里做了一个偏移
*/
static const int kCharacterLookaheadBufferSize = ;
int source_pos() {
return static_cast<int>(source_->pos()) - kCharacterLookaheadBufferSize;
}
然后那个mapping数组可以稍微给一下出处,源码如下。
/**
* 总结起来就是GetOneCharToken(0),GetOneCharToken(1),...,GetOneCharToken(127)全部调用一遍
* 其中IsDecimalDigit负责判断是否是数字
* 而IsAsciiIdentifier负责判断是否是标识符,例如$、_、a-z等等
* 最后生成的one_char_tokens数组下标代表Unicode编码 值代表对应的Token类型
*/ #define INT_0_TO_127_LIST(V) \
V() V() V() V() V() V() V() V() V() V() \
// ...
V() V() V() V() V() V() V() V() static const constexpr Token::Value one_char_tokens[] = {
#define CALL_GET_SCAN_FLAGS(N) GetOneCharToken(N),
INT_0_TO_127_LIST(CALL_GET_SCAN_FLAGS)
#undef CALL_GET_SCAN_FLAGS
}; constexpr Token::Value GetOneCharToken(char c) {
// clang-format off
return
c == '(' ? Token::LPAREN :
c == ')' ? Token::RPAREN :
// 其余字符...
IsDecimalDigit(c) ? Token::NUMBER :
IsAsciiIdentifier(c) ? Token::IDENTIFIER :
Token::ILLEGAL;
}
之前说过,c0_代表的是当前解析字符的Unicode编码,于是这里直接通过数组索引查找其对应的类型,按照例子中,我们的字符是一个单引号,而单引号的类型如下。
/**
* 单双引号均会被识别为字符串标记
* 而es6的模板字符串比较特殊 暂时不搞他
*/
c == '"' ? Token::STRING :
c == '\'' ? Token::STRING :
c == '`' ? Token::TEMPLATE_SPAN :
所以,当前token被赋值为Token::STRING,因此,case分支进入ScanString的方法。这个方法内容比较多,下一篇讲吧,午休时间。
深入V8引擎-AST(4)的更多相关文章
- 深入V8引擎-AST(1)
没办法了,开坑吧,接下来的几篇会讲述JavaScript字符串源码在v8中转换成AST(抽象语法树)的过程. JS代码在V8的解析只有简单的几步,其中第一步就是将源字符串转换为抽象语法树,非常类似于v ...
- 深入V8引擎-AST(3)
上篇简单介绍了入口方法的流程以及scanner类相关的部分内容,这一篇主要讲scanner的初始化,即 scanner_.Initialize(); 注意,这不是调用静态方法.实际上Parser实例生 ...
- 深入V8引擎-AST(6)
花了5篇才把一个字符串词法给解析完,不知道要多久才能刷完整个流程,GC.复杂数据类型的V8实现那些估计又是几十篇,天呐,真是给自己挖了个大坑. 前面几篇实际上只是执行了scanner.Initiali ...
- 深入V8引擎-AST(2)
先声明一下,这种长系列的大块头博客只能保证尽可能的深入到每一行源码,有些代码我不乐意深究就写个注释说明一下作用.另外,由于本地整理的比较好,博客就随心写了. 整个Compile过程目前只看到asmjs ...
- 深入V8引擎-AST(5)
懒得发首页了,有时候因为贴的代码太多会被下,而且这东西本来也只是对自己学习的记录,阅读体验极差,所以就本地自娱自乐的写着吧! 由于是解析字符串,所以在开始之前介绍一下词法结构体中关于管理字符串类的属性 ...
- [翻译] V8引擎的解析
原文:Parsing in V8 explained 本文档介绍了 V8 引擎是如何解析 JavaScript 源代码的,以及我们将改进它的计划. 动机 我们有个解析器和一个更快的预解析器(~2x), ...
- 精读《V8 引擎 Lazy Parsing》
1. 引言 本周精读的文章是 V8 引擎 Lazy Parsing,看看 V8 引擎为了优化性能,做了怎样的尝试吧! 这篇文章介绍的优化技术叫 preparser,是通过跳过不必要函数编译的方式优化性 ...
- Javascript的V8引擎研究
1.针对上下文的Snapshot技术 什么是上下文(Contexts)?实际是JS应用程序的运行环境,避免应用程序的修改相互影响,例如一个页面js修改内置对象方法toString,不应该影响到另外页面 ...
- V8引擎——详解
前言 JavaScript绝对是最火的编程语言之一,一直具有很大的用户群,随着在服务端的使用(NodeJs),更是爆发了极强的生命力.编程语言分为编译型语言和解释型语言两类,编译型语言在执行之前要先进 ...
随机推荐
- XMPPFramework
XMPP Extensible Messaging and Present Protocol 可扩展消息处理现场协议 特征: XMPP使用tcp传XML流程, 做IM xmpp.org objcio. ...
- 办ZigBee实验SmartRF Flash Programmer软件界面无法打开
开SmartRF Flash Programmer: 打开任务管理器.在任务管理器里右键点击.将其最大化: 将最大化的界面拖动到屏幕中间: 然后关闭SmartRF Flash Programmer,之 ...
- ASP.NET Core 静态文件 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 静态文件 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 静态文件 前几章节中,我们学习了 ASP.NET Core 的中间件 ...
- Ubuntu下可以直接安装mingw(sudo apt-get install mingw32 mingw32-binutils mingw32-runtime,附例子,简单好用,亲测成功)good
Mingw:在Linux系统下编译Windows的程序 Ubuntu下可以直接安装:sudo apt-get install mingw32 mingw32-binutils mingw32-runt ...
- 作为学术用的 matlab
1. 可重复实验 程序实现的所谓随机,并非完全的随机,而是由某一算法(或者再需要一个种子值)生成出来的. randn('state', 0) % set state so that example c ...
- 用callgraph生成的函数调用关系图
Wu Zhangjin 创作于 2015/04/05 评论打赏 By Falcon of TinyLab.org 2015/04/03 1 故事缘由 源码分析是程序员离不开的话题.无论是研究开源项目, ...
- Vhost Architecture
在前面的文章中在介绍virtio机制中,能够看到在通常的应用中一般使用QEMU用户态程序来模拟I/O訪问,而Guest中的数据要通过Guest到Host Userspace的第一次拷贝,再经过Host ...
- Nucleus PLUS系统架构和组件
(一个)方法论和软件组件 1.软件组件(Software Component)定义 从一般意义上来说.组件(Component)是系统中能够明白辨识的组成部分,一个不透明的功能实现体.软件开发中,组件 ...
- sql执行分页查询
declare @PageSize int,@PageIndex int;set @PageSize=5;set @PageIndex=2;WITH Pagination AS( SELECT * ...
- 简单易用的MongoDB
从我第一次听到Nosql这个概念到如今已经走过4个年头了,但仍然没有具体的去做过相应的实践.最近获得一段学习休息时间,购买了Nosql技术实践一书,正在慢慢的学习.在主流观点中,Nosql大体分为4类 ...