深入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),更是爆发了极强的生命力.编程语言分为编译型语言和解释型语言两类,编译型语言在执行之前要先进 ...
随机推荐
- CSRF 专题
一.CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造. 也被称为:one click attack/session riding(一 ...
- 【UVA】11992 - Fast Matrix Operations(段树模板)
主体段树,要注意,因为有set和add操作,当慵懒的标志下推.递归优先set,后复发add,每次运行set行动add马克清0 WA了好几次是由于计算那一段的时候出问题了,可笑的是我对着模板找了一个多小 ...
- 目标检测的图像特征提取(一)HOG特点
1.HOG特点: 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检測的特征描写叙述子.它通过计算和统计图像局部区 ...
- Android Ant 和 Gradle 包装工艺和效率控制
一个.Ant 包:(下载ant.配置环境变量不说) 1.进入命令行模式,并切换到项目文件夹,运行例如以下命令为ADT创建的项目加入ant build支持: android update project ...
- WPF中Style文件的引用——使用xaml代码或者C#代码动态加载
原文:WPF中Style文件的引用--使用xaml代码或者C#代码动态加载 WPF中控件拥有很多依赖属性(Dependency Property),我们可以通过编写自定义Style文件来控制控件的外观 ...
- 线程安全ConcurrentBag
ConcurrentBag并行,不保证顺序,线程安全 public static void ConcurrentBagWithPallel() { ConcurrentBag<int> l ...
- 【C#】wpf自定义calendar日期选择控件的样式
原文:[C#]wpf自定义calendar日期选择控件的样式 首先上图看下样式 原理 总览 ItemsControl内容的生成 实现 界面的实现 后台ViewModel的实现 首先上图,看下样式 原理 ...
- SQLServer 进程无法向表进行大容量复制(错误号: 22018 20253)
原文:SQLServer 进程无法向表进行大容量复制 我的环境:SQL SERVER 2008 R2:发布者 ->SQL SERVER 2017 订阅者 进程无法向表“"dbo&quo ...
- SQLite Expert Professional 打开加密SQLite数据库
原文 SQLite Expert Professional 打开加密数据库 (已修改) 版本:sqlite expert professional 4.2.0.739 (x86) 目的:用SQLite ...
- 类选择器和所作用的标签一起写为什么不起作用? - CSDN博客
原文:类选择器和所作用的标签一起写为什么不起作用? - CSDN博客 HTML代码: css样式: 这不是将样式作用于circle类下的有current类的li标签吗?为什么不起作用? 原因: 选择器 ...