如何为类似液体的模板语言编写简单的 peg 语法?
how to write a simple peg grammar for a liquid-like templating language?
编辑:您可以在此处关注进度:https://github.com/simple-updates/template
我正在使用 peg.js 并尝试编写一些可以解释模板的东西,例如:
hello {{ "world" }}
{% if a %}
good {{ a }}
{% else %}
bad
{% endif %}
我已经尝试了很多东西,但假设这是我的起点:
Template
= ws markup ws
ws = " "*
open_interpolation = "{{"
close_interpolation = "}}"
open_tag = "{%"
close_tag = "%}"
char = . // ?
markup =
(open_tag tag:char* close_tag)
{ return { 'tag': tag.join('') } } /
(open_interpolation interpolation:char* close_interpolation)
{ return { 'interpolation': interpolation.join('') } } /
chars:char*
{ return { 'chars': chars.join('') } }
例如,当我尝试字符串 {{ test }}
时,它只会将其解释为字符而不是插值。
知道我该怎么做吗?
(显然嵌套 "markups" 会更复杂)
好的,我还没有进入任何嵌套部分,但我的 tags/interpolations 开始工作了
关键是那些!not_something value
当前语法:
{
function j(value) {
return value.join('')
}
}
Template
= ws markup:markup ws { return markup }
ws = " "*
open_interpolation = "{{"
close_interpolation = "}}"
open_tag = "{%"
close_tag = "%}"
value = .
not_close_interpolation =
ws !close_interpolation value:value ws { return value }
not_close_tag =
ws !close_tag value:value ws { return value }
not_open_tag_or_interpolation =
!open_interpolation !open_tag value:value { return value }
markup =
(
open_interpolation interpolation:not_close_interpolation+ close_interpolation {
return { 'interpolation': j(interpolation) }
} /
open_tag tag:not_close_tag+ close_tag {
return { 'tag': j(tag) }
} /
value:not_open_tag_or_interpolation+ { return j(value) }
)+
像这样的东西作为开始怎么样:
Template
= Atom*
Atom
= IfTag
/ Interpolation
/ [^{]
/ !"{%" !"{{" "{"
Interpolation
= "{{" _ Expression _ "}}"
IfTag
= If Template ( Else Template )? EndIf
If
= "{%" _ "if" _ Expression _ "%}"
Else
= "{%" _ "else" _ "%}"
EndIf
= "{%" _ "endif" _ "%}"
Expression
= "\"" [^"]* "\""
/ [a-zA-Z]+
/ [0-9]+
_
= [ \t\n\r]*
这里棘手的部分是 Atom
生产的 !"{%" !"{{" "{"
替代方案,其内容如下:
When no "{%" and "{{" can be seen ahead of the current position, match a single "{"
编辑:您可以在此处关注进度:https://github.com/simple-updates/template
我正在使用 peg.js 并尝试编写一些可以解释模板的东西,例如:
hello {{ "world" }}
{% if a %}
good {{ a }}
{% else %}
bad
{% endif %}
我已经尝试了很多东西,但假设这是我的起点:
Template
= ws markup ws
ws = " "*
open_interpolation = "{{"
close_interpolation = "}}"
open_tag = "{%"
close_tag = "%}"
char = . // ?
markup =
(open_tag tag:char* close_tag)
{ return { 'tag': tag.join('') } } /
(open_interpolation interpolation:char* close_interpolation)
{ return { 'interpolation': interpolation.join('') } } /
chars:char*
{ return { 'chars': chars.join('') } }
例如,当我尝试字符串 {{ test }}
时,它只会将其解释为字符而不是插值。
知道我该怎么做吗?
(显然嵌套 "markups" 会更复杂)
好的,我还没有进入任何嵌套部分,但我的 tags/interpolations 开始工作了
关键是那些!not_something value
当前语法:
{
function j(value) {
return value.join('')
}
}
Template
= ws markup:markup ws { return markup }
ws = " "*
open_interpolation = "{{"
close_interpolation = "}}"
open_tag = "{%"
close_tag = "%}"
value = .
not_close_interpolation =
ws !close_interpolation value:value ws { return value }
not_close_tag =
ws !close_tag value:value ws { return value }
not_open_tag_or_interpolation =
!open_interpolation !open_tag value:value { return value }
markup =
(
open_interpolation interpolation:not_close_interpolation+ close_interpolation {
return { 'interpolation': j(interpolation) }
} /
open_tag tag:not_close_tag+ close_tag {
return { 'tag': j(tag) }
} /
value:not_open_tag_or_interpolation+ { return j(value) }
)+
像这样的东西作为开始怎么样:
Template
= Atom*
Atom
= IfTag
/ Interpolation
/ [^{]
/ !"{%" !"{{" "{"
Interpolation
= "{{" _ Expression _ "}}"
IfTag
= If Template ( Else Template )? EndIf
If
= "{%" _ "if" _ Expression _ "%}"
Else
= "{%" _ "else" _ "%}"
EndIf
= "{%" _ "endif" _ "%}"
Expression
= "\"" [^"]* "\""
/ [a-zA-Z]+
/ [0-9]+
_
= [ \t\n\r]*
这里棘手的部分是 Atom
生产的 !"{%" !"{{" "{"
替代方案,其内容如下:
When no "{%" and "{{" can be seen ahead of the current position, match a single "{"