fix grammar
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
feature:
|
feature:
|
||||||
* add template for expressions
|
* add template for expressions
|
||||||
|
* add template if expressions
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
* move fuzzing instrumentation to different repository
|
* move fuzzing instrumentation to different repository
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -6,7 +6,7 @@ tree-sitter grammar for the [HCL](https://github.com/hashicorp/hcl/blob/main/hcl
|
|||||||
|
|
||||||
Highlighting `example/example.hcl`:
|
Highlighting `example/example.hcl`:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Developing
|
## Developing
|
||||||
|
|
||||||
@@ -30,15 +30,3 @@ Total parses: 1892; successful parses: 1892; failed parses: 0; success percentag
|
|||||||
|
|
||||||
See the [fuzzing repo for this parser](https://github.com/MichaHoffmann/tree-sitter-hcl-fuzz)
|
See the [fuzzing repo for this parser](https://github.com/MichaHoffmann/tree-sitter-hcl-fuzz)
|
||||||
|
|
||||||
## Todo
|
|
||||||
|
|
||||||
* [ ] add [template expressions](https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md#template-expressions)
|
|
||||||
* [x] add template interpolations
|
|
||||||
* [ ] add template directives
|
|
||||||
* [x] add template for expressions
|
|
||||||
* [ ] add template if expressions
|
|
||||||
* [x] add quoted templates
|
|
||||||
* [x] add heredoc templates
|
|
||||||
* [ ] quality
|
|
||||||
* [x] add CI job that ensures the parser builds on different plattforms
|
|
||||||
* [ ] add CI job that parses crashers that were found during fuzzing
|
|
||||||
|
|||||||
@@ -1,54 +1,95 @@
|
|||||||
// comment
|
resource "example" "literals" {
|
||||||
# comment
|
|
||||||
/*
|
|
||||||
comment
|
|
||||||
*/
|
|
||||||
|
|
||||||
resource_1 "strlit1" "strlit2" {
|
|
||||||
attr1 = "val1"
|
attr1 = "val1"
|
||||||
tupl1 = [ 1, 2, 3.4, "foo" ]
|
tupl1 = [ 1, 2, 3.4, "foo" ]
|
||||||
tupl2 = []
|
tupl2 = []
|
||||||
obj1 = { foo = "bar", baz = quoz }
|
obj1 = { foo = "bar", baz = quz }
|
||||||
null1 = null
|
null1 = null
|
||||||
bool1 = true
|
bool1 = true
|
||||||
bool2 = false
|
bool2 = false
|
||||||
splat1 = tuple.*.foo.bar[0]
|
|
||||||
splat2 = tuple[*].foo.bar[0]
|
|
||||||
for1 = { for i, v in ["a", "a", "b"] : v => i... }
|
|
||||||
for2 = [ for k, v in var.map : "${k}-${v}" ]
|
|
||||||
for3 = { for k, v in var.map : k => v }
|
|
||||||
for4 = [ for v in var.list : v ]
|
|
||||||
for5 = { for v in var.list : v => v }
|
|
||||||
for6 = [ for v in var.list : v if v < 3 ]
|
|
||||||
func1 = is_number("123")
|
|
||||||
cond1 = (1 == 2) ? 1 : "foobar"
|
|
||||||
bin1 = ((1+2)%3)*4
|
|
||||||
esc1 = "\" \t \UFF11FF22 \uFFFF \n"
|
esc1 = "\" \t \UFF11FF22 \uFFFF \n"
|
||||||
esc2 = "$${} %%{}"
|
esc2 = "$${} %%{}"
|
||||||
tpl1 = "prefix-${var.bar}"
|
num1 = 2
|
||||||
tpl2 = "prefix-${func("bar")}"
|
num2 = 2.112
|
||||||
tpl3 = "prefix-${func("nested-${var.bar}")}"
|
num3 = 2.112e-12
|
||||||
|
num4 = 2.112e+12
|
||||||
|
num5 = 2.112E+12
|
||||||
|
num6 = 2.112E-12
|
||||||
|
num7 = 0x21FF
|
||||||
|
}
|
||||||
|
|
||||||
tpl4 = <<EOF
|
resource "example" "comments" {
|
||||||
prefix
|
// comment
|
||||||
${func("foo${ var.bar }")}
|
# comment
|
||||||
suffix
|
/*
|
||||||
EOF
|
comment
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
func_of_object = func({
|
resource "example" "splat_expressions" {
|
||||||
|
splat1 = foo.*.bar.baz[0]
|
||||||
|
splat2 = foo[*].bar.baz[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "example" "for_expressions" {
|
||||||
|
for1 = { for i, v in ["a", "a", "b"] : v => i... }
|
||||||
|
for2 = [ for k, v in x : "${k}-${v}" ]
|
||||||
|
for3 = { for k, v in x: k => v }
|
||||||
|
for4 = [ for v in x : v ]
|
||||||
|
for5 = { for v in x : v => v }
|
||||||
|
for6 = [ for v in x : v if v < 3 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "example" "function_expressions" {
|
||||||
|
func1 = is_number("123")
|
||||||
|
func2 = multiline(
|
||||||
|
arg1,
|
||||||
|
arg2,
|
||||||
|
arg3...
|
||||||
|
)
|
||||||
|
func3 = withobject({
|
||||||
"foo" : 2,
|
"foo" : 2,
|
||||||
"bar" : baz,
|
"bar" : baz,
|
||||||
key : val,
|
key : val,
|
||||||
fizz : buzz,
|
fizz : buzz,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
nested_resource_1 {
|
resource "example" "binary_expressions" {
|
||||||
attr1 = 2
|
cond1 = (1 == 2) ? 1 : "foobar"
|
||||||
attr2 = 2.112
|
bin1 = ((1+2)%3)*4
|
||||||
attr3 = 2.112e-12
|
}
|
||||||
attr4 = 2.112e+12
|
|
||||||
attr5 = 2.112E+12
|
resource "example" "template_expressions" {
|
||||||
attr6 = 2.112E-12
|
tpl1 = "prefix-${var.bar}"
|
||||||
attr7 = 0x21FF
|
tpl2 = "prefix-${func("bar")}"
|
||||||
|
tpl3 = "prefix-${func("nested-${var.bar}")}"
|
||||||
|
|
||||||
|
tpl4 = <<EOF
|
||||||
|
%{ for a in f(b) ~}
|
||||||
|
${func("foo${ a }")}
|
||||||
|
%{ endfor ~}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
tpl5 = <<-EOF
|
||||||
|
%{~if cond~}
|
||||||
|
"foo"
|
||||||
|
%{~else~}
|
||||||
|
4
|
||||||
|
%{~endif~}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
tpl6 = <<-EOF
|
||||||
|
%{ for a in f(b) ~}
|
||||||
|
%{~if a~} "true" %{~else~} "false" %{~endif~}
|
||||||
|
%{ endfor ~}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "example" "nested_blocks" {
|
||||||
|
nested_block "first" {
|
||||||
|
attr1 = "foo"
|
||||||
|
nested_block "second" {
|
||||||
|
attr1 = "bar"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
43
grammar.js
43
grammar.js
@@ -231,7 +231,7 @@ module.exports = grammar({
|
|||||||
function_arguments: $ => prec.right(seq(
|
function_arguments: $ => prec.right(seq(
|
||||||
$.expression,
|
$.expression,
|
||||||
repeat(seq($._comma, $.expression,)),
|
repeat(seq($._comma, $.expression,)),
|
||||||
optional(choice(',', $.ellipsis)),
|
optional(choice($._comma, $.ellipsis)),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
ellipsis: $ => token('...'),
|
ellipsis: $ => token('...'),
|
||||||
@@ -307,7 +307,7 @@ module.exports = grammar({
|
|||||||
// TODO
|
// TODO
|
||||||
template_directive: $ => choice(
|
template_directive: $ => choice(
|
||||||
$.template_for,
|
$.template_for,
|
||||||
//$.template_if,
|
$.template_if,
|
||||||
),
|
),
|
||||||
|
|
||||||
template_for: $ => seq(
|
template_for: $ => seq(
|
||||||
@@ -336,6 +336,45 @@ module.exports = grammar({
|
|||||||
$.template_directive_end
|
$.template_directive_end
|
||||||
),
|
),
|
||||||
|
|
||||||
|
template_if: $ => seq(
|
||||||
|
$.template_if_branch,
|
||||||
|
optional($.template_else_branch),
|
||||||
|
$.template_if_end,
|
||||||
|
),
|
||||||
|
|
||||||
|
template_if_branch: $ => seq(
|
||||||
|
$.template_if_intro, $._template
|
||||||
|
),
|
||||||
|
|
||||||
|
template_if_intro: $ => seq(
|
||||||
|
$.template_directive_start,
|
||||||
|
optional($.strip_marker),
|
||||||
|
"if",
|
||||||
|
$.expression,
|
||||||
|
optional($.strip_marker),
|
||||||
|
$.template_directive_end
|
||||||
|
),
|
||||||
|
|
||||||
|
template_else_branch: $ => seq(
|
||||||
|
$.template_else_intro, $._template
|
||||||
|
),
|
||||||
|
|
||||||
|
template_else_intro: $ => seq(
|
||||||
|
$.template_directive_start,
|
||||||
|
optional($.strip_marker),
|
||||||
|
"else",
|
||||||
|
optional($.strip_marker),
|
||||||
|
$.template_directive_end
|
||||||
|
),
|
||||||
|
|
||||||
|
template_if_end: $ => seq(
|
||||||
|
$.template_directive_start,
|
||||||
|
optional($.strip_marker),
|
||||||
|
"endif",
|
||||||
|
optional($.strip_marker),
|
||||||
|
$.template_directive_end
|
||||||
|
),
|
||||||
|
|
||||||
// http://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment/36328890#36328890
|
// http://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment/36328890#36328890
|
||||||
comment: $ => token(choice(
|
comment: $ => token(choice(
|
||||||
seq('#', /.*/),
|
seq('#', /.*/),
|
||||||
|
|||||||
186
src/grammar.json
186
src/grammar.json
@@ -885,8 +885,8 @@
|
|||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "SYMBOL",
|
||||||
"value": ","
|
"name": "_comma"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
@@ -1344,6 +1344,10 @@
|
|||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "template_for"
|
"name": "template_for"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_if"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -1487,6 +1491,184 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"template_if": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_if_branch"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_else_branch"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_if_end"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"template_if_branch": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_if_intro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "_template"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"template_if_intro": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_directive_start"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "strip_marker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "if"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "expression"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "strip_marker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_directive_end"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"template_else_branch": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_else_intro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "_template"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"template_else_intro": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_directive_start"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "strip_marker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "else"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "strip_marker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_directive_end"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"template_if_end": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_directive_start"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "strip_marker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "endif"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "strip_marker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "template_directive_end"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"comment": {
|
"comment": {
|
||||||
"type": "TOKEN",
|
"type": "TOKEN",
|
||||||
"content": {
|
"content": {
|
||||||
|
|||||||
@@ -729,6 +729,60 @@
|
|||||||
{
|
{
|
||||||
"type": "template_for",
|
"type": "template_for",
|
||||||
"named": true
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_if",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_else_branch",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": true,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "template_directive",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_else_intro",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_interpolation",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_literal",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_else_intro",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": true,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "strip_marker",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_directive_end",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_directive_start",
|
||||||
|
"named": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -837,6 +891,106 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "template_if",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": true,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "template_else_branch",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_if_branch",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_if_end",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_if_branch",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": true,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "template_directive",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_if_intro",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_interpolation",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_literal",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_if_end",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": true,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "strip_marker",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_directive_end",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_directive_start",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_if_intro",
|
||||||
|
"named": true,
|
||||||
|
"fields": {},
|
||||||
|
"children": {
|
||||||
|
"multiple": true,
|
||||||
|
"required": true,
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"type": "expression",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "strip_marker",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_directive_end",
|
||||||
|
"named": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "template_directive_start",
|
||||||
|
"named": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "template_interpolation",
|
"type": "template_interpolation",
|
||||||
"named": true,
|
"named": true,
|
||||||
@@ -1088,10 +1242,18 @@
|
|||||||
"type": "ellipsis",
|
"type": "ellipsis",
|
||||||
"named": true
|
"named": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "else",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "endfor",
|
"type": "endfor",
|
||||||
"named": false
|
"named": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "endif",
|
||||||
|
"named": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "false",
|
"type": "false",
|
||||||
"named": false
|
"named": false
|
||||||
|
|||||||
28008
src/parser.c
28008
src/parser.c
File diff suppressed because it is too large
Load Diff
@@ -447,3 +447,39 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
|||||||
(heredoc_start)
|
(heredoc_start)
|
||||||
(heredoc_identifier)
|
(heredoc_identifier)
|
||||||
(heredoc_identifier)))))))
|
(heredoc_identifier)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
template if directive in quoted template
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
foo = "%{if cond } foo %{else} bar %{endif}"
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(config_file
|
||||||
|
(body
|
||||||
|
(attribute
|
||||||
|
(identifier)
|
||||||
|
(expression
|
||||||
|
(template_expr
|
||||||
|
(quoted_template
|
||||||
|
(quoted_template_start)
|
||||||
|
(template_directive
|
||||||
|
(template_if
|
||||||
|
(template_if_branch
|
||||||
|
(template_if_intro
|
||||||
|
(template_directive_start)
|
||||||
|
(expression
|
||||||
|
(variable_expr
|
||||||
|
(identifier)))
|
||||||
|
(template_directive_end))
|
||||||
|
(template_literal))
|
||||||
|
(template_else_branch
|
||||||
|
(template_else_intro
|
||||||
|
(template_directive_start)
|
||||||
|
(template_directive_end))
|
||||||
|
(template_literal))
|
||||||
|
(template_if_end
|
||||||
|
(template_directive_start)
|
||||||
|
(template_directive_end))))
|
||||||
|
(quoted_template_end)))))))
|
||||||
|
|||||||
Reference in New Issue
Block a user