Go 源码阅读笔记 text/template/parse
为什么80%的码农都做不了架构师?>>>
文件组成
- lex.go 词法定义与解析
- node.go node 定义与创建
- parse.go 生成 template 语法树 tree
lex.go 要点
itemType 常量表次序规则:itemKeyword 用来分界词法中的关键字和其他词法元素,参见下列实现
func (i item) String() string
func lexIdentifier(l *lexer) stateFn
node.go 要点
各种 NodeType 要实现 Node 接口
type Node interface {Type() NodeTypeString() stringCopy() NodePosition() Pos unexported()
}
parse.go 要点
每个模板都有唯一的模板名,并对应生成一个 Tree
type Tree struct {Name stringParseName stringRoot *ListNodetext stringfuncs []map[string]interface{}lex *lexertoken [3]itempeekCount intvars []string
}
Tree 的 Parse 方法中 defer t.recover(&err) 捕获解析过程中发生的 error ,如果是 runtime.Error 就 panic,否则 stopParse
Parse方法首先进行的是词法分析(内部使用goroutine和chan并行完成,其实和节点的生成是同步的)
t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim))
lex.go 中的 lexer定义
type lexer struct {name string // the name of the input; used only for error reportsinput string // the string being scannedleftDelim string // start of actionrightDelim string // end of actionstate stateFn // the next lexing function to enterpos Pos // current position in the inputstart Pos // start position of this itemwidth Pos // width of last rune read from inputlastPos Pos // position of most recent item returned by nextItemitems chan item // channel of scanned itemsparenDepth int // nesting depth of ( ) exprs
}
lexer在解析过程中的顺序总是从一个 lexText 开始,遍历 input 。lexText 负责查找
- itemLeftDelim 默认"{{",可以自定义
把处理过程交给 func lexLeftDelim,lexLeftDelim 负责查找注释和非注释(被称做lexInsideAction),处理过程交给 func lexComment,lexComment 解析到注释结束后,又把处理过程交给lexText,进行 lexInsideAction 解析。
lexInsideAction 要点
所有定义的词法都在这个函数中处理,根据词法定义交给具体的词法处理函数,形成词法处理链,完成遍历。每一个词法处理函数负责检查词法有效性。这个过程仅仅是一个词法处理链,遍历 input
某个词法分析通过后,会生成对应的节点,私有方法 parse 完成此过程。
t.parse(treeSet)
第一个节点 Tree.Root 要点
type ListNode struct {NodeTypePosNodes []Node // The element nodes in lexical order.
}
Root 是一个 ListNode ,保存 Tree 解析所有的 Node.
前面说过lex分析的时候分只有两种情况 lexText , lexInsideAction ,因此 parse 中
n := t.textOrAction()
这是所有的节点生成的入口点
func (t *Tree) textOrAction() Node {switch token := t.nextNonSpace(); token.typ {case itemText:return newText(token.pos, token.val)case itemLeftDelim:return t.action() //这里所有{{...}}中的代码都由action处理default:t.unexpected(token, "input")}return nil
}
func (t *Tree) action() (n Node) {switch token := t.nextNonSpace(); token.typ {case itemElse:return t.elseControl()case itemEnd:return t.endControl()case itemIf:return t.ifControl()case itemRange:return t.rangeControl()case itemTemplate:return t.templateControl()case itemWith:return t.withControl()}t.backup()// Do not pop variables; they persist until "end".return newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command"))
}
而action方法把模板中的关键字划分为 xxxControl 处理,其他都由 newAction 生成 ActionNode ,
也可以理解为:template 的节点分两大类
- ActionNode,其实封装了各种pipline的识别信息,
- xxxxControl,流程控制类,IfNode,RangeNode,WithNode这些
return newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command"))
这里面的要点:
t.pipeline("command")
看pipeline的实现,其实所有的 pipeline 节点都都封装为 NodeCommand, An element of a pipeline
pipeline 方法中对所有已知的 action 进行处理,阅读代码发现 template 的语法设计中使用这种pipeline的方式,使得解析器只需要向下分析,也就是所谓的 peek ,不需要回退,这种设计无疑简化了分析器,我不知道对以后的扩展是否会有所限制
从 Parse->parse->textOrAction->pipeline 递归向下生成了所有的节点,而最终 parse 中 t.Root.append(n) 把所有生成的节点全部添加到 Tree.Root
从struct来说,经过了一层层的封装 lex.go itemType -> node.go NodeType->node.go XxxxNode 进入Tree.Root.Nodes
转载于:https://my.oschina.net/achun/blog/131558
Go 源码阅读笔记 text/template/parse相关推荐
- syzkaller 源码阅读笔记1(syz-extract syz-sysgen)
文章目录 1. syz-extract 1-0 总结 1-1. `main()` 1-2 `archList()` - `1-1 (3)` 获取架构 name list 1-3 `createArch ...
- Yii源码阅读笔记 - 日志组件
2015-03-09 一 By youngsterxyf 使用 Yii框架为开发者提供两个静态方法进行日志记录: Yii::log($message, $level, $category); Yii: ...
- 【Flink】Flink 源码阅读笔记(15)- Flink SQL 整体执行框架
1.概述 转载:Flink 源码阅读笔记(15)- Flink SQL 整体执行框架 在数据处理领域,无论是实时数据处理还是离线数据处理,使用 SQL 简化开发将会是未来的整体发展趋势.尽管 SQL ...
- Transformers包tokenizer.encode()方法源码阅读笔记
Transformers包tokenizer.encode()方法源码阅读笔记_天才小呵呵的博客-CSDN博客_tokenizer.encode
- 源码阅读笔记 BiLSTM+CRF做NER任务 流程图
源码阅读笔记 BiLSTM+CRF做NER任务(二) 源码地址:https://github.com/ZhixiuYe/NER-pytorch 本篇正式进入源码的阅读,按照流程顺序,一一解剖. 一.流 ...
- 代码分析:NASM源码阅读笔记
NASM源码阅读笔记 NASM(Netwide Assembler)的使用文档和代码间的注释相当齐全,这给阅读源码 提供了很大的方便.按作者的说法,这是一个模块化的,可重用的x86汇编器, 而且能够被 ...
- CI框架源码阅读笔记4 引导文件CodeIgniter.php
到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http:// ...
- AQS源码阅读笔记(一)
AQS源码阅读笔记 先看下这个类张非常重要的一个静态内部类Node.如下: static final class Node {//表示当前节点以共享模式等待锁static final Node SHA ...
- 【Flink】Flink 源码阅读笔记(20)- Flink 基于 Mailbox 的线程模型
1.概述 转载:Flink 源码阅读笔记(20)- Flink 基于 Mailbox 的线程模型 相似文章:[Flink]Flink 基于 MailBox 实现的 StreamTask 线程模型 Fl ...
最新文章
- 算法设计与分析第3章 贪心算法
- http://www.cnblogs.com/youfan/articles/3216816.html
- python数组每个元素加1_python-根据键转换numpy数组中的每个元素
- QML基础类型之real
- es6-promise源码重点分析难点解析
- java网络编程 个人心得
- 计算一个时间,是否在规定的时期时间之间
- 客户关系管理之会员管理(转)
- Linux平台升级chrome浏览器后,再打开会提示:“您的个人资料来自新版 Google Chrome 浏览器,因此无法使用。某些功能可能无法使用。请指定其他个人资料目录,或使用新版本”
- 单片机学习笔记(一)——概述
- 助力操作系统国产化:Testin云测试服贸会首发鸿蒙系统测试平台
- 计算机网络存储设备有哪些,存储设备有哪些
- win10Ie重置.html默认应用设置,win10系统IE浏览器设置为默认浏览器的操作方法
- rds是什么云模式_IaaS、PaaS、SaaS、DaaS都是什么?
- VMware 8安装Mac OS X 10.7
- ConcurrentHashMap的锁
- 用TELNET登录QQ邮箱
- 手办商城app开发功能分析
- Camera摄像头模组硬件
- Clojure CLR 入门