首页 理论 架构 工程 文档 白皮书 著作 研究 案例 下载 博客 关于 开始使用 →

第59章 SATE 模板语法

第59章 SATE 模板语法

SATE 模板语法是 Template 与 TemplateEngine 之间的规则表达层

第57章定义了 Template 的基本组成,第58章建立了 TemplateEngine 的运行流程。本章进一步规定:

模板如何书写,以及 TemplateParser 如何识别这些语法。

SATE 模板语法的核心原则是:

模板语法
    ↓
Parser 识别
    ↓
结构化节点
    ↓
Compiler
    ↓
TemplateEngine
    ↓
Render

模板语法本身不负责认知、推理、决策和学习。


1. 变量

变量是 SATE 最基础的模板语法。

基本形式:

{{name}}

例如:

<h1>{{title}}</h1>
<p>{{content}}</p>

数据:

{
    "title": "WSaiOS",
    "content": "SAI Template Engine"
}

执行结果:

<h1>WSaiOS</h1>
<p>SAI Template Engine</p>

1.1 对象变量

可以直接引用对象:

{{Company}}

也可以引用对象属性:

{{Company.name}}

形成:

Variable
    ↓
Object
    ↓
Property
    ↓
Value

1.2 变量路径

支持层级路径:

{{Company.address.city}}

解析:

Company
 ↓
address
 ↓
city
 ↓
Value

1.3 变量不存在

如果变量不存在:

{{Company.phone}}

SATE 不应该自动生成数据。

根据模板配置,可以返回:

EMPTY
MISSING
UNKNOWN

或者使用默认值:

{{Company.phone | default:"N/A"}}

结果:

N/A

2. 属性

属性语法用于访问对象属性。

基本形式:

{{Object.Property}}

例如:

{{Product.name}}
{{Product.price}}
{{Product.state}}

数据:

Product
{
    name: "Product A",
    price: 29.90,
    state: "active"
}

模板:

<h1>{{Product.name}}</h1>
<p>{{Product.price}}</p>

2.1 多级属性

{{Company.contact.email}}

解析:

Company
 ↓
contact
 ↓
email

2.2 属性与变量的区别

{{name}}

表示当前 Context 中的变量。

而:

{{Product.name}}

表示:

Product 对象
    ↓
name 属性

因此:

Variable = 数据引用
Property = 对象数据访问

3. 方法

SATE 可以允许模板调用经过授权的方法。

基本形式:

{{Object.method()}}

例如:

{{Product.getName()}}

或者:

{{Product.formatPrice()}}

数据:

Product.price = 29.9

方法:

formatPrice()

返回:

29.90

模板:

<p>{{Product.formatPrice()}}</p>

3.1 带参数方法

可以支持:

{{Product.formatPrice(2)}}

表示:

formatPrice(2)

但是方法参数必须经过解析和验证。


3.2 方法权限

模板不能任意调用系统方法。

应当采用:

Template
 ↓
Method Resolver
 ↓
Allowed Method
 ↓
Execute

例如允许:

getName()
format()
display()
escape()

而不是允许模板执行任意系统命令。


3.3 方法与属性

{{Product.name}}

是属性访问。

{{Product.getName()}}

是方法调用。

因此:

Property → Read
Method   → Operation

4. 条件

条件语法控制某一段模板是否表现。

基本形式:

{{if condition}}
    ...
{{/if}}

例如:

{{if Product.state == "active"}}
    <p>Available</p>
{{/if}}

4.1 IF / ELSE

{{if Product.stock > 0}}
    <p>In Stock</p>
{{else}}
    <p>Out of Stock</p>
{{/if}}

执行:

Product.stock > 0
        ↓
   Condition
    ┌───┴───┐
  TRUE    FALSE
   ↓         ↓
In Stock  Out of Stock

4.2 多条件

可以支持:

AND
OR
NOT

例如:

{{if Product.state == "active" AND Product.stock > 0}}
    <p>Available</p>
{{/if}}

解析为:

AND
├── Product.state == active
└── Product.stock > 0

4.3 条件状态

模板条件可以产生:

TRUE
FALSE
UNKNOWN
CONFLICT

例如:

Product.stock

不存在时:

Product.stock > 0

不能直接认为:

FALSE

更合理的是:

UNKNOWN

具体表现由 SATE 的条件策略决定。


5. 循环

循环用于重复表现集合数据。

基本形式:

{{foreach Items as Item}}
    ...
{{/foreach}}

例如:

<ul>

{{foreach Products as Product}}

    <li>
        {{Product.name}}
    </li>

{{/foreach}}

</ul>

5.1 Loop Context

每次循环都会产生当前对象:

Products
│
├── Product A
├── Product B
└── Product C

执行:

Loop Context
├── Product = Product A
├── Product = Product B
└── Product = Product C

因此:

{{Product.name}}

在每一次循环中对应当前 Product。


5.2 Index

可以提供循环索引:

{{foreach Products as Product}}
    {{index}}. {{Product.name}}
{{/foreach}}

结果:

1. Product A
2. Product B
3. Product C

Index 属于 Loop Context,而不是 Product 本身。


5.3 空集合

如果:

Products = []

则:

{{foreach Products as Product}}
    ...
{{/foreach}}

循环次数为:

0

可以配合条件:

{{if Products}}
    {{foreach Products as Product}}
        <p>{{Product.name}}</p>
    {{/foreach}}
{{else}}
    <p>No Products</p>
{{/if}}

6. Include

Include 用于把另一个模板包含到当前模板。

基本形式:

{{include "header.html"}}

例如:

{{include "header.html"}}

<main>
    <h1>{{title}}</h1>
</main>

{{include "footer.html"}}

结构:

main.html
│
├── header.html
├── main content
└── footer.html

6.1 Include 的作用

Include 主要用于模板复用:

Header
Footer
Navigation
Sidebar
Common Block

例如:

templates/
├── header.html
├── footer.html
├── navigation.html
└── product.html

product.html

{{include "header.html"}}

<h1>{{Product.name}}</h1>

{{include "footer.html"}}

6.2 Include Context

Include 可以继承当前 Context:

Main Context
     ↓
Include
     ↓
Header Template

例如:

Context
{
    Company,
    User,
    Product
}

Header 可以访问:

{{Company.name}}

也可以设计独立 Context:

{{include "header.html" with Header}}

形成:

Main Context
      ↓
Header Context

具体采用哪一种方式,由 SATE 语法规范确定。


6.3 Include 防止无限递归

例如:

A.html
 ↓
include B.html

B.html
 ↓
include A.html

形成:

A → B → A → B → ...

因此 TemplateEngine 应该记录 Include 路径:

Include Stack
[
    A.html,
    B.html
]

如果发现:

A.html

再次进入当前栈,则产生:

INCLUDE_RECURSION

而不是无限执行。


7. Extend

Extend 用于建立模板继承关系。

例如:

{{extend "layout.html"}}

表示当前模板继承:

layout.html

结构:

layout.html
     ↑
     │ extend
     │
product.html

7.1 Layout Template

基础模板:

<html>

<head>
    {{block "head"}}
    {{/block}}
</head>

<body>

    {{block "content"}}
    {{/block}}

</body>

</html>

子模板:

{{extend "layout.html"}}

{{block "content"}}

<h1>{{Product.name}}</h1>

{{/block}}

最终:

layout
│
├── head block
│
└── content block
      ↓
   Product Content

7.2 Extend 与 Include 的区别

两者不能混淆:

Include
→ 把一个模板放进当前模板

Extend
→ 当前模板继承基础模板结构

例如:

Include:
A + B

而:

Extend:
Base
 ↑
Child

8. Block

Block 是 Extend 体系中的模板占位区域。

基础模板:

{{block "content"}}

Default Content

{{/block}}

子模板:

{{extend "layout.html"}}

{{block "content"}}

<h1>Product A</h1>

{{/block}}

执行时:

Base Block
     ↓
Find Child Block
     ↓
Replace / Override
     ↓
Render

8.1 Block 的结构

可以抽象:

Block
{
    name
    content
    parent
    state
}

例如:

Block
{
    name: "content",
    content: "...",
    state: "ACTIVE"
}

8.2 Block 默认内容

如果子模板没有覆盖:

{{block "content"}}
    Default Content
{{/block}}

则使用:

Default Content

这样基础模板可以独立运行。


8.3 Block 与 Include

Include
→ 引入模板

Block
→ 定义可替换区域

通常:

Extend + Block

组成模板继承机制。


9. 自定义标签

SATE 可以定义自定义标签。

例如:

{{product Product}}

或者:

{{display Product.name}}

这些标签不是 HTML 标签,而是 SATE Template Tag。


9.1 自定义标签结构

可以定义:

CustomTag
{
    name
    parameters
    body
    handler
    state
}

例如:

CustomTag
{
    name: "product",
    parameters: ["Product"]
}

Parser 识别:

{{product Product}}

然后:

Tag Resolver
 ↓
CustomTag Handler
 ↓
Result
 ↓
Render

9.2 自定义标签示例

定义:

{{price Product.price}}

数据:

Product.price = 29.9

标签处理器:

price()

得到:

29.90

模板:

<p>{{price Product.price}}</p>

结果:

<p>29.90</p>

9.3 自定义标签的边界

自定义标签不能成为隐藏的认知引擎。

它应该主要用于:

格式处理
表现处理
数据映射
输出组件

而不是:

推理
决策
学习
知识生成

否则 Template 层和 ICAI 核心认知层会发生职责混乱。


10. 模板语法解析

TemplateParser 是整个语法体系的入口。

它需要把:

Template Source

转换成:

Template Nodes

10.1 Lexer / Tokenizer

第一步可以进行 Token 分析。

例如:

<h1>{{Product.name}}</h1>

解析:

TEXT
VARIABLE_START
PATH
VARIABLE_END
TEXT

形成:

[
    TEXT("<h1>"),
    VARIABLE("Product.name"),
    TEXT("</h1>")
]

10.2 Block Token

例如:

{{if Product.state == "active"}}
    Available
{{/if}}

解析:

IF_START
CONDITION
TEXT
IF_END

然后形成结构:

IF
├── Condition
└── Body
    └── Text

10.3 Loop Token

{{foreach Products as Product}}
    {{Product.name}}
{{/foreach}}

解析:

FOREACH_START
COLLECTION
VARIABLE
TEXT / VARIABLE
FOREACH_END

最终:

FOREACH
├── Products
├── Product
└── Body
    └── Product.name

10.4 Include Token

{{include "header.html"}}

解析:

INCLUDE
└── "header.html"

10.5 Extend Token

{{extend "layout.html"}}

解析:

EXTEND
└── "layout.html"

10.6 Block Token

{{block "content"}}
    ...
{{/block}}

解析:

BLOCK
├── name: content
└── body

10.7 Template AST

所有语法最终可以组织成模板结构树。

例如:

{{extend "layout.html"}}

{{block "content"}}

<h1>{{Company.name}}</h1>

{{if Company.state == "active"}}

    {{foreach Products as Product}}

        <p>{{Product.name}}</p>

    {{/foreach}}

{{/if}}

{{/block}}

解析为:

Template
│
├── Extend
│   └── layout.html
│
└── Block
    └── content
        │
        ├── Text
        │
        ├── Variable
        │   └── Company.name
        │
        └── Condition
            │
            └── Loop
                │
                ├── Collection
                │   └── Products
                │
                └── Variable
                    └── Product.name

这就是 SATE Template 的内部结构。


10.8 语法解析完整流程

Template Source
       ↓
Tokenizer
       ↓
Token
       ↓
Parser
       ↓
Syntax Validation
       ↓
Template Structure
       ↓
AST
       ↓
Compiler
       ↓
Compiled Template

SATE 模板语法总表

语法 作用
{{name}} 变量
{{Object.property}} 属性
{{Object.method()}} 方法
{{if ...}} 条件
{{else}} 条件分支
{{/if}} 条件结束
{{foreach ...}} 循环
{{/foreach}} 循环结束
{{include ...}} 模板包含
{{extend ...}} 模板继承
{{block ...}} 模板区块
{{/block}} 区块结束
{{custom ...}} 自定义标签

SATE Template Syntax 总体结构

SATE Template Syntax
│
├── Variable
│
├── Property
│
├── Method
│
├── Condition
│   ├── IF
│   ├── ELSE
│   └── Operators
│
├── Loop
│   └── FOREACH
│
├── Include
│
├── Extend
│
├── Block
│
└── Custom Tag

最终进入:

Template Syntax
       ↓
Tokenizer
       ↓
Parser
       ↓
Template Structure
       ↓
Compiler
       ↓
TemplateEngine
       ↓
Context + Data
       ↓
Render
       ↓
Expression Output

本章核心定义

SATE 模板语法是 SATE Template 用于描述变量访问、对象属性、方法调用、条件表现、循环表现、模板包含、模板继承、区块覆盖及自定义表现标签的一组确定性语法规则;TemplateParser 将这些语法解析为结构化模板节点,再由 TemplateCompiler 和 TemplateEngine 执行。

核心边界:

Template Syntax
     ↓
描述“如何表现”
     ↓
TemplateParser
     ↓
TemplateCompiler
     ↓
TemplateEngine
     ↓
Render

而不是:

Template Syntax
     ↓
认知
推理
决策
学习

因此,SATE 的模板语法可以保持为一个独立、可解析、可编译、可执行、确定性的表现语法体系

Leave a Reply

Your email address will not be published. Required fields are marked *