fix: precedence of unary operators and expressions

Signed-off-by: Michael Hoffmann <mhoffm@posteo.de>
This commit is contained in:
Michael Hoffmann
2025-03-30 13:33:58 +02:00
parent 009def4ae3
commit 28e327cd3f
15 changed files with 7189 additions and 6812 deletions

View File

@@ -38,18 +38,11 @@ jobs:
uses: actions/checkout@v4
- name: Set up tree-sitter
uses: tree-sitter/setup-action/cli@v1
- name: Regenerate with ABI 14
# TODO: remove when node & swift support ABI 15
run: |-
tree-sitter generate --abi=14
cd dialects/terraform
tree-sitter generate --abi=14
- name: Run parser and binding tests
uses: tree-sitter/parser-test-action@v2
with:
test-node: true
test-rust: ${{runner.os == 'Linux'}}
test-swift: ${{runner.os == 'macOS'}}
- name: Parse sample files
uses: tree-sitter/parse-action@v4
id: parse-files

8
Package.resolved generated
View File

@@ -6,8 +6,8 @@
"repositoryURL": "https://github.com/tree-sitter/swift-tree-sitter",
"state": {
"branch": null,
"revision": "36aa61d1b531f744f35229f010efba9c6d6cbbdd",
"version": "0.9.0"
"revision": "08ef81eb8620617b55b08868126707ad72bf754f",
"version": "0.25.0"
}
},
{
@@ -15,8 +15,8 @@
"repositoryURL": "https://github.com/tree-sitter/tree-sitter",
"state": {
"branch": null,
"revision": "d97db6d63507eb62c536bcb2c4ac7d70c8ec665e",
"version": "0.23.2"
"revision" : "460118b4c82318b083b4d527c9c750426730f9c0",
"version" : "0.25.5"
}
}
]

3
Package.swift generated
View File

@@ -4,11 +4,12 @@ import PackageDescription
let package = Package(
name: "TreeSitterHCL",
platforms: [.macOS(.v10_13), .iOS(.v11)],
products: [
.library(name: "TreeSitterHCL", targets: ["TreeSitterHCL"]),
],
dependencies: [
.package(name: "SwiftTreeSitter", url: "https://github.com/tree-sitter/swift-tree-sitter", from: "0.9.0"),
.package(name: "SwiftTreeSitter", url: "https://github.com/tree-sitter/swift-tree-sitter", from: "0.25.0"),
],
targets: [
.target(

View File

@@ -124,7 +124,8 @@
"members": [
{
"type": "PATTERN",
"value": "\\p{ID_Start}"
"value": "\\p{ID_Start}",
"flags": "u"
},
{
"type": "STRING",
@@ -139,7 +140,8 @@
"members": [
{
"type": "PATTERN",
"value": "\\p{ID_Continue}"
"value": "\\p{ID_Continue}",
"flags": "u"
},
{
"type": "STRING",
@@ -204,43 +206,55 @@
"name": "operation"
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "index"
}
]
"type": "PREC_RIGHT",
"value": 8,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "index"
}
]
}
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "get_attr"
}
]
"type": "PREC_RIGHT",
"value": 8,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "get_attr"
}
]
}
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "splat"
}
]
"type": "PREC_RIGHT",
"value": 8,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "splat"
}
]
}
},
{
"type": "SEQ",
@@ -1784,4 +1798,4 @@
"inline": [],
"supertypes": [],
"reserved": {}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -129,7 +129,7 @@ static unsigned serialize(Scanner *scanner, char *buf) {
memcpy(&buf[size], &(scanner->context_stack.len), sizeof(uint32_t));
size += sizeof(uint32_t);
for (int i = 0; i < scanner->context_stack.len; i++) {
for (uint32_t i = 0; i < scanner->context_stack.len; i++) {
Context *context = &scanner->context_stack.data[i];
if (size + sizeof(ContextType) + sizeof(uint32_t) + context->heredoc_identifier.len >= TREE_SITTER_SERIALIZATION_BUFFER_SIZE) {
return 0;
@@ -413,7 +413,7 @@ bool tree_sitter_terraform_external_scanner_scan(void *payload, TSLexer *lexer,
void tree_sitter_terraform_external_scanner_destroy(void *payload) {
Scanner *scanner = (Scanner *)payload;
for (int i = 0; i < scanner->context_stack.len; i++) {
for (uint32_t i = 0; i < scanner->context_stack.len; i++) {
STRING_FREE(scanner->context_stack.data[i].heredoc_identifier);
}
VEC_FREE(scanner->context_stack);

View File

@@ -4,6 +4,8 @@
/** @param {string} dialect */
module.exports = function make_grammar(dialect) {
const PREC = {
// unary negation should not pull expressions apart
expr: 8,
unary: 7,
binary_mult: 6,
binary_add: 5,
@@ -75,9 +77,9 @@ module.exports = function make_grammar(dialect) {
$.function_call,
$.for_expr,
$.operation,
seq($._expr_term, $.index),
seq($._expr_term, $.get_attr),
seq($._expr_term, $.splat),
prec.right(PREC.expr, seq($._expr_term, $.index)),
prec.right(PREC.expr, seq($._expr_term, $.get_attr)),
prec.right(PREC.expr, seq($._expr_term, $.splat)),
seq("(", $.expression, ")"),
),

16
package-lock.json generated
View File

@@ -15,10 +15,10 @@
},
"devDependencies": {
"prebuildify": "^6.0.1",
"tree-sitter-cli": "^0.25.3"
"tree-sitter-cli": "^0.25.6"
},
"peerDependencies": {
"tree-sitter": "^0.22.4"
"tree-sitter": "^0.25.0"
},
"peerDependenciesMeta": {
"tree-sitter": {
@@ -338,9 +338,9 @@
}
},
"node_modules/tree-sitter": {
"version": "0.22.4",
"resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.22.4.tgz",
"integrity": "sha512-usbHZP9/oxNsUY65MQUsduGRqDHQOou1cagUSwjhoSYAmSahjQDAVsh9s+SlZkn8X8+O1FULRGwHu7AFP3kjzg==",
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/tree-sitter/-/tree-sitter-0.25.0.tgz",
"integrity": "sha512-PGZZzFW63eElZJDe/b/R/LbsjDDYJa5UEjLZJB59RQsMX+fo0j54fqBPn1MGKav/QNa0JR0zBiVaikYDWCj5KQ==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -351,9 +351,9 @@
}
},
"node_modules/tree-sitter-cli": {
"version": "0.25.3",
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.25.3.tgz",
"integrity": "sha512-Bk6ZUXG+cKnwZpfR/te4NDrKld90p6350eqWlbLwSpV9/8vmL/x8LCw+3k7quY9oMDaYoMXHMvokXJbkM5A7bA==",
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.25.6.tgz",
"integrity": "sha512-UhkXRkMPtBgE4OatZtYVtDsT3HFUliqAJcs49XQaZv8d2sbeTzEhpJVpMaCqBR3HGhb1WpyoodaFXQaMuOLPEg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",

4
package.json generated
View File

@@ -30,10 +30,10 @@
},
"devDependencies": {
"prebuildify": "^6.0.1",
"tree-sitter-cli": "^0.25.3"
"tree-sitter-cli": "^0.25.6"
},
"peerDependencies": {
"tree-sitter": "^0.22.4"
"tree-sitter": "^0.25.0"
},
"peerDependenciesMeta": {
"tree-sitter": {

View File

@@ -7,8 +7,11 @@ pkgs.mkShell {
gdb
valgrind
nodejs
tree-sitter
emscripten
];
shellHook = ''
npm install
export PATH="$(git rev-parse --show-toplevel)/node_modules/.bin:$PATH"
'';
}

84
src/grammar.json generated
View File

@@ -124,7 +124,8 @@
"members": [
{
"type": "PATTERN",
"value": "\\p{ID_Start}"
"value": "\\p{ID_Start}",
"flags": "u"
},
{
"type": "STRING",
@@ -139,7 +140,8 @@
"members": [
{
"type": "PATTERN",
"value": "\\p{ID_Continue}"
"value": "\\p{ID_Continue}",
"flags": "u"
},
{
"type": "STRING",
@@ -204,43 +206,55 @@
"name": "operation"
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "index"
}
]
"type": "PREC_RIGHT",
"value": 8,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "index"
}
]
}
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "get_attr"
}
]
"type": "PREC_RIGHT",
"value": 8,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "get_attr"
}
]
}
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "splat"
}
]
"type": "PREC_RIGHT",
"value": 8,
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expr_term"
},
{
"type": "SYMBOL",
"name": "splat"
}
]
}
},
{
"type": "SEQ",

6827
src/parser.c generated

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
======
Unary operation on variable with splat expression
=====
foo = !var.bar
------
(config_file
(body
(attribute
(identifier)
(expression
(operation
(unary_operation
(variable_expr
(identifier))
(get_attr
(identifier))))))))
=====
Attribute as conditional expression
=====
foo = local.bar == local.baz
-----
(config_file
(body
(attribute
(identifier)
(expression
(operation
(binary_operation
(variable_expr
(identifier))
(get_attr
(identifier))
(variable_expr
(identifier))
(get_attr
(identifier))))))))

View File

@@ -81,3 +81,48 @@ foo = a != b && c == d
(identifier))
(variable_expr
(identifier))))))))))
================================================================================
precedence in binary operators 2
================================================================================
foo = a.foo != "" && b.foo == "" ? 1 : 0
--------------------------------------------------------------------------------
(config_file
(body
(attribute
(identifier)
(expression
(conditional
(expression
(operation
(binary_operation
(operation
(binary_operation
(variable_expr
(identifier))
(get_attr
(identifier))
(literal_value
(string_lit
(quoted_template_start)
(quoted_template_end)))))
(operation
(binary_operation
(variable_expr
(identifier))
(get_attr
(identifier))
(literal_value
(string_lit
(quoted_template_start)
(quoted_template_end))))))))
(expression
(literal_value
(numeric_lit)))
(expression
(literal_value
(numeric_lit))))))))

View File

@@ -390,24 +390,24 @@ resource "azurerm_storage_blob" "proxy_cert" {
(binary_operation
(operation
(binary_operation
(operation
(binary_operation
(variable_expr
(identifier))
(get_attr
(identifier))
(literal_value
(string_lit
(quoted_template_start)
(quoted_template_end)))))
(variable_expr
(identifier))))
(get_attr
(identifier))
(literal_value
(string_lit
(quoted_template_start)
(quoted_template_end))))))
(identifier))
(get_attr
(identifier))
(literal_value
(string_lit
(quoted_template_start)
(quoted_template_end)))))
(operation
(binary_operation
(variable_expr
(identifier))
(get_attr
(identifier))
(literal_value
(string_lit
(quoted_template_start)
(quoted_template_end))))))))
(expression
(literal_value
(numeric_lit)))