jude 7 سال پیش
والد
کامیت
4fec908b22
1فایلهای تغییر یافته به همراه8 افزوده شده و 8 حذف شده
  1. 8 8
      docs/art/81vue-lexical-analysis.md

+ 8 - 8
docs/art/81vue-lexical-analysis.md

@@ -54,7 +54,7 @@ return {
 const ast = parse(template.trim(), options)
 ```
 
-也就是 `Vue` 的 `parser`,它是如何将字符串模板解析为抽象语法树(`AST`)。
+也就是 `Vue` 的 `parser`,它是如何将字符串模板解析为抽象语法树(`AST`)
 
 ## 对 parser 的简单介绍
 
@@ -66,7 +66,7 @@ const ast = parse(template.trim(), options)
 
 `parser` 是把某种特定格式的文本转换成某种数据结构的程序,其中“特定格式的文本”可以理解为普通的字符串,而 `parser` 的作用就是将这个字符串转换成一种数据结构(通常是一个对象),并且这个数据结构是编译器能够理解的,因为编译器的后续步骤,比如上面提到的 句法分析,类型检查/推导,代码优化,代码生成 等等都依赖于该数据结构,正因如此我们才说 `parser` 是编译器处理源代码的第一步,并且这种数据结构是抽象的,我们常称其为抽象语法树,即 `AST`。
 
-`Vue` 的编译器也不例外,大致也分为三个阶段,即:词法分析 -> 句法分析 -> 代码生成。在词法分析阶段 `Vue` 会把字符串模板解析成一个个的令牌(`token`),该令牌将用于句法分析阶段,在句法分析阶段会根据令牌生成一 `AST`,最后再根据该 `AST` 生成最终的渲染函数,这样就完成了代码的生成。按照顺序我们需要先了解的是词法分析阶段,看一看 `Vue` 是如何对字符串模板进行拆解的。
+`Vue` 的编译器也不例外,大致也分为三个阶段,即:词法分析 -> 句法分析 -> 代码生成。在词法分析阶段 `Vue` 会把字符串模板解析成一个个的令牌(`token`),该令牌将用于句法分析阶段,在句法分析阶段会根据令牌生成一 `AST`,最后再根据该 `AST` 生成最终的渲染函数,这样就完成了代码的生成。按照顺序我们需要先了解的是词法分析阶段,看一看 `Vue` 是如何对字符串模板进行拆解的。
 
 ## Vue 中的 html-parser
 
@@ -112,7 +112,7 @@ export function parse (
 }
 ```
 
-同时我们注意到在 `parse` 函数内部主要通过调用 `parseHTML` 函数对模板字符串进行解析,实际上 `parseHTML` 函数的作用就是用来做词法分析的,而 `parse` 函数的作用则是在词法分析的基础上做句法分析从而生成一 `AST`。本节我们主要分析一下 `Vue` 是如何对模板字符串进行词法分析的,也就是 `parseHTML` 函数的实现。
+同时我们注意到在 `parse` 函数内部主要通过调用 `parseHTML` 函数对模板字符串进行解析,实际上 `parseHTML` 函数的作用就是用来做词法分析的,而 `parse` 函数的作用则是在词法分析的基础上做句法分析从而生成一 `AST`。本节我们主要分析一下 `Vue` 是如何对模板字符串进行词法分析的,也就是 `parseHTML` 函数的实现。
 
 根据文件头部的引用关系可知 `parseHTML` 函数来自 `src/compiler/parser/html-parser.js` 文件,实际上整个 `html-parser.js` 文件所做的事情都是在做词法分析,接下来我们就研究一下它是如何实现的。打开该文件,其开头是一段注释:
 
@@ -267,7 +267,7 @@ const ncname = '[a-zA-Z_][\\w\\-\\.]*'
 
 我们可以在 `Vue` 的源码中看到其给出了一个连接:[https://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-QName](https://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-QName),其实 `qname` 就是:`<前缀:标签名称>`,也就是合法的XML标签。
 
-了解了这些,我们再来看 `ncname` 的正则表达式,它定义了 `ncname` 的合法组成,这个正则所匹配的内容很简单:*字母、数字或下划线开头,后面可以跟任意数量的字符、中横线和 `.`*。
+了解了这些,我们再来看 `ncname` 的正则表达式,它定义了 `ncname` 的合法组成,这个正则所匹配的内容很简单:*字母或下划线开头,后面可以跟任意数量的字符、中横线和 `.`*。
 
 ### qnameCapture
 
@@ -1012,7 +1012,7 @@ if (startTagMatch) {
 }
 ```
 
-`startTagMatch` 常量存储着 `parseStartTag` 函数的返回值,在前面的分析中我们得知,只有在成功匹配到开始的情况下 `parseStartTag` 才会返回解析结果(一个对象),否则返回 `undefined`。也就是说如果匹配失败则不会执行 `if` 语句块,现在我们假设匹配成功,那么 `if` 语句块中的代码将会被执行,此时会将解析结果作为参数传递给 `handleStartTag` 函数,`handleStartTag` 函数定义在 `parseStartTag` 函数的下方,源码如下:
+`startTagMatch` 常量存储着 `parseStartTag` 函数的返回值,在前面的分析中我们得知,只有在成功匹配到开始标签的情况下 `parseStartTag` 才会返回解析结果(一个对象),否则返回 `undefined`。也就是说如果匹配失败则不会执行 `if` 语句块,现在我们假设匹配成功,那么 `if` 语句块中的代码将会被执行,此时会将解析结果作为参数传递给 `handleStartTag` 函数,`handleStartTag` 函数定义在 `parseStartTag` 函数的下方,源码如下:
 
 ```js
 function handleStartTag (match) {
@@ -1134,7 +1134,7 @@ const value = args[3] || args[4] || args[5] || ''
 ]
 ```
 
-我们知道,数组的第 `3`、`4`、`5` 项其中之一可能会包含属性值,所以常量 `value` 中就保存着最终的属性值,如果第 `3`、`4`、`5` 项都没有获取到属性值,那么属性值将被设置为一个空字符串:`''`。
+我们知道,数组的第 `4`、`5`、`6` 项其中之一可能会包含属性值,所以常量 `value` 中就保存着最终的属性值,如果第 `4`、`5`、`6` 项都没有获取到属性值,那么属性值将被设置为一个空字符串:`''`。
 
 属性值获取到了之后,就可以拼装最终的 `attrs` 数组了,如下:
 
@@ -1511,7 +1511,7 @@ if (tagName) {
 
 ## textEnd 大于等于 0 的情况
 
-以上是 `textEnd` 等于 `0` 的情况,此时代表字符 `<` 为字符串的第一个字符,所以会优先作为 **注释标签**、**条件注释**、**开始标识** 以及 **结束标签** 处理,但以即使字符串的第一个字符是 `<` 以不能保证成功匹配以上四种情况,比如字符串 `'< 2'`,这个字符串虽然以 `<` 开头,但他什么标签都不是,这将会进入另外一个 `if` 语句块的判断,即如下代码:
+以上是 `textEnd` 等于 `0` 的情况,此时代表字符 `<` 为字符串的第一个字符,所以会优先作为 **注释标签**、**条件注释**、**开始标识** 以及 **结束标签** 处理,但是即使字符串的第一个字符是 `<` 也不能保证成功匹配以上四种情况,比如字符串 `'< 2'`,这个字符串虽然以 `<` 开头,但他什么标签都不是,这将会进入另外一个 `if` 语句块的判断,即如下代码:
 
 ```js
 let text, rest, next
@@ -1880,4 +1880,4 @@ parseHTML(templateString, {
 })
 ```
 
-`comment` 钩子函数也接收一个参数,该参数的值为注释节点的内容。
+`comment` 钩子函数也接收一个参数,该参数的值为注释节点的内容。