AderTemplate
http://www.cnblogs.com/kwklover/archive/2007/07/12/815509.html
概述
AderTemplate是一个小型的模板引擎。无论是拿来直接使用还是用来研究模板引擎实现方式,都是一个不错的选择。本文尝试对其源代码做一些分析。
数据流程
AderTemplate的数据处理流程可以总结为:
模版文件 -> 模版分析 -> Template对象 -> 分析处理Template的Element集合 -> 输出目标文本
模版语法
简化描述如下:
1,变量替换 :如#variable#
2,循环语句 :<ad:foreach var="x" collection="#values#" index=”i”></ad:foreach>
3,判断语句 :<ad:if test="#value#"> </ad:if>
详细请参看AderTemplate的相关说明.
模版分析
模版分析的过程可以分成两步:
1,把模版文件分析成Token流 ;
2,对Token流进行分析,形成Element集合
所以,首先要了解Token和Element的结构与异同。
Token的类结构:
TokenKind(Token的类型)的详细说明:
|
TokenKind |
说明 |
|
EOF |
结束符 |
|
Comment |
注释,但在AderTemplate没看到具体实现 |
|
ID |
这个比较难描述,下面会通过输出Token流来直官了解下ID |
|
TextData |
文本数据,不包含模版语法的独立文本区 |
|
TagStart |
Tag的开始标记,即<ad: 注:Tag是一个Element,后面详述 |
|
TagEnd |
Tag的结束符,即 > ,注意与TagClose的区别 |
|
TagEndClose |
Tag的自闭结束符 ,即 /> |
|
TagClose |
Tag的结束标记 即</ad: 与<ad:对应,所以与TagEnd很容易区别 |
|
TagEquals |
Tag的=符号。与Tag无关的=属于TextData,非TagEquals |
|
ExpStart |
在AderTemplate中,语法#v#被定义为Expression.左#为ExpStart |
|
ExpEnd |
在AderTemplate中,语法#v#被定义为Expression.右#为ExpEnd |
|
LParent |
左括号 ( |
|
RParent |
右括号 ) |
|
Dot |
即一个点 . |
|
Comma |
逗号 , |
|
Integer |
数字 |
|
StringStart |
文本的开始符,即” |
|
StringEnd |
文本的结束符,即” |
|
StringText |
How to description ? |
为了获得更直观的认识。下面尝试把一个简单的模版文件分析的Token流输出。
模版文件,我们暂且命名为templateFile
<ad:foreach collection="#GetBookList(3)#" var="book" index="i">
<tr>
<td>#i#</td>
<td>#book.BookName#</td>
<td>#book.BookCount#</td>
</tr>
</ad:foreach>
分析的代码:
static void Main(string[] args)
{
string data = string.Empty;
using (System.IO.StreamReader reader = new System.IO.StreamReader(templateFile))
{
data = reader.ReadToEnd();
}
//模版分析,形成Token流
TemplateLexer lexer = new TemplateLexer(data);
Console.WriteLine("=======开始输出TemplateLexer分析出Token流=======");
do
{
Token token = lexer.Next();
Console.WriteLine("\tToken类型:{0}\t行列:({1}, {2})\t数据:{3}", token.TokenKind.ToString(), token.Line, token.Col
, token.Data.Replace("\r\n", ""));
if (token.TokenKind == TokenKind.EOF)
break;
} while (true);
Console.WriteLine("=======结束输出TemplateLexer分析出Token流=======\r\n");
}
输出结果:
对照表格的说明和输出结果。可以把Token理解为特定类型的”文本区’,即把模版文件按照TokenKind定义的类型分解成多个文本区(Token),所以分析模版文件形成的Token流(集合)是一种相对线性的结构。是对模版文件的初步分析与处理。
下面继续说说Element的类体系:
上述类关系图中可以看到Element主要有四个继承体系。
但每个类表达的意义是什么呢?
下面用一个表格做一个简单的说明。
|
类名 |
指代及其含义 |
|
Element |
各种Element的基类 |
|
Text |
文本类的Element , 与TokenKind为TextData的Token相似的概念 |
|
TagClose |
Tag结束符号 |
|
Tag |
Tag是一个比较广的概念。上述的模版可以表示一个foreach tag |
|
Expression |
AderTemplate把语法类似#values#定义为一个Expression |
|
FCall |
Expression子类之一,表示该Expression是一个外部函数(Function) |
|
FieldAccess |
Expression子类之一,可以近似的理解成”字段访问”,如#book.BookName# |
|
Name |
Expression子类之一,可以近似的理解成”外部变量”,如#i# |
|
StringLiteral |
Expression子类之一,可以近似的理解成”非数字型变量”。 |
|
IntLiteral |
Expression子类之一,可以近似的理解成”数字型变量”。 |
|
StringExpression |
Expression子类之一,但其表示的是Expression的集合封装类 |
为了获得更直观的了解。我们可以通过分析上述的模版文件输出的Element来理解。因为此部分代码比较多。所以不列出了。后面会提供包含本文提到的所有代码的example.
这里需要说明的是Tag Element,Tag是一个复合结构.Tag在不同的分析阶段,会些许不同。
如下面代码的(1)和(2)分析出的Element是不同的。可通过输出结果来跟踪异同。
TemplateLexer lexer = new TemplateLexer(templateData);
TemplateParser parser = new TemplateParser(lexer);
List<Element> elems = parser.Parse(); --(1)
TagParser tagParser = new TagParser(elems);
elems = tagParser.CreateHierarchy(); --(2)
Token与Element异同分析:
在上面已经提到,Token是对模版文件的一种初步分析和分解。AderTemplate对模版文件的分析处理目标是把模版文件表达为一个Template对象。而Template对象的本质其实就是Element集合的封装类,也就是AderTemplate的对模版文件的分析其实是希望把模版文件在程序结构层面表达为一个Element的集合,从上面的Element和Token类关系图可以看出。Element远比Token复杂的多。如果直接从模版文件直接分析成Element集合结构的话,可以预见分析过程会变的相当复杂。所以AderTemplate引入了Token数据结构作为一种辅助分析手段。使得AderTemplate的对模版文件的分析过程变得更流畅和清晰了。程序的架构也变得相对优雅。所以我认为阅读AderTemplate的源代码,关键是理解Token与Element的结构和作用。特别是Element结构。因为它是AderTemplate的基础结构。即解决了在程序层面用什么结构来表达模版文件的问题。
模版分析涉及到的处理类:
TemplateLexer : 从模版文件中分析成Token流。
TemplateParser: 基于Token流分析成初步的Element集合结构。
TagParser : 把TemplateParser分析出的Element集合做最后的优化处理。
Template(模版)对象:
在AderTemplate中。我们可以简单地认为一个Template就是经过模版分析后形成的最终的Element集合的封装体。
Template(模版)处理:
对Template的Element集合进行分析。生成目标文本。
此过程涉及到的技术其实不复杂,就是反射和委托,所以本文不打算详细分析此过程。否则篇幅过大。而且没什么意义。在后面我会提供一个模拟AderTemplate从Element分析处理到生成目标文本过程的例字。
相关例子
为了辅助理解AderTemplate的整个处理过程。我写了几个例子。
1,输出Token的结构信息。对比模版文件辅助理解Token的结构
2,输出从Token流中分析出的Element集合的结构信息。以辅助理解Element的结构。
3,模拟从Element集合中生成目标文本的过程。辅助理解从Element集合到生成目标文本的整个处理流程和过程。这个过程是相对简单的。从这个角度来看,AderTemplate用Element集合来表达模版文件是一个比较优秀的设计。
至于如何从模版文件分析成Element集合(Template对象)则是一个相对复杂的过程了。最好的解释还是源代码本身了。所以就不在此不做更多的分析了。
总结
AderTemplate是一个小型的模版引擎。功能并不算强大。但基本功能已经具备。从应用的角度来说,可能未必是一个最好的选择。但想学习模版引擎的开发。确是一个很不错的选择。我个人认为其架构还是比较优秀的。而且数据处理流程也很清晰。
AderTemplate的更多相关文章
随机推荐
- RGB和HSL色彩的相互转换
转自: http://blog.csdn.net/aniven/article/details/2205851 RGB和HSL(也叫HSB/HSV)是两种色彩空间,即:红,绿,蓝(Red,Green, ...
- CAS 与 无锁队列
http://coolshell.cn/articles/8239.html http://www.tuicool.com/articles/VZ3IBv http://blog.csdn.net/r ...
- javascript Date日期类
四.Date日期类 迁移时间:2017年5月27日18:43:02 Author:Marydon (一)对日期进行格式化(日期转字符串) 自定义Date日期类的format()格式化方法 方式一: ...
- Android自己定义之流式布局
流式布局,优点就是父类布局能够自己主动的推断子孩子是不是须要换行,什么时候须要换行,能够做到网页版的标签的效果. 今天就是简单的做了自己定义的流式布局. 详细效果: 原理: 事实上非常easy,Mea ...
- PL/SQL 美化器不能解析文本
1.问题:PL/SQL美化器不能解析文本 原始sql语句如下: CREATE OR REPLACE VIEW V_GGXZBM AS SELECT XZBM,XZMC,CASE WHEN PARENT ...
- 【转载】XGBoost调参
General Parameters: Guide the overall functioning Booster Parameters: Guide the individual booster ( ...
- 【转载】Java 日常开发 - 常见异常
转自 http://blog.sina.com.cn/s/blog_ab345e5d01010zaq.html 算术异常类:ArithmeticExecption 空指针异常类:NullPointer ...
- .Net 程序员面试 C# 语言篇 (回答Scott Hanselman的问题)
过去几年都在忙着找项目,赶项目,没有时间好好整理深究自己在工作中学到的东西.现在好了,趁着找工作的这段空余时间,正好可以总结和再继续夯实自己的.Net, C#基本功.在05年的时候,Scott Han ...
- 저장소system.runtime.remoting.messaging.callcontext
https://msdn.microsoft.com/ko-kr/library/system.runtime.remoting.messaging.callcontext(v=vs.110).asp ...
- vsftp 虚拟用户高级设置(转载)
发布:xiaokk 来源:net [大 中 小] vsftp 虚拟用户高级设置 本文转自:http://www.jbxue.com/article/1724.html 1.安装所需软件包 ...