├── .gitignore ├── .prettierrc ├── test ├── go.mod ├── corpus │ ├── variables.txt │ ├── text.txt │ ├── arguments.txt │ ├── pipelines.txt │ ├── literals.txt │ ├── examples.txt │ └── actions.txt └── corpus_test.go ├── grammar.js ├── dialects └── helm │ ├── grammar.js │ └── src │ └── tree_sitter │ ├── alloc.h │ ├── parser.h │ └── array.h ├── shell.nix ├── go.mod ├── bindings ├── go │ ├── binding.go │ └── binding_test.go ├── node │ ├── index.js │ └── binding.cc └── rust │ ├── build.rs │ └── lib.rs ├── .gitattributes ├── binding.gyp ├── Cargo.toml ├── package.json ├── LICENSE ├── tree-sitter.json ├── src ├── tree_sitter │ ├── alloc.h │ ├── parser.h │ └── array.h └── node-types.json ├── queries └── highlights.scm ├── .github └── workflows │ └── ci.yaml ├── README.md ├── go.sum └── make_grammar.js /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | node_modules 3 | build 4 | *.log 5 | examples 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | trailingComma: "es5" 2 | tabWidth: 4 3 | semi: false 4 | singleQuote: true 5 | -------------------------------------------------------------------------------- /test/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ngalaiko/tree-sitter-go-template/test 2 | 3 | go 1.24.5 4 | -------------------------------------------------------------------------------- /grammar.js: -------------------------------------------------------------------------------- 1 | const make_grammar = require('./make_grammar') 2 | 3 | module.exports = make_grammar('gotmpl') 4 | -------------------------------------------------------------------------------- /dialects/helm/grammar.js: -------------------------------------------------------------------------------- 1 | const make_grammar = require('./../../make_grammar'); 2 | 3 | module.exports = make_grammar('helm'); 4 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import { } }: 2 | 3 | pkgs.mkShell { 4 | buildInputs = with pkgs; [ 5 | nodejs 6 | nodePackages.node-gyp 7 | tree-sitter 8 | python3 9 | graphviz 10 | ]; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ngalaiko/tree-sitter-go-template 2 | 3 | go 1.23 4 | 5 | toolchain go1.24.6 6 | 7 | require github.com/tree-sitter/go-tree-sitter v0.25.0 8 | 9 | require github.com/mattn/go-pointer v0.0.1 // indirect 10 | -------------------------------------------------------------------------------- /bindings/go/binding.go: -------------------------------------------------------------------------------- 1 | package tree_sitter_gotemplate 2 | 3 | // #cgo CFLAGS: -std=c11 -fPIC 4 | // #include "../../src/parser.c" 5 | import "C" 6 | 7 | import ( 8 | "unsafe" 9 | ) 10 | 11 | func Language() unsafe.Pointer { 12 | return unsafe.Pointer(C.tree_sitter_gotmpl()) 13 | } 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | # Generated source files 4 | src/*.json linguist-generated 5 | src/parser.c linguist-generated 6 | src/tree_sitter/* linguist-generated 7 | 8 | dialects/helm/src/*.json linguist-generated 9 | dialects/helm/src/parser.c linguist-generated 10 | dialects/helm/src/tree_sitter/* linguist-generated 11 | 12 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_go_template_binding", 5 | "include_dirs": [ 6 | "", 7 | ] 8 | keywords = ["incremental", "parsing", "go-template"] 9 | categories = ["parsing", "text-editors"] 10 | repository = "https://github.com/ngalaiko/tree-sitter-go-template" 11 | edition = "2018" 12 | license = "MIT" 13 | 14 | build = "bindings/rust/build.rs" 15 | include = [ 16 | "bindings/rust/*", 17 | "grammar.js", 18 | "queries/*", 19 | "src/*", 20 | ] 21 | 22 | [lib] 23 | path = "bindings/rust/lib.rs" 24 | 25 | [dependencies] 26 | tree-sitter = "0.19" 27 | 28 | [build-dependencies] 29 | cc = "1.0" 30 | -------------------------------------------------------------------------------- /bindings/go/binding_test.go: -------------------------------------------------------------------------------- 1 | package tree_sitter_gotemplate_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/ngalaiko/tree-sitter-go-template/bindings/go" 7 | tree_sitter "github.com/tree-sitter/go-tree-sitter" 8 | ) 9 | 10 | func TestGrammar(t *testing.T) { 11 | language := tree_sitter.NewLanguage(tree_sitter_gotemplate.Language()) 12 | if language == nil { 13 | t.Errorf("Error loading gotemplate grammar") 14 | } 15 | 16 | parser := tree_sitter.NewParser() 17 | defer parser.Close() 18 | parser.SetLanguage(language) 19 | 20 | tree := parser.Parse([]byte("{{ nil }}"), nil) 21 | if tree == nil { 22 | t.Errorf("Error parsing code") 23 | } 24 | defer tree.Close() 25 | 26 | root := tree.RootNode() 27 | if root == nil { 28 | t.Errorf("Error parsing code") 29 | } 30 | 31 | if root.ToSexp() != "(template (nil))" { 32 | t.Errorf("Unexpected tree: %s", root.ToSexp()) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-go-template", 3 | "version": "0.19.5", 4 | "description": "Golang template grammar for tree-sitter", 5 | "main": "bindings/node", 6 | "keywords": [ 7 | "parser", 8 | "json", 9 | "go-template", 10 | "helm" 11 | ], 12 | "author": "Nikita Galaiko", 13 | "license": "MIT", 14 | "dependencies": { 15 | "nan": "^2.23.0" 16 | }, 17 | "devDependencies": { 18 | "tree-sitter-cli": "^0.25.8", 19 | "prettier": "^3.6.2" 20 | }, 21 | "scripts": { 22 | "build": "tree-sitter generate && node-gyp build && npm run build-helm", 23 | "build-helm": "cd dialects/helm && tree-sitter generate --no-bindings", 24 | "test": "tree-sitter test && cd test && go test -v", 25 | "parse": "tree-sitter parse", 26 | "highlight": "tree-sitter highlight" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /bindings/node/binding.cc: -------------------------------------------------------------------------------- 1 | #include "tree_sitter/parser.h" 2 | #include 3 | #include "nan.h" 4 | 5 | using namespace v8; 6 | 7 | extern "C" TSLanguage * tree_sitter_go_template(); 8 | 9 | namespace { 10 | 11 | NAN_METHOD(New) {} 12 | 13 | void Init(Local exports, Local module) { 14 | Local tpl = Nan::New(New); 15 | tpl->SetClassName(Nan::New("Language").ToLocalChecked()); 16 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 17 | 18 | Local constructor = Nan::GetFunction(tpl).ToLocalChecked(); 19 | Local instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked(); 20 | Nan::SetInternalFieldPointer(instance, 0, tree_sitter_go_template()); 21 | 22 | Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("go_template").ToLocalChecked()); 23 | Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance); 24 | } 25 | 26 | NODE_MODULE(tree_sitter_go_template_binding, Init) 27 | 28 | } // namespace 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Nikita Galaiko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tree-sitter.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "version": "0.19.5", 4 | "license": "MIT", 5 | "description": "Golang template grammar for tree-sitter", 6 | "authors": [ 7 | { 8 | "name": "Nikita Galaiko" 9 | } 10 | ], 11 | "links": { 12 | "repository": "https://github.com/tree-sitter/tree-sitter-go-template" 13 | } 14 | }, 15 | "grammars": [ 16 | { 17 | "name": "go-template", 18 | "camelcase": "GoTemplate", 19 | "scope": "source.gotexttmpl", 20 | "path": ".", 21 | "file-types": ["gotmpl", "gotexttmpl", "gohtmltmpl", "yaml"], 22 | "content-regex": "{{.+}}" 23 | }, 24 | { 25 | "name": "go-template-helm", 26 | "camelcase": "GoTemplateHelm", 27 | "scope": "source.helm", 28 | "path": "dialects/helm", 29 | "file-types": ["helm"] 30 | } 31 | ], 32 | "bindings": { 33 | "c": true, 34 | "go": true, 35 | "node": true, 36 | "python": true, 37 | "rust": true, 38 | "swift": true 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/corpus/variables.txt: -------------------------------------------------------------------------------- 1 | ==================================== 2 | Variable definition 3 | ==================================== 4 | {{ $variable := pipeline }} 5 | {{ $1var := pipeline }} 6 | --- 7 | (template 8 | (variable_definition 9 | (variable 10 | (identifier)) 11 | (function_call 12 | (identifier))) 13 | (text) 14 | (variable_definition 15 | (variable 16 | (identifier)) 17 | (function_call 18 | (identifier)))) 19 | 20 | ==================================== 21 | Variable assignment 22 | ==================================== 23 | {{ $variable = pipeline }} 24 | --- 25 | (template 26 | (assignment 27 | (variable (identifier)) 28 | (function_call (identifier)))) 29 | 30 | ==================================== 31 | Range pipeline assignment 32 | ==================================== 33 | {{ range $index, $element := pipeline }}{{ $index }}{{ $element }}{{ end }} 34 | --- 35 | (template 36 | (range_action 37 | (range_variable_definition 38 | (variable (identifier)) 39 | (variable (identifier)) 40 | (function_call 41 | (identifier))) 42 | (variable (identifier)) 43 | (variable (identifier)))) 44 | -------------------------------------------------------------------------------- /src/tree_sitter/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ALLOC_H_ 2 | #define TREE_SITTER_ALLOC_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | // Allow clients to override allocation functions 13 | #ifdef TREE_SITTER_REUSE_ALLOCATOR 14 | 15 | extern void *(*ts_current_malloc)(size_t size); 16 | extern void *(*ts_current_calloc)(size_t count, size_t size); 17 | extern void *(*ts_current_realloc)(void *ptr, size_t size); 18 | extern void (*ts_current_free)(void *ptr); 19 | 20 | #ifndef ts_malloc 21 | #define ts_malloc ts_current_malloc 22 | #endif 23 | #ifndef ts_calloc 24 | #define ts_calloc ts_current_calloc 25 | #endif 26 | #ifndef ts_realloc 27 | #define ts_realloc ts_current_realloc 28 | #endif 29 | #ifndef ts_free 30 | #define ts_free ts_current_free 31 | #endif 32 | 33 | #else 34 | 35 | #ifndef ts_malloc 36 | #define ts_malloc malloc 37 | #endif 38 | #ifndef ts_calloc 39 | #define ts_calloc calloc 40 | #endif 41 | #ifndef ts_realloc 42 | #define ts_realloc realloc 43 | #endif 44 | #ifndef ts_free 45 | #define ts_free free 46 | #endif 47 | 48 | #endif 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif // TREE_SITTER_ALLOC_H_ 55 | -------------------------------------------------------------------------------- /dialects/helm/src/tree_sitter/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ALLOC_H_ 2 | #define TREE_SITTER_ALLOC_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | // Allow clients to override allocation functions 13 | #ifdef TREE_SITTER_REUSE_ALLOCATOR 14 | 15 | extern void *(*ts_current_malloc)(size_t size); 16 | extern void *(*ts_current_calloc)(size_t count, size_t size); 17 | extern void *(*ts_current_realloc)(void *ptr, size_t size); 18 | extern void (*ts_current_free)(void *ptr); 19 | 20 | #ifndef ts_malloc 21 | #define ts_malloc ts_current_malloc 22 | #endif 23 | #ifndef ts_calloc 24 | #define ts_calloc ts_current_calloc 25 | #endif 26 | #ifndef ts_realloc 27 | #define ts_realloc ts_current_realloc 28 | #endif 29 | #ifndef ts_free 30 | #define ts_free ts_current_free 31 | #endif 32 | 33 | #else 34 | 35 | #ifndef ts_malloc 36 | #define ts_malloc malloc 37 | #endif 38 | #ifndef ts_calloc 39 | #define ts_calloc calloc 40 | #endif 41 | #ifndef ts_realloc 42 | #define ts_realloc realloc 43 | #endif 44 | #ifndef ts_free 45 | #define ts_free free 46 | #endif 47 | 48 | #endif 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif // TREE_SITTER_ALLOC_H_ 55 | -------------------------------------------------------------------------------- /queries/highlights.scm: -------------------------------------------------------------------------------- 1 | ; Identifiers 2 | 3 | [ 4 | (field) 5 | (field_identifier) 6 | ] @property 7 | 8 | (variable) @variable 9 | 10 | ; Function calls 11 | 12 | (function_call 13 | function: (identifier) @function) 14 | 15 | (method_call 16 | method: (selector_expression 17 | field: (field_identifier) @function)) 18 | 19 | ; Operators 20 | 21 | "|" @operator 22 | ":=" @operator 23 | 24 | ; Builtin functions 25 | 26 | ((identifier) @function.builtin 27 | (#match? @function.builtin "^(and|call|html|index|slice|js|len|not|or|print|printf|println|urlquery|eq|ne|lt|ge|gt|ge)$")) 28 | 29 | ; Delimiters 30 | 31 | "." @punctuation.delimiter 32 | "," @punctuation.delimiter 33 | 34 | "{{" @punctuation.bracket 35 | "}}" @punctuation.bracket 36 | "{{-" @punctuation.bracket 37 | "-}}" @punctuation.bracket 38 | ")" @punctuation.bracket 39 | "(" @punctuation.bracket 40 | 41 | ; Keywords 42 | 43 | "else" @keyword 44 | "if" @keyword 45 | "range" @keyword 46 | "with" @keyword 47 | "end" @keyword 48 | "template" @keyword 49 | "define" @keyword 50 | "block" @keyword 51 | 52 | ; Literals 53 | 54 | [ 55 | (interpreted_string_literal) 56 | (raw_string_literal) 57 | (rune_literal) 58 | ] @string 59 | 60 | (escape_sequence) @string.special 61 | 62 | [ 63 | (int_literal) 64 | (float_literal) 65 | (imaginary_literal) 66 | ] @number 67 | 68 | [ 69 | (true) 70 | (false) 71 | (nil) 72 | ] @constant.builtin 73 | 74 | (comment) @comment 75 | (ERROR) @error 76 | -------------------------------------------------------------------------------- /bindings/rust/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let src_dir = std::path::Path::new("src"); 3 | 4 | let mut c_config = cc::Build::new(); 5 | c_config.include(&src_dir); 6 | c_config 7 | .flag_if_supported("-Wno-unused-parameter") 8 | .flag_if_supported("-Wno-unused-but-set-variable") 9 | .flag_if_supported("-Wno-trigraphs"); 10 | let parser_path = src_dir.join("parser.c"); 11 | c_config.file(&parser_path); 12 | 13 | // If your language uses an external scanner written in C, 14 | // then include this block of code: 15 | 16 | /* 17 | let scanner_path = src_dir.join("scanner.c"); 18 | c_config.file(&scanner_path); 19 | println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); 20 | */ 21 | 22 | c_config.compile("parser"); 23 | println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); 24 | 25 | // If your language uses an external scanner written in C++, 26 | // then include this block of code: 27 | 28 | /* 29 | let mut cpp_config = cc::Build::new(); 30 | cpp_config.cpp(true); 31 | cpp_config.include(&src_dir); 32 | cpp_config 33 | .flag_if_supported("-Wno-unused-parameter") 34 | .flag_if_supported("-Wno-unused-but-set-variable"); 35 | let scanner_path = src_dir.join("scanner.cc"); 36 | cpp_config.file(&scanner_path); 37 | cpp_config.compile("scanner"); 38 | println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); 39 | */ 40 | } 41 | -------------------------------------------------------------------------------- /test/corpus/text.txt: -------------------------------------------------------------------------------- 1 | ==================================== 2 | Valid curly brackets combination inside text block 3 | ==================================== 4 | {{ if condition }} 5 | }} 6 | {} 7 | }{ 8 | } 9 | { 10 | }}} 11 | {{ end }} 12 | --- 13 | (template 14 | (if_action 15 | (function_call (identifier)) 16 | (text) 17 | (text) 18 | (text) 19 | (text) 20 | (text) 21 | (text) 22 | (text))) 23 | 24 | ==================================== 25 | Invalid curly brackets combination inside text block 26 | ==================================== 27 | {{ if condition }} 28 | {{ 29 | {{ end }} 30 | --- 31 | (template 32 | (if_action 33 | (function_call (identifier)) 34 | (text) 35 | (ERROR))) 36 | 37 | ==================================== 38 | No injection text 39 | ==================================== 40 | foo: 41 | bar: {{ .Values.foo.bar }}-{{ .Values.foo.bar }} 42 | --- 43 | (template 44 | (text) 45 | (selector_expression 46 | (selector_expression 47 | (field 48 | (identifier)) 49 | (field_identifier)) 50 | (field_identifier)) 51 | (yaml_no_injection_text) 52 | (selector_expression 53 | (selector_expression 54 | (field 55 | (identifier)) 56 | (field_identifier)) 57 | (field_identifier))) 58 | 59 | ==================================== 60 | Normal text 61 | ==================================== 62 | this: 63 | - is a yaml-list 64 | --- 65 | (template 66 | (text)) 67 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: Build/test 2 | on: 3 | push: 4 | branches: 5 | - 'master' 6 | pull_request: 7 | jobs: 8 | test: 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | fail-fast: true 12 | matrix: 13 | os: [macos-latest, ubuntu-latest] 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: actions/setup-python@v4 17 | with: 18 | python-version: '3.11' 19 | - uses: actions/setup-go@v5 20 | with: 21 | go-version: '1.23' 22 | - uses: actions/setup-node@v3 23 | with: 24 | node-version: '18' 25 | - run: npm install 26 | - name: generate grammar 27 | run: npm run build 28 | - name: check for uncommited changes 29 | run: git diff --exit-code 30 | - run: npm test 31 | 32 | test_go_binding: 33 | runs-on: ${{ matrix.os }} 34 | strategy: 35 | fail-fast: true 36 | matrix: 37 | os: [macos-latest, ubuntu-latest] 38 | steps: 39 | - uses: actions/checkout@v4 40 | - uses: actions/setup-go@v5 41 | with: 42 | go-version: '1.22.x' 43 | - run: go test -v ./bindings/go 44 | 45 | prettier: 46 | runs-on: ubuntu-latest 47 | steps: 48 | - uses: actions/checkout@v3 49 | - run: npx prettier --check *.js 50 | -------------------------------------------------------------------------------- /bindings/rust/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides go_template language support for the [tree-sitter][] parsing library. 2 | //! 3 | //! Typically, you will use the [language][language func] function to add this language to a 4 | //! tree-sitter [Parser][], and then use the parser to parse some code: 5 | //! 6 | //! ``` 7 | //! let code = ""; 8 | //! let mut parser = tree_sitter::Parser::new(); 9 | //! parser.set_language(tree_sitter_go_template::language()).expect("Error loading go-template grammar"); 10 | //! let tree = parser.parse(code, None).unwrap(); 11 | //! ``` 12 | //! 13 | //! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html 14 | //! [language func]: fn.language.html 15 | //! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html 16 | //! [tree-sitter]: https://tree-sitter.github.io/ 17 | 18 | use tree_sitter::Language; 19 | 20 | extern "C" { 21 | fn tree_sitter_go_template() -> Language; 22 | } 23 | 24 | /// Get the tree-sitter [Language][] for this grammar. 25 | /// 26 | /// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html 27 | pub fn language() -> Language { 28 | unsafe { tree_sitter_go_template() } 29 | } 30 | 31 | /// The content of the [`node-types.json`][] file for this grammar. 32 | /// 33 | /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types 34 | pub const NODE_TYPES: &'static str = include_str!("../../src/node-types.json"); 35 | 36 | // Uncomment these to include any queries that this grammar contains 37 | 38 | // pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm"); 39 | // pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm"); 40 | // pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm"); 41 | // pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm"); 42 | 43 | #[cfg(test)] 44 | mod tests { 45 | #[test] 46 | fn test_can_load_grammar() { 47 | let mut parser = tree_sitter::Parser::new(); 48 | parser 49 | .set_language(super::language()) 50 | .expect("Error loading go_template language"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /test/corpus/arguments.txt: -------------------------------------------------------------------------------- 1 | ==================================== 2 | Nil 3 | ==================================== 4 | {{ nil }} 5 | --- 6 | (template 7 | (nil)) 8 | 9 | ==================================== 10 | Dot field 11 | ==================================== 12 | {{ . }} 13 | --- 14 | (template 15 | (dot)) 16 | 17 | ==================================== 18 | Field 19 | ==================================== 20 | {{ .Field }} 21 | --- 22 | (template 23 | (field 24 | (identifier))) 25 | 26 | ==================================== 27 | Chained fields 28 | ==================================== 29 | {{ .Field.Field2 }} 30 | --- 31 | (template 32 | (selector_expression 33 | (field 34 | (identifier)) 35 | (field_identifier))) 36 | 37 | ==================================== 38 | Variable without name 39 | ==================================== 40 | {{ $ }} 41 | --- 42 | (template 43 | (variable)) 44 | 45 | ==================================== 46 | Unnamed variable with field 47 | ==================================== 48 | {{ $.Field }} 49 | --- 50 | (template 51 | (selector_expression 52 | (variable) 53 | (field_identifier))) 54 | 55 | ==================================== 56 | Unnamed variable with chained field 57 | ==================================== 58 | {{ $.Field.Field2 }} 59 | --- 60 | (template 61 | (selector_expression 62 | (selector_expression 63 | (variable) 64 | (field_identifier)) 65 | (field_identifier))) 66 | 67 | ==================================== 68 | Named variable 69 | ==================================== 70 | {{ $var }} 71 | --- 72 | (template 73 | (variable 74 | (identifier))) 75 | 76 | ==================================== 77 | Named variable with field 78 | ==================================== 79 | {{ $var.Field }} 80 | --- 81 | (template 82 | (selector_expression 83 | (variable 84 | (identifier)) 85 | (field_identifier))) 86 | 87 | ==================================== 88 | Named variable with chained field 89 | ==================================== 90 | {{ $var.Field.Field2 }} 91 | --- 92 | (template 93 | (selector_expression 94 | (selector_expression 95 | (variable 96 | (identifier)) 97 | (field_identifier)) 98 | (field_identifier))) 99 | 100 | ==================================== 101 | Two fields seperated by whitespace / method call with field as argument 102 | ==================================== 103 | {{ .Field .Field }} 104 | --- 105 | (template 106 | (method_call 107 | (field 108 | (identifier)) 109 | (argument_list 110 | (field 111 | (identifier))))) 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Announcement 2 | 3 | The original author stopped using helm (which he mostly wrote this package for) on a daily basis, so he didn't really keep up with the development of tree sitter, and nvim-tree-sitter. 4 | Some people have been found to keep the repo going, so if you have ideas for improvements feel free to open issues or pull requests. 5 | 6 | # tree-sitter-go-template 7 | 8 | [![Build/test](https://github.com/ngalaiko/tree-sitter-go-template/actions/workflows/ci.yaml/badge.svg)](https://github.com/ngalaiko/tree-sitter-go-template/actions/workflows/ci.yaml) 9 | 10 | [Golang templates][] grammar for [tree-sitter][]. 11 | 12 | Also includes a [helm][] dialect. The concept of a dialect is that it uses the same parser, but can have different queries (e.g. for different injections). 13 | More dialects could be added in the future (e.g. for html templates). 14 | 15 | ## NeoVim integration using [nvim-treesitter][] 16 | 17 | - Setup filetype detection: 18 | 19 | - using [lua](https://neovim.io/doc/user/lua.html#vim.filetype): 20 | 21 | ```lua 22 | vim.filetype.add({ 23 | extension = { 24 | gotmpl = 'gotmpl', 25 | }, 26 | pattern = { 27 | [".*/templates/.*%.tpl"] = "helm", 28 | [".*/templates/.*%.ya?ml"] = "helm", 29 | ["helmfile.*%.ya?ml"] = "helm", 30 | }, 31 | }) 32 | ``` 33 | 34 | - Install [nvim-treesitter][] as described here: [nvim-treesitter-install][] 35 | - Install the parser you want to use: 36 | 37 | ```vim 38 | :TSInstall gotmpl 39 | :TSInstall helm 40 | ``` 41 | 42 | ### Highlighting for the templated language 43 | 44 | To get proper highlighting for the language that is templated (e.g. html) you need to add injections for 45 | that language to `.config/nvim/queries/gotmpl/injections.scm`: 46 | 47 | ```scm 48 | ((text) @injection.content 49 | (#set! injection.language "html") 50 | (#set! injection.combined)) 51 | ``` 52 | 53 | Replace html with the tree-sitter name of your required language and make sure to install it with `:TSInstall`. 54 | 55 | More advanced use cases would require adding more dialects (as done for helm). 56 | 57 | > [!NOTE] 58 | > 59 | > If you are using helm, you should also install the yaml parser (:TSInstall yaml) to get [language injection][] for yaml. 60 | > 61 | > In case you are using [AstroNvim][] you can just install the [astrocommunity][] helm pack or when using [LazyVim][] its [LazyVimHelm] plugin. 62 | 63 | [tree-sitter]: https://github.com/tree-sitter/tree-sitter 64 | [Golang templates]: https://golang.org/pkg/text/template/ 65 | [nvim-treesitter instructions]: https://github.com/nvim-treesitter/nvim-treesitter#adding-parsers 66 | [nvim-treesitter-install]: https://github.com/nvim-treesitter/nvim-treesitter?tab=readme-ov-file#installation 67 | [nvim-treesitter]: https://github.com/nvim-treesitter/nvim-treesitter 68 | [helm]: https://helm.sh 69 | [vim-helm]: https://github.com/towolf/vim-helm 70 | [language injection]: https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection 71 | [AstroNvim]: https://github.com/AstroNvim/AstroNvim 72 | [astrocommunity]: https://github.com/AstroNvim/astrocommunity 73 | [LazyVim]: https://www.lazyvim.org/ 74 | [LazyVimHelm]: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/lang/helm.lua 75 | -------------------------------------------------------------------------------- /test/corpus_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "regexp" 8 | "strings" 9 | "testing" 10 | "text/template" 11 | ) 12 | 13 | var ( 14 | TESTCASE_SEPARATOR = regexp.MustCompile("(?m)^(=+)$") 15 | INPUT_OUTPUT_SEPARATOR = regexp.MustCompile("\n(-+)\n") 16 | TRIM_TESTCASE_SEPARATOR = regexp.MustCompile("^(=+)\n") 17 | TESTS_DIR = "./corpus" 18 | ) 19 | 20 | func TestCorpus(t *testing.T) { 21 | testCases, err := getTestCases() 22 | if err != nil { 23 | t.Fatal(err) 24 | } 25 | 26 | fmt.Printf("Got %d test cases\n", len(testCases)) 27 | 28 | for _, testCase := range testCases { 29 | t.Run(testCase.name, func(t *testing.T) { 30 | testTemplate(t, testCase.input, testCase.isError) 31 | }) 32 | } 33 | } 34 | 35 | func testTemplate(t *testing.T, input string, isError bool) { 36 | t.Helper() 37 | 38 | input = fmt.Sprintf("{{ $var := 1}} \n %s", input) // prevent variable not found errors 39 | _, err := template.New("template").Funcs( 40 | template.FuncMap{ 41 | "pipeline": func() string { return "" }, 42 | "functionName": func() string { return "" }, 43 | "condition": func() string { return "" }, 44 | }, 45 | ).Parse(input) 46 | 47 | if err != nil && !isError { 48 | t.Fatal(err) 49 | } else if err == nil && isError { 50 | t.Fatal("expected error") 51 | } 52 | } 53 | 54 | type TestCase struct { 55 | file string 56 | name string 57 | input string 58 | sExpression string 59 | isError bool 60 | } 61 | 62 | func NewTestCase(file, name, input, sExpression string) TestCase { 63 | return TestCase{ 64 | name: fmt.Sprintf("%s: %s", file, name), 65 | input: input, 66 | sExpression: sExpression, 67 | isError: strings.Contains(sExpression, "(ERROR") || strings.Contains(sExpression, "(MISSING"), 68 | } 69 | } 70 | 71 | func getTestCasesForFile(filename string, content string) []TestCase { 72 | testCases := []TestCase{} 73 | parts := []string{} 74 | 75 | // split and remove empty parts 76 | for _, part := range TESTCASE_SEPARATOR.Split(content, -1) { 77 | if part != "" { 78 | parts = append(parts, part) 79 | } 80 | } 81 | 82 | for i := 0; i < len(parts)-1; i += 2 { 83 | testName := strings.TrimSpace(parts[i]) 84 | testContent := parts[i+1] 85 | testParts := INPUT_OUTPUT_SEPARATOR.Split(testContent, -1) 86 | 87 | if len(testParts) != 2 { 88 | fmt.Printf("Error parsing %s: Testcase has invalid format %s\n", filename, testName) 89 | continue 90 | } 91 | 92 | testCases = append(testCases, 93 | NewTestCase( 94 | filename, 95 | testName, 96 | testParts[0], 97 | testParts[1], 98 | ), 99 | ) 100 | } 101 | 102 | return testCases 103 | } 104 | 105 | func getTestCases() ([]TestCase, error) { 106 | var testCases []TestCase 107 | 108 | err := filepath.Walk(TESTS_DIR, func(path string, info os.FileInfo, err error) error { 109 | if err != nil { 110 | return err 111 | } 112 | if !info.IsDir() && strings.HasSuffix(info.Name(), ".txt") { 113 | content, err := os.ReadFile(path) 114 | if err != nil { 115 | return err 116 | } 117 | 118 | testCases = append(testCases, getTestCasesForFile(path, string(content))...) 119 | } 120 | return nil 121 | }) 122 | if err != nil { 123 | fmt.Println("Error walking the path:", err) 124 | return nil, err 125 | } 126 | 127 | return testCases, nil 128 | } 129 | -------------------------------------------------------------------------------- /test/corpus/pipelines.txt: -------------------------------------------------------------------------------- 1 | ==================================== 2 | Function without arguments 3 | ==================================== 4 | {{ functionName }} 5 | --- 6 | (template 7 | (function_call 8 | (identifier))) 9 | 10 | ==================================== 11 | Function with argument 12 | ==================================== 13 | {{ functionName $ }} 14 | --- 15 | (template 16 | (function_call 17 | (identifier) 18 | (argument_list 19 | (variable)))) 20 | 21 | ==================================== 22 | Function with arguments 23 | ==================================== 24 | {{ functionName $ . .Field.Field2 1 }} 25 | --- 26 | (template 27 | (function_call 28 | (identifier) 29 | (argument_list 30 | (variable) 31 | (dot) 32 | (selector_expression 33 | (field 34 | (identifier)) 35 | (field_identifier)) 36 | (int_literal)))) 37 | 38 | ==================================== 39 | Method without arguments 40 | ==================================== 41 | {{ .Method }} 42 | --- 43 | (template 44 | (field (identifier))) 45 | 46 | ==================================== 47 | Method with argument 48 | ==================================== 49 | {{ .Method $ }} 50 | --- 51 | (template 52 | (method_call 53 | (field 54 | (identifier)) 55 | (argument_list 56 | (variable)))) 57 | 58 | ==================================== 59 | Method with arguments 60 | ==================================== 61 | {{ .Method $ . .Field.Field2 1 }} 62 | --- 63 | (template 64 | (method_call 65 | (field 66 | (identifier)) 67 | (argument_list 68 | (variable) 69 | (dot) 70 | (selector_expression 71 | (field (identifier)) 72 | (field_identifier)) 73 | (int_literal)))) 74 | 75 | ==================================== 76 | Method on a field without arguments 77 | ==================================== 78 | {{ .Field.Method }} 79 | --- 80 | (template 81 | (selector_expression 82 | (field 83 | (identifier)) 84 | (field_identifier))) 85 | 86 | ==================================== 87 | Method on a field with arguments 88 | ==================================== 89 | {{ .Field.Method $ . .Field.Field2 1 }} 90 | --- 91 | (template 92 | (method_call 93 | (selector_expression 94 | (field 95 | (identifier)) 96 | (field_identifier)) 97 | (argument_list 98 | (variable) 99 | (dot) 100 | (selector_expression 101 | (field 102 | (identifier)) 103 | (field_identifier)) 104 | (int_literal)))) 105 | 106 | ==================================== 107 | Selector expression on a parenthesized pipeline 108 | ==================================== 109 | {{ (pipeline).Field }} 110 | --- 111 | (template 112 | (selector_expression 113 | (parenthesized_pipeline 114 | (function_call 115 | (identifier))) 116 | (field_identifier))) 117 | 118 | ==================================== 119 | Selector expression on a function call 120 | ==================================== 121 | {{ pipeline.Field }} 122 | --- 123 | (template 124 | (selector_expression 125 | (identifier) 126 | (field_identifier))) 127 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= 4 | github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= 5 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 8 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 9 | github.com/tree-sitter/go-tree-sitter v0.25.0 h1:sx6kcg8raRFCvc9BnXglke6axya12krCJF5xJ2sftRU= 10 | github.com/tree-sitter/go-tree-sitter v0.25.0/go.mod h1:r77ig7BikoZhHrrsjAnv8RqGti5rtSyvDHPzgTPsUuU= 11 | github.com/tree-sitter/tree-sitter-c v0.23.4 h1:nBPH3FV07DzAD7p0GfNvXM+Y7pNIoPenQWBpvM++t4c= 12 | github.com/tree-sitter/tree-sitter-c v0.23.4/go.mod h1:MkI5dOiIpeN94LNjeCp8ljXN/953JCwAby4bClMr6bw= 13 | github.com/tree-sitter/tree-sitter-cpp v0.23.4 h1:LaWZsiqQKvR65yHgKmnaqA+uz6tlDJTJFCyFIeZU/8w= 14 | github.com/tree-sitter/tree-sitter-cpp v0.23.4/go.mod h1:doqNW64BriC7WBCQ1klf0KmJpdEvfxyXtoEybnBo6v8= 15 | github.com/tree-sitter/tree-sitter-embedded-template v0.23.2 h1:nFkkH6Sbe56EXLmZBqHHcamTpmz3TId97I16EnGy4rg= 16 | github.com/tree-sitter/tree-sitter-embedded-template v0.23.2/go.mod h1:HNPOhN0qF3hWluYLdxWs5WbzP/iE4aaRVPMsdxuzIaQ= 17 | github.com/tree-sitter/tree-sitter-go v0.23.4 h1:yt5KMGnTHS+86pJmLIAZMWxukr8W7Ae1STPvQUuNROA= 18 | github.com/tree-sitter/tree-sitter-go v0.23.4/go.mod h1:Jrx8QqYN0v7npv1fJRH1AznddllYiCMUChtVjxPK040= 19 | github.com/tree-sitter/tree-sitter-html v0.23.2 h1:1UYDV+Yd05GGRhVnTcbP58GkKLSHHZwVaN+lBZV11Lc= 20 | github.com/tree-sitter/tree-sitter-html v0.23.2/go.mod h1:gpUv/dG3Xl/eebqgeYeFMt+JLOY9cgFinb/Nw08a9og= 21 | github.com/tree-sitter/tree-sitter-java v0.23.5 h1:J9YeMGMwXYlKSP3K4Us8CitC6hjtMjqpeOf2GGo6tig= 22 | github.com/tree-sitter/tree-sitter-java v0.23.5/go.mod h1:NRKlI8+EznxA7t1Yt3xtraPk1Wzqh3GAIC46wxvc320= 23 | github.com/tree-sitter/tree-sitter-javascript v0.23.1 h1:1fWupaRC0ArlHJ/QJzsfQ3Ibyopw7ZfQK4xXc40Zveo= 24 | github.com/tree-sitter/tree-sitter-javascript v0.23.1/go.mod h1:lmGD1EJdCA+v0S1u2fFgepMg/opzSg/4pgFym2FPGAs= 25 | github.com/tree-sitter/tree-sitter-json v0.24.8 h1:tV5rMkihgtiOe14a9LHfDY5kzTl5GNUYe6carZBn0fQ= 26 | github.com/tree-sitter/tree-sitter-json v0.24.8/go.mod h1:F351KK0KGvCaYbZ5zxwx/gWWvZhIDl0eMtn+1r+gQbo= 27 | github.com/tree-sitter/tree-sitter-php v0.23.11 h1:iHewsLNDmznh8kgGyfWfujsZxIz1YGbSd2ZTEM0ZiP8= 28 | github.com/tree-sitter/tree-sitter-php v0.23.11/go.mod h1:T/kbfi+UcCywQfUNAJnGTN/fMSUjnwPXA8k4yoIks74= 29 | github.com/tree-sitter/tree-sitter-python v0.23.6 h1:qHnWFR5WhtMQpxBZRwiaU5Hk/29vGju6CVtmvu5Haas= 30 | github.com/tree-sitter/tree-sitter-python v0.23.6/go.mod h1:cpdthSy/Yoa28aJFBscFHlGiU+cnSiSh1kuDVtI8YeM= 31 | github.com/tree-sitter/tree-sitter-ruby v0.23.1 h1:T/NKHUA+iVbHM440hFx+lzVOzS4dV6z8Qw8ai+72bYo= 32 | github.com/tree-sitter/tree-sitter-ruby v0.23.1/go.mod h1:kUS4kCCQloFcdX6sdpr8p6r2rogbM6ZjTox5ZOQy8cA= 33 | github.com/tree-sitter/tree-sitter-rust v0.23.2 h1:6AtoooCW5GqNrRpfnvl0iUhxTAZEovEmLKDbyHlfw90= 34 | github.com/tree-sitter/tree-sitter-rust v0.23.2/go.mod h1:hfeGWic9BAfgTrc7Xf6FaOAguCFJRo3RBbs7QJ6D7MI= 35 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 36 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 37 | -------------------------------------------------------------------------------- /test/corpus/literals.txt: -------------------------------------------------------------------------------- 1 | ==================================== 2 | Number literals. 3 | ==================================== 4 | {{ 0 }} 5 | {{ 42 }} 6 | {{ 007 }} // octal 7 | {{ 00 }} // extra zero 8 | {{ 0o77 }} // explicit octal 9 | {{ 0b1010 }} // binary 10 | {{ 0x1F }} // hex 11 | {{ 0XABC }} // hex uppercase 12 | {{ 123_456 }} // digit separator 13 | {{ 1_000_000 }} // large number with underscores 14 | 15 | {{ 0.0 }} 16 | {{ 3.1415 }} 17 | {{ 1.0e10 }} 18 | {{ 2.5E-3 }} 19 | {{ .5 }} 20 | {{ 0.5e+1 }} 21 | {{ 1_234.567_890 }} // float with underscores 22 | {{ .5e1 }} 23 | 24 | {{ 0x1.fp10 }} // hex float 25 | {{ 0xABC.123p+3 }} 26 | 27 | {{ 0b1010_0101 }} // binary with underscores 28 | {{ 0o7_7 }} // octal with underscores 29 | {{ 0xAB_CD_EF }} // hex with underscores 30 | --- 31 | (template 32 | (int_literal) 33 | (text) 34 | (int_literal) 35 | (text) 36 | (int_literal) 37 | (text) 38 | (int_literal) 39 | (text) 40 | (int_literal) 41 | (text) 42 | (int_literal) 43 | (text) 44 | (int_literal) 45 | (text) 46 | (int_literal) 47 | (text) 48 | (int_literal) 49 | (text) 50 | (int_literal) 51 | (text) 52 | (float_literal) 53 | (text) 54 | (float_literal) 55 | (text) 56 | (float_literal) 57 | (text) 58 | (float_literal) 59 | (text) 60 | (float_literal) 61 | (text) 62 | (float_literal) 63 | (text) 64 | (float_literal) 65 | (text) 66 | (float_literal) 67 | (text) 68 | (float_literal) 69 | (text) 70 | (float_literal) 71 | (text) 72 | (int_literal) 73 | (text) 74 | (int_literal) 75 | (text) 76 | (int_literal) 77 | (text)) 78 | 79 | ==================================== 80 | Negative number literals. 81 | ==================================== 82 | {{ -0 }} 83 | {{ -42 }} 84 | {{ -0xFF }} 85 | {{ -0o77 }} 86 | {{ -0b1010 }} 87 | 88 | {{ -0.0 }} 89 | {{ -3.14 }} 90 | {{ -1.0e5 }} 91 | {{ -0.5e+2 }} 92 | {{ -.5e-1 }} 93 | {{ -0x1.fp-2 }} 94 | --- 95 | (template 96 | (int_literal) 97 | (text) 98 | (int_literal) 99 | (text) 100 | (int_literal) 101 | (text) 102 | (int_literal) 103 | (text) 104 | (int_literal) 105 | (text) 106 | (float_literal) 107 | (text) 108 | (float_literal) 109 | (text) 110 | (float_literal) 111 | (text) 112 | (float_literal) 113 | (text) 114 | (float_literal) 115 | (text) 116 | (float_literal)) 117 | 118 | ==================================== 119 | Positive number literals. 120 | ==================================== 121 | {{ +0 }} 122 | {{ +123 }} 123 | {{ +0x1A }} 124 | {{ +0b1111 }} 125 | 126 | {{ +0.0 }} 127 | {{ +2.71 }} 128 | {{ +1.0e3 }} 129 | {{ +.25e-1 }} 130 | {{ +.5e1 }} 131 | {{ +0xABC.123p+3 }} 132 | --- 133 | (template 134 | (int_literal) 135 | (text) 136 | (int_literal) 137 | (text) 138 | (int_literal) 139 | (text) 140 | (int_literal) 141 | (text) 142 | (float_literal) 143 | (text) 144 | (float_literal) 145 | (text) 146 | (float_literal) 147 | (text) 148 | (float_literal) 149 | (text) 150 | (float_literal) 151 | (text) 152 | (float_literal)) 153 | 154 | ==================================== 155 | Imaginary number literals. 156 | ==================================== 157 | {{ 5i }} 158 | {{ -5i }} 159 | {{ +5i }} 160 | {{ 3.14i }} 161 | {{ -2.71i }} 162 | {{ +0.5e1i }} 163 | {{ 0x1Fp10i }} 164 | {{ -0x1.fp-2i }} 165 | --- 166 | (template 167 | (imaginary_literal) 168 | (text) 169 | (imaginary_literal) 170 | (text) 171 | (imaginary_literal) 172 | (text) 173 | (imaginary_literal) 174 | (text) 175 | (imaginary_literal) 176 | (text) 177 | (imaginary_literal) 178 | (text) 179 | (imaginary_literal) 180 | (text) 181 | (imaginary_literal)) 182 | -------------------------------------------------------------------------------- /test/corpus/examples.txt: -------------------------------------------------------------------------------- 1 | ==================================== 2 | A string constant. 3 | ==================================== 4 | {{"\"output\""}} 5 | --- 6 | (template 7 | (interpreted_string_literal 8 | (escape_sequence) 9 | (escape_sequence))) 10 | 11 | ==================================== 12 | A invalid string constant. 13 | ==================================== 14 | {{"output 15 | "}} 16 | --- 17 | (template 18 | (ERROR 19 | (ERROR))) 20 | 21 | ==================================== 22 | A raw string constant. 23 | ==================================== 24 | {{`"output"`}} 25 | --- 26 | (template (raw_string_literal)) 27 | 28 | ==================================== 29 | A function call. 30 | ==================================== 31 | {{printf "%q" "output"}} 32 | --- 33 | (template 34 | (function_call 35 | (identifier) 36 | (argument_list 37 | (interpreted_string_literal) 38 | (interpreted_string_literal)))) 39 | 40 | ==================================== 41 | A function call whose final argument comes from the previous command. 42 | ==================================== 43 | {{"output" | printf "%q"}} 44 | --- 45 | (template 46 | (chained_pipeline 47 | (interpreted_string_literal) 48 | (function_call 49 | (identifier) 50 | (argument_list 51 | (interpreted_string_literal))))) 52 | 53 | ==================================== 54 | A parenthesized argument. 55 | ==================================== 56 | {{printf "%q" (print "out" "put")}} 57 | --- 58 | (template 59 | (function_call 60 | (identifier) 61 | (argument_list 62 | (interpreted_string_literal) 63 | (parenthesized_pipeline 64 | (function_call 65 | (identifier) 66 | (argument_list 67 | (interpreted_string_literal) 68 | (interpreted_string_literal))))))) 69 | 70 | ==================================== 71 | A more elaborate call. 72 | ==================================== 73 | {{"put" | printf "%s%s" "out" | printf "%q"}} 74 | --- 75 | (template 76 | (chained_pipeline 77 | (chained_pipeline 78 | (interpreted_string_literal) 79 | (function_call 80 | (identifier) 81 | (argument_list 82 | (interpreted_string_literal) 83 | (interpreted_string_literal)))) 84 | (function_call 85 | (identifier) 86 | (argument_list 87 | (interpreted_string_literal))))) 88 | 89 | ==================================== 90 | A longer chain. 91 | ==================================== 92 | {{"output" | printf "%s" | printf "%q"}} 93 | --- 94 | (template 95 | (chained_pipeline 96 | (chained_pipeline 97 | (interpreted_string_literal) 98 | (function_call 99 | (identifier) 100 | (argument_list 101 | (interpreted_string_literal)))) 102 | (function_call 103 | (identifier) 104 | (argument_list 105 | (interpreted_string_literal))))) 106 | 107 | ==================================== 108 | A with action using dot. 109 | ==================================== 110 | {{with "output"}}{{printf "%q" .}}{{end}} 111 | --- 112 | (template 113 | (with_action 114 | (interpreted_string_literal) 115 | (function_call 116 | (identifier) 117 | (argument_list 118 | (interpreted_string_literal) 119 | (dot))))) 120 | 121 | ==================================== 122 | A with action using dot. 123 | ==================================== 124 | {{with "output"}}{{printf "%q" .}}{{end}} 125 | --- 126 | (template 127 | (with_action 128 | (interpreted_string_literal) 129 | (function_call 130 | (identifier) 131 | (argument_list 132 | (interpreted_string_literal) 133 | (dot))))) 134 | 135 | ==================================== 136 | A with action that creates and uses a variable. 137 | ==================================== 138 | {{with $x := "output" | printf "%q"}}{{$x}}{{end}} 139 | --- 140 | (template 141 | (with_action 142 | (variable_definition 143 | (variable (identifier)) 144 | (chained_pipeline 145 | (interpreted_string_literal) 146 | (function_call 147 | (identifier) 148 | (argument_list 149 | (interpreted_string_literal))))) 150 | (variable (identifier)))) 151 | 152 | ==================================== 153 | A with action that uses the variable in another action. 154 | ==================================== 155 | {{with $x := "output"}}{{printf "%q" $x}}{{end}} 156 | --- 157 | (template 158 | (with_action 159 | (variable_definition 160 | (variable (identifier)) 161 | (interpreted_string_literal)) 162 | (function_call 163 | (identifier) 164 | (argument_list 165 | (interpreted_string_literal) 166 | (variable (identifier)))))) 167 | 168 | ==================================== 169 | The same, but pipelined. 170 | ==================================== 171 | {{with $x := "output"}}{{$x | printf "%q"}}{{end}} 172 | --- 173 | (template 174 | (with_action 175 | (variable_definition 176 | (variable 177 | (identifier)) 178 | (interpreted_string_literal)) 179 | (chained_pipeline 180 | (variable 181 | (identifier)) 182 | (function_call 183 | (identifier) 184 | (argument_list 185 | (interpreted_string_literal)))))) 186 | -------------------------------------------------------------------------------- /src/tree_sitter/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_PARSER_H_ 2 | #define TREE_SITTER_PARSER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define ts_builtin_sym_error ((TSSymbol)-1) 13 | #define ts_builtin_sym_end 0 14 | #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 15 | 16 | #ifndef TREE_SITTER_API_H_ 17 | typedef uint16_t TSStateId; 18 | typedef uint16_t TSSymbol; 19 | typedef uint16_t TSFieldId; 20 | typedef struct TSLanguage TSLanguage; 21 | typedef struct TSLanguageMetadata { 22 | uint8_t major_version; 23 | uint8_t minor_version; 24 | uint8_t patch_version; 25 | } TSLanguageMetadata; 26 | #endif 27 | 28 | typedef struct { 29 | TSFieldId field_id; 30 | uint8_t child_index; 31 | bool inherited; 32 | } TSFieldMapEntry; 33 | 34 | // Used to index the field and supertype maps. 35 | typedef struct { 36 | uint16_t index; 37 | uint16_t length; 38 | } TSMapSlice; 39 | 40 | typedef struct { 41 | bool visible; 42 | bool named; 43 | bool supertype; 44 | } TSSymbolMetadata; 45 | 46 | typedef struct TSLexer TSLexer; 47 | 48 | struct TSLexer { 49 | int32_t lookahead; 50 | TSSymbol result_symbol; 51 | void (*advance)(TSLexer *, bool); 52 | void (*mark_end)(TSLexer *); 53 | uint32_t (*get_column)(TSLexer *); 54 | bool (*is_at_included_range_start)(const TSLexer *); 55 | bool (*eof)(const TSLexer *); 56 | void (*log)(const TSLexer *, const char *, ...); 57 | }; 58 | 59 | typedef enum { 60 | TSParseActionTypeShift, 61 | TSParseActionTypeReduce, 62 | TSParseActionTypeAccept, 63 | TSParseActionTypeRecover, 64 | } TSParseActionType; 65 | 66 | typedef union { 67 | struct { 68 | uint8_t type; 69 | TSStateId state; 70 | bool extra; 71 | bool repetition; 72 | } shift; 73 | struct { 74 | uint8_t type; 75 | uint8_t child_count; 76 | TSSymbol symbol; 77 | int16_t dynamic_precedence; 78 | uint16_t production_id; 79 | } reduce; 80 | uint8_t type; 81 | } TSParseAction; 82 | 83 | typedef struct { 84 | uint16_t lex_state; 85 | uint16_t external_lex_state; 86 | } TSLexMode; 87 | 88 | typedef struct { 89 | uint16_t lex_state; 90 | uint16_t external_lex_state; 91 | uint16_t reserved_word_set_id; 92 | } TSLexerMode; 93 | 94 | typedef union { 95 | TSParseAction action; 96 | struct { 97 | uint8_t count; 98 | bool reusable; 99 | } entry; 100 | } TSParseActionEntry; 101 | 102 | typedef struct { 103 | int32_t start; 104 | int32_t end; 105 | } TSCharacterRange; 106 | 107 | struct TSLanguage { 108 | uint32_t abi_version; 109 | uint32_t symbol_count; 110 | uint32_t alias_count; 111 | uint32_t token_count; 112 | uint32_t external_token_count; 113 | uint32_t state_count; 114 | uint32_t large_state_count; 115 | uint32_t production_id_count; 116 | uint32_t field_count; 117 | uint16_t max_alias_sequence_length; 118 | const uint16_t *parse_table; 119 | const uint16_t *small_parse_table; 120 | const uint32_t *small_parse_table_map; 121 | const TSParseActionEntry *parse_actions; 122 | const char * const *symbol_names; 123 | const char * const *field_names; 124 | const TSMapSlice *field_map_slices; 125 | const TSFieldMapEntry *field_map_entries; 126 | const TSSymbolMetadata *symbol_metadata; 127 | const TSSymbol *public_symbol_map; 128 | const uint16_t *alias_map; 129 | const TSSymbol *alias_sequences; 130 | const TSLexerMode *lex_modes; 131 | bool (*lex_fn)(TSLexer *, TSStateId); 132 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 133 | TSSymbol keyword_capture_token; 134 | struct { 135 | const bool *states; 136 | const TSSymbol *symbol_map; 137 | void *(*create)(void); 138 | void (*destroy)(void *); 139 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 140 | unsigned (*serialize)(void *, char *); 141 | void (*deserialize)(void *, const char *, unsigned); 142 | } external_scanner; 143 | const TSStateId *primary_state_ids; 144 | const char *name; 145 | const TSSymbol *reserved_words; 146 | uint16_t max_reserved_word_set_size; 147 | uint32_t supertype_count; 148 | const TSSymbol *supertype_symbols; 149 | const TSMapSlice *supertype_map_slices; 150 | const TSSymbol *supertype_map_entries; 151 | TSLanguageMetadata metadata; 152 | }; 153 | 154 | static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { 155 | uint32_t index = 0; 156 | uint32_t size = len - index; 157 | while (size > 1) { 158 | uint32_t half_size = size / 2; 159 | uint32_t mid_index = index + half_size; 160 | const TSCharacterRange *range = &ranges[mid_index]; 161 | if (lookahead >= range->start && lookahead <= range->end) { 162 | return true; 163 | } else if (lookahead > range->end) { 164 | index = mid_index; 165 | } 166 | size -= half_size; 167 | } 168 | const TSCharacterRange *range = &ranges[index]; 169 | return (lookahead >= range->start && lookahead <= range->end); 170 | } 171 | 172 | /* 173 | * Lexer Macros 174 | */ 175 | 176 | #ifdef _MSC_VER 177 | #define UNUSED __pragma(warning(suppress : 4101)) 178 | #else 179 | #define UNUSED __attribute__((unused)) 180 | #endif 181 | 182 | #define START_LEXER() \ 183 | bool result = false; \ 184 | bool skip = false; \ 185 | UNUSED \ 186 | bool eof = false; \ 187 | int32_t lookahead; \ 188 | goto start; \ 189 | next_state: \ 190 | lexer->advance(lexer, skip); \ 191 | start: \ 192 | skip = false; \ 193 | lookahead = lexer->lookahead; 194 | 195 | #define ADVANCE(state_value) \ 196 | { \ 197 | state = state_value; \ 198 | goto next_state; \ 199 | } 200 | 201 | #define ADVANCE_MAP(...) \ 202 | { \ 203 | static const uint16_t map[] = { __VA_ARGS__ }; \ 204 | for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ 205 | if (map[i] == lookahead) { \ 206 | state = map[i + 1]; \ 207 | goto next_state; \ 208 | } \ 209 | } \ 210 | } 211 | 212 | #define SKIP(state_value) \ 213 | { \ 214 | skip = true; \ 215 | state = state_value; \ 216 | goto next_state; \ 217 | } 218 | 219 | #define ACCEPT_TOKEN(symbol_value) \ 220 | result = true; \ 221 | lexer->result_symbol = symbol_value; \ 222 | lexer->mark_end(lexer); 223 | 224 | #define END_STATE() return result; 225 | 226 | /* 227 | * Parse Table Macros 228 | */ 229 | 230 | #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) 231 | 232 | #define STATE(id) id 233 | 234 | #define ACTIONS(id) id 235 | 236 | #define SHIFT(state_value) \ 237 | {{ \ 238 | .shift = { \ 239 | .type = TSParseActionTypeShift, \ 240 | .state = (state_value) \ 241 | } \ 242 | }} 243 | 244 | #define SHIFT_REPEAT(state_value) \ 245 | {{ \ 246 | .shift = { \ 247 | .type = TSParseActionTypeShift, \ 248 | .state = (state_value), \ 249 | .repetition = true \ 250 | } \ 251 | }} 252 | 253 | #define SHIFT_EXTRA() \ 254 | {{ \ 255 | .shift = { \ 256 | .type = TSParseActionTypeShift, \ 257 | .extra = true \ 258 | } \ 259 | }} 260 | 261 | #define REDUCE(symbol_name, children, precedence, prod_id) \ 262 | {{ \ 263 | .reduce = { \ 264 | .type = TSParseActionTypeReduce, \ 265 | .symbol = symbol_name, \ 266 | .child_count = children, \ 267 | .dynamic_precedence = precedence, \ 268 | .production_id = prod_id \ 269 | }, \ 270 | }} 271 | 272 | #define RECOVER() \ 273 | {{ \ 274 | .type = TSParseActionTypeRecover \ 275 | }} 276 | 277 | #define ACCEPT_INPUT() \ 278 | {{ \ 279 | .type = TSParseActionTypeAccept \ 280 | }} 281 | 282 | #ifdef __cplusplus 283 | } 284 | #endif 285 | 286 | #endif // TREE_SITTER_PARSER_H_ 287 | -------------------------------------------------------------------------------- /dialects/helm/src/tree_sitter/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_PARSER_H_ 2 | #define TREE_SITTER_PARSER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define ts_builtin_sym_error ((TSSymbol)-1) 13 | #define ts_builtin_sym_end 0 14 | #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 15 | 16 | #ifndef TREE_SITTER_API_H_ 17 | typedef uint16_t TSStateId; 18 | typedef uint16_t TSSymbol; 19 | typedef uint16_t TSFieldId; 20 | typedef struct TSLanguage TSLanguage; 21 | typedef struct TSLanguageMetadata { 22 | uint8_t major_version; 23 | uint8_t minor_version; 24 | uint8_t patch_version; 25 | } TSLanguageMetadata; 26 | #endif 27 | 28 | typedef struct { 29 | TSFieldId field_id; 30 | uint8_t child_index; 31 | bool inherited; 32 | } TSFieldMapEntry; 33 | 34 | // Used to index the field and supertype maps. 35 | typedef struct { 36 | uint16_t index; 37 | uint16_t length; 38 | } TSMapSlice; 39 | 40 | typedef struct { 41 | bool visible; 42 | bool named; 43 | bool supertype; 44 | } TSSymbolMetadata; 45 | 46 | typedef struct TSLexer TSLexer; 47 | 48 | struct TSLexer { 49 | int32_t lookahead; 50 | TSSymbol result_symbol; 51 | void (*advance)(TSLexer *, bool); 52 | void (*mark_end)(TSLexer *); 53 | uint32_t (*get_column)(TSLexer *); 54 | bool (*is_at_included_range_start)(const TSLexer *); 55 | bool (*eof)(const TSLexer *); 56 | void (*log)(const TSLexer *, const char *, ...); 57 | }; 58 | 59 | typedef enum { 60 | TSParseActionTypeShift, 61 | TSParseActionTypeReduce, 62 | TSParseActionTypeAccept, 63 | TSParseActionTypeRecover, 64 | } TSParseActionType; 65 | 66 | typedef union { 67 | struct { 68 | uint8_t type; 69 | TSStateId state; 70 | bool extra; 71 | bool repetition; 72 | } shift; 73 | struct { 74 | uint8_t type; 75 | uint8_t child_count; 76 | TSSymbol symbol; 77 | int16_t dynamic_precedence; 78 | uint16_t production_id; 79 | } reduce; 80 | uint8_t type; 81 | } TSParseAction; 82 | 83 | typedef struct { 84 | uint16_t lex_state; 85 | uint16_t external_lex_state; 86 | } TSLexMode; 87 | 88 | typedef struct { 89 | uint16_t lex_state; 90 | uint16_t external_lex_state; 91 | uint16_t reserved_word_set_id; 92 | } TSLexerMode; 93 | 94 | typedef union { 95 | TSParseAction action; 96 | struct { 97 | uint8_t count; 98 | bool reusable; 99 | } entry; 100 | } TSParseActionEntry; 101 | 102 | typedef struct { 103 | int32_t start; 104 | int32_t end; 105 | } TSCharacterRange; 106 | 107 | struct TSLanguage { 108 | uint32_t abi_version; 109 | uint32_t symbol_count; 110 | uint32_t alias_count; 111 | uint32_t token_count; 112 | uint32_t external_token_count; 113 | uint32_t state_count; 114 | uint32_t large_state_count; 115 | uint32_t production_id_count; 116 | uint32_t field_count; 117 | uint16_t max_alias_sequence_length; 118 | const uint16_t *parse_table; 119 | const uint16_t *small_parse_table; 120 | const uint32_t *small_parse_table_map; 121 | const TSParseActionEntry *parse_actions; 122 | const char * const *symbol_names; 123 | const char * const *field_names; 124 | const TSMapSlice *field_map_slices; 125 | const TSFieldMapEntry *field_map_entries; 126 | const TSSymbolMetadata *symbol_metadata; 127 | const TSSymbol *public_symbol_map; 128 | const uint16_t *alias_map; 129 | const TSSymbol *alias_sequences; 130 | const TSLexerMode *lex_modes; 131 | bool (*lex_fn)(TSLexer *, TSStateId); 132 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 133 | TSSymbol keyword_capture_token; 134 | struct { 135 | const bool *states; 136 | const TSSymbol *symbol_map; 137 | void *(*create)(void); 138 | void (*destroy)(void *); 139 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 140 | unsigned (*serialize)(void *, char *); 141 | void (*deserialize)(void *, const char *, unsigned); 142 | } external_scanner; 143 | const TSStateId *primary_state_ids; 144 | const char *name; 145 | const TSSymbol *reserved_words; 146 | uint16_t max_reserved_word_set_size; 147 | uint32_t supertype_count; 148 | const TSSymbol *supertype_symbols; 149 | const TSMapSlice *supertype_map_slices; 150 | const TSSymbol *supertype_map_entries; 151 | TSLanguageMetadata metadata; 152 | }; 153 | 154 | static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { 155 | uint32_t index = 0; 156 | uint32_t size = len - index; 157 | while (size > 1) { 158 | uint32_t half_size = size / 2; 159 | uint32_t mid_index = index + half_size; 160 | const TSCharacterRange *range = &ranges[mid_index]; 161 | if (lookahead >= range->start && lookahead <= range->end) { 162 | return true; 163 | } else if (lookahead > range->end) { 164 | index = mid_index; 165 | } 166 | size -= half_size; 167 | } 168 | const TSCharacterRange *range = &ranges[index]; 169 | return (lookahead >= range->start && lookahead <= range->end); 170 | } 171 | 172 | /* 173 | * Lexer Macros 174 | */ 175 | 176 | #ifdef _MSC_VER 177 | #define UNUSED __pragma(warning(suppress : 4101)) 178 | #else 179 | #define UNUSED __attribute__((unused)) 180 | #endif 181 | 182 | #define START_LEXER() \ 183 | bool result = false; \ 184 | bool skip = false; \ 185 | UNUSED \ 186 | bool eof = false; \ 187 | int32_t lookahead; \ 188 | goto start; \ 189 | next_state: \ 190 | lexer->advance(lexer, skip); \ 191 | start: \ 192 | skip = false; \ 193 | lookahead = lexer->lookahead; 194 | 195 | #define ADVANCE(state_value) \ 196 | { \ 197 | state = state_value; \ 198 | goto next_state; \ 199 | } 200 | 201 | #define ADVANCE_MAP(...) \ 202 | { \ 203 | static const uint16_t map[] = { __VA_ARGS__ }; \ 204 | for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ 205 | if (map[i] == lookahead) { \ 206 | state = map[i + 1]; \ 207 | goto next_state; \ 208 | } \ 209 | } \ 210 | } 211 | 212 | #define SKIP(state_value) \ 213 | { \ 214 | skip = true; \ 215 | state = state_value; \ 216 | goto next_state; \ 217 | } 218 | 219 | #define ACCEPT_TOKEN(symbol_value) \ 220 | result = true; \ 221 | lexer->result_symbol = symbol_value; \ 222 | lexer->mark_end(lexer); 223 | 224 | #define END_STATE() return result; 225 | 226 | /* 227 | * Parse Table Macros 228 | */ 229 | 230 | #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) 231 | 232 | #define STATE(id) id 233 | 234 | #define ACTIONS(id) id 235 | 236 | #define SHIFT(state_value) \ 237 | {{ \ 238 | .shift = { \ 239 | .type = TSParseActionTypeShift, \ 240 | .state = (state_value) \ 241 | } \ 242 | }} 243 | 244 | #define SHIFT_REPEAT(state_value) \ 245 | {{ \ 246 | .shift = { \ 247 | .type = TSParseActionTypeShift, \ 248 | .state = (state_value), \ 249 | .repetition = true \ 250 | } \ 251 | }} 252 | 253 | #define SHIFT_EXTRA() \ 254 | {{ \ 255 | .shift = { \ 256 | .type = TSParseActionTypeShift, \ 257 | .extra = true \ 258 | } \ 259 | }} 260 | 261 | #define REDUCE(symbol_name, children, precedence, prod_id) \ 262 | {{ \ 263 | .reduce = { \ 264 | .type = TSParseActionTypeReduce, \ 265 | .symbol = symbol_name, \ 266 | .child_count = children, \ 267 | .dynamic_precedence = precedence, \ 268 | .production_id = prod_id \ 269 | }, \ 270 | }} 271 | 272 | #define RECOVER() \ 273 | {{ \ 274 | .type = TSParseActionTypeRecover \ 275 | }} 276 | 277 | #define ACCEPT_INPUT() \ 278 | {{ \ 279 | .type = TSParseActionTypeAccept \ 280 | }} 281 | 282 | #ifdef __cplusplus 283 | } 284 | #endif 285 | 286 | #endif // TREE_SITTER_PARSER_H_ 287 | -------------------------------------------------------------------------------- /src/tree_sitter/array.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ARRAY_H_ 2 | #define TREE_SITTER_ARRAY_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "./alloc.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef _MSC_VER 17 | #pragma warning(push) 18 | #pragma warning(disable : 4101) 19 | #elif defined(__GNUC__) || defined(__clang__) 20 | #pragma GCC diagnostic push 21 | #pragma GCC diagnostic ignored "-Wunused-variable" 22 | #endif 23 | 24 | #define Array(T) \ 25 | struct { \ 26 | T *contents; \ 27 | uint32_t size; \ 28 | uint32_t capacity; \ 29 | } 30 | 31 | /// Initialize an array. 32 | #define array_init(self) \ 33 | ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) 34 | 35 | /// Create an empty array. 36 | #define array_new() \ 37 | { NULL, 0, 0 } 38 | 39 | /// Get a pointer to the element at a given `index` in the array. 40 | #define array_get(self, _index) \ 41 | (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) 42 | 43 | /// Get a pointer to the first element in the array. 44 | #define array_front(self) array_get(self, 0) 45 | 46 | /// Get a pointer to the last element in the array. 47 | #define array_back(self) array_get(self, (self)->size - 1) 48 | 49 | /// Clear the array, setting its size to zero. Note that this does not free any 50 | /// memory allocated for the array's contents. 51 | #define array_clear(self) ((self)->size = 0) 52 | 53 | /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is 54 | /// less than the array's current capacity, this function has no effect. 55 | #define array_reserve(self, new_capacity) \ 56 | _array__reserve((Array *)(self), array_elem_size(self), new_capacity) 57 | 58 | /// Free any memory allocated for this array. Note that this does not free any 59 | /// memory allocated for the array's contents. 60 | #define array_delete(self) _array__delete((Array *)(self)) 61 | 62 | /// Push a new `element` onto the end of the array. 63 | #define array_push(self, element) \ 64 | (_array__grow((Array *)(self), 1, array_elem_size(self)), \ 65 | (self)->contents[(self)->size++] = (element)) 66 | 67 | /// Increase the array's size by `count` elements. 68 | /// New elements are zero-initialized. 69 | #define array_grow_by(self, count) \ 70 | do { \ 71 | if ((count) == 0) break; \ 72 | _array__grow((Array *)(self), count, array_elem_size(self)); \ 73 | memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ 74 | (self)->size += (count); \ 75 | } while (0) 76 | 77 | /// Append all elements from one array to the end of another. 78 | #define array_push_all(self, other) \ 79 | array_extend((self), (other)->size, (other)->contents) 80 | 81 | /// Append `count` elements to the end of the array, reading their values from the 82 | /// `contents` pointer. 83 | #define array_extend(self, count, contents) \ 84 | _array__splice( \ 85 | (Array *)(self), array_elem_size(self), (self)->size, \ 86 | 0, count, contents \ 87 | ) 88 | 89 | /// Remove `old_count` elements from the array starting at the given `index`. At 90 | /// the same index, insert `new_count` new elements, reading their values from the 91 | /// `new_contents` pointer. 92 | #define array_splice(self, _index, old_count, new_count, new_contents) \ 93 | _array__splice( \ 94 | (Array *)(self), array_elem_size(self), _index, \ 95 | old_count, new_count, new_contents \ 96 | ) 97 | 98 | /// Insert one `element` into the array at the given `index`. 99 | #define array_insert(self, _index, element) \ 100 | _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element)) 101 | 102 | /// Remove one element from the array at the given `index`. 103 | #define array_erase(self, _index) \ 104 | _array__erase((Array *)(self), array_elem_size(self), _index) 105 | 106 | /// Pop the last element off the array, returning the element by value. 107 | #define array_pop(self) ((self)->contents[--(self)->size]) 108 | 109 | /// Assign the contents of one array to another, reallocating if necessary. 110 | #define array_assign(self, other) \ 111 | _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self)) 112 | 113 | /// Swap one array with another 114 | #define array_swap(self, other) \ 115 | _array__swap((Array *)(self), (Array *)(other)) 116 | 117 | /// Get the size of the array contents 118 | #define array_elem_size(self) (sizeof *(self)->contents) 119 | 120 | /// Search a sorted array for a given `needle` value, using the given `compare` 121 | /// callback to determine the order. 122 | /// 123 | /// If an existing element is found to be equal to `needle`, then the `index` 124 | /// out-parameter is set to the existing value's index, and the `exists` 125 | /// out-parameter is set to true. Otherwise, `index` is set to an index where 126 | /// `needle` should be inserted in order to preserve the sorting, and `exists` 127 | /// is set to false. 128 | #define array_search_sorted_with(self, compare, needle, _index, _exists) \ 129 | _array__search_sorted(self, 0, compare, , needle, _index, _exists) 130 | 131 | /// Search a sorted array for a given `needle` value, using integer comparisons 132 | /// of a given struct field (specified with a leading dot) to determine the order. 133 | /// 134 | /// See also `array_search_sorted_with`. 135 | #define array_search_sorted_by(self, field, needle, _index, _exists) \ 136 | _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) 137 | 138 | /// Insert a given `value` into a sorted array, using the given `compare` 139 | /// callback to determine the order. 140 | #define array_insert_sorted_with(self, compare, value) \ 141 | do { \ 142 | unsigned _index, _exists; \ 143 | array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ 144 | if (!_exists) array_insert(self, _index, value); \ 145 | } while (0) 146 | 147 | /// Insert a given `value` into a sorted array, using integer comparisons of 148 | /// a given struct field (specified with a leading dot) to determine the order. 149 | /// 150 | /// See also `array_search_sorted_by`. 151 | #define array_insert_sorted_by(self, field, value) \ 152 | do { \ 153 | unsigned _index, _exists; \ 154 | array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ 155 | if (!_exists) array_insert(self, _index, value); \ 156 | } while (0) 157 | 158 | // Private 159 | 160 | typedef Array(void) Array; 161 | 162 | /// This is not what you're looking for, see `array_delete`. 163 | static inline void _array__delete(Array *self) { 164 | if (self->contents) { 165 | ts_free(self->contents); 166 | self->contents = NULL; 167 | self->size = 0; 168 | self->capacity = 0; 169 | } 170 | } 171 | 172 | /// This is not what you're looking for, see `array_erase`. 173 | static inline void _array__erase(Array *self, size_t element_size, 174 | uint32_t index) { 175 | assert(index < self->size); 176 | char *contents = (char *)self->contents; 177 | memmove(contents + index * element_size, contents + (index + 1) * element_size, 178 | (self->size - index - 1) * element_size); 179 | self->size--; 180 | } 181 | 182 | /// This is not what you're looking for, see `array_reserve`. 183 | static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) { 184 | if (new_capacity > self->capacity) { 185 | if (self->contents) { 186 | self->contents = ts_realloc(self->contents, new_capacity * element_size); 187 | } else { 188 | self->contents = ts_malloc(new_capacity * element_size); 189 | } 190 | self->capacity = new_capacity; 191 | } 192 | } 193 | 194 | /// This is not what you're looking for, see `array_assign`. 195 | static inline void _array__assign(Array *self, const Array *other, size_t element_size) { 196 | _array__reserve(self, element_size, other->size); 197 | self->size = other->size; 198 | memcpy(self->contents, other->contents, self->size * element_size); 199 | } 200 | 201 | /// This is not what you're looking for, see `array_swap`. 202 | static inline void _array__swap(Array *self, Array *other) { 203 | Array swap = *other; 204 | *other = *self; 205 | *self = swap; 206 | } 207 | 208 | /// This is not what you're looking for, see `array_push` or `array_grow_by`. 209 | static inline void _array__grow(Array *self, uint32_t count, size_t element_size) { 210 | uint32_t new_size = self->size + count; 211 | if (new_size > self->capacity) { 212 | uint32_t new_capacity = self->capacity * 2; 213 | if (new_capacity < 8) new_capacity = 8; 214 | if (new_capacity < new_size) new_capacity = new_size; 215 | _array__reserve(self, element_size, new_capacity); 216 | } 217 | } 218 | 219 | /// This is not what you're looking for, see `array_splice`. 220 | static inline void _array__splice(Array *self, size_t element_size, 221 | uint32_t index, uint32_t old_count, 222 | uint32_t new_count, const void *elements) { 223 | uint32_t new_size = self->size + new_count - old_count; 224 | uint32_t old_end = index + old_count; 225 | uint32_t new_end = index + new_count; 226 | assert(old_end <= self->size); 227 | 228 | _array__reserve(self, element_size, new_size); 229 | 230 | char *contents = (char *)self->contents; 231 | if (self->size > old_end) { 232 | memmove( 233 | contents + new_end * element_size, 234 | contents + old_end * element_size, 235 | (self->size - old_end) * element_size 236 | ); 237 | } 238 | if (new_count > 0) { 239 | if (elements) { 240 | memcpy( 241 | (contents + index * element_size), 242 | elements, 243 | new_count * element_size 244 | ); 245 | } else { 246 | memset( 247 | (contents + index * element_size), 248 | 0, 249 | new_count * element_size 250 | ); 251 | } 252 | } 253 | self->size += new_count - old_count; 254 | } 255 | 256 | /// A binary search routine, based on Rust's `std::slice::binary_search_by`. 257 | /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. 258 | #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ 259 | do { \ 260 | *(_index) = start; \ 261 | *(_exists) = false; \ 262 | uint32_t size = (self)->size - *(_index); \ 263 | if (size == 0) break; \ 264 | int comparison; \ 265 | while (size > 1) { \ 266 | uint32_t half_size = size / 2; \ 267 | uint32_t mid_index = *(_index) + half_size; \ 268 | comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ 269 | if (comparison <= 0) *(_index) = mid_index; \ 270 | size -= half_size; \ 271 | } \ 272 | comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ 273 | if (comparison == 0) *(_exists) = true; \ 274 | else if (comparison < 0) *(_index) += 1; \ 275 | } while (0) 276 | 277 | /// Helper macro for the `_sorted_by` routines below. This takes the left (existing) 278 | /// parameter by reference in order to work with the generic sorting function above. 279 | #define _compare_int(a, b) ((int)*(a) - (int)(b)) 280 | 281 | #ifdef _MSC_VER 282 | #pragma warning(pop) 283 | #elif defined(__GNUC__) || defined(__clang__) 284 | #pragma GCC diagnostic pop 285 | #endif 286 | 287 | #ifdef __cplusplus 288 | } 289 | #endif 290 | 291 | #endif // TREE_SITTER_ARRAY_H_ 292 | -------------------------------------------------------------------------------- /dialects/helm/src/tree_sitter/array.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ARRAY_H_ 2 | #define TREE_SITTER_ARRAY_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "./alloc.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef _MSC_VER 17 | #pragma warning(push) 18 | #pragma warning(disable : 4101) 19 | #elif defined(__GNUC__) || defined(__clang__) 20 | #pragma GCC diagnostic push 21 | #pragma GCC diagnostic ignored "-Wunused-variable" 22 | #endif 23 | 24 | #define Array(T) \ 25 | struct { \ 26 | T *contents; \ 27 | uint32_t size; \ 28 | uint32_t capacity; \ 29 | } 30 | 31 | /// Initialize an array. 32 | #define array_init(self) \ 33 | ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) 34 | 35 | /// Create an empty array. 36 | #define array_new() \ 37 | { NULL, 0, 0 } 38 | 39 | /// Get a pointer to the element at a given `index` in the array. 40 | #define array_get(self, _index) \ 41 | (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) 42 | 43 | /// Get a pointer to the first element in the array. 44 | #define array_front(self) array_get(self, 0) 45 | 46 | /// Get a pointer to the last element in the array. 47 | #define array_back(self) array_get(self, (self)->size - 1) 48 | 49 | /// Clear the array, setting its size to zero. Note that this does not free any 50 | /// memory allocated for the array's contents. 51 | #define array_clear(self) ((self)->size = 0) 52 | 53 | /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is 54 | /// less than the array's current capacity, this function has no effect. 55 | #define array_reserve(self, new_capacity) \ 56 | _array__reserve((Array *)(self), array_elem_size(self), new_capacity) 57 | 58 | /// Free any memory allocated for this array. Note that this does not free any 59 | /// memory allocated for the array's contents. 60 | #define array_delete(self) _array__delete((Array *)(self)) 61 | 62 | /// Push a new `element` onto the end of the array. 63 | #define array_push(self, element) \ 64 | (_array__grow((Array *)(self), 1, array_elem_size(self)), \ 65 | (self)->contents[(self)->size++] = (element)) 66 | 67 | /// Increase the array's size by `count` elements. 68 | /// New elements are zero-initialized. 69 | #define array_grow_by(self, count) \ 70 | do { \ 71 | if ((count) == 0) break; \ 72 | _array__grow((Array *)(self), count, array_elem_size(self)); \ 73 | memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ 74 | (self)->size += (count); \ 75 | } while (0) 76 | 77 | /// Append all elements from one array to the end of another. 78 | #define array_push_all(self, other) \ 79 | array_extend((self), (other)->size, (other)->contents) 80 | 81 | /// Append `count` elements to the end of the array, reading their values from the 82 | /// `contents` pointer. 83 | #define array_extend(self, count, contents) \ 84 | _array__splice( \ 85 | (Array *)(self), array_elem_size(self), (self)->size, \ 86 | 0, count, contents \ 87 | ) 88 | 89 | /// Remove `old_count` elements from the array starting at the given `index`. At 90 | /// the same index, insert `new_count` new elements, reading their values from the 91 | /// `new_contents` pointer. 92 | #define array_splice(self, _index, old_count, new_count, new_contents) \ 93 | _array__splice( \ 94 | (Array *)(self), array_elem_size(self), _index, \ 95 | old_count, new_count, new_contents \ 96 | ) 97 | 98 | /// Insert one `element` into the array at the given `index`. 99 | #define array_insert(self, _index, element) \ 100 | _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element)) 101 | 102 | /// Remove one element from the array at the given `index`. 103 | #define array_erase(self, _index) \ 104 | _array__erase((Array *)(self), array_elem_size(self), _index) 105 | 106 | /// Pop the last element off the array, returning the element by value. 107 | #define array_pop(self) ((self)->contents[--(self)->size]) 108 | 109 | /// Assign the contents of one array to another, reallocating if necessary. 110 | #define array_assign(self, other) \ 111 | _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self)) 112 | 113 | /// Swap one array with another 114 | #define array_swap(self, other) \ 115 | _array__swap((Array *)(self), (Array *)(other)) 116 | 117 | /// Get the size of the array contents 118 | #define array_elem_size(self) (sizeof *(self)->contents) 119 | 120 | /// Search a sorted array for a given `needle` value, using the given `compare` 121 | /// callback to determine the order. 122 | /// 123 | /// If an existing element is found to be equal to `needle`, then the `index` 124 | /// out-parameter is set to the existing value's index, and the `exists` 125 | /// out-parameter is set to true. Otherwise, `index` is set to an index where 126 | /// `needle` should be inserted in order to preserve the sorting, and `exists` 127 | /// is set to false. 128 | #define array_search_sorted_with(self, compare, needle, _index, _exists) \ 129 | _array__search_sorted(self, 0, compare, , needle, _index, _exists) 130 | 131 | /// Search a sorted array for a given `needle` value, using integer comparisons 132 | /// of a given struct field (specified with a leading dot) to determine the order. 133 | /// 134 | /// See also `array_search_sorted_with`. 135 | #define array_search_sorted_by(self, field, needle, _index, _exists) \ 136 | _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) 137 | 138 | /// Insert a given `value` into a sorted array, using the given `compare` 139 | /// callback to determine the order. 140 | #define array_insert_sorted_with(self, compare, value) \ 141 | do { \ 142 | unsigned _index, _exists; \ 143 | array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ 144 | if (!_exists) array_insert(self, _index, value); \ 145 | } while (0) 146 | 147 | /// Insert a given `value` into a sorted array, using integer comparisons of 148 | /// a given struct field (specified with a leading dot) to determine the order. 149 | /// 150 | /// See also `array_search_sorted_by`. 151 | #define array_insert_sorted_by(self, field, value) \ 152 | do { \ 153 | unsigned _index, _exists; \ 154 | array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ 155 | if (!_exists) array_insert(self, _index, value); \ 156 | } while (0) 157 | 158 | // Private 159 | 160 | typedef Array(void) Array; 161 | 162 | /// This is not what you're looking for, see `array_delete`. 163 | static inline void _array__delete(Array *self) { 164 | if (self->contents) { 165 | ts_free(self->contents); 166 | self->contents = NULL; 167 | self->size = 0; 168 | self->capacity = 0; 169 | } 170 | } 171 | 172 | /// This is not what you're looking for, see `array_erase`. 173 | static inline void _array__erase(Array *self, size_t element_size, 174 | uint32_t index) { 175 | assert(index < self->size); 176 | char *contents = (char *)self->contents; 177 | memmove(contents + index * element_size, contents + (index + 1) * element_size, 178 | (self->size - index - 1) * element_size); 179 | self->size--; 180 | } 181 | 182 | /// This is not what you're looking for, see `array_reserve`. 183 | static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) { 184 | if (new_capacity > self->capacity) { 185 | if (self->contents) { 186 | self->contents = ts_realloc(self->contents, new_capacity * element_size); 187 | } else { 188 | self->contents = ts_malloc(new_capacity * element_size); 189 | } 190 | self->capacity = new_capacity; 191 | } 192 | } 193 | 194 | /// This is not what you're looking for, see `array_assign`. 195 | static inline void _array__assign(Array *self, const Array *other, size_t element_size) { 196 | _array__reserve(self, element_size, other->size); 197 | self->size = other->size; 198 | memcpy(self->contents, other->contents, self->size * element_size); 199 | } 200 | 201 | /// This is not what you're looking for, see `array_swap`. 202 | static inline void _array__swap(Array *self, Array *other) { 203 | Array swap = *other; 204 | *other = *self; 205 | *self = swap; 206 | } 207 | 208 | /// This is not what you're looking for, see `array_push` or `array_grow_by`. 209 | static inline void _array__grow(Array *self, uint32_t count, size_t element_size) { 210 | uint32_t new_size = self->size + count; 211 | if (new_size > self->capacity) { 212 | uint32_t new_capacity = self->capacity * 2; 213 | if (new_capacity < 8) new_capacity = 8; 214 | if (new_capacity < new_size) new_capacity = new_size; 215 | _array__reserve(self, element_size, new_capacity); 216 | } 217 | } 218 | 219 | /// This is not what you're looking for, see `array_splice`. 220 | static inline void _array__splice(Array *self, size_t element_size, 221 | uint32_t index, uint32_t old_count, 222 | uint32_t new_count, const void *elements) { 223 | uint32_t new_size = self->size + new_count - old_count; 224 | uint32_t old_end = index + old_count; 225 | uint32_t new_end = index + new_count; 226 | assert(old_end <= self->size); 227 | 228 | _array__reserve(self, element_size, new_size); 229 | 230 | char *contents = (char *)self->contents; 231 | if (self->size > old_end) { 232 | memmove( 233 | contents + new_end * element_size, 234 | contents + old_end * element_size, 235 | (self->size - old_end) * element_size 236 | ); 237 | } 238 | if (new_count > 0) { 239 | if (elements) { 240 | memcpy( 241 | (contents + index * element_size), 242 | elements, 243 | new_count * element_size 244 | ); 245 | } else { 246 | memset( 247 | (contents + index * element_size), 248 | 0, 249 | new_count * element_size 250 | ); 251 | } 252 | } 253 | self->size += new_count - old_count; 254 | } 255 | 256 | /// A binary search routine, based on Rust's `std::slice::binary_search_by`. 257 | /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. 258 | #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ 259 | do { \ 260 | *(_index) = start; \ 261 | *(_exists) = false; \ 262 | uint32_t size = (self)->size - *(_index); \ 263 | if (size == 0) break; \ 264 | int comparison; \ 265 | while (size > 1) { \ 266 | uint32_t half_size = size / 2; \ 267 | uint32_t mid_index = *(_index) + half_size; \ 268 | comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ 269 | if (comparison <= 0) *(_index) = mid_index; \ 270 | size -= half_size; \ 271 | } \ 272 | comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ 273 | if (comparison == 0) *(_exists) = true; \ 274 | else if (comparison < 0) *(_index) += 1; \ 275 | } while (0) 276 | 277 | /// Helper macro for the `_sorted_by` routines below. This takes the left (existing) 278 | /// parameter by reference in order to work with the generic sorting function above. 279 | #define _compare_int(a, b) ((int)*(a) - (int)(b)) 280 | 281 | #ifdef _MSC_VER 282 | #pragma warning(pop) 283 | #elif defined(__GNUC__) || defined(__clang__) 284 | #pragma GCC diagnostic pop 285 | #endif 286 | 287 | #ifdef __cplusplus 288 | } 289 | #endif 290 | 291 | #endif // TREE_SITTER_ARRAY_H_ 292 | -------------------------------------------------------------------------------- /test/corpus/actions.txt: -------------------------------------------------------------------------------- 1 | ============================================ 2 | comment 3 | ============================================ 4 | {{/* comment */}} 5 | {{- /* comment */ -}} 6 | {{/* comment */ -}} 7 | {{- /* comment */}} 8 | {{/* multi 9 | line 10 | comment */}} 11 | {{- /* multi 12 | line 13 | comment */ -}} 14 | --- 15 | 16 | (template 17 | (comment) 18 | (text) 19 | (comment) 20 | (text) 21 | (comment) 22 | (text) 23 | (comment) 24 | (text) 25 | (comment) 26 | (text) 27 | (comment)) 28 | 29 | ============================================ 30 | invalid comment - space after opening delimiter 31 | ============================================ 32 | 33 | {{ /* invalid comment */}} 34 | --- 35 | 36 | (template 37 | (text) 38 | (ERROR 39 | (ERROR 40 | (UNEXPECTED '/')) 41 | (function_call 42 | (identifier) 43 | (argument_list 44 | (function_call 45 | (identifier)))) 46 | (UNEXPECTED '*'))) 47 | 48 | ============================================ 49 | invalid comment - space before closing delimiter 50 | ============================================ 51 | 52 | {{/* invalid comment */ }} 53 | --- 54 | 55 | (template 56 | (text) 57 | (comment) 58 | (ERROR)) 59 | 60 | ============================================ 61 | invalid comment - no space after {{- 62 | ============================================ 63 | 64 | {{-/* invalid comment */ -}} 65 | --- 66 | 67 | (template 68 | (text) 69 | (ERROR 70 | (yaml_no_injection_text)) 71 | (comment)) 72 | 73 | ============================================ 74 | invalid comment - no space before -}} 75 | ============================================ 76 | 77 | {{- /* invalid comment */-}} 78 | --- 79 | 80 | (template 81 | (text) 82 | (comment) 83 | (ERROR 84 | (yaml_no_injection_text))) 85 | 86 | ============================================ 87 | invalid comment - newline and space after {{- 88 | ============================================ 89 | 90 | {{- 91 | /* invalid comment */ -}} 92 | --- 93 | 94 | (template 95 | (text) 96 | (ERROR 97 | (ERROR 98 | (UNEXPECTED '/')) 99 | (function_call 100 | (identifier) 101 | (argument_list 102 | (function_call 103 | (identifier)))) 104 | (UNEXPECTED '*')) 105 | (text)) 106 | 107 | ============================================ 108 | invalid comment - newline and space before -}} 109 | ============================================ 110 | 111 | {{- /* invalid comment */ 112 | -}} 113 | --- 114 | 115 | (template 116 | (text) 117 | (comment) 118 | (MISSING "-}}") 119 | (text)) 120 | 121 | ============================================ 122 | valid comment - exactly one newline after {{- 123 | ============================================ 124 | 125 | {{- 126 | /* valid comment */ -}} 127 | --- 128 | 129 | (template 130 | (text) 131 | (comment)) 132 | 133 | ============================================ 134 | valid comment - exactly one newline before -}} 135 | ============================================ 136 | 137 | {{- /* valid comment */ 138 | -}} 139 | --- 140 | 141 | (template 142 | (text) 143 | (comment)) 144 | 145 | ============================================ 146 | pipeline 147 | ============================================ 148 | {{ pipeline }} 149 | --- 150 | 151 | (template 152 | (function_call (identifier))) 153 | 154 | ============================================ 155 | pipeline with leading whitespace trimming 156 | ============================================ 157 | {{- pipeline }} 158 | --- 159 | 160 | (template 161 | (function_call (identifier))) 162 | 163 | ============================================= 164 | if 165 | ============================================= 166 | {{if pipeline}} t1 {{end}} 167 | --- 168 | (template 169 | (if_action 170 | (function_call (identifier)) 171 | (text))) 172 | 173 | ============================================= 174 | if with leading whitespace trimming 175 | ============================================= 176 | {{- if pipeline }} t1 {{end}} 177 | --- 178 | (template 179 | (if_action 180 | (function_call (identifier)) 181 | (text))) 182 | 183 | ============================================= 184 | if with leading whitespace trimming and newline 185 | ============================================= 186 | {{- 187 | if pipeline }} t1 {{end}} 188 | --- 189 | (template 190 | (if_action 191 | (function_call (identifier)) 192 | (text))) 193 | 194 | ============================================= 195 | if else 196 | ============================================= 197 | {{if pipeline}} t1 {{ else }} t2 {{ end }} 198 | --- 199 | (template 200 | (if_action 201 | (function_call (identifier)) 202 | (text) 203 | (text))) 204 | 205 | ============================================= 206 | if else with text and template in if 207 | ============================================= 208 | {{if pipeline}} t1 {{ pipeline }} {{ else }} t2 {{ end }} 209 | --- 210 | (template 211 | (if_action 212 | (function_call (identifier)) 213 | (text) 214 | (function_call (identifier)) 215 | (text) 216 | (text))) 217 | 218 | ============================================= 219 | if-else 220 | ============================================= 221 | {{if pipeline}} t1 {{ else if pipeline }} t2 {{ end }} 222 | --- 223 | (template 224 | (if_action 225 | (function_call (identifier)) 226 | (text) 227 | (function_call (identifier)) 228 | (text))) 229 | 230 | ============================================= 231 | if-else with text and template in if 232 | ============================================= 233 | {{if pipeline}} t1 {{ pipeline }} {{ else if pipeline }} t2 {{ end }} 234 | --- 235 | (template 236 | (if_action 237 | (function_call (identifier)) 238 | (text) 239 | (function_call (identifier)) 240 | (text) 241 | (function_call (identifier)) 242 | (text))) 243 | 244 | ============================================= 245 | if-else else 246 | ============================================= 247 | {{if pipeline}} t1 {{ else if pipeline }} t2 {{ else }} t3 {{ end }} 248 | --- 249 | (template 250 | (if_action 251 | (function_call (identifier)) 252 | (text) 253 | (function_call (identifier)) 254 | (text) 255 | (text))) 256 | 257 | ============================================= 258 | if-else else with template and text in else 259 | ============================================= 260 | {{if pipeline}} t1 {{ else if pipeline }} t2 {{ else }} {{ .Values.test }} test {{ end }} 261 | --- 262 | (template 263 | (if_action 264 | (function_call (identifier)) 265 | (text) 266 | (function_call (identifier)) 267 | (text) 268 | (text) 269 | (selector_expression 270 | (field 271 | (identifier)) 272 | (field_identifier)) 273 | (text))) 274 | 275 | ============================================= 276 | if-else else with text and template in else 277 | ============================================= 278 | {{if pipeline}} t1 {{ else if pipeline }} t2 {{ else }} test {{ .Values.test }} {{ end }} 279 | --- 280 | (template 281 | (if_action 282 | (function_call (identifier)) 283 | (text) 284 | (function_call (identifier)) 285 | (text) 286 | (text) 287 | (selector_expression 288 | (field 289 | (identifier)) 290 | (field_identifier)) 291 | (text))) 292 | 293 | ============================================= 294 | if-else else with text and template in if-else 295 | ============================================= 296 | {{if pipeline}} t1 {{ else if pipeline }} test {{ .Values.test }} {{ else }} t3 {{ end }} 297 | --- 298 | (template 299 | (if_action 300 | (function_call (identifier)) 301 | (text) 302 | (function_call (identifier)) 303 | (text) 304 | (selector_expression 305 | (field 306 | (identifier)) 307 | (field_identifier)) 308 | (text) 309 | (text))) 310 | 311 | ============================================= 312 | if-else else with text and template in else and text and template in if-else 313 | ============================================= 314 | {{if pipeline}} t1 {{ else if pipeline }} test {{ .Values.test }} {{ else }} t3 {{ .Values.test }} {{ end }} 315 | --- 316 | (template 317 | (if_action 318 | (function_call (identifier)) 319 | (text) 320 | (function_call (identifier)) 321 | (text) 322 | (selector_expression 323 | (field 324 | (identifier)) 325 | (field_identifier)) 326 | (text) 327 | (text) 328 | (selector_expression 329 | (field 330 | (identifier)) 331 | (field_identifier)) 332 | (text))) 333 | 334 | ============================================= 335 | if-else with text and template in if-else 336 | ============================================= 337 | {{if pipeline}} t1 {{ else if pipeline }} test {{ .Values.test }} {{ end }} 338 | --- 339 | (template 340 | (if_action 341 | (function_call (identifier)) 342 | (text) 343 | (function_call (identifier)) 344 | (text) 345 | (selector_expression 346 | (field 347 | (identifier)) 348 | (field_identifier)) 349 | (text))) 350 | 351 | ============================================= 352 | range 353 | ============================================= 354 | {{range pipeline}} t1 {{ end }} 355 | --- 356 | (template 357 | (range_action 358 | (function_call (identifier)) 359 | (text))) 360 | 361 | ============================================= 362 | range else 363 | ============================================= 364 | {{range pipeline}} t1 {{ else }} t2 {{ end }} 365 | --- 366 | (template 367 | (range_action 368 | (function_call (identifier)) 369 | (text) 370 | (text))) 371 | 372 | ============================================= 373 | range break 374 | ============================================= 375 | {{range pipeline}} {{break}} {{ end }} 376 | --- 377 | (template 378 | (range_action 379 | (function_call (identifier)) 380 | (text) 381 | (break_action) 382 | (text))) 383 | 384 | ============================================= 385 | range continue 386 | ============================================= 387 | {{range pipeline}} {{continue}} {{ end }} 388 | --- 389 | (template 390 | (range_action 391 | (function_call (identifier)) 392 | (text) 393 | (continue_action) 394 | (text))) 395 | 396 | ============================================= 397 | template 398 | ============================================= 399 | {{template "name"}} 400 | --- 401 | (template 402 | (template_action 403 | (interpreted_string_literal))) 404 | 405 | ============================================= 406 | template with argument 407 | ============================================= 408 | {{template "name" pipeline}} 409 | --- 410 | (template 411 | (template_action 412 | (interpreted_string_literal) 413 | (function_call (identifier)))) 414 | 415 | ============================================= 416 | define 417 | ============================================= 418 | {{define "name"}} t1 {{ end }} 419 | --- 420 | (template 421 | (define_action 422 | (interpreted_string_literal) 423 | (text))) 424 | 425 | ============================================= 426 | invalid block (missing pipeline) 427 | ============================================= 428 | {{block "name"}} T1 {{end}} 429 | --- 430 | 431 | (template 432 | (block_action 433 | (interpreted_string_literal) 434 | (dot 435 | (MISSING ".")) 436 | (text))) 437 | 438 | ============================================= 439 | block with argument 440 | ============================================= 441 | {{block "name" pipeline }} T1 {{end}} 442 | --- 443 | 444 | (template 445 | (block_action 446 | (interpreted_string_literal) 447 | (function_call 448 | (identifier)) 449 | (text))) 450 | 451 | ============================================= 452 | with 453 | ============================================= 454 | {{with pipeline}} T1 {{end}} 455 | --- 456 | 457 | (template 458 | (with_action 459 | (function_call 460 | (identifier)) 461 | (text))) 462 | 463 | ============================================= 464 | with else 465 | ============================================= 466 | {{with pipeline}} T1 {{else}} T0 {{end}} 467 | --- 468 | 469 | (template 470 | (with_action 471 | (function_call 472 | (identifier)) 473 | (text) 474 | (text))) 475 | 476 | ============================================= 477 | with else with 478 | ============================================= 479 | {{with pipeline}} T2 {{else with pipeline}} T1 {{else}} T0 {{end}} 480 | --- 481 | 482 | (template 483 | (with_action 484 | (function_call 485 | (identifier)) 486 | (text) 487 | (function_call 488 | (identifier)) 489 | (text) 490 | (text))) 491 | 492 | ============================================= 493 | with else with text and template in with 494 | ============================================= 495 | {{with pipeline}} t1 {{ pipeline }} {{ else }} t2 {{ end }} 496 | --- 497 | (template 498 | (with_action 499 | (function_call (identifier)) 500 | (text) 501 | (function_call (identifier)) 502 | (text) 503 | (text))) 504 | 505 | ============================================= 506 | with-else with text and template in with 507 | ============================================= 508 | {{with pipeline}} t1 {{ pipeline }} {{ else with pipeline }} t2 {{ end }} 509 | --- 510 | (template 511 | (with_action 512 | (function_call (identifier)) 513 | (text) 514 | (function_call (identifier)) 515 | (text) 516 | (function_call (identifier)) 517 | (text))) 518 | 519 | ============================================= 520 | with-else else with template and text in else 521 | ============================================= 522 | {{with pipeline}} t1 {{ else with pipeline }} t2 {{ else }} {{ .Values.test }} test {{ end }} 523 | --- 524 | (template 525 | (with_action 526 | (function_call (identifier)) 527 | (text) 528 | (function_call (identifier)) 529 | (text) 530 | (text) 531 | (selector_expression 532 | (field 533 | (identifier)) 534 | (field_identifier)) 535 | (text))) 536 | 537 | ============================================= 538 | with-else else with text and template in else 539 | ============================================= 540 | {{with pipeline}} t1 {{ else with pipeline }} t2 {{ else }} test {{ .Values.test }} {{ end }} 541 | --- 542 | (template 543 | (with_action 544 | (function_call (identifier)) 545 | (text) 546 | (function_call (identifier)) 547 | (text) 548 | (text) 549 | (selector_expression 550 | (field 551 | (identifier)) 552 | (field_identifier)) 553 | (text))) 554 | 555 | ============================================= 556 | with-else else with text and template in with-else 557 | ============================================= 558 | {{with pipeline}} t1 {{ else with pipeline }} test {{ .Values.test }} {{ else }} t3 {{ end }} 559 | --- 560 | (template 561 | (with_action 562 | (function_call (identifier)) 563 | (text) 564 | (function_call (identifier)) 565 | (text) 566 | (selector_expression 567 | (field 568 | (identifier)) 569 | (field_identifier)) 570 | (text) 571 | (text))) 572 | 573 | ============================================= 574 | with-else else with text and template in else and text and template in with-else 575 | ============================================= 576 | {{with pipeline}} t1 {{ else with pipeline }} test {{ .Values.test }} {{ else }} t3 {{ .Values.test }} {{ end }} 577 | --- 578 | (template 579 | (with_action 580 | (function_call (identifier)) 581 | (text) 582 | (function_call (identifier)) 583 | (text) 584 | (selector_expression 585 | (field 586 | (identifier)) 587 | (field_identifier)) 588 | (text) 589 | (text) 590 | (selector_expression 591 | (field 592 | (identifier)) 593 | (field_identifier)) 594 | (text))) 595 | 596 | ============================================= 597 | with-else with text and template in with-else 598 | ============================================= 599 | {{with pipeline}} t1 {{ else with pipeline }} test {{ .Values.test }} {{ end }} 600 | --- 601 | (template 602 | (with_action 603 | (function_call (identifier)) 604 | (text) 605 | (function_call (identifier)) 606 | (text) 607 | (selector_expression 608 | (field 609 | (identifier)) 610 | (field_identifier)) 611 | (text))) 612 | -------------------------------------------------------------------------------- /make_grammar.js: -------------------------------------------------------------------------------- 1 | const PREC = { 2 | primary: 1, 3 | else_if: 1, 4 | else_with: 1, 5 | else: 2, 6 | }, 7 | unicodeLetter = /\p{L}/, 8 | unicodeDigit = /[0-9]/, 9 | letter = choice(unicodeLetter, '_'), 10 | hexDigit = /[0-9a-fA-F]/, 11 | octalDigit = /[0-7]/, 12 | decimalDigit = /[0-9]/, 13 | binaryDigit = /[01]/, 14 | hexDigits = seq(hexDigit, repeat(seq(optional('_'), hexDigit))), 15 | octalDigits = seq(octalDigit, repeat(seq(optional('_'), octalDigit))), 16 | decimalDigits = seq(decimalDigit, repeat(seq(optional('_'), decimalDigit))), 17 | binaryDigits = seq(binaryDigit, repeat(seq(optional('_'), binaryDigit))), 18 | hexLiteral = seq('0', choice('x', 'X'), optional('_'), hexDigits), 19 | octalLiteral = seq( 20 | '0', 21 | optional(choice('o', 'O')), 22 | optional('_'), 23 | octalDigits 24 | ), 25 | decimalLiteral = choice( 26 | '0', 27 | seq(/[1-9]/, optional(seq(optional('_'), decimalDigits))) 28 | ), 29 | binaryLiteral = seq('0', choice('b', 'B'), optional('_'), binaryDigits), 30 | intLiteral = seq( 31 | optional(choice('-', '+')), 32 | choice(binaryLiteral, decimalLiteral, octalLiteral, hexLiteral) 33 | ), 34 | decimalExponent = seq( 35 | choice('e', 'E'), 36 | optional(choice('+', '-')), 37 | decimalDigits 38 | ), 39 | decimalFloatLiteral = choice( 40 | seq( 41 | decimalDigits, 42 | '.', 43 | optional(decimalDigits), 44 | optional(decimalExponent) 45 | ), 46 | seq(decimalDigits, decimalExponent), 47 | seq('.', decimalDigits, optional(decimalExponent)) 48 | ), 49 | hexExponent = seq( 50 | choice('p', 'P'), 51 | optional(choice('+', '-')), 52 | decimalDigits 53 | ), 54 | hexMantissa = choice( 55 | seq(optional('_'), hexDigits, '.', optional(hexDigits)), 56 | seq(optional('_'), hexDigits), 57 | seq('.', hexDigits) 58 | ), 59 | hexFloatLiteral = seq( 60 | optional(choice('-', '+')), 61 | '0', 62 | choice('x', 'X'), 63 | hexMantissa, 64 | hexExponent 65 | ), 66 | floatLiteral = seq( 67 | optional(choice('-', '+')), 68 | choice(decimalFloatLiteral, hexFloatLiteral) 69 | ), 70 | imaginaryLiteral = seq( 71 | choice( 72 | seq(optional(choice('-', '+')), decimalDigits), 73 | intLiteral, 74 | floatLiteral 75 | ), 76 | 'i' 77 | ) 78 | 79 | module.exports = function make_grammar(dialect) { 80 | return grammar({ 81 | name: dialect, 82 | conflicts: ($) => [ 83 | // conflict between a template in an else if clause and the beginning of the 84 | // else clause in not solveable with LR(1) 85 | [$._else_clause], 86 | [$._else_if_clause], 87 | [$._else_with_clause], 88 | ], 89 | rules: { 90 | template: ($) => repeat($._block), 91 | 92 | _block: ($) => choice($.yaml_no_injection_text, $.text, $._action), 93 | 94 | // This rule is a workaround to fix https://github.com/ngalaiko/tree-sitter-go-template/issues/23 95 | // by creating a new node type that is not used for injections of the yaml language. 96 | // The better solution would be to fix the issue in the yaml grammar. 97 | // If https://github.com/tree-sitter-grammars/tree-sitter-yaml/issues/12 is resolved, this rule can be removed. 98 | yaml_no_injection_text: (_) => '-', 99 | 100 | text: (_) => 101 | choice( 102 | // forbid '{{', the rest is valid 103 | /[^{]+/, 104 | /\{/ 105 | ), 106 | 107 | _action: ($) => 108 | prec( 109 | 2, 110 | choice( 111 | $._comment_action, 112 | $._pipeline_action, 113 | $.if_action, 114 | $.range_action, 115 | $.break_action, 116 | $.continue_action, 117 | $.template_action, 118 | $.define_action, 119 | $.block_action, 120 | $.with_action 121 | ) 122 | ), 123 | 124 | _action_end: ($) => 125 | seq($._left_delimiter, 'end', $._right_delimiter), 126 | 127 | _comment_action: ($) => 128 | seq( 129 | $._left_delimiter, 130 | $.comment, 131 | choice( 132 | token.immediate('}}'), 133 | seq(token.immediate(/\s/), token.immediate('-}}')) 134 | ) 135 | ), 136 | 137 | _pipeline_action: ($) => 138 | seq($._left_delimiter, $._pipeline, $._right_delimiter), 139 | 140 | if_action: ($) => 141 | seq( 142 | $._left_delimiter, 143 | 'if', 144 | field('condition', $._pipeline), 145 | $._right_delimiter, 146 | 147 | field('consequence', repeat($._block)), 148 | 149 | repeat($._else_if_clause), 150 | 151 | optional($._else_clause), 152 | prec.right(0, $._action_end) 153 | ), 154 | 155 | _else_if_clause: ($) => 156 | prec.dynamic( 157 | PREC.else_if, 158 | seq( 159 | $._left_delimiter, 160 | 'else', 161 | 'if', 162 | field('condition', $._pipeline), 163 | $._right_delimiter, 164 | field('option', repeat($._block)) 165 | ) 166 | ), 167 | 168 | _else_clause: ($) => 169 | prec.dynamic( 170 | PREC.else, 171 | seq( 172 | $._left_delimiter, 173 | 'else', 174 | $._right_delimiter, 175 | field('alternative', repeat($._block)) 176 | ) 177 | ), 178 | 179 | _else_with_clause: ($) => 180 | prec.dynamic( 181 | PREC.else_with, 182 | seq( 183 | $._left_delimiter, 184 | 'else', 185 | 'with', 186 | field('condition', $._pipeline), 187 | $._right_delimiter, 188 | field('option', repeat($._block)) 189 | ) 190 | ), 191 | 192 | range_variable_definition: ($) => 193 | seq( 194 | field('index', $.variable), 195 | ',', 196 | field('element', $.variable), 197 | token(':='), 198 | field('range', $._pipeline) 199 | ), 200 | 201 | range_action: ($) => 202 | seq( 203 | $._left_delimiter, 204 | 'range', 205 | choice( 206 | $.range_variable_definition, 207 | field('range', $._pipeline) 208 | ), 209 | $._right_delimiter, 210 | 211 | field('body', repeat($._block)), 212 | 213 | optional( 214 | seq( 215 | $._left_delimiter, 216 | 'else', 217 | $._right_delimiter, 218 | field('alternative', repeat($._block)) 219 | ) 220 | ), 221 | 222 | $._left_delimiter, 223 | 'end', 224 | $._right_delimiter 225 | ), 226 | 227 | break_action: ($) => 228 | seq($._left_delimiter, 'break', $._right_delimiter), 229 | 230 | continue_action: ($) => 231 | seq($._left_delimiter, 'continue', $._right_delimiter), 232 | 233 | template_action: ($) => 234 | seq( 235 | $._left_delimiter, 236 | 'template', 237 | field('name', $._string_literal), 238 | optional(field('argument', $._pipeline)), 239 | $._right_delimiter 240 | ), 241 | 242 | define_action: ($) => 243 | seq( 244 | $._left_delimiter, 245 | 'define', 246 | field('name', $._string_literal), 247 | $._right_delimiter, 248 | 249 | field('body', repeat($._block)), 250 | 251 | $._left_delimiter, 252 | 'end', 253 | $._right_delimiter 254 | ), 255 | 256 | block_action: ($) => 257 | seq( 258 | $._left_delimiter, 259 | 'block', 260 | field('name', $._string_literal), 261 | field('argument', $._pipeline), 262 | $._right_delimiter, 263 | 264 | field('body', repeat($._block)), 265 | 266 | $._left_delimiter, 267 | 'end', 268 | $._right_delimiter 269 | ), 270 | 271 | with_action: ($) => 272 | seq( 273 | $._left_delimiter, 274 | 'with', 275 | field('condition', $._pipeline), 276 | $._right_delimiter, 277 | 278 | field('consequence', repeat($._block)), 279 | 280 | repeat($._else_with_clause), 281 | 282 | optional($._else_clause), 283 | prec.right(0, $._action_end) 284 | ), 285 | 286 | _pipeline: ($) => 287 | choice( 288 | $._expression, 289 | $.function_call, 290 | $.method_call, 291 | $.chained_pipeline, 292 | $.parenthesized_pipeline, 293 | $.variable_definition, 294 | $.assignment 295 | ), 296 | 297 | variable_definition: ($) => 298 | seq( 299 | field('variable', $.variable), 300 | ':=', 301 | field('value', $._pipeline) 302 | ), 303 | 304 | assignment: ($) => 305 | seq( 306 | field('variable', $.variable), 307 | '=', 308 | field('value', $._pipeline) 309 | ), 310 | 311 | chained_pipeline: ($) => 312 | prec.left(PREC.primary, seq($._pipeline, '|', $._pipeline)), 313 | 314 | parenthesized_pipeline: ($) => seq('(', $._pipeline, ')'), 315 | 316 | method_call: ($) => 317 | seq( 318 | field('method', choice($.field, $.selector_expression)), 319 | field('arguments', $.argument_list) 320 | ), 321 | 322 | function_call: ($) => 323 | prec.right( 324 | PREC.primary, 325 | seq( 326 | field('function', $.identifier), 327 | optional(field('arguments', $.argument_list)) 328 | ) 329 | ), 330 | 331 | argument_list: ($) => 332 | prec.right( 333 | seq( 334 | $._pipeline, 335 | repeat(seq(' ', $._pipeline)), 336 | optional(' ') 337 | ) 338 | ), 339 | 340 | pipeline_stub: (_) => token('pipeline'), 341 | 342 | _expression: ($) => 343 | prec( 344 | PREC.primary, 345 | choice( 346 | $._literal, 347 | $.nil, 348 | $.dot, 349 | $.field, 350 | $.variable, 351 | $.selector_expression 352 | ) 353 | ), 354 | 355 | selector_expression: ($) => 356 | prec( 357 | PREC.primary, 358 | seq( 359 | field( 360 | 'operand', 361 | choice( 362 | $.parenthesized_pipeline, 363 | $.field, 364 | $.variable, 365 | $.selector_expression, 366 | $.identifier 367 | ) 368 | ), 369 | token.immediate('.'), 370 | field('field', $._field_identifier) 371 | ) 372 | ), 373 | 374 | _field_identifier: ($) => alias($.identifier, $.field_identifier), 375 | 376 | field: ($) => seq('.', field('name', $.identifier)), 377 | 378 | variable: ($) => 379 | seq( 380 | '$', 381 | optional( 382 | field( 383 | 'name', 384 | alias( 385 | token(repeat1(choice(letter, unicodeDigit))), 386 | $.identifier 387 | ) 388 | ) 389 | ) 390 | ), 391 | 392 | identifier: (_) => 393 | token(seq(letter, repeat(choice(letter, unicodeDigit)))), 394 | 395 | _literal: ($) => 396 | choice( 397 | $._boolean_literal, 398 | $._string_literal, 399 | $.rune_literal, 400 | $.int_literal, 401 | $.float_literal, 402 | $.imaginary_literal 403 | ), 404 | 405 | int_literal: (_) => token(intLiteral), 406 | 407 | float_literal: (_) => token(floatLiteral), 408 | 409 | imaginary_literal: (_) => token(imaginaryLiteral), 410 | 411 | rune_literal: (_) => 412 | token( 413 | seq( 414 | "'", 415 | choice( 416 | /[^'\\]/, 417 | seq( 418 | '\\', 419 | choice( 420 | seq('x', hexDigit, hexDigit), 421 | seq(octalDigit, octalDigit, octalDigit), 422 | seq( 423 | 'u', 424 | hexDigit, 425 | hexDigit, 426 | hexDigit, 427 | hexDigit 428 | ), 429 | seq( 430 | 'U', 431 | hexDigit, 432 | hexDigit, 433 | hexDigit, 434 | hexDigit, 435 | hexDigit, 436 | hexDigit, 437 | hexDigit, 438 | hexDigit 439 | ), 440 | seq( 441 | choice( 442 | 'a', 443 | 'b', 444 | 'f', 445 | 'n', 446 | 'r', 447 | 't', 448 | 'v', 449 | '\\', 450 | "'", 451 | '"' 452 | ) 453 | ) 454 | ) 455 | ) 456 | ), 457 | "'" 458 | ) 459 | ), 460 | 461 | _boolean_literal: ($) => choice($.true, $.false), 462 | 463 | true: (_) => 'true', 464 | false: (_) => 'false', 465 | 466 | nil: (_) => 'nil', 467 | 468 | dot: (_) => prec(1, '.'), 469 | 470 | _string_literal: ($) => 471 | choice($.raw_string_literal, $.interpreted_string_literal), 472 | 473 | raw_string_literal: (_) => token(seq('`', repeat(/[^`]/), '`')), 474 | 475 | interpreted_string_literal: ($) => 476 | seq( 477 | '"', 478 | repeat( 479 | choice( 480 | token.immediate(prec(1, /[^"\n\\]+/)), 481 | $.escape_sequence 482 | ) 483 | ), 484 | token.immediate('"') 485 | ), 486 | 487 | escape_sequence: (_) => 488 | token.immediate( 489 | seq( 490 | '\\', 491 | choice( 492 | /[^xuU]/, 493 | /\d{2,3}/, 494 | /x[0-9a-fA-F]{2,}/, 495 | /u[0-9a-fA-F]{4}/, 496 | /U[0-9a-fA-F]{8}/ 497 | ) 498 | ) 499 | ), 500 | 501 | // http://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment/36328890#36328890 502 | comment: (_) => 503 | token.immediate(seq('/*', /[^*]*\*+([^/*][^*]*\*+)*/, '/')), 504 | 505 | _left_delimiter: (_) => 506 | choice(token('{{'), alias(token(seq('{{-', /\s/)), '{{-')), 507 | _right_delimiter: (_) => choice(token('}}'), token('-}}')), 508 | }, 509 | }) 510 | } 511 | -------------------------------------------------------------------------------- /src/node-types.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "argument_list", 4 | "named": true, 5 | "fields": {}, 6 | "children": { 7 | "multiple": true, 8 | "required": true, 9 | "types": [ 10 | { 11 | "type": "assignment", 12 | "named": true 13 | }, 14 | { 15 | "type": "chained_pipeline", 16 | "named": true 17 | }, 18 | { 19 | "type": "dot", 20 | "named": true 21 | }, 22 | { 23 | "type": "false", 24 | "named": true 25 | }, 26 | { 27 | "type": "field", 28 | "named": true 29 | }, 30 | { 31 | "type": "float_literal", 32 | "named": true 33 | }, 34 | { 35 | "type": "function_call", 36 | "named": true 37 | }, 38 | { 39 | "type": "imaginary_literal", 40 | "named": true 41 | }, 42 | { 43 | "type": "int_literal", 44 | "named": true 45 | }, 46 | { 47 | "type": "interpreted_string_literal", 48 | "named": true 49 | }, 50 | { 51 | "type": "method_call", 52 | "named": true 53 | }, 54 | { 55 | "type": "nil", 56 | "named": true 57 | }, 58 | { 59 | "type": "parenthesized_pipeline", 60 | "named": true 61 | }, 62 | { 63 | "type": "raw_string_literal", 64 | "named": true 65 | }, 66 | { 67 | "type": "rune_literal", 68 | "named": true 69 | }, 70 | { 71 | "type": "selector_expression", 72 | "named": true 73 | }, 74 | { 75 | "type": "true", 76 | "named": true 77 | }, 78 | { 79 | "type": "variable", 80 | "named": true 81 | }, 82 | { 83 | "type": "variable_definition", 84 | "named": true 85 | } 86 | ] 87 | } 88 | }, 89 | { 90 | "type": "assignment", 91 | "named": true, 92 | "fields": { 93 | "value": { 94 | "multiple": false, 95 | "required": true, 96 | "types": [ 97 | { 98 | "type": "assignment", 99 | "named": true 100 | }, 101 | { 102 | "type": "chained_pipeline", 103 | "named": true 104 | }, 105 | { 106 | "type": "dot", 107 | "named": true 108 | }, 109 | { 110 | "type": "false", 111 | "named": true 112 | }, 113 | { 114 | "type": "field", 115 | "named": true 116 | }, 117 | { 118 | "type": "float_literal", 119 | "named": true 120 | }, 121 | { 122 | "type": "function_call", 123 | "named": true 124 | }, 125 | { 126 | "type": "imaginary_literal", 127 | "named": true 128 | }, 129 | { 130 | "type": "int_literal", 131 | "named": true 132 | }, 133 | { 134 | "type": "interpreted_string_literal", 135 | "named": true 136 | }, 137 | { 138 | "type": "method_call", 139 | "named": true 140 | }, 141 | { 142 | "type": "nil", 143 | "named": true 144 | }, 145 | { 146 | "type": "parenthesized_pipeline", 147 | "named": true 148 | }, 149 | { 150 | "type": "raw_string_literal", 151 | "named": true 152 | }, 153 | { 154 | "type": "rune_literal", 155 | "named": true 156 | }, 157 | { 158 | "type": "selector_expression", 159 | "named": true 160 | }, 161 | { 162 | "type": "true", 163 | "named": true 164 | }, 165 | { 166 | "type": "variable", 167 | "named": true 168 | }, 169 | { 170 | "type": "variable_definition", 171 | "named": true 172 | } 173 | ] 174 | }, 175 | "variable": { 176 | "multiple": false, 177 | "required": true, 178 | "types": [ 179 | { 180 | "type": "variable", 181 | "named": true 182 | } 183 | ] 184 | } 185 | } 186 | }, 187 | { 188 | "type": "block_action", 189 | "named": true, 190 | "fields": { 191 | "argument": { 192 | "multiple": false, 193 | "required": true, 194 | "types": [ 195 | { 196 | "type": "assignment", 197 | "named": true 198 | }, 199 | { 200 | "type": "chained_pipeline", 201 | "named": true 202 | }, 203 | { 204 | "type": "dot", 205 | "named": true 206 | }, 207 | { 208 | "type": "false", 209 | "named": true 210 | }, 211 | { 212 | "type": "field", 213 | "named": true 214 | }, 215 | { 216 | "type": "float_literal", 217 | "named": true 218 | }, 219 | { 220 | "type": "function_call", 221 | "named": true 222 | }, 223 | { 224 | "type": "imaginary_literal", 225 | "named": true 226 | }, 227 | { 228 | "type": "int_literal", 229 | "named": true 230 | }, 231 | { 232 | "type": "interpreted_string_literal", 233 | "named": true 234 | }, 235 | { 236 | "type": "method_call", 237 | "named": true 238 | }, 239 | { 240 | "type": "nil", 241 | "named": true 242 | }, 243 | { 244 | "type": "parenthesized_pipeline", 245 | "named": true 246 | }, 247 | { 248 | "type": "raw_string_literal", 249 | "named": true 250 | }, 251 | { 252 | "type": "rune_literal", 253 | "named": true 254 | }, 255 | { 256 | "type": "selector_expression", 257 | "named": true 258 | }, 259 | { 260 | "type": "true", 261 | "named": true 262 | }, 263 | { 264 | "type": "variable", 265 | "named": true 266 | }, 267 | { 268 | "type": "variable_definition", 269 | "named": true 270 | } 271 | ] 272 | }, 273 | "body": { 274 | "multiple": true, 275 | "required": false, 276 | "types": [ 277 | { 278 | "type": "-}}", 279 | "named": false 280 | }, 281 | { 282 | "type": "assignment", 283 | "named": true 284 | }, 285 | { 286 | "type": "block_action", 287 | "named": true 288 | }, 289 | { 290 | "type": "break_action", 291 | "named": true 292 | }, 293 | { 294 | "type": "chained_pipeline", 295 | "named": true 296 | }, 297 | { 298 | "type": "comment", 299 | "named": true 300 | }, 301 | { 302 | "type": "continue_action", 303 | "named": true 304 | }, 305 | { 306 | "type": "define_action", 307 | "named": true 308 | }, 309 | { 310 | "type": "dot", 311 | "named": true 312 | }, 313 | { 314 | "type": "false", 315 | "named": true 316 | }, 317 | { 318 | "type": "field", 319 | "named": true 320 | }, 321 | { 322 | "type": "float_literal", 323 | "named": true 324 | }, 325 | { 326 | "type": "function_call", 327 | "named": true 328 | }, 329 | { 330 | "type": "if_action", 331 | "named": true 332 | }, 333 | { 334 | "type": "imaginary_literal", 335 | "named": true 336 | }, 337 | { 338 | "type": "int_literal", 339 | "named": true 340 | }, 341 | { 342 | "type": "interpreted_string_literal", 343 | "named": true 344 | }, 345 | { 346 | "type": "method_call", 347 | "named": true 348 | }, 349 | { 350 | "type": "nil", 351 | "named": true 352 | }, 353 | { 354 | "type": "parenthesized_pipeline", 355 | "named": true 356 | }, 357 | { 358 | "type": "range_action", 359 | "named": true 360 | }, 361 | { 362 | "type": "raw_string_literal", 363 | "named": true 364 | }, 365 | { 366 | "type": "rune_literal", 367 | "named": true 368 | }, 369 | { 370 | "type": "selector_expression", 371 | "named": true 372 | }, 373 | { 374 | "type": "template_action", 375 | "named": true 376 | }, 377 | { 378 | "type": "text", 379 | "named": true 380 | }, 381 | { 382 | "type": "true", 383 | "named": true 384 | }, 385 | { 386 | "type": "variable", 387 | "named": true 388 | }, 389 | { 390 | "type": "variable_definition", 391 | "named": true 392 | }, 393 | { 394 | "type": "with_action", 395 | "named": true 396 | }, 397 | { 398 | "type": "yaml_no_injection_text", 399 | "named": true 400 | }, 401 | { 402 | "type": "{{", 403 | "named": false 404 | }, 405 | { 406 | "type": "{{-", 407 | "named": false 408 | }, 409 | { 410 | "type": "}}", 411 | "named": false 412 | } 413 | ] 414 | }, 415 | "name": { 416 | "multiple": false, 417 | "required": true, 418 | "types": [ 419 | { 420 | "type": "interpreted_string_literal", 421 | "named": true 422 | }, 423 | { 424 | "type": "raw_string_literal", 425 | "named": true 426 | } 427 | ] 428 | } 429 | } 430 | }, 431 | { 432 | "type": "break_action", 433 | "named": true, 434 | "fields": {} 435 | }, 436 | { 437 | "type": "chained_pipeline", 438 | "named": true, 439 | "fields": {}, 440 | "children": { 441 | "multiple": true, 442 | "required": true, 443 | "types": [ 444 | { 445 | "type": "assignment", 446 | "named": true 447 | }, 448 | { 449 | "type": "chained_pipeline", 450 | "named": true 451 | }, 452 | { 453 | "type": "dot", 454 | "named": true 455 | }, 456 | { 457 | "type": "false", 458 | "named": true 459 | }, 460 | { 461 | "type": "field", 462 | "named": true 463 | }, 464 | { 465 | "type": "float_literal", 466 | "named": true 467 | }, 468 | { 469 | "type": "function_call", 470 | "named": true 471 | }, 472 | { 473 | "type": "imaginary_literal", 474 | "named": true 475 | }, 476 | { 477 | "type": "int_literal", 478 | "named": true 479 | }, 480 | { 481 | "type": "interpreted_string_literal", 482 | "named": true 483 | }, 484 | { 485 | "type": "method_call", 486 | "named": true 487 | }, 488 | { 489 | "type": "nil", 490 | "named": true 491 | }, 492 | { 493 | "type": "parenthesized_pipeline", 494 | "named": true 495 | }, 496 | { 497 | "type": "raw_string_literal", 498 | "named": true 499 | }, 500 | { 501 | "type": "rune_literal", 502 | "named": true 503 | }, 504 | { 505 | "type": "selector_expression", 506 | "named": true 507 | }, 508 | { 509 | "type": "true", 510 | "named": true 511 | }, 512 | { 513 | "type": "variable", 514 | "named": true 515 | }, 516 | { 517 | "type": "variable_definition", 518 | "named": true 519 | } 520 | ] 521 | } 522 | }, 523 | { 524 | "type": "continue_action", 525 | "named": true, 526 | "fields": {} 527 | }, 528 | { 529 | "type": "define_action", 530 | "named": true, 531 | "fields": { 532 | "body": { 533 | "multiple": true, 534 | "required": false, 535 | "types": [ 536 | { 537 | "type": "-}}", 538 | "named": false 539 | }, 540 | { 541 | "type": "assignment", 542 | "named": true 543 | }, 544 | { 545 | "type": "block_action", 546 | "named": true 547 | }, 548 | { 549 | "type": "break_action", 550 | "named": true 551 | }, 552 | { 553 | "type": "chained_pipeline", 554 | "named": true 555 | }, 556 | { 557 | "type": "comment", 558 | "named": true 559 | }, 560 | { 561 | "type": "continue_action", 562 | "named": true 563 | }, 564 | { 565 | "type": "define_action", 566 | "named": true 567 | }, 568 | { 569 | "type": "dot", 570 | "named": true 571 | }, 572 | { 573 | "type": "false", 574 | "named": true 575 | }, 576 | { 577 | "type": "field", 578 | "named": true 579 | }, 580 | { 581 | "type": "float_literal", 582 | "named": true 583 | }, 584 | { 585 | "type": "function_call", 586 | "named": true 587 | }, 588 | { 589 | "type": "if_action", 590 | "named": true 591 | }, 592 | { 593 | "type": "imaginary_literal", 594 | "named": true 595 | }, 596 | { 597 | "type": "int_literal", 598 | "named": true 599 | }, 600 | { 601 | "type": "interpreted_string_literal", 602 | "named": true 603 | }, 604 | { 605 | "type": "method_call", 606 | "named": true 607 | }, 608 | { 609 | "type": "nil", 610 | "named": true 611 | }, 612 | { 613 | "type": "parenthesized_pipeline", 614 | "named": true 615 | }, 616 | { 617 | "type": "range_action", 618 | "named": true 619 | }, 620 | { 621 | "type": "raw_string_literal", 622 | "named": true 623 | }, 624 | { 625 | "type": "rune_literal", 626 | "named": true 627 | }, 628 | { 629 | "type": "selector_expression", 630 | "named": true 631 | }, 632 | { 633 | "type": "template_action", 634 | "named": true 635 | }, 636 | { 637 | "type": "text", 638 | "named": true 639 | }, 640 | { 641 | "type": "true", 642 | "named": true 643 | }, 644 | { 645 | "type": "variable", 646 | "named": true 647 | }, 648 | { 649 | "type": "variable_definition", 650 | "named": true 651 | }, 652 | { 653 | "type": "with_action", 654 | "named": true 655 | }, 656 | { 657 | "type": "yaml_no_injection_text", 658 | "named": true 659 | }, 660 | { 661 | "type": "{{", 662 | "named": false 663 | }, 664 | { 665 | "type": "{{-", 666 | "named": false 667 | }, 668 | { 669 | "type": "}}", 670 | "named": false 671 | } 672 | ] 673 | }, 674 | "name": { 675 | "multiple": false, 676 | "required": true, 677 | "types": [ 678 | { 679 | "type": "interpreted_string_literal", 680 | "named": true 681 | }, 682 | { 683 | "type": "raw_string_literal", 684 | "named": true 685 | } 686 | ] 687 | } 688 | } 689 | }, 690 | { 691 | "type": "dot", 692 | "named": true, 693 | "fields": {} 694 | }, 695 | { 696 | "type": "field", 697 | "named": true, 698 | "fields": { 699 | "name": { 700 | "multiple": false, 701 | "required": true, 702 | "types": [ 703 | { 704 | "type": "identifier", 705 | "named": true 706 | } 707 | ] 708 | } 709 | } 710 | }, 711 | { 712 | "type": "function_call", 713 | "named": true, 714 | "fields": { 715 | "arguments": { 716 | "multiple": false, 717 | "required": false, 718 | "types": [ 719 | { 720 | "type": "argument_list", 721 | "named": true 722 | } 723 | ] 724 | }, 725 | "function": { 726 | "multiple": false, 727 | "required": true, 728 | "types": [ 729 | { 730 | "type": "identifier", 731 | "named": true 732 | } 733 | ] 734 | } 735 | } 736 | }, 737 | { 738 | "type": "if_action", 739 | "named": true, 740 | "fields": { 741 | "alternative": { 742 | "multiple": true, 743 | "required": false, 744 | "types": [ 745 | { 746 | "type": "-}}", 747 | "named": false 748 | }, 749 | { 750 | "type": "assignment", 751 | "named": true 752 | }, 753 | { 754 | "type": "block_action", 755 | "named": true 756 | }, 757 | { 758 | "type": "break_action", 759 | "named": true 760 | }, 761 | { 762 | "type": "chained_pipeline", 763 | "named": true 764 | }, 765 | { 766 | "type": "comment", 767 | "named": true 768 | }, 769 | { 770 | "type": "continue_action", 771 | "named": true 772 | }, 773 | { 774 | "type": "define_action", 775 | "named": true 776 | }, 777 | { 778 | "type": "dot", 779 | "named": true 780 | }, 781 | { 782 | "type": "false", 783 | "named": true 784 | }, 785 | { 786 | "type": "field", 787 | "named": true 788 | }, 789 | { 790 | "type": "float_literal", 791 | "named": true 792 | }, 793 | { 794 | "type": "function_call", 795 | "named": true 796 | }, 797 | { 798 | "type": "if_action", 799 | "named": true 800 | }, 801 | { 802 | "type": "imaginary_literal", 803 | "named": true 804 | }, 805 | { 806 | "type": "int_literal", 807 | "named": true 808 | }, 809 | { 810 | "type": "interpreted_string_literal", 811 | "named": true 812 | }, 813 | { 814 | "type": "method_call", 815 | "named": true 816 | }, 817 | { 818 | "type": "nil", 819 | "named": true 820 | }, 821 | { 822 | "type": "parenthesized_pipeline", 823 | "named": true 824 | }, 825 | { 826 | "type": "range_action", 827 | "named": true 828 | }, 829 | { 830 | "type": "raw_string_literal", 831 | "named": true 832 | }, 833 | { 834 | "type": "rune_literal", 835 | "named": true 836 | }, 837 | { 838 | "type": "selector_expression", 839 | "named": true 840 | }, 841 | { 842 | "type": "template_action", 843 | "named": true 844 | }, 845 | { 846 | "type": "text", 847 | "named": true 848 | }, 849 | { 850 | "type": "true", 851 | "named": true 852 | }, 853 | { 854 | "type": "variable", 855 | "named": true 856 | }, 857 | { 858 | "type": "variable_definition", 859 | "named": true 860 | }, 861 | { 862 | "type": "with_action", 863 | "named": true 864 | }, 865 | { 866 | "type": "yaml_no_injection_text", 867 | "named": true 868 | }, 869 | { 870 | "type": "{{", 871 | "named": false 872 | }, 873 | { 874 | "type": "{{-", 875 | "named": false 876 | }, 877 | { 878 | "type": "}}", 879 | "named": false 880 | } 881 | ] 882 | }, 883 | "condition": { 884 | "multiple": true, 885 | "required": true, 886 | "types": [ 887 | { 888 | "type": "assignment", 889 | "named": true 890 | }, 891 | { 892 | "type": "chained_pipeline", 893 | "named": true 894 | }, 895 | { 896 | "type": "dot", 897 | "named": true 898 | }, 899 | { 900 | "type": "false", 901 | "named": true 902 | }, 903 | { 904 | "type": "field", 905 | "named": true 906 | }, 907 | { 908 | "type": "float_literal", 909 | "named": true 910 | }, 911 | { 912 | "type": "function_call", 913 | "named": true 914 | }, 915 | { 916 | "type": "imaginary_literal", 917 | "named": true 918 | }, 919 | { 920 | "type": "int_literal", 921 | "named": true 922 | }, 923 | { 924 | "type": "interpreted_string_literal", 925 | "named": true 926 | }, 927 | { 928 | "type": "method_call", 929 | "named": true 930 | }, 931 | { 932 | "type": "nil", 933 | "named": true 934 | }, 935 | { 936 | "type": "parenthesized_pipeline", 937 | "named": true 938 | }, 939 | { 940 | "type": "raw_string_literal", 941 | "named": true 942 | }, 943 | { 944 | "type": "rune_literal", 945 | "named": true 946 | }, 947 | { 948 | "type": "selector_expression", 949 | "named": true 950 | }, 951 | { 952 | "type": "true", 953 | "named": true 954 | }, 955 | { 956 | "type": "variable", 957 | "named": true 958 | }, 959 | { 960 | "type": "variable_definition", 961 | "named": true 962 | } 963 | ] 964 | }, 965 | "consequence": { 966 | "multiple": true, 967 | "required": false, 968 | "types": [ 969 | { 970 | "type": "-}}", 971 | "named": false 972 | }, 973 | { 974 | "type": "assignment", 975 | "named": true 976 | }, 977 | { 978 | "type": "block_action", 979 | "named": true 980 | }, 981 | { 982 | "type": "break_action", 983 | "named": true 984 | }, 985 | { 986 | "type": "chained_pipeline", 987 | "named": true 988 | }, 989 | { 990 | "type": "comment", 991 | "named": true 992 | }, 993 | { 994 | "type": "continue_action", 995 | "named": true 996 | }, 997 | { 998 | "type": "define_action", 999 | "named": true 1000 | }, 1001 | { 1002 | "type": "dot", 1003 | "named": true 1004 | }, 1005 | { 1006 | "type": "false", 1007 | "named": true 1008 | }, 1009 | { 1010 | "type": "field", 1011 | "named": true 1012 | }, 1013 | { 1014 | "type": "float_literal", 1015 | "named": true 1016 | }, 1017 | { 1018 | "type": "function_call", 1019 | "named": true 1020 | }, 1021 | { 1022 | "type": "if_action", 1023 | "named": true 1024 | }, 1025 | { 1026 | "type": "imaginary_literal", 1027 | "named": true 1028 | }, 1029 | { 1030 | "type": "int_literal", 1031 | "named": true 1032 | }, 1033 | { 1034 | "type": "interpreted_string_literal", 1035 | "named": true 1036 | }, 1037 | { 1038 | "type": "method_call", 1039 | "named": true 1040 | }, 1041 | { 1042 | "type": "nil", 1043 | "named": true 1044 | }, 1045 | { 1046 | "type": "parenthesized_pipeline", 1047 | "named": true 1048 | }, 1049 | { 1050 | "type": "range_action", 1051 | "named": true 1052 | }, 1053 | { 1054 | "type": "raw_string_literal", 1055 | "named": true 1056 | }, 1057 | { 1058 | "type": "rune_literal", 1059 | "named": true 1060 | }, 1061 | { 1062 | "type": "selector_expression", 1063 | "named": true 1064 | }, 1065 | { 1066 | "type": "template_action", 1067 | "named": true 1068 | }, 1069 | { 1070 | "type": "text", 1071 | "named": true 1072 | }, 1073 | { 1074 | "type": "true", 1075 | "named": true 1076 | }, 1077 | { 1078 | "type": "variable", 1079 | "named": true 1080 | }, 1081 | { 1082 | "type": "variable_definition", 1083 | "named": true 1084 | }, 1085 | { 1086 | "type": "with_action", 1087 | "named": true 1088 | }, 1089 | { 1090 | "type": "yaml_no_injection_text", 1091 | "named": true 1092 | }, 1093 | { 1094 | "type": "{{", 1095 | "named": false 1096 | }, 1097 | { 1098 | "type": "{{-", 1099 | "named": false 1100 | }, 1101 | { 1102 | "type": "}}", 1103 | "named": false 1104 | } 1105 | ] 1106 | }, 1107 | "option": { 1108 | "multiple": true, 1109 | "required": false, 1110 | "types": [ 1111 | { 1112 | "type": "-}}", 1113 | "named": false 1114 | }, 1115 | { 1116 | "type": "assignment", 1117 | "named": true 1118 | }, 1119 | { 1120 | "type": "block_action", 1121 | "named": true 1122 | }, 1123 | { 1124 | "type": "break_action", 1125 | "named": true 1126 | }, 1127 | { 1128 | "type": "chained_pipeline", 1129 | "named": true 1130 | }, 1131 | { 1132 | "type": "comment", 1133 | "named": true 1134 | }, 1135 | { 1136 | "type": "continue_action", 1137 | "named": true 1138 | }, 1139 | { 1140 | "type": "define_action", 1141 | "named": true 1142 | }, 1143 | { 1144 | "type": "dot", 1145 | "named": true 1146 | }, 1147 | { 1148 | "type": "false", 1149 | "named": true 1150 | }, 1151 | { 1152 | "type": "field", 1153 | "named": true 1154 | }, 1155 | { 1156 | "type": "float_literal", 1157 | "named": true 1158 | }, 1159 | { 1160 | "type": "function_call", 1161 | "named": true 1162 | }, 1163 | { 1164 | "type": "if_action", 1165 | "named": true 1166 | }, 1167 | { 1168 | "type": "imaginary_literal", 1169 | "named": true 1170 | }, 1171 | { 1172 | "type": "int_literal", 1173 | "named": true 1174 | }, 1175 | { 1176 | "type": "interpreted_string_literal", 1177 | "named": true 1178 | }, 1179 | { 1180 | "type": "method_call", 1181 | "named": true 1182 | }, 1183 | { 1184 | "type": "nil", 1185 | "named": true 1186 | }, 1187 | { 1188 | "type": "parenthesized_pipeline", 1189 | "named": true 1190 | }, 1191 | { 1192 | "type": "range_action", 1193 | "named": true 1194 | }, 1195 | { 1196 | "type": "raw_string_literal", 1197 | "named": true 1198 | }, 1199 | { 1200 | "type": "rune_literal", 1201 | "named": true 1202 | }, 1203 | { 1204 | "type": "selector_expression", 1205 | "named": true 1206 | }, 1207 | { 1208 | "type": "template_action", 1209 | "named": true 1210 | }, 1211 | { 1212 | "type": "text", 1213 | "named": true 1214 | }, 1215 | { 1216 | "type": "true", 1217 | "named": true 1218 | }, 1219 | { 1220 | "type": "variable", 1221 | "named": true 1222 | }, 1223 | { 1224 | "type": "variable_definition", 1225 | "named": true 1226 | }, 1227 | { 1228 | "type": "with_action", 1229 | "named": true 1230 | }, 1231 | { 1232 | "type": "yaml_no_injection_text", 1233 | "named": true 1234 | }, 1235 | { 1236 | "type": "{{", 1237 | "named": false 1238 | }, 1239 | { 1240 | "type": "{{-", 1241 | "named": false 1242 | }, 1243 | { 1244 | "type": "}}", 1245 | "named": false 1246 | } 1247 | ] 1248 | } 1249 | } 1250 | }, 1251 | { 1252 | "type": "interpreted_string_literal", 1253 | "named": true, 1254 | "fields": {}, 1255 | "children": { 1256 | "multiple": true, 1257 | "required": false, 1258 | "types": [ 1259 | { 1260 | "type": "escape_sequence", 1261 | "named": true 1262 | } 1263 | ] 1264 | } 1265 | }, 1266 | { 1267 | "type": "method_call", 1268 | "named": true, 1269 | "fields": { 1270 | "arguments": { 1271 | "multiple": false, 1272 | "required": true, 1273 | "types": [ 1274 | { 1275 | "type": "argument_list", 1276 | "named": true 1277 | } 1278 | ] 1279 | }, 1280 | "method": { 1281 | "multiple": false, 1282 | "required": true, 1283 | "types": [ 1284 | { 1285 | "type": "field", 1286 | "named": true 1287 | }, 1288 | { 1289 | "type": "selector_expression", 1290 | "named": true 1291 | } 1292 | ] 1293 | } 1294 | } 1295 | }, 1296 | { 1297 | "type": "parenthesized_pipeline", 1298 | "named": true, 1299 | "fields": {}, 1300 | "children": { 1301 | "multiple": false, 1302 | "required": true, 1303 | "types": [ 1304 | { 1305 | "type": "assignment", 1306 | "named": true 1307 | }, 1308 | { 1309 | "type": "chained_pipeline", 1310 | "named": true 1311 | }, 1312 | { 1313 | "type": "dot", 1314 | "named": true 1315 | }, 1316 | { 1317 | "type": "false", 1318 | "named": true 1319 | }, 1320 | { 1321 | "type": "field", 1322 | "named": true 1323 | }, 1324 | { 1325 | "type": "float_literal", 1326 | "named": true 1327 | }, 1328 | { 1329 | "type": "function_call", 1330 | "named": true 1331 | }, 1332 | { 1333 | "type": "imaginary_literal", 1334 | "named": true 1335 | }, 1336 | { 1337 | "type": "int_literal", 1338 | "named": true 1339 | }, 1340 | { 1341 | "type": "interpreted_string_literal", 1342 | "named": true 1343 | }, 1344 | { 1345 | "type": "method_call", 1346 | "named": true 1347 | }, 1348 | { 1349 | "type": "nil", 1350 | "named": true 1351 | }, 1352 | { 1353 | "type": "parenthesized_pipeline", 1354 | "named": true 1355 | }, 1356 | { 1357 | "type": "raw_string_literal", 1358 | "named": true 1359 | }, 1360 | { 1361 | "type": "rune_literal", 1362 | "named": true 1363 | }, 1364 | { 1365 | "type": "selector_expression", 1366 | "named": true 1367 | }, 1368 | { 1369 | "type": "true", 1370 | "named": true 1371 | }, 1372 | { 1373 | "type": "variable", 1374 | "named": true 1375 | }, 1376 | { 1377 | "type": "variable_definition", 1378 | "named": true 1379 | } 1380 | ] 1381 | } 1382 | }, 1383 | { 1384 | "type": "range_action", 1385 | "named": true, 1386 | "fields": { 1387 | "alternative": { 1388 | "multiple": true, 1389 | "required": false, 1390 | "types": [ 1391 | { 1392 | "type": "-}}", 1393 | "named": false 1394 | }, 1395 | { 1396 | "type": "assignment", 1397 | "named": true 1398 | }, 1399 | { 1400 | "type": "block_action", 1401 | "named": true 1402 | }, 1403 | { 1404 | "type": "break_action", 1405 | "named": true 1406 | }, 1407 | { 1408 | "type": "chained_pipeline", 1409 | "named": true 1410 | }, 1411 | { 1412 | "type": "comment", 1413 | "named": true 1414 | }, 1415 | { 1416 | "type": "continue_action", 1417 | "named": true 1418 | }, 1419 | { 1420 | "type": "define_action", 1421 | "named": true 1422 | }, 1423 | { 1424 | "type": "dot", 1425 | "named": true 1426 | }, 1427 | { 1428 | "type": "false", 1429 | "named": true 1430 | }, 1431 | { 1432 | "type": "field", 1433 | "named": true 1434 | }, 1435 | { 1436 | "type": "float_literal", 1437 | "named": true 1438 | }, 1439 | { 1440 | "type": "function_call", 1441 | "named": true 1442 | }, 1443 | { 1444 | "type": "if_action", 1445 | "named": true 1446 | }, 1447 | { 1448 | "type": "imaginary_literal", 1449 | "named": true 1450 | }, 1451 | { 1452 | "type": "int_literal", 1453 | "named": true 1454 | }, 1455 | { 1456 | "type": "interpreted_string_literal", 1457 | "named": true 1458 | }, 1459 | { 1460 | "type": "method_call", 1461 | "named": true 1462 | }, 1463 | { 1464 | "type": "nil", 1465 | "named": true 1466 | }, 1467 | { 1468 | "type": "parenthesized_pipeline", 1469 | "named": true 1470 | }, 1471 | { 1472 | "type": "range_action", 1473 | "named": true 1474 | }, 1475 | { 1476 | "type": "raw_string_literal", 1477 | "named": true 1478 | }, 1479 | { 1480 | "type": "rune_literal", 1481 | "named": true 1482 | }, 1483 | { 1484 | "type": "selector_expression", 1485 | "named": true 1486 | }, 1487 | { 1488 | "type": "template_action", 1489 | "named": true 1490 | }, 1491 | { 1492 | "type": "text", 1493 | "named": true 1494 | }, 1495 | { 1496 | "type": "true", 1497 | "named": true 1498 | }, 1499 | { 1500 | "type": "variable", 1501 | "named": true 1502 | }, 1503 | { 1504 | "type": "variable_definition", 1505 | "named": true 1506 | }, 1507 | { 1508 | "type": "with_action", 1509 | "named": true 1510 | }, 1511 | { 1512 | "type": "yaml_no_injection_text", 1513 | "named": true 1514 | }, 1515 | { 1516 | "type": "{{", 1517 | "named": false 1518 | }, 1519 | { 1520 | "type": "{{-", 1521 | "named": false 1522 | }, 1523 | { 1524 | "type": "}}", 1525 | "named": false 1526 | } 1527 | ] 1528 | }, 1529 | "body": { 1530 | "multiple": true, 1531 | "required": false, 1532 | "types": [ 1533 | { 1534 | "type": "-}}", 1535 | "named": false 1536 | }, 1537 | { 1538 | "type": "assignment", 1539 | "named": true 1540 | }, 1541 | { 1542 | "type": "block_action", 1543 | "named": true 1544 | }, 1545 | { 1546 | "type": "break_action", 1547 | "named": true 1548 | }, 1549 | { 1550 | "type": "chained_pipeline", 1551 | "named": true 1552 | }, 1553 | { 1554 | "type": "comment", 1555 | "named": true 1556 | }, 1557 | { 1558 | "type": "continue_action", 1559 | "named": true 1560 | }, 1561 | { 1562 | "type": "define_action", 1563 | "named": true 1564 | }, 1565 | { 1566 | "type": "dot", 1567 | "named": true 1568 | }, 1569 | { 1570 | "type": "false", 1571 | "named": true 1572 | }, 1573 | { 1574 | "type": "field", 1575 | "named": true 1576 | }, 1577 | { 1578 | "type": "float_literal", 1579 | "named": true 1580 | }, 1581 | { 1582 | "type": "function_call", 1583 | "named": true 1584 | }, 1585 | { 1586 | "type": "if_action", 1587 | "named": true 1588 | }, 1589 | { 1590 | "type": "imaginary_literal", 1591 | "named": true 1592 | }, 1593 | { 1594 | "type": "int_literal", 1595 | "named": true 1596 | }, 1597 | { 1598 | "type": "interpreted_string_literal", 1599 | "named": true 1600 | }, 1601 | { 1602 | "type": "method_call", 1603 | "named": true 1604 | }, 1605 | { 1606 | "type": "nil", 1607 | "named": true 1608 | }, 1609 | { 1610 | "type": "parenthesized_pipeline", 1611 | "named": true 1612 | }, 1613 | { 1614 | "type": "range_action", 1615 | "named": true 1616 | }, 1617 | { 1618 | "type": "raw_string_literal", 1619 | "named": true 1620 | }, 1621 | { 1622 | "type": "rune_literal", 1623 | "named": true 1624 | }, 1625 | { 1626 | "type": "selector_expression", 1627 | "named": true 1628 | }, 1629 | { 1630 | "type": "template_action", 1631 | "named": true 1632 | }, 1633 | { 1634 | "type": "text", 1635 | "named": true 1636 | }, 1637 | { 1638 | "type": "true", 1639 | "named": true 1640 | }, 1641 | { 1642 | "type": "variable", 1643 | "named": true 1644 | }, 1645 | { 1646 | "type": "variable_definition", 1647 | "named": true 1648 | }, 1649 | { 1650 | "type": "with_action", 1651 | "named": true 1652 | }, 1653 | { 1654 | "type": "yaml_no_injection_text", 1655 | "named": true 1656 | }, 1657 | { 1658 | "type": "{{", 1659 | "named": false 1660 | }, 1661 | { 1662 | "type": "{{-", 1663 | "named": false 1664 | }, 1665 | { 1666 | "type": "}}", 1667 | "named": false 1668 | } 1669 | ] 1670 | }, 1671 | "range": { 1672 | "multiple": false, 1673 | "required": false, 1674 | "types": [ 1675 | { 1676 | "type": "assignment", 1677 | "named": true 1678 | }, 1679 | { 1680 | "type": "chained_pipeline", 1681 | "named": true 1682 | }, 1683 | { 1684 | "type": "dot", 1685 | "named": true 1686 | }, 1687 | { 1688 | "type": "false", 1689 | "named": true 1690 | }, 1691 | { 1692 | "type": "field", 1693 | "named": true 1694 | }, 1695 | { 1696 | "type": "float_literal", 1697 | "named": true 1698 | }, 1699 | { 1700 | "type": "function_call", 1701 | "named": true 1702 | }, 1703 | { 1704 | "type": "imaginary_literal", 1705 | "named": true 1706 | }, 1707 | { 1708 | "type": "int_literal", 1709 | "named": true 1710 | }, 1711 | { 1712 | "type": "interpreted_string_literal", 1713 | "named": true 1714 | }, 1715 | { 1716 | "type": "method_call", 1717 | "named": true 1718 | }, 1719 | { 1720 | "type": "nil", 1721 | "named": true 1722 | }, 1723 | { 1724 | "type": "parenthesized_pipeline", 1725 | "named": true 1726 | }, 1727 | { 1728 | "type": "raw_string_literal", 1729 | "named": true 1730 | }, 1731 | { 1732 | "type": "rune_literal", 1733 | "named": true 1734 | }, 1735 | { 1736 | "type": "selector_expression", 1737 | "named": true 1738 | }, 1739 | { 1740 | "type": "true", 1741 | "named": true 1742 | }, 1743 | { 1744 | "type": "variable", 1745 | "named": true 1746 | }, 1747 | { 1748 | "type": "variable_definition", 1749 | "named": true 1750 | } 1751 | ] 1752 | } 1753 | }, 1754 | "children": { 1755 | "multiple": false, 1756 | "required": false, 1757 | "types": [ 1758 | { 1759 | "type": "range_variable_definition", 1760 | "named": true 1761 | } 1762 | ] 1763 | } 1764 | }, 1765 | { 1766 | "type": "range_variable_definition", 1767 | "named": true, 1768 | "fields": { 1769 | "element": { 1770 | "multiple": false, 1771 | "required": true, 1772 | "types": [ 1773 | { 1774 | "type": "variable", 1775 | "named": true 1776 | } 1777 | ] 1778 | }, 1779 | "index": { 1780 | "multiple": false, 1781 | "required": true, 1782 | "types": [ 1783 | { 1784 | "type": "variable", 1785 | "named": true 1786 | } 1787 | ] 1788 | }, 1789 | "range": { 1790 | "multiple": false, 1791 | "required": true, 1792 | "types": [ 1793 | { 1794 | "type": "assignment", 1795 | "named": true 1796 | }, 1797 | { 1798 | "type": "chained_pipeline", 1799 | "named": true 1800 | }, 1801 | { 1802 | "type": "dot", 1803 | "named": true 1804 | }, 1805 | { 1806 | "type": "false", 1807 | "named": true 1808 | }, 1809 | { 1810 | "type": "field", 1811 | "named": true 1812 | }, 1813 | { 1814 | "type": "float_literal", 1815 | "named": true 1816 | }, 1817 | { 1818 | "type": "function_call", 1819 | "named": true 1820 | }, 1821 | { 1822 | "type": "imaginary_literal", 1823 | "named": true 1824 | }, 1825 | { 1826 | "type": "int_literal", 1827 | "named": true 1828 | }, 1829 | { 1830 | "type": "interpreted_string_literal", 1831 | "named": true 1832 | }, 1833 | { 1834 | "type": "method_call", 1835 | "named": true 1836 | }, 1837 | { 1838 | "type": "nil", 1839 | "named": true 1840 | }, 1841 | { 1842 | "type": "parenthesized_pipeline", 1843 | "named": true 1844 | }, 1845 | { 1846 | "type": "raw_string_literal", 1847 | "named": true 1848 | }, 1849 | { 1850 | "type": "rune_literal", 1851 | "named": true 1852 | }, 1853 | { 1854 | "type": "selector_expression", 1855 | "named": true 1856 | }, 1857 | { 1858 | "type": "true", 1859 | "named": true 1860 | }, 1861 | { 1862 | "type": "variable", 1863 | "named": true 1864 | }, 1865 | { 1866 | "type": "variable_definition", 1867 | "named": true 1868 | } 1869 | ] 1870 | } 1871 | } 1872 | }, 1873 | { 1874 | "type": "selector_expression", 1875 | "named": true, 1876 | "fields": { 1877 | "field": { 1878 | "multiple": false, 1879 | "required": true, 1880 | "types": [ 1881 | { 1882 | "type": "field_identifier", 1883 | "named": true 1884 | } 1885 | ] 1886 | }, 1887 | "operand": { 1888 | "multiple": false, 1889 | "required": true, 1890 | "types": [ 1891 | { 1892 | "type": "field", 1893 | "named": true 1894 | }, 1895 | { 1896 | "type": "identifier", 1897 | "named": true 1898 | }, 1899 | { 1900 | "type": "parenthesized_pipeline", 1901 | "named": true 1902 | }, 1903 | { 1904 | "type": "selector_expression", 1905 | "named": true 1906 | }, 1907 | { 1908 | "type": "variable", 1909 | "named": true 1910 | } 1911 | ] 1912 | } 1913 | } 1914 | }, 1915 | { 1916 | "type": "template", 1917 | "named": true, 1918 | "root": true, 1919 | "fields": {}, 1920 | "children": { 1921 | "multiple": true, 1922 | "required": false, 1923 | "types": [ 1924 | { 1925 | "type": "assignment", 1926 | "named": true 1927 | }, 1928 | { 1929 | "type": "block_action", 1930 | "named": true 1931 | }, 1932 | { 1933 | "type": "break_action", 1934 | "named": true 1935 | }, 1936 | { 1937 | "type": "chained_pipeline", 1938 | "named": true 1939 | }, 1940 | { 1941 | "type": "comment", 1942 | "named": true 1943 | }, 1944 | { 1945 | "type": "continue_action", 1946 | "named": true 1947 | }, 1948 | { 1949 | "type": "define_action", 1950 | "named": true 1951 | }, 1952 | { 1953 | "type": "dot", 1954 | "named": true 1955 | }, 1956 | { 1957 | "type": "false", 1958 | "named": true 1959 | }, 1960 | { 1961 | "type": "field", 1962 | "named": true 1963 | }, 1964 | { 1965 | "type": "float_literal", 1966 | "named": true 1967 | }, 1968 | { 1969 | "type": "function_call", 1970 | "named": true 1971 | }, 1972 | { 1973 | "type": "if_action", 1974 | "named": true 1975 | }, 1976 | { 1977 | "type": "imaginary_literal", 1978 | "named": true 1979 | }, 1980 | { 1981 | "type": "int_literal", 1982 | "named": true 1983 | }, 1984 | { 1985 | "type": "interpreted_string_literal", 1986 | "named": true 1987 | }, 1988 | { 1989 | "type": "method_call", 1990 | "named": true 1991 | }, 1992 | { 1993 | "type": "nil", 1994 | "named": true 1995 | }, 1996 | { 1997 | "type": "parenthesized_pipeline", 1998 | "named": true 1999 | }, 2000 | { 2001 | "type": "range_action", 2002 | "named": true 2003 | }, 2004 | { 2005 | "type": "raw_string_literal", 2006 | "named": true 2007 | }, 2008 | { 2009 | "type": "rune_literal", 2010 | "named": true 2011 | }, 2012 | { 2013 | "type": "selector_expression", 2014 | "named": true 2015 | }, 2016 | { 2017 | "type": "template_action", 2018 | "named": true 2019 | }, 2020 | { 2021 | "type": "text", 2022 | "named": true 2023 | }, 2024 | { 2025 | "type": "true", 2026 | "named": true 2027 | }, 2028 | { 2029 | "type": "variable", 2030 | "named": true 2031 | }, 2032 | { 2033 | "type": "variable_definition", 2034 | "named": true 2035 | }, 2036 | { 2037 | "type": "with_action", 2038 | "named": true 2039 | }, 2040 | { 2041 | "type": "yaml_no_injection_text", 2042 | "named": true 2043 | } 2044 | ] 2045 | } 2046 | }, 2047 | { 2048 | "type": "template_action", 2049 | "named": true, 2050 | "fields": { 2051 | "argument": { 2052 | "multiple": false, 2053 | "required": false, 2054 | "types": [ 2055 | { 2056 | "type": "assignment", 2057 | "named": true 2058 | }, 2059 | { 2060 | "type": "chained_pipeline", 2061 | "named": true 2062 | }, 2063 | { 2064 | "type": "dot", 2065 | "named": true 2066 | }, 2067 | { 2068 | "type": "false", 2069 | "named": true 2070 | }, 2071 | { 2072 | "type": "field", 2073 | "named": true 2074 | }, 2075 | { 2076 | "type": "float_literal", 2077 | "named": true 2078 | }, 2079 | { 2080 | "type": "function_call", 2081 | "named": true 2082 | }, 2083 | { 2084 | "type": "imaginary_literal", 2085 | "named": true 2086 | }, 2087 | { 2088 | "type": "int_literal", 2089 | "named": true 2090 | }, 2091 | { 2092 | "type": "interpreted_string_literal", 2093 | "named": true 2094 | }, 2095 | { 2096 | "type": "method_call", 2097 | "named": true 2098 | }, 2099 | { 2100 | "type": "nil", 2101 | "named": true 2102 | }, 2103 | { 2104 | "type": "parenthesized_pipeline", 2105 | "named": true 2106 | }, 2107 | { 2108 | "type": "raw_string_literal", 2109 | "named": true 2110 | }, 2111 | { 2112 | "type": "rune_literal", 2113 | "named": true 2114 | }, 2115 | { 2116 | "type": "selector_expression", 2117 | "named": true 2118 | }, 2119 | { 2120 | "type": "true", 2121 | "named": true 2122 | }, 2123 | { 2124 | "type": "variable", 2125 | "named": true 2126 | }, 2127 | { 2128 | "type": "variable_definition", 2129 | "named": true 2130 | } 2131 | ] 2132 | }, 2133 | "name": { 2134 | "multiple": false, 2135 | "required": true, 2136 | "types": [ 2137 | { 2138 | "type": "interpreted_string_literal", 2139 | "named": true 2140 | }, 2141 | { 2142 | "type": "raw_string_literal", 2143 | "named": true 2144 | } 2145 | ] 2146 | } 2147 | } 2148 | }, 2149 | { 2150 | "type": "text", 2151 | "named": true, 2152 | "fields": {} 2153 | }, 2154 | { 2155 | "type": "variable", 2156 | "named": true, 2157 | "fields": { 2158 | "name": { 2159 | "multiple": false, 2160 | "required": false, 2161 | "types": [ 2162 | { 2163 | "type": "identifier", 2164 | "named": true 2165 | } 2166 | ] 2167 | } 2168 | } 2169 | }, 2170 | { 2171 | "type": "variable_definition", 2172 | "named": true, 2173 | "fields": { 2174 | "value": { 2175 | "multiple": false, 2176 | "required": true, 2177 | "types": [ 2178 | { 2179 | "type": "assignment", 2180 | "named": true 2181 | }, 2182 | { 2183 | "type": "chained_pipeline", 2184 | "named": true 2185 | }, 2186 | { 2187 | "type": "dot", 2188 | "named": true 2189 | }, 2190 | { 2191 | "type": "false", 2192 | "named": true 2193 | }, 2194 | { 2195 | "type": "field", 2196 | "named": true 2197 | }, 2198 | { 2199 | "type": "float_literal", 2200 | "named": true 2201 | }, 2202 | { 2203 | "type": "function_call", 2204 | "named": true 2205 | }, 2206 | { 2207 | "type": "imaginary_literal", 2208 | "named": true 2209 | }, 2210 | { 2211 | "type": "int_literal", 2212 | "named": true 2213 | }, 2214 | { 2215 | "type": "interpreted_string_literal", 2216 | "named": true 2217 | }, 2218 | { 2219 | "type": "method_call", 2220 | "named": true 2221 | }, 2222 | { 2223 | "type": "nil", 2224 | "named": true 2225 | }, 2226 | { 2227 | "type": "parenthesized_pipeline", 2228 | "named": true 2229 | }, 2230 | { 2231 | "type": "raw_string_literal", 2232 | "named": true 2233 | }, 2234 | { 2235 | "type": "rune_literal", 2236 | "named": true 2237 | }, 2238 | { 2239 | "type": "selector_expression", 2240 | "named": true 2241 | }, 2242 | { 2243 | "type": "true", 2244 | "named": true 2245 | }, 2246 | { 2247 | "type": "variable", 2248 | "named": true 2249 | }, 2250 | { 2251 | "type": "variable_definition", 2252 | "named": true 2253 | } 2254 | ] 2255 | }, 2256 | "variable": { 2257 | "multiple": false, 2258 | "required": true, 2259 | "types": [ 2260 | { 2261 | "type": "variable", 2262 | "named": true 2263 | } 2264 | ] 2265 | } 2266 | } 2267 | }, 2268 | { 2269 | "type": "with_action", 2270 | "named": true, 2271 | "fields": { 2272 | "alternative": { 2273 | "multiple": true, 2274 | "required": false, 2275 | "types": [ 2276 | { 2277 | "type": "-}}", 2278 | "named": false 2279 | }, 2280 | { 2281 | "type": "assignment", 2282 | "named": true 2283 | }, 2284 | { 2285 | "type": "block_action", 2286 | "named": true 2287 | }, 2288 | { 2289 | "type": "break_action", 2290 | "named": true 2291 | }, 2292 | { 2293 | "type": "chained_pipeline", 2294 | "named": true 2295 | }, 2296 | { 2297 | "type": "comment", 2298 | "named": true 2299 | }, 2300 | { 2301 | "type": "continue_action", 2302 | "named": true 2303 | }, 2304 | { 2305 | "type": "define_action", 2306 | "named": true 2307 | }, 2308 | { 2309 | "type": "dot", 2310 | "named": true 2311 | }, 2312 | { 2313 | "type": "false", 2314 | "named": true 2315 | }, 2316 | { 2317 | "type": "field", 2318 | "named": true 2319 | }, 2320 | { 2321 | "type": "float_literal", 2322 | "named": true 2323 | }, 2324 | { 2325 | "type": "function_call", 2326 | "named": true 2327 | }, 2328 | { 2329 | "type": "if_action", 2330 | "named": true 2331 | }, 2332 | { 2333 | "type": "imaginary_literal", 2334 | "named": true 2335 | }, 2336 | { 2337 | "type": "int_literal", 2338 | "named": true 2339 | }, 2340 | { 2341 | "type": "interpreted_string_literal", 2342 | "named": true 2343 | }, 2344 | { 2345 | "type": "method_call", 2346 | "named": true 2347 | }, 2348 | { 2349 | "type": "nil", 2350 | "named": true 2351 | }, 2352 | { 2353 | "type": "parenthesized_pipeline", 2354 | "named": true 2355 | }, 2356 | { 2357 | "type": "range_action", 2358 | "named": true 2359 | }, 2360 | { 2361 | "type": "raw_string_literal", 2362 | "named": true 2363 | }, 2364 | { 2365 | "type": "rune_literal", 2366 | "named": true 2367 | }, 2368 | { 2369 | "type": "selector_expression", 2370 | "named": true 2371 | }, 2372 | { 2373 | "type": "template_action", 2374 | "named": true 2375 | }, 2376 | { 2377 | "type": "text", 2378 | "named": true 2379 | }, 2380 | { 2381 | "type": "true", 2382 | "named": true 2383 | }, 2384 | { 2385 | "type": "variable", 2386 | "named": true 2387 | }, 2388 | { 2389 | "type": "variable_definition", 2390 | "named": true 2391 | }, 2392 | { 2393 | "type": "with_action", 2394 | "named": true 2395 | }, 2396 | { 2397 | "type": "yaml_no_injection_text", 2398 | "named": true 2399 | }, 2400 | { 2401 | "type": "{{", 2402 | "named": false 2403 | }, 2404 | { 2405 | "type": "{{-", 2406 | "named": false 2407 | }, 2408 | { 2409 | "type": "}}", 2410 | "named": false 2411 | } 2412 | ] 2413 | }, 2414 | "condition": { 2415 | "multiple": true, 2416 | "required": true, 2417 | "types": [ 2418 | { 2419 | "type": "assignment", 2420 | "named": true 2421 | }, 2422 | { 2423 | "type": "chained_pipeline", 2424 | "named": true 2425 | }, 2426 | { 2427 | "type": "dot", 2428 | "named": true 2429 | }, 2430 | { 2431 | "type": "false", 2432 | "named": true 2433 | }, 2434 | { 2435 | "type": "field", 2436 | "named": true 2437 | }, 2438 | { 2439 | "type": "float_literal", 2440 | "named": true 2441 | }, 2442 | { 2443 | "type": "function_call", 2444 | "named": true 2445 | }, 2446 | { 2447 | "type": "imaginary_literal", 2448 | "named": true 2449 | }, 2450 | { 2451 | "type": "int_literal", 2452 | "named": true 2453 | }, 2454 | { 2455 | "type": "interpreted_string_literal", 2456 | "named": true 2457 | }, 2458 | { 2459 | "type": "method_call", 2460 | "named": true 2461 | }, 2462 | { 2463 | "type": "nil", 2464 | "named": true 2465 | }, 2466 | { 2467 | "type": "parenthesized_pipeline", 2468 | "named": true 2469 | }, 2470 | { 2471 | "type": "raw_string_literal", 2472 | "named": true 2473 | }, 2474 | { 2475 | "type": "rune_literal", 2476 | "named": true 2477 | }, 2478 | { 2479 | "type": "selector_expression", 2480 | "named": true 2481 | }, 2482 | { 2483 | "type": "true", 2484 | "named": true 2485 | }, 2486 | { 2487 | "type": "variable", 2488 | "named": true 2489 | }, 2490 | { 2491 | "type": "variable_definition", 2492 | "named": true 2493 | } 2494 | ] 2495 | }, 2496 | "consequence": { 2497 | "multiple": true, 2498 | "required": false, 2499 | "types": [ 2500 | { 2501 | "type": "-}}", 2502 | "named": false 2503 | }, 2504 | { 2505 | "type": "assignment", 2506 | "named": true 2507 | }, 2508 | { 2509 | "type": "block_action", 2510 | "named": true 2511 | }, 2512 | { 2513 | "type": "break_action", 2514 | "named": true 2515 | }, 2516 | { 2517 | "type": "chained_pipeline", 2518 | "named": true 2519 | }, 2520 | { 2521 | "type": "comment", 2522 | "named": true 2523 | }, 2524 | { 2525 | "type": "continue_action", 2526 | "named": true 2527 | }, 2528 | { 2529 | "type": "define_action", 2530 | "named": true 2531 | }, 2532 | { 2533 | "type": "dot", 2534 | "named": true 2535 | }, 2536 | { 2537 | "type": "false", 2538 | "named": true 2539 | }, 2540 | { 2541 | "type": "field", 2542 | "named": true 2543 | }, 2544 | { 2545 | "type": "float_literal", 2546 | "named": true 2547 | }, 2548 | { 2549 | "type": "function_call", 2550 | "named": true 2551 | }, 2552 | { 2553 | "type": "if_action", 2554 | "named": true 2555 | }, 2556 | { 2557 | "type": "imaginary_literal", 2558 | "named": true 2559 | }, 2560 | { 2561 | "type": "int_literal", 2562 | "named": true 2563 | }, 2564 | { 2565 | "type": "interpreted_string_literal", 2566 | "named": true 2567 | }, 2568 | { 2569 | "type": "method_call", 2570 | "named": true 2571 | }, 2572 | { 2573 | "type": "nil", 2574 | "named": true 2575 | }, 2576 | { 2577 | "type": "parenthesized_pipeline", 2578 | "named": true 2579 | }, 2580 | { 2581 | "type": "range_action", 2582 | "named": true 2583 | }, 2584 | { 2585 | "type": "raw_string_literal", 2586 | "named": true 2587 | }, 2588 | { 2589 | "type": "rune_literal", 2590 | "named": true 2591 | }, 2592 | { 2593 | "type": "selector_expression", 2594 | "named": true 2595 | }, 2596 | { 2597 | "type": "template_action", 2598 | "named": true 2599 | }, 2600 | { 2601 | "type": "text", 2602 | "named": true 2603 | }, 2604 | { 2605 | "type": "true", 2606 | "named": true 2607 | }, 2608 | { 2609 | "type": "variable", 2610 | "named": true 2611 | }, 2612 | { 2613 | "type": "variable_definition", 2614 | "named": true 2615 | }, 2616 | { 2617 | "type": "with_action", 2618 | "named": true 2619 | }, 2620 | { 2621 | "type": "yaml_no_injection_text", 2622 | "named": true 2623 | }, 2624 | { 2625 | "type": "{{", 2626 | "named": false 2627 | }, 2628 | { 2629 | "type": "{{-", 2630 | "named": false 2631 | }, 2632 | { 2633 | "type": "}}", 2634 | "named": false 2635 | } 2636 | ] 2637 | }, 2638 | "option": { 2639 | "multiple": true, 2640 | "required": false, 2641 | "types": [ 2642 | { 2643 | "type": "-}}", 2644 | "named": false 2645 | }, 2646 | { 2647 | "type": "assignment", 2648 | "named": true 2649 | }, 2650 | { 2651 | "type": "block_action", 2652 | "named": true 2653 | }, 2654 | { 2655 | "type": "break_action", 2656 | "named": true 2657 | }, 2658 | { 2659 | "type": "chained_pipeline", 2660 | "named": true 2661 | }, 2662 | { 2663 | "type": "comment", 2664 | "named": true 2665 | }, 2666 | { 2667 | "type": "continue_action", 2668 | "named": true 2669 | }, 2670 | { 2671 | "type": "define_action", 2672 | "named": true 2673 | }, 2674 | { 2675 | "type": "dot", 2676 | "named": true 2677 | }, 2678 | { 2679 | "type": "false", 2680 | "named": true 2681 | }, 2682 | { 2683 | "type": "field", 2684 | "named": true 2685 | }, 2686 | { 2687 | "type": "float_literal", 2688 | "named": true 2689 | }, 2690 | { 2691 | "type": "function_call", 2692 | "named": true 2693 | }, 2694 | { 2695 | "type": "if_action", 2696 | "named": true 2697 | }, 2698 | { 2699 | "type": "imaginary_literal", 2700 | "named": true 2701 | }, 2702 | { 2703 | "type": "int_literal", 2704 | "named": true 2705 | }, 2706 | { 2707 | "type": "interpreted_string_literal", 2708 | "named": true 2709 | }, 2710 | { 2711 | "type": "method_call", 2712 | "named": true 2713 | }, 2714 | { 2715 | "type": "nil", 2716 | "named": true 2717 | }, 2718 | { 2719 | "type": "parenthesized_pipeline", 2720 | "named": true 2721 | }, 2722 | { 2723 | "type": "range_action", 2724 | "named": true 2725 | }, 2726 | { 2727 | "type": "raw_string_literal", 2728 | "named": true 2729 | }, 2730 | { 2731 | "type": "rune_literal", 2732 | "named": true 2733 | }, 2734 | { 2735 | "type": "selector_expression", 2736 | "named": true 2737 | }, 2738 | { 2739 | "type": "template_action", 2740 | "named": true 2741 | }, 2742 | { 2743 | "type": "text", 2744 | "named": true 2745 | }, 2746 | { 2747 | "type": "true", 2748 | "named": true 2749 | }, 2750 | { 2751 | "type": "variable", 2752 | "named": true 2753 | }, 2754 | { 2755 | "type": "variable_definition", 2756 | "named": true 2757 | }, 2758 | { 2759 | "type": "with_action", 2760 | "named": true 2761 | }, 2762 | { 2763 | "type": "yaml_no_injection_text", 2764 | "named": true 2765 | }, 2766 | { 2767 | "type": "{{", 2768 | "named": false 2769 | }, 2770 | { 2771 | "type": "{{-", 2772 | "named": false 2773 | }, 2774 | { 2775 | "type": "}}", 2776 | "named": false 2777 | } 2778 | ] 2779 | } 2780 | } 2781 | }, 2782 | { 2783 | "type": " ", 2784 | "named": false 2785 | }, 2786 | { 2787 | "type": "\"", 2788 | "named": false 2789 | }, 2790 | { 2791 | "type": "$", 2792 | "named": false 2793 | }, 2794 | { 2795 | "type": "(", 2796 | "named": false 2797 | }, 2798 | { 2799 | "type": ")", 2800 | "named": false 2801 | }, 2802 | { 2803 | "type": ",", 2804 | "named": false 2805 | }, 2806 | { 2807 | "type": "-}}", 2808 | "named": false 2809 | }, 2810 | { 2811 | "type": ".", 2812 | "named": false 2813 | }, 2814 | { 2815 | "type": ":=", 2816 | "named": false 2817 | }, 2818 | { 2819 | "type": "=", 2820 | "named": false 2821 | }, 2822 | { 2823 | "type": "block", 2824 | "named": false 2825 | }, 2826 | { 2827 | "type": "break", 2828 | "named": false 2829 | }, 2830 | { 2831 | "type": "comment", 2832 | "named": true 2833 | }, 2834 | { 2835 | "type": "continue", 2836 | "named": false 2837 | }, 2838 | { 2839 | "type": "define", 2840 | "named": false 2841 | }, 2842 | { 2843 | "type": "else", 2844 | "named": false 2845 | }, 2846 | { 2847 | "type": "end", 2848 | "named": false 2849 | }, 2850 | { 2851 | "type": "escape_sequence", 2852 | "named": true 2853 | }, 2854 | { 2855 | "type": "false", 2856 | "named": true 2857 | }, 2858 | { 2859 | "type": "field_identifier", 2860 | "named": true 2861 | }, 2862 | { 2863 | "type": "float_literal", 2864 | "named": true 2865 | }, 2866 | { 2867 | "type": "identifier", 2868 | "named": true 2869 | }, 2870 | { 2871 | "type": "if", 2872 | "named": false 2873 | }, 2874 | { 2875 | "type": "imaginary_literal", 2876 | "named": true 2877 | }, 2878 | { 2879 | "type": "int_literal", 2880 | "named": true 2881 | }, 2882 | { 2883 | "type": "nil", 2884 | "named": true 2885 | }, 2886 | { 2887 | "type": "range", 2888 | "named": false 2889 | }, 2890 | { 2891 | "type": "raw_string_literal", 2892 | "named": true 2893 | }, 2894 | { 2895 | "type": "rune_literal", 2896 | "named": true 2897 | }, 2898 | { 2899 | "type": "template", 2900 | "named": false 2901 | }, 2902 | { 2903 | "type": "true", 2904 | "named": true 2905 | }, 2906 | { 2907 | "type": "with", 2908 | "named": false 2909 | }, 2910 | { 2911 | "type": "yaml_no_injection_text", 2912 | "named": true 2913 | }, 2914 | { 2915 | "type": "{{", 2916 | "named": false 2917 | }, 2918 | { 2919 | "type": "{{-", 2920 | "named": false 2921 | }, 2922 | { 2923 | "type": "|", 2924 | "named": false 2925 | }, 2926 | { 2927 | "type": "}}", 2928 | "named": false 2929 | } 2930 | ] --------------------------------------------------------------------------------