関数型のテンプレートエンジンを作ってみる(0.2) - スコープ・変数定義の導入

前回は、テンプレート中のプレースホルダ(変数)を置き換える部分を作ったので、次はテンプレート中で変数を定義できるようにする。また、変数の有効な範囲(スコープ)を明確にする。スコープは静的スコープにしたい。


要素がプレースホルダだけなら単純に「{」と「}」で囲んだ内容を変数名とするだけで良いけど、今後いろんな要素が出てくるので、もう少し文法的なものを定義しておく。


テンプレートの「地」(=普通の文字列)の部分以外に「タグ」を使う。タグは「{」と「}」で囲んだ部分とし、中身は以下のような並びにする。
シングルタグ:

{タグ名 属性名=属性値 ... /}

コンテナタグ:

{タグ名 属性名=属性値 ...}
...
{/タグ名 属性名=属性値 ...}

まあXMLみたいな感じですわ。属性は0個以上幾つでも書ける。

属性名にはSymbol、属性値には、SymbolとExpressionと使用できるようにする。ダブルクォートで囲うとExpression。

{define name=surname value="板東" /}

タグ名は、とりあえず「insert」と「define」だけとする。defineはvalueを取っても良いし、コンテナにして、囲んだ部分を値としても良い。

{define name=header}
<h1>ヘッダを定義する</h1>
{/define}
...
ヘッダを出力する:
{insert value=header/}


insertの値がテンプレートの場合*1、テンプレートに適用する変数をdefineタグで列挙する。逆に言うと、defineで指定しない変数は渡されない。

{define name=helloWold}
Hello, {insert value=yourName /}!
{/define}
...
{insert value=helloWold}
{define name=yourName value="テラゾー" /}
{/insert}
{insert value=helloWold}
{define name=yourName value="terazzo" /}
{/insert}

上のテンプレートは以下のような文字列になるはず。

...
Hello, テラゾー!
Hello, terazzo!

では実装に入って行く。長いので順番にいく。まずタグのパーサを書くところから。

*1:というか定義上全部テンプレートなんだけど