WHITESPACE = _{" "|"\n"}
modifier = {"|" ~ identifier ~ argument*}
argument = { ":" ~ value }
calculated = {!"\\" ~ "{" ~ calculated_value ~ "}"}
calculated_value = { value ~ modifier* }
identifier = @{!(key_words) ~ 'a'..'z' ~ ('A'..'Z'|'a'..'z'|'0'..'9'|"_")*}
text = {(!"{" ~ ("\\{" | ANY))+}
assign = !{"{" ~ identifier ~ "=" ~ calculated_value ~ "}"}
// Template
template = {SOI ~ template_content ~ EOI}
template_content = ${ (while_loop|assign|calculated|text|conditional)* }
// Values
string = { "\"" ~ inner_string ~ "\"" }
inner_string = {(!"\"" ~ ( "\\\""| ANY))*}
number = { ("+"|"-")? ~ ASCII_DIGIT+ ~ ("." ~ ASCII_DIGIT+)? }
boolean = {true_key_word|false_key_word}
value = { boolean|identifier|number|string }
// Blocks
conditional = !{
"{" ~ if_key_word ~ condition ~ "}" ~
template_content ~
(
"{" ~ else_key_word ~ "}" ~
template_content
)? ~
"{" ~ endif_key_word ~ "}" ~ "\n"?
}
while_loop = !{
"{" ~ while_key_word ~ condition ~ "}" ~
template_content ~
"{" ~ endwhile_key_word ~ "}" ~ "\n"?
}
// Condition
condition = {
(
("(" ~ condition ~ ")") |
compare_condition |
calculated_value
)~
(
(and_operator|or_operator) ~
(compare_condition | calculated_value | condition)
)*
}
compare_condition = { calculated_value ~ compare_operator ~ calculated_value }
compare_operator = {
eq_operator|
ne_operator|
lt_operator|
le_operator|
gt_operator|
ge_operator
}
eq_operator = { "==" }
ne_operator = { "!=" }
lt_operator = { "<" }
le_operator = { "<=" }
gt_operator = { ">" }
ge_operator = { ">=" }
and_operator = {"&&"}
or_operator = {"||"}
// Keywords
if_key_word = _{"if"}
else_key_word = _{"else"}
endif_key_word = _{"endif"}
while_key_word = _{"while"}
endwhile_key_word = _{"endwhile"}
true_key_word = _{"true"}
false_key_word = _{"false"}
key_words = { if_key_word | else_key_word | endif_key_word | true_key_word | false_key_word | while_key_word | endwhile_key_word }