(再声明一下,为了简单暴力的讲解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)的更多相关文章

  1. 深入V8引擎-AST(1)

    没办法了,开坑吧,接下来的几篇会讲述JavaScript字符串源码在v8中转换成AST(抽象语法树)的过程. JS代码在V8的解析只有简单的几步,其中第一步就是将源字符串转换为抽象语法树,非常类似于v ...

  2. 深入V8引擎-AST(3)

    上篇简单介绍了入口方法的流程以及scanner类相关的部分内容,这一篇主要讲scanner的初始化,即 scanner_.Initialize(); 注意,这不是调用静态方法.实际上Parser实例生 ...

  3. 深入V8引擎-AST(6)

    花了5篇才把一个字符串词法给解析完,不知道要多久才能刷完整个流程,GC.复杂数据类型的V8实现那些估计又是几十篇,天呐,真是给自己挖了个大坑. 前面几篇实际上只是执行了scanner.Initiali ...

  4. 深入V8引擎-AST(2)

    先声明一下,这种长系列的大块头博客只能保证尽可能的深入到每一行源码,有些代码我不乐意深究就写个注释说明一下作用.另外,由于本地整理的比较好,博客就随心写了. 整个Compile过程目前只看到asmjs ...

  5. 深入V8引擎-AST(5)

    懒得发首页了,有时候因为贴的代码太多会被下,而且这东西本来也只是对自己学习的记录,阅读体验极差,所以就本地自娱自乐的写着吧! 由于是解析字符串,所以在开始之前介绍一下词法结构体中关于管理字符串类的属性 ...

  6. [翻译] V8引擎的解析

    原文:Parsing in V8 explained 本文档介绍了 V8 引擎是如何解析 JavaScript 源代码的,以及我们将改进它的计划. 动机 我们有个解析器和一个更快的预解析器(~2x), ...

  7. 精读《V8 引擎 Lazy Parsing》

    1. 引言 本周精读的文章是 V8 引擎 Lazy Parsing,看看 V8 引擎为了优化性能,做了怎样的尝试吧! 这篇文章介绍的优化技术叫 preparser,是通过跳过不必要函数编译的方式优化性 ...

  8. Javascript的V8引擎研究

    1.针对上下文的Snapshot技术 什么是上下文(Contexts)?实际是JS应用程序的运行环境,避免应用程序的修改相互影响,例如一个页面js修改内置对象方法toString,不应该影响到另外页面 ...

  9. V8引擎——详解

    前言 JavaScript绝对是最火的编程语言之一,一直具有很大的用户群,随着在服务端的使用(NodeJs),更是爆发了极强的生命力.编程语言分为编译型语言和解释型语言两类,编译型语言在执行之前要先进 ...

随机推荐

  1. 机器学习: Tensor Flow +CNN 做笑脸识别

    Tensor Flow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库.节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数 ...

  2. linux的各个子系统

    Linux基本的子系统主要有CPU.Memory.IO.Network. 在这些子系统中,它们之间相互之间高度依赖.不论什么一个子系统的高负载都会引起其它子系统出现故障. 比如: 大量的页调入请求对内 ...

  3. readline库的使用

    接口十分简单,readline和addhistory: #include <stdlib.h> #include <stdio.h> #include <unistd.h ...

  4. 【甘道夫】基于Mahout0.9+CDH5.2执行分布式ItemCF推荐算法

    环境: hadoop-2.5.0-cdh5.2.0 mahout-0.9-cdh5.2.0 引言 尽管Mahout已经宣布不再继续基于Mapreduce开发,迁移到Spark.可是实际面临的情况是公司 ...

  5. Linux性能测试 sar命令

    sar命令包含在sysstat工具包中,提供系统的众多统计数据.其在不同的系统上命令有些差异 sar 命令行的常用格式: [root@C44 ~]# sar sysstat version (C) S ...

  6. WPF x:static的使用

    <Window x:Class="XamlTest.Window1"        xmlns="http://schemas.microsoft.com/winf ...

  7. WPF MVVM+EF 增删改查 简单示例(一)

    实现了那些功能,先看看效果图: 项目工程目录: 接下来开始具体的步骤: 第一步:在VS中新建工程 第二步:使用NuGet 安装EntityFramework 第三步:使用NuGet 安装EntityF ...

  8. Medical Image Report论文合辑

    Learning to Read Chest X-Rays:Recurrent Neural Cascade Model for Automated Image Annotation (CVPR 20 ...

  9. Unpaired/Partially/Unsupervised Image Captioning

    这篇涉及到以下三篇论文: Unpaired Image Captioning by Language Pivoting (ECCV 2018) Show, Tell and Discriminate: ...

  10. 使用BGP的虚拟下一跳实现IGP的路由负载

    网络拓扑: XRV1 ============================================================== !hostname XRV1! interface ...