私はWhittle gemを使用してテンプレート言語を解析し、ルールに含まれていないものと一致させたいと考えました。私はそこに他のテンプレートエンジンをよく知っていますが、これは生産上の事例よりも学問的なものです。whittleパーサー条件付きルールアクティブ化
私が遭遇した問題は、パーサーが:raw
上記:id
の優先順位を無視し、まだ{{
後:raw
タグに待っていることです。
:raw
ルールを式の中に適用し、式の中にのみ:spc
ルールを適用することは許可されていません。
パーサコード
class Parser < Whittle::Parser
# Skip whitespaces (should not apply in :raw)
rule(:spc => /\s+/).skip!
# Various delimiters
rule("{{")^4
rule("}}")^4
rule("{%")^4
rule("%}")^4
rule("|")^4
rule("end")^4
# Defines an id (very large match)
rule(:id => /[a-zA-Z_.$<>=!:]+(\((\w+|\s+|,|")+\))?/)^2
# inline tag
rule(:inline) do |r|
r["{{", :inline_head, "}}"].as { |_,id,_| Tag::Inline.new(id) }
end
# inline tag contents
# allows "|" chaining
rule(:inline_head) do |r|
r[:inline_head, "|", :id].as { |head, _, id| head << id }
r[:id].as { |id| [id] }
r[].as { [] }
end
# block tag
rule(:block) do |r|
r["{%", :block_head, "%}", :all, "{%", "end", "%}"].as { |_,head,_,tags,_,_,_|
Tag::Block.new(head, tags)
}
end
# block tag heading
# separates all the keywords
rule(:block_head) do |r|
r[:block_head, :id].as { |head, id| head << id }
#r[:id].as { |id| [id] }
r[].as { [] }
end
# one rule to match them all
rule(:all) do |r|
r[:all,:inline].as { |all, inline| all << inline }
r[:all, :block].as { |all, block| all << block }
r[:all, :raw].as { |all, raw| all << raw }
r[].as { [] }
end
# the everything but tags rule
rule(:raw => /[^\{\}%]+/).as { |text| Tag::Raw.new(text) }^1
# starting rule
start(:all)
end
そして、入力されたテキストは以下のようになり、出力はオブジェクトによって表される抽象構文木(彼らは単に今のオブジェクトのようにハッシュされている)です。
<html>
<head>
<title>{{ title|capitalize }}</title>
</head>
<body>
<div class="news">
{% for news in articles %}
{{ news.title }}
{{ news.body | limit(100) }}
{{ tags | join(",", name) }}
{% end %}
</div>
</body>
</html>
著者自身からのWoah!私はこれをできるだけ早く試みている。ありがとうございました –
作業し、いくつかの調整後にすべての私の問題を解決しました。素晴らしいプロジェクト! –