fix: template expression precedence

This commit is contained in:
Michael Hoffmann
2022-12-02 19:47:43 +01:00
parent 99298c8ace
commit 6b74f88b3d
7 changed files with 10824 additions and 9401 deletions

View File

@@ -1,5 +1,13 @@
# Changelog # Changelog
## 1.0.0 - 2022-12-02
breaking:
* remove `template_if_branch` and `template_else_branch`
fix:
* fix precedence in template expressions
## 0.7.0 - 2022-06-02 ## 0.7.0 - 2022-06-02
housekeeping: housekeeping:

Binary file not shown.

View File

@@ -16,9 +16,6 @@ const
module.exports = grammar({ module.exports = grammar({
name: 'hcl', name: 'hcl',
conflicts: $ => [
],
externals: $ => [ externals: $ => [
$.quoted_template_start, $.quoted_template_start,
$.quoted_template_end, $.quoted_template_end,
@@ -269,12 +266,6 @@ module.exports = grammar({
$.heredoc_template, $.heredoc_template,
), ),
_template: $ => prec.left(repeat1(choice(
$.template_literal,
$.template_interpolation,
$.template_directive,
))),
quoted_template: $ => prec(PREC.quoted_template, seq( quoted_template: $ => prec(PREC.quoted_template, seq(
$.quoted_template_start, $.quoted_template_start,
optional($._template), optional($._template),
@@ -292,6 +283,12 @@ module.exports = grammar({
strip_marker: $ => '~', strip_marker: $ => '~',
_template: $ => repeat1(choice(
$.template_interpolation,
$.template_directive,
$.template_literal,
)),
template_literal: $ => prec.right(repeat1( template_literal: $ => prec.right(repeat1(
$._template_literal_chunk, $._template_literal_chunk,
)), )),
@@ -304,7 +301,6 @@ module.exports = grammar({
$.template_interpolation_end, $.template_interpolation_end,
), ),
// TODO
template_directive: $ => choice( template_directive: $ => choice(
$.template_for, $.template_for,
$.template_if, $.template_if,
@@ -337,15 +333,12 @@ module.exports = grammar({
), ),
template_if: $ => seq( template_if: $ => seq(
$.template_if_branch, $.template_if_intro,
optional($.template_else_branch), optional($._template),
optional(seq($.template_else_intro, optional($._template))),
$.template_if_end, $.template_if_end,
), ),
template_if_branch: $ => seq(
$.template_if_intro, $._template
),
template_if_intro: $ => seq( template_if_intro: $ => seq(
$.template_directive_start, $.template_directive_start,
optional($.strip_marker), optional($.strip_marker),
@@ -355,10 +348,6 @@ module.exports = grammar({
$.template_directive_end $.template_directive_end
), ),
template_else_branch: $ => seq(
$.template_else_intro, $._template
),
template_else_intro: $ => seq( template_else_intro: $ => seq(
$.template_directive_start, $.template_directive_start,
optional($.strip_marker), optional($.strip_marker),

View File

@@ -1187,30 +1187,6 @@
} }
] ]
}, },
"_template": {
"type": "PREC_LEFT",
"value": 0,
"content": {
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "template_literal"
},
{
"type": "SYMBOL",
"name": "template_interpolation"
},
{
"type": "SYMBOL",
"name": "template_directive"
}
]
}
}
},
"quoted_template": { "quoted_template": {
"type": "PREC", "type": "PREC",
"value": 1, "value": 1,
@@ -1286,6 +1262,26 @@
"type": "STRING", "type": "STRING",
"value": "~" "value": "~"
}, },
"_template": {
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "template_interpolation"
},
{
"type": "SYMBOL",
"name": "template_directive"
},
{
"type": "SYMBOL",
"name": "template_literal"
}
]
}
},
"template_literal": { "template_literal": {
"type": "PREC_RIGHT", "type": "PREC_RIGHT",
"value": 0, "value": 0,
@@ -1504,14 +1500,43 @@
"members": [ "members": [
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "template_if_branch" "name": "template_if_intro"
}, },
{ {
"type": "CHOICE", "type": "CHOICE",
"members": [ "members": [
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "template_else_branch" "name": "_template"
},
{
"type": "BLANK"
}
]
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "template_else_intro"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_template"
},
{
"type": "BLANK"
}
]
}
]
}, },
{ {
"type": "BLANK" "type": "BLANK"
@@ -1524,19 +1549,6 @@
} }
] ]
}, },
"template_if_branch": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "template_if_intro"
},
{
"type": "SYMBOL",
"name": "_template"
}
]
},
"template_if_intro": { "template_if_intro": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@@ -1582,19 +1594,6 @@
} }
] ]
}, },
"template_else_branch": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "template_else_intro"
},
{
"type": "SYMBOL",
"name": "_template"
}
]
},
"template_else_intro": { "template_else_intro": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [

View File

@@ -737,33 +737,6 @@
] ]
} }
}, },
{
"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", "type": "template_else_intro",
"named": true, "named": true,
@@ -900,31 +873,16 @@
"required": true, "required": true,
"types": [ "types": [
{ {
"type": "template_else_branch", "type": "template_directive",
"named": true "named": true
}, },
{ {
"type": "template_if_branch", "type": "template_else_intro",
"named": true "named": true
}, },
{ {
"type": "template_if_end", "type": "template_if_end",
"named": true "named": true
}
]
}
},
{
"type": "template_if_branch",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "template_directive",
"named": true
}, },
{ {
"type": "template_if_intro", "type": "template_if_intro",

19727
src/parser.c

File diff suppressed because it is too large Load Diff

View File

@@ -452,7 +452,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
template if directive in quoted template template if directive in quoted template
================================================================================ ================================================================================
foo = "%{if cond } foo %{else} bar %{endif}" foo = "%{if cond} foo %{else} bar %{endif}"
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@@ -466,20 +466,304 @@ foo = "%{if cond } foo %{else} bar %{endif}"
(quoted_template_start) (quoted_template_start)
(template_directive (template_directive
(template_if (template_if
(template_if_branch (template_if_intro
(template_if_intro (template_directive_start)
(template_directive_start) (expression
(expression (variable_expr
(variable_expr (identifier)))
(identifier))) (template_directive_end))
(template_directive_end)) (template_literal)
(template_literal)) (template_else_intro
(template_else_branch (template_directive_start)
(template_else_intro (template_directive_end))
(template_directive_start) (template_literal)
(template_directive_end))
(template_literal))
(template_if_end (template_if_end
(template_directive_start) (template_directive_start)
(template_directive_end)))) (template_directive_end))))
(quoted_template_end))))))) (quoted_template_end)))))))
================================================================================
template nested for directives with interlaced chunks
================================================================================
foo = "%{for a in b} x %{for c in a} ${c} %{endfor} %{endfor}"
--------------------------------------------------------------------------------
(config_file
(body
(attribute
(identifier)
(expression
(template_expr
(quoted_template
(quoted_template_start)
(template_directive
(template_for
(template_for_start
(template_directive_start)
(identifier)
(expression
(variable_expr
(identifier)))
(template_directive_end))
(template_literal)
(template_directive
(template_for
(template_for_start
(template_directive_start)
(identifier)
(expression
(variable_expr
(identifier)))
(template_directive_end))
(template_interpolation
(template_interpolation_start)
(expression
(variable_expr
(identifier)))
(template_interpolation_end))
(template_for_end
(template_directive_start)
(template_directive_end))))
(template_for_end
(template_directive_start)
(template_directive_end))))
(quoted_template_end)))))))
================================================================================
template nested if directives with interlaced chunks
================================================================================
foo = "%{if a} %{if b} y %{else} x %{endif} %{endif}"
--------------------------------------------------------------------------------
(config_file
(body
(attribute
(identifier)
(expression
(template_expr
(quoted_template
(quoted_template_start)
(template_directive
(template_if
(template_if_intro
(template_directive_start)
(expression
(variable_expr
(identifier)))
(template_directive_end))
(template_directive
(template_if
(template_if_intro
(template_directive_start)
(expression
(variable_expr
(identifier)))
(template_directive_end))
(template_literal)
(template_else_intro
(template_directive_start)
(template_directive_end))
(template_literal)
(template_if_end
(template_directive_start)
(template_directive_end))))
(template_if_end
(template_directive_start)
(template_directive_end))))
(quoted_template_end)))))))
================================================================================
template empty if else statement
================================================================================
foo = "%{if a} %{else} %{endif}"
--------------------------------------------------------------------------------
(config_file
(body
(attribute
(identifier)
(expression
(template_expr
(quoted_template
(quoted_template_start)
(template_directive
(template_if
(template_if_intro
(template_directive_start)
(expression
(variable_expr
(identifier)))
(template_directive_end))
(template_else_intro
(template_directive_start)
(template_directive_end))
(template_if_end
(template_directive_start)
(template_directive_end))))
(quoted_template_end)))))))
================================================================================
template empty for statement
================================================================================
foo = "%{for a in b} %{endfor}"
--------------------------------------------------------------------------------
(config_file
(body
(attribute
(identifier)
(expression
(template_expr
(quoted_template
(quoted_template_start)
(template_directive
(template_for
(template_for_start
(template_directive_start)
(identifier)
(expression
(variable_expr
(identifier)))
(template_directive_end))
(template_for_end
(template_directive_start)
(template_directive_end))))
(quoted_template_end)))))))
================================================================================
template parenthesis in heredoc for directive with nested if 1
================================================================================
tpl6 = <<-EOF
%{ for a in f(b) ~}
( %{~if a~} "true" %{~else~} "false" %{~endif~} )
%{ endfor ~}
EOF
--------------------------------------------------------------------------------
(config_file
(body
(attribute
(identifier)
(expression
(template_expr
(heredoc_template
(heredoc_start)
(heredoc_identifier)
(template_directive
(template_for
(template_for_start
(template_directive_start)
(identifier)
(expression
(function_call
(identifier)
(function_arguments
(expression
(variable_expr
(identifier))))))
(strip_marker)
(template_directive_end))
(template_literal)
(template_directive
(template_if
(template_if_intro
(template_directive_start)
(strip_marker)
(expression
(variable_expr
(identifier)))
(strip_marker)
(template_directive_end))
(template_literal)
(template_else_intro
(template_directive_start)
(strip_marker)
(strip_marker)
(template_directive_end))
(template_literal)
(template_if_end
(template_directive_start)
(strip_marker)
(strip_marker)
(template_directive_end))))
(template_literal)
(template_for_end
(template_directive_start)
(strip_marker)
(template_directive_end))))
(heredoc_identifier)))))))
================================================================================
template parenthesis in heredoc for directive with nested if 2
================================================================================
tpl6 = <<-EOF
%{ for a in f(b) ~}
("foo")
%{~if a~} "true" %{~else~} "false" %{~endif~}
%{ endfor ~}
EOF
--------------------------------------------------------------------------------
(config_file
(body
(attribute
(identifier)
(expression
(template_expr
(heredoc_template
(heredoc_start)
(heredoc_identifier)
(template_directive
(template_for
(template_for_start
(template_directive_start)
(identifier)
(expression
(function_call
(identifier)
(function_arguments
(expression
(variable_expr
(identifier))))))
(strip_marker)
(template_directive_end))
(template_literal)
(template_directive
(template_if
(template_if_intro
(template_directive_start)
(strip_marker)
(expression
(variable_expr
(identifier)))
(strip_marker)
(template_directive_end))
(template_literal)
(template_else_intro
(template_directive_start)
(strip_marker)
(strip_marker)
(template_directive_end))
(template_literal)
(template_if_end
(template_directive_start)
(strip_marker)
(strip_marker)
(template_directive_end))))
(template_for_end
(template_directive_start)
(strip_marker)
(template_directive_end))))
(heredoc_identifier)))))))