插值式序列
插值式序列
(IES
)是散布串字面数据和值的式
.插值式
按类似串
编写.
按可重载或由模板函数
处理的序列
式转换它
.
IES
字面
InterpolationExpressionSequence:
InterpolatedDoubleQuotedLiteral
InterpolatedWysiwygLiteral
InterpolatedTokenLiteral
插值式
序列可以是所见即所得
的引号
,双引号或令牌字面
.只有双引号字面
才能包含转义符
.
与串字面
不同,IES
字面不能有定义串式
的符类型宽度
的后缀
.
双引号IES
字面
InterpolatedDoubleQuotedLiteral:
i" InterpolatedDoubleQuotedCharacters opt "
InterpolatedDoubleQuotedCharacters:
InterpolatedDoubleQuotedCharacter
InterpolatedDoubleQuotedCharacter InterpolatedDoubleQuotedCharacters
InterpolatedDoubleQuotedCharacter:
DoubleQuotedCharacter
InterpolationEscapeSequence
InterpolationExpression
InterpolationEscapeSequence:
EscapeSequence
\$
InterpolationExpression:
$( AssignExpression )
与双引号串
一样,双引号IES
字面中可包含转义符
.在普通转义
中添加
的还有转义
字面$
的能力
在式
中,除左括号以外的符
的$
都按字面$
对待,无需转义它
.
插值式
中的式
是完整的D式
,式的该部分
不需要转义
.
所见即所得的IES
字面
InterpolatedWysiwygLiteral:
i` InterpolatedWysiwygCharacters opt `
InterpolatedWysiwygCharacters:
InterpolatedWysiwygCharacter
InterpolatedWysiwygCharacter InterpolatedWysiwygCharacters
InterpolatedWysiwygCharacter:
WysiwygCharacter
InterpolationExpression
所见即所得
的IES
字面的定义
类似所见即所得的串
,但仅支持反引号语法
.这些字面
中不会识别转义
.
令牌IES
字面
InterpolatedTokenLiteral:
iq{ InterpolatedTokenStringTokens opt }
InterpolatedTokenStringTokens:
InterpolatedTokenStringToken
InterpolatedTokenStringToken InterpolatedTokenStringTokens
InterpolatedTokenStringToken:
InterpolatedTokenNoBraces
{ InterpolatedTokenStringTokens opt }
InterpolatedTokenNoBraces:
TokenNoBraces
InterpolationExpression
与令牌串
一样,IES
令牌字面必须
仅包含有效
的D令牌
,但插值式
除外.不会识别转义
.
翻译式
当词法分析器
遇见插值式序列
时,按替换单个令牌的式序列
转换该令牌
.序列
总是以core.interpolation.InterpolationHeader()
式开头,总是以core.interpolation.InterpolationFooter()
结尾.
按core.interpolation.InterpolatedLiteral!(str)
式转换令牌
的每个串
部分(即字面串数据
)
按core.interpolation.InterpolatedExpression!(expr),expr
序列转换
,插值式
的令牌
的每个$(expr)
部分.
//`std.typecons.Tuple`的简单版本
struct Tuple(T...) { T value; }
Tuple!T tuple(T...)(T value) { return Tuple!T(value); }
import core.interpolation;
string name = "John Doe";
auto items = tuple(i"Hello, $(name), how are you ");
assert(items == tuple(
InterpolationHeader(),
//表示`IES`的开始
InterpolatedLiteral!("Hello, ")(),
//字面串数据
InterpolatedExpression!("name")(),
//式字面数据
name,
//直接传递的式
InterpolatedLiteral!(", how are you ")(),
//字面串数据
InterpolationFooter()));
//表示`IES`的结束
core.interpolation
类型
无需导入core.interpolation
中定义的类型
,即可使用IES
.这些是在使用IES
时自动导入
的.定义这些类
是为了方便在编译时内省IES
处理.
插值头
和插值脚
插值头
和插值脚
类型是允许轻松重载函数
以处理IES
的空结构
.还可用它们
来理解式列表
的哪些部分
是通过IES
传递的.
这些类
还有返回空串
的toString
定义,以允许按文本
转换IES
的函数(如std.stdio.writeln
或std.conv.text
)处理.
插值字面
插值字面
类型是一个编译时访问IES
的串字面部分
的空结构
.它还有个返回此值替换的序列部分
的toString
成员函数.
已插值式
内插式
已插值式
类型是一个对以下式
编译时访问字面
的空结构
.它提供了一个返回空串
的toString
成员函数.
它还有一个用来构造类型
的元
参数的枚举
式成员.
string name = "John Doe";
auto ies = i"Hello, $(name)";
static assert(is(typeof(ies[0]) == InterpolationHeader));
static assert(ies[1].toString() == "Hello, ");
static assert(ies[2].expression == "name");
assert(ies[3] == name);
static assert(is(typeof(ies[4]) == InterpolationFooter));
接受和处理IES
接受IES
的推荐机制
是提供变参模板函数
来匹配显式插值头
和插值脚
参数包围的序列
内的各种参数
.
void processIES(Sequence...)(InterpolationHeader, Sequence data, InterpolationFooter)
{
//在此处处理`'数据'`
}
IES
还可按插值式包含类型
.可通过传递给变参模板参数
来使用它.
template processIESAtCompileTime(InterpolationHeader header, Sequence...)
{
static assert(Sequence[$-1] == InterpolationFooter());
}
alias result = processIES!i"Here is a type: $(int)";
按String
转换
许多时候,需要按串转换IES
.Phobos
函数std.conv.text
可在需要串的环境
按串转换IES
来用,如赋值给串变量
,或调用接受串的函数
.
import std.conv : text;
string name = "John Doe";
string badgreeting = i"Hello, $(name)";
//错误
string greeting = i"Hello, $(name)".text;
//好
assert(greeting == "Hello, John Doe");
强烈建议想接受IES
的库作者
提供接受它们的重载
,而不是依赖std.conv
,因为这会导致不必要的赋值
.当某些类型的注入攻击
可能来自恶意用户提供的数据
时,它尤其重要
.