fix grammar

This commit is contained in:
mhoffm
2021-09-19 13:25:57 +02:00
committed by Michael Hoffmann
parent b048a42c6d
commit 5c348bd23c
8 changed files with 15076 additions and 13487 deletions

View File

@@ -4,6 +4,7 @@
feature:
* add template for expressions
* add template if expressions
cleanup:
* move fuzzing instrumentation to different repository

View File

@@ -6,7 +6,7 @@ tree-sitter grammar for the [HCL](https://github.com/hashicorp/hcl/blob/main/hcl
Highlighting `example/example.hcl`:
![Highlighting Example](https://i.imgur.com/4XFVNVT.png)
![Highlighting Example](https://i.imgur.com/yUJ0ybK.png)
## 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)
## 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

View File

@@ -1,54 +1,95 @@
// comment
# comment
/*
comment
*/
resource_1 "strlit1" "strlit2" {
resource "example" "literals" {
attr1 = "val1"
tupl1 = [ 1, 2, 3.4, "foo" ]
tupl2 = []
obj1 = { foo = "bar", baz = quoz }
obj1 = { foo = "bar", baz = quz }
null1 = null
bool1 = true
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"
esc2 = "$${} %%{}"
tpl1 = "prefix-${var.bar}"
tpl2 = "prefix-${func("bar")}"
tpl3 = "prefix-${func("nested-${var.bar}")}"
num1 = 2
num2 = 2.112
num3 = 2.112e-12
num4 = 2.112e+12
num5 = 2.112E+12
num6 = 2.112E-12
num7 = 0x21FF
}
tpl4 = <<EOF
prefix
${func("foo${ var.bar }")}
suffix
EOF
resource "example" "comments" {
// comment
# comment
/*
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,
"bar" : baz,
key : val,
fizz : buzz,
})
}
nested_resource_1 {
attr1 = 2
attr2 = 2.112
attr3 = 2.112e-12
attr4 = 2.112e+12
attr5 = 2.112E+12
attr6 = 2.112E-12
attr7 = 0x21FF
resource "example" "binary_expressions" {
cond1 = (1 == 2) ? 1 : "foobar"
bin1 = ((1+2)%3)*4
}
resource "example" "template_expressions" {
tpl1 = "prefix-${var.bar}"
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"
}
}
}

View File

@@ -231,7 +231,7 @@ module.exports = grammar({
function_arguments: $ => prec.right(seq(
$.expression,
repeat(seq($._comma, $.expression,)),
optional(choice(',', $.ellipsis)),
optional(choice($._comma, $.ellipsis)),
)),
ellipsis: $ => token('...'),
@@ -307,7 +307,7 @@ module.exports = grammar({
// TODO
template_directive: $ => choice(
$.template_for,
//$.template_if,
$.template_if,
),
template_for: $ => seq(
@@ -336,6 +336,45 @@ module.exports = grammar({
$.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
comment: $ => token(choice(
seq('#', /.*/),

View File

@@ -885,8 +885,8 @@
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
"type": "SYMBOL",
"name": "_comma"
},
{
"type": "SYMBOL",
@@ -1344,6 +1344,10 @@
{
"type": "SYMBOL",
"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": {
"type": "TOKEN",
"content": {

View File

@@ -729,6 +729,60 @@
{
"type": "template_for",
"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",
"named": true,
@@ -1088,10 +1242,18 @@
"type": "ellipsis",
"named": true
},
{
"type": "else",
"named": false
},
{
"type": "endfor",
"named": false
},
{
"type": "endif",
"named": false
},
{
"type": "false",
"named": false

28008
src/parser.c

File diff suppressed because it is too large Load Diff

View File

@@ -447,3 +447,39 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
(heredoc_start)
(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)))))))