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的更多相关文章

随机推荐

  1. JavaScript | 对象详解

    ————————————————————————————————————————————————————————— 对象有哪些(导图) 内建对象 数据封装对象 Object对象 Object.prot ...

  2. Linux-使用 screen 管理你的远程会话

    转自:http://www.ibm.com/developerworks/cn/linux/l-cn-screen/ 你是不是经常需要 SSH 或者 telent 远程登录到 Linux 服务器?你是 ...

  3. myBatis的引出

    jdbc 优点:简单易学,上手快,非常灵活构建sql,效率高. l缺点:代码繁琐,难以写出高质量的代码(资源的释放,SQL注入安全性等),开发者关注多,又要写业务逻辑,又要关注对象的创建和销毁. Hi ...

  4. C#实现冲顶大会辅助工具(截图+图像识别+搜索)

    前两天在博客园看到 .NET开发一个微信跳一跳辅助程序, 原来可以通过C#连接手机操作.正好朋友圈有人分享“冲顶大会”.冲顶大会是一个在线答题APP.每次12道题,每道题有10秒钟的答题时间,全对者瓜 ...

  5. Linux yum操作无效的解决方法

    1.没网,试着:ping www.baidu.com 如果显示没有连接的话,就说明没网,也就无法使用yum 命令. 2.ping通了的话,还是是用不了yum命令,说明是yum镜像没有了,那么就得下载一 ...

  6. python-循环while

    while 只要…条件成立,就一直做…. for 循环会在可迭代的序列被穷尽的时候停止,while 则是在条件不成立的时候停止,因此 while 的作用概括成一句话就是:只要…条件成立,就一直做…. ...

  7. 【c#】设置Socket连接、接收超时

    用到Socket,发现如果连接错误,比如Connect的端口不对,会造成很长时间的延时,程序就僵在那里,效果很不好: 在网上找到很方便的设置办法,分享如下: Socket.SetSocketOptio ...

  8. Unity3D刚体不同力的测试(ForceMode,AddForce,RelativeAddForce)

    摘自圣典的一段翻译: ForceAdd a continuous force to the rigidbody, using its mass.添加一个可持续力到刚体,使用它的质量.Accelerat ...

  9. 关于scut在unity上的主动推送

    自带的samples里面,chat的例子涉及主动推送,可作为参考. 在unity里面接收主动推送用Net.CommonCallback 服务端最近的新版本更改了接口,有两种方法推送: ActionFa ...

  10. Java内存分析工具jmap

    1. jmap 1.1 概述 JVM Memory Map命令用于生成heap dump文件,如果不使用这个命令,还可以使用-XX:+HeapDumpOnOutOfMemoryError参数来让虚拟机 ...