├── .github ├── CODEOWNERS ├── dependabot.yml ├── pull_request_template.md ├── ISSUE_TEMPLATE │ ├── implementation-ticket.yml │ ├── bug-report.yml │ ├── regression-report.yml │ └── feature-request.yml └── workflows │ └── build_python.yml ├── bindings ├── python │ ├── pyproject.toml │ ├── MANIFEST.in │ ├── tree_sitter_jinja2 │ │ └── __init__.py │ ├── README.md │ ├── setup.cfg │ └── setup.py ├── rust │ ├── README.md │ ├── build.rs │ └── lib.rs └── node │ └── binding.cc ├── package.json ├── .gitignore ├── Cargo.toml ├── test └── corpus │ ├── string_tests.txt │ ├── misc_tests.txt │ ├── comment_tests.txt │ ├── integer_tests.txt │ ├── macro_block_tests.txt │ ├── float_tests.txt │ ├── dict_tests.txt │ ├── list_tests.txt │ └── fn_call_tests.txt ├── README.md ├── Makefile ├── grammar.js ├── src ├── tree_sitter │ └── parser.h ├── node-types.json ├── grammar.json └── parser.c ├── CONTRIBUTING.md └── LICENSE /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Owning team for this repo 2 | * @dbt-labs/core-group 3 | -------------------------------------------------------------------------------- /bindings/python/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "wheel", "setuptools-dso==2.0a1"] 3 | -------------------------------------------------------------------------------- /bindings/python/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include pyproject.toml 2 | include include/*.c 3 | include include/tree_sitter/*.h 4 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_jinja2/__init__.py: -------------------------------------------------------------------------------- 1 | from tree_sitter import Language 2 | import setuptools_dso 3 | 4 | so_file = setuptools_dso.find_dso('tree-sitter-jinja2.language') 5 | 6 | JINJA2_LANGUAGE = Language(so_file, 'jinja2') 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-jinja2", 3 | "version": "0.0.1", 4 | "description": "jinja2 grammar for tree-sitter", 5 | "main": "bindings/node", 6 | "keywords": [ 7 | "parsing", 8 | "incremental" 9 | ], 10 | "dependencies": { 11 | "nan": "^2.17.0" 12 | }, 13 | "devDependencies": { 14 | "tree-sitter-cli": "0.20.8" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # npm 2 | node_modules/ 3 | 4 | # tree-sitter targets 5 | *.gyp 6 | *.wasm 7 | index.js 8 | 9 | # python binding targets 10 | bindings/python3/build/ 11 | build/ 12 | bindings/python3/tree-sitter-jinja2/dist/ 13 | bindings/python3/include/*.c 14 | bindings/python3/include/tree_sitter/ 15 | bindings/python3/dist 16 | *.egg-info 17 | *.whl 18 | __pycache__/ 19 | *.py[cod] 20 | 21 | # rust binding targets 22 | Cargo.lock 23 | target/ 24 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # python dependencies 4 | - package-ecosystem: "pip" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | rebase-strategy: "disabled" 9 | 10 | - package-ecosystem: "cargo" 11 | directory: "/" 12 | schedule: 13 | interval: "daily" 14 | rebase-strategy: "disabled" 15 | 16 | # github dependencies 17 | - package-ecosystem: "github-actions" 18 | directory: "/" 19 | schedule: 20 | interval: "weekly" 21 | rebase-strategy: "disabled" 22 | -------------------------------------------------------------------------------- /bindings/rust/README.md: -------------------------------------------------------------------------------- 1 | # Bindings for Rust 2 | 3 | ## To use the bindings in your project: 4 | 5 | `Cargo.toml`: 6 | 7 | ``` 8 | [dependencies] 9 | tree-sitter = "0.19" 10 | tree-sitter-jinja2 = { git = "ssh://git@github.com/dbt-labs/tree-sitter-jinja2", branch =" main" } 11 | ``` 12 | 13 | ```rust 14 | let code = r#"This text supports {{ 'jinja' }}."#; 15 | let mut parser = tree_sitter::Parser::new(); 16 | parser.set_language(tree_sitter_jinja2::language()).expect("Error loading jinja2 grammar"); 17 | let tree = parser.parse(code, None); 18 | ``` 19 | -------------------------------------------------------------------------------- /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 | c_config.compile("parser"); 14 | println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); 15 | } 16 | -------------------------------------------------------------------------------- /bindings/python/README.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/dbt-labs/tree-sitter-jinja2/actions/workflows/build_wheels.yml/badge.svg) 2 | ![](https://pypip.in/v/tree-sitter-jinja2/badge.svg) 3 | 4 | # Bindings for Python 5 | 6 | ## To use the bindings in your project: 7 | 8 | `requirements.txt`: 9 | 10 | ``` 11 | tree-sitter==0.19.0 12 | tree-sitter-jinja2==0.1.0a1 13 | ``` 14 | 15 | ```python 16 | from tree_sitter_jinja2 import JINJA2_LANGUAGE 17 | from tree_sitter import Parser 18 | 19 | source = bytes("{{ True }}", "utf8") 20 | 21 | parser = Parser() 22 | parser.set_language(JINJA2_LANGUAGE) 23 | 24 | tree = parser.parse(source) 25 | ``` 26 | 27 | ## To build the wheel locally 28 | 29 | ``` 30 | make bindings 31 | ``` 32 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tree-sitter-jinja2" 3 | description = "Jinja2 grammar for the tree-sitter parsing library" 4 | version = "0.2.0" 5 | readme = "bindings/rust/README.md" 6 | keywords = ["incremental", "parsing", "jinja"] 7 | categories = ["parsing", "text-editors"] 8 | homepage = "https://github.com/dbt-labs/tree-sitter-jinja2" 9 | repository = "https://github.com/dbt-labs/tree-sitter-jinja2" 10 | edition = "2018" 11 | publish = false 12 | license = "Apache-2.0" 13 | 14 | build = "bindings/rust/build.rs" 15 | include = [ 16 | "bindings/rust/*", 17 | "grammar.js", 18 | "src/*", 19 | ] 20 | 21 | [lib] 22 | path = "bindings/rust/lib.rs" 23 | 24 | [dependencies] 25 | tree-sitter = "0.20.8" 26 | 27 | [build-dependencies] 28 | cc = "*" 29 | -------------------------------------------------------------------------------- /test/corpus/string_tests.txt: -------------------------------------------------------------------------------- 1 | ================== 2 | only jinja syntax in top-level quotes is parsed 3 | ================== 4 | 5 | '{{ "this will be parsed as jinja" }}' 6 | 7 | {{ '{{ this inner jinja is just parsed as a string }}' }} 8 | 9 | --- 10 | 11 | (source_file 12 | (lit_string) 13 | (lit_string) 14 | ) 15 | 16 | ================== 17 | python string escapes work 18 | ================== 19 | 20 | {{ "this \"quoted\" string parses" }} 21 | {{ 'this \'quoted\' string also parses' }} 22 | 23 | --- 24 | 25 | (source_file 26 | (lit_string) 27 | (lit_string) 28 | ) 29 | 30 | ================== 31 | the kind of quotes you use don't matter 32 | ================== 33 | 34 | {{ 'a' }} 35 | {{ "b" }} 36 | 37 | --- 38 | 39 | (source_file 40 | (lit_string) 41 | (lit_string) 42 | ) -------------------------------------------------------------------------------- /bindings/python/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = tree-sitter-jinja2 3 | version = 0.1.0a1 4 | description = A Jinja2 grammar for tree-sitter 5 | long_description = file: README.md 6 | long_description_content_type = text/markdown 7 | url = https://github.com/dbt-labs/tree-sitter-jinja2 8 | author = dbt Labs 9 | author_email = info@dbtlabs.com 10 | classifiers = 11 | Programming Language :: Python :: 3 12 | Programming Language :: Python :: 3 :: Only 13 | Programming Language :: Python :: 3.8 14 | Programming Language :: Python :: 3.9 15 | Programming Language :: Python :: 3.10 16 | Programming Language :: Python :: 3.11 17 | 18 | [options] 19 | python_requires = >=3.8.0 20 | packages = tree_sitter_jinja2 21 | install_requires = 22 | tree_sitter==0.19.0 23 | setuptools-dso==2.0a1 24 | zip_safe = False 25 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | resolves # 2 | 3 | 8 | 9 | ### Description 10 | 11 | 15 | 16 | ### Checklist 17 | 18 | - [ ] I have read [the contributing guide](https://github.com/dbt-labs/tree-sitter-jinja2/blob/main/CONTRIBUTING.md) and understand what's expected of me 19 | - [ ] I have signed the [CLA](https://docs.getdbt.com/docs/contributor-license-agreements) 20 | - [ ] I have run this code in development and it appears to resolve the stated issue 21 | -------------------------------------------------------------------------------- /bindings/python/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | from platform import system 3 | from setuptools_dso import DSO, setup 4 | from setuptools.command.install import install 5 | 6 | 7 | class InstallPlatlib(install): 8 | def finalize_options(self): 9 | install.finalize_options(self) 10 | if self.distribution.has_ext_modules(): 11 | self.install_lib = self.install_platlib 12 | 13 | dso = DSO( 14 | 'tree-sitter-jinja2.language', 15 | [os.path.abspath("include/parser.c")], 16 | include_dirs=[os.path.abspath("include")], 17 | extra_compile_args=( 18 | ["-std=c99", "-fPIC"] if system() != "Windows" else None 19 | ), 20 | ) 21 | 22 | setup( 23 | # fixes issue with manylinux build 24 | # (https://github.com/bigartm/bigartm/issues/840#issuecomment-342825690) 25 | cmdclass={'install': InstallPlatlib}, 26 | x_dsos=[dso], 27 | # this forces platform specific wheels 28 | has_ext_modules=lambda: True 29 | ) 30 | -------------------------------------------------------------------------------- /test/corpus/misc_tests.txt: -------------------------------------------------------------------------------- 1 | ================== 2 | bare words fail 3 | ================== 4 | 5 | {{ text }} 6 | 7 | --- 8 | 9 | (source_file 10 | (ERROR 11 | (identifier) 12 | ) 13 | ) 14 | 15 | ================== 16 | multiple jinja calls 17 | ================== 18 | 19 | some text {{ 'floating lit' }} more text {{ config() }} text. 20 | 21 | --- 22 | 23 | (source_file 24 | (lit_string) 25 | (fn_call 26 | (identifier) 27 | (argument_list) 28 | ) 29 | ) 30 | 31 | ================== 32 | text with curlys works 33 | ================== 34 | 35 | some curlys { } 36 | 37 | --- 38 | 39 | (source_file) 40 | 41 | ================== 42 | doesn't hang on the empty string 43 | ================== 44 | --- 45 | 46 | (source_file) 47 | 48 | ================== 49 | unclosed jinja calls fail 50 | ================== 51 | 52 | {{ fn() 53 | 54 | --- 55 | 56 | (source_file 57 | (fn_call 58 | (identifier) 59 | (argument_list) 60 | ) 61 | (MISSING "}}") 62 | ) 63 | -------------------------------------------------------------------------------- /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_jinja2(); 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_jinja2()); 21 | 22 | Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("jinja2").ToLocalChecked()); 23 | Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance); 24 | } 25 | 26 | NODE_MODULE(tree_sitter_jinja2_binding, Init) 27 | 28 | } // namespace 29 | -------------------------------------------------------------------------------- /test/corpus/comment_tests.txt: -------------------------------------------------------------------------------- 1 | ================== 2 | comments around jinja 3 | ================== 4 | 5 | {# jinja comment #} 6 | {{ True }} 7 | {# jinja comment #} 8 | 9 | --- 10 | 11 | (source_file 12 | (bool) 13 | ) 14 | 15 | ================== 16 | empty comment 17 | ================== 18 | 19 | {##} 20 | {{ True }} 21 | 22 | 23 | --- 24 | 25 | (source_file 26 | (bool) 27 | ) 28 | 29 | ================== 30 | wild comment formatting 31 | ================== 32 | 33 | {{ True }} 34 | {############ 35 | # {comment} # 36 | #############} 37 | {{ False }} 38 | 39 | --- 40 | 41 | (source_file 42 | (bool) 43 | (bool) 44 | ) 45 | 46 | ================== 47 | wild comment formatting 48 | ================== 49 | 50 | {# {{ ref('valid jinja') }} #} 51 | 52 | --- 53 | 54 | (source_file) 55 | 56 | ================== 57 | text ending in a bracket fails 58 | ================== 59 | I'd like this to work, but it doesn't rn and this test 60 | makes a note of that { 61 | --- 62 | 63 | (source_file (ERROR)) 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Understanding tree-sitter-jinja2 2 | 3 | This Jinja2 grammar for tree-sitter is currently incomplete. 4 | 5 | ## Getting started 6 | 7 | ### demo 8 | To run the built-in tree-sitter demo for this grammar: 9 | 10 | - make sure the docker daemon is running 11 | - run `make demo` 12 | 13 | ## Join the dbt Community 14 | 15 | - Be part of the conversation in the [dbt Community Slack](http://community.getdbt.com/) 16 | - Read more on the [dbt Community Discourse](https://discourse.getdbt.com) 17 | 18 | ## Reporting bugs and contributing code 19 | 20 | - Want to report a bug or request a feature? Let us know and open [an issue](https://github.com/dbt-labs/tree-sitter-jinja2/issues/new/choose) 21 | - Want to help us build dbt? Check out the [Contributing Guide](https://github.com/dbt-labs/tree-sitter-jinja2/blob/HEAD/CONTRIBUTING.md) 22 | 23 | ## Code of Conduct 24 | 25 | Everyone interacting in the dbt project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [dbt Code of Conduct](https://community.getdbt.com/code-of-conduct). 26 | -------------------------------------------------------------------------------- /test/corpus/integer_tests.txt: -------------------------------------------------------------------------------- 1 | ================== 2 | zero 3 | ================== 4 | 5 | {{ 0 }} 6 | 7 | --- 8 | 9 | (source_file 10 | (integer) 11 | ) 12 | 13 | ================== 14 | verbose zero 15 | ================== 16 | 17 | {{ 000000 }} 18 | 19 | --- 20 | 21 | (source_file 22 | (integer) 23 | ) 24 | 25 | ================== 26 | negative zero 27 | ================== 28 | 29 | {{ -000000 }} 30 | 31 | --- 32 | 33 | (source_file 34 | (integer) 35 | ) 36 | 37 | ================== 38 | leading zeros 39 | ================== 40 | 41 | {{ 0000001 }} 42 | 43 | --- 44 | 45 | (source_file 46 | (integer) 47 | ) 48 | 49 | ================== 50 | large number 51 | ================== 52 | 53 | {{ 4294967296 }} 54 | 55 | --- 56 | 57 | (source_file 58 | (integer) 59 | ) 60 | 61 | ================== 62 | negative number 63 | ================== 64 | 65 | {{ -4294967296 }} 66 | 67 | --- 68 | 69 | (source_file 70 | (integer) 71 | ) 72 | 73 | ================== 74 | pandigital number 75 | ================== 76 | 77 | {{ -123456789 }} 78 | 79 | --- 80 | 81 | (source_file 82 | (integer) 83 | ) 84 | 85 | ================== 86 | explicit positive 87 | ================== 88 | 89 | {{ +8 }} 90 | 91 | --- 92 | 93 | (source_file 94 | (integer) 95 | ) -------------------------------------------------------------------------------- /test/corpus/macro_block_tests.txt: -------------------------------------------------------------------------------- 1 | ================== 2 | parses a jinja expression 3 | ================== 4 | 5 | select * from table 6 | {% if(True) call_function() %} 7 | select * from other_table 8 | 9 | --- 10 | 11 | (source_file (jinja_expression)) 12 | 13 | ================== 14 | ignores valid syntax in a jinja expression 15 | ================== 16 | 17 | {% ref('my_table') %} 18 | 19 | --- 20 | 21 | (source_file (jinja_expression)) 22 | 23 | 24 | ================== 25 | finds nested jinja expression 26 | ================== 27 | 28 | {{ config(key='value') }} 29 | with 30 | something as ( 31 | select whatever from {{ ref('my_table') }} 32 | where {% is_incremental() %} and my_bool 33 | ), 34 | other as ( 35 | more sql 36 | ) 37 | 38 | --- 39 | 40 | (source_file 41 | (fn_call 42 | (identifier) 43 | (argument_list 44 | (kwarg 45 | (identifier) 46 | (lit_string) 47 | ) 48 | ) 49 | ) 50 | (fn_call 51 | (identifier) 52 | (argument_list 53 | (lit_string) 54 | ) 55 | ) 56 | (jinja_expression) 57 | ) 58 | 59 | ================== 60 | jinja expression recognized over multiple line breaks 61 | ================== 62 | 63 | {% 64 | expression 65 | %} 66 | 67 | --- 68 | 69 | (source_file (jinja_expression)) 70 | 71 | ================== 72 | not a jinja expression 73 | ================== 74 | 75 | {%} 76 | 77 | --- 78 | 79 | (source_file 80 | (ERROR) 81 | ) 82 | -------------------------------------------------------------------------------- /test/corpus/float_tests.txt: -------------------------------------------------------------------------------- 1 | ================== 2 | common zero 3 | ================== 4 | 5 | {{ 0.0 }} 6 | 7 | --- 8 | 9 | (source_file 10 | (float) 11 | ) 12 | 13 | ================== 14 | trailing-point zero 15 | ================== 16 | 17 | {{ 0. }} 18 | 19 | --- 20 | 21 | (source_file 22 | (float) 23 | ) 24 | 25 | ================== 26 | leading-point zero 27 | ================== 28 | 29 | {{ .0 }} 30 | 31 | --- 32 | 33 | (source_file 34 | (float) 35 | ) 36 | 37 | ================== 38 | pi 39 | ================== 40 | 41 | {{ 3.1415926535897932 }} 42 | 43 | --- 44 | 45 | (source_file 46 | (float) 47 | ) 48 | 49 | ================== 50 | exponent 51 | ================== 52 | 53 | {{ 6.02e23 }} 54 | 55 | --- 56 | 57 | (source_file 58 | (float) 59 | ) 60 | 61 | ================== 62 | negative exponent 63 | ================== 64 | 65 | {{ 10e-10 }} 66 | 67 | --- 68 | 69 | (source_file 70 | (float) 71 | ) 72 | 73 | ================== 74 | negative 75 | ================== 76 | 77 | {{ -1.61803398875 }} 78 | 79 | --- 80 | 81 | (source_file 82 | (float) 83 | ) 84 | 85 | ================== 86 | negative leading point 87 | ================== 88 | 89 | {{ -.61803398875 }} 90 | 91 | --- 92 | 93 | (source_file 94 | (float) 95 | ) 96 | 97 | ================== 98 | exponent but no point 99 | ================== 100 | 101 | {{ 6E-32 }} 102 | 103 | --- 104 | 105 | (source_file 106 | (float) 107 | ) 108 | 109 | ================== 110 | explicit positives 111 | ================== 112 | 113 | {{ +6.02e+23 }} 114 | 115 | --- 116 | 117 | (source_file 118 | (float) 119 | ) 120 | 121 | 122 | -------------------------------------------------------------------------------- /test/corpus/dict_tests.txt: -------------------------------------------------------------------------------- 1 | ================== 2 | floating dict 3 | ================== 4 | 5 | {{ {'k':'v', 'list': ['a', 'b']} }} 6 | 7 | --- 8 | 9 | (source_file 10 | (dict 11 | (pair 12 | (lit_string) 13 | (lit_string) 14 | ) 15 | (pair 16 | (lit_string) 17 | (list 18 | (lit_string) 19 | (lit_string) 20 | ) 21 | ) 22 | ) 23 | ) 24 | 25 | ================== 26 | dict as arg 27 | ================== 28 | 29 | {{ config('x', {'k':'v'}) }} 30 | 31 | --- 32 | 33 | (source_file 34 | (fn_call 35 | (identifier) 36 | (argument_list 37 | (lit_string) 38 | (dict 39 | (pair 40 | (lit_string) 41 | (lit_string) 42 | ) 43 | ) 44 | ) 45 | ) 46 | ) 47 | 48 | ================== 49 | proper config call 50 | ================== 51 | 52 | {{ config(x={'k':'v'}) }} 53 | 54 | --- 55 | 56 | (source_file 57 | (fn_call 58 | (identifier) 59 | (argument_list 60 | (kwarg 61 | (identifier) 62 | (dict 63 | (pair 64 | (lit_string) 65 | (lit_string) 66 | ) 67 | ) 68 | ) 69 | ) 70 | ) 71 | ) 72 | 73 | ================== 74 | dict spread over lines 75 | ================== 76 | 77 | {{ { 78 | 'k':'v', 79 | 'x':[] 80 | } }} 81 | 82 | --- 83 | 84 | (source_file 85 | (dict 86 | (pair 87 | (lit_string) 88 | (lit_string) 89 | ) 90 | (pair 91 | (lit_string) 92 | (list) 93 | ) 94 | ) 95 | ) 96 | 97 | ================== 98 | dict with bools 99 | ================== 100 | 101 | {{ {'x':True, 'y': False} }} 102 | 103 | --- 104 | 105 | (source_file 106 | (dict 107 | (pair 108 | (lit_string) 109 | (bool) 110 | ) 111 | (pair 112 | (lit_string) 113 | (bool) 114 | ) 115 | ) 116 | ) 117 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/implementation-ticket.yml: -------------------------------------------------------------------------------- 1 | name: 🛠️ Implementation 2 | description: This is an implementation ticket intended for use by the maintainers of tree-sitter-jinja2 3 | title: "[] " 4 | labels: ["user docs"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: This is an implementation ticket intended for use by the maintainers of tree-sitter-jinja2 9 | - type: checkboxes 10 | attributes: 11 | label: Housekeeping 12 | description: > 13 | A couple friendly reminders: 14 | 1. Link any blocking issues in the "Blocked on" field under the "Core devs & maintainers" project. 15 | options: 16 | - label: I am a maintainer of tree-sitter-jinja2 17 | required: true 18 | - type: textarea 19 | attributes: 20 | label: Short description 21 | description: | 22 | Describe the scope of the ticket, a high-level implementation approach and any tradeoffs to consider 23 | validations: 24 | required: true 25 | - type: textarea 26 | attributes: 27 | label: Acceptance criteria 28 | description: | 29 | What is the definition of done for this ticket? Include any relevant edge cases and/or test cases 30 | validations: 31 | required: true 32 | - type: textarea 33 | attributes: 34 | label: Impact to Other Teams 35 | description: | 36 | Will this change impact other teams? Include details of the kinds of changes required (new tests, code changes, related tickets) and _add the relevant `Impact:[team]` label_. 37 | placeholder: | 38 | Example: This change impacts `dbt-redshift` because the tests will need to be modified. The `Impact:[Adapter]` label has been added. 39 | validations: 40 | required: true 41 | - type: textarea 42 | attributes: 43 | label: Context 44 | description: | 45 | Provide the "why", motivation, and alternative approaches considered -- linking to previous refinement issues, spikes, docs as appropriate 46 | validations: 47 | validations: 48 | required: false 49 | -------------------------------------------------------------------------------- /bindings/rust/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides jinja2 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 = "This text supports {{ 'jinja' }}."; 8 | //! let mut parser = tree_sitter::Parser::new(); 9 | //! parser.set_language(tree_sitter_jinja2::language()).expect("Error loading jinja2 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_jinja2() -> 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_jinja2() } 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 jinja2 language"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /test/corpus/list_tests.txt: -------------------------------------------------------------------------------- 1 | ================== 2 | list of string lits 3 | ================== 4 | 5 | {{ ['a','bc','def'] }} 6 | 7 | --- 8 | 9 | (source_file 10 | (list 11 | (lit_string) 12 | (lit_string) 13 | (lit_string) 14 | ) 15 | ) 16 | 17 | ================== 18 | empty list 19 | ================== 20 | 21 | {{ [] }} 22 | 23 | --- 24 | 25 | (source_file 26 | (list) 27 | ) 28 | 29 | ================== 30 | list with trailing comma 31 | ================== 32 | 33 | {{ ['a','bc','def',] }} 34 | 35 | --- 36 | 37 | (source_file 38 | (list 39 | (lit_string) 40 | (lit_string) 41 | (lit_string) 42 | ) 43 | ) 44 | 45 | ================== 46 | config with list of string lits 47 | ================== 48 | 49 | {{ 50 | config( 51 | k='v', 52 | k2='v2', 53 | list=['a','bc','def'] 54 | ) 55 | }} 56 | 57 | --- 58 | 59 | (source_file 60 | (fn_call 61 | (identifier) 62 | (argument_list 63 | (kwarg 64 | (identifier) 65 | (lit_string) 66 | ) 67 | (kwarg 68 | (identifier) 69 | (lit_string) 70 | ) 71 | (kwarg 72 | (identifier) 73 | (list 74 | (lit_string) 75 | (lit_string) 76 | (lit_string) 77 | ) 78 | ) 79 | ) 80 | ) 81 | ) 82 | 83 | ================== 84 | deeply nested lists and dicts 85 | ================== 86 | 87 | "{{ [{'k':['v', {'x': 'y'}]}, ['a', 'b', 'c']] }}" 88 | 89 | --- 90 | 91 | (source_file 92 | (list 93 | (dict 94 | (pair 95 | (lit_string) 96 | (list 97 | (lit_string) 98 | (dict 99 | (pair 100 | (lit_string) 101 | (lit_string) 102 | ) 103 | ) 104 | ) 105 | ) 106 | ) 107 | (list 108 | (lit_string) 109 | (lit_string) 110 | (lit_string) 111 | ) 112 | ) 113 | ) 114 | 115 | ================== 116 | list with booleans 117 | ================== 118 | 119 | {{ [True, False, 'string'] }} 120 | 121 | --- 122 | 123 | (source_file 124 | (list 125 | (bool) 126 | (bool) 127 | (lit_string) 128 | ) 129 | ) -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug 2 | description: Report a bug or an issue you've found with tree-sitter-jinja2 3 | title: "[Bug] <title>" 4 | labels: ["bug", "triage"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this bug report! 10 | - type: checkboxes 11 | attributes: 12 | label: Is this a new bug in tree-sitter-jinja2? 13 | description: > 14 | In other words, is this an error, flaw, failure or fault in our software? 15 | 16 | If this is a bug that broke existing functionality that used to work, please open a regression issue. 17 | 18 | Please search to see if an issue already exists for the bug you encountered. 19 | options: 20 | - label: I believe this is a new bug in tree-sitter-jinja2 21 | required: true 22 | - label: I have searched the existing issues, and I could not find an existing issue for this bug 23 | required: true 24 | - type: textarea 25 | attributes: 26 | label: Current Behavior 27 | description: A concise description of what you're experiencing. 28 | validations: 29 | required: true 30 | - type: textarea 31 | attributes: 32 | label: Expected Behavior 33 | description: A concise description of what you expected to happen. 34 | validations: 35 | required: true 36 | - type: textarea 37 | attributes: 38 | label: Steps To Reproduce 39 | description: Steps to reproduce the behavior. 40 | placeholder: | 41 | 1. In this environment... 42 | 2. With this config... 43 | 3. Run '...' 44 | 4. See error... 45 | validations: 46 | required: true 47 | - type: textarea 48 | id: logs 49 | attributes: 50 | label: Relevant log output 51 | description: | 52 | If applicable, log output to help explain your problem. 53 | render: shell 54 | validations: 55 | required: false 56 | - type: textarea 57 | attributes: 58 | label: Additional Context 59 | description: | 60 | Links? References? Anything that will give us more context about the issue you are encountering! 61 | 62 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. 63 | validations: 64 | required: false 65 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/regression-report.yml: -------------------------------------------------------------------------------- 1 | name: ☣️ Regression 2 | description: Report a regression you've observed in a newer version of tree-sitter-jinja2 3 | title: "[Regression] <title>" 4 | labels: ["bug", "regression", "triage"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this regression report! 10 | - type: checkboxes 11 | attributes: 12 | label: Is this a regression in a recent version of tree-sitter-jinja2? 13 | description: > 14 | A regression is when documented functionality works as expected in an older version of tree-sitter-jinja2, 15 | and no longer works after upgrading to a newer version of tree-sitter-jinja2 16 | options: 17 | - label: I believe this is a regression in tree-sitter-jinja2 functionality 18 | required: true 19 | - label: I have searched the existing issues, and I could not find an existing issue for this regression 20 | required: true 21 | - type: textarea 22 | attributes: 23 | label: Current Behavior 24 | description: A concise description of what you're experiencing. 25 | validations: 26 | required: true 27 | - type: textarea 28 | attributes: 29 | label: Expected/Previous Behavior 30 | description: A concise description of what you expected to happen. 31 | validations: 32 | required: true 33 | - type: textarea 34 | attributes: 35 | label: Steps To Reproduce 36 | description: Steps to reproduce the behavior. 37 | placeholder: | 38 | 1. In this environment... 39 | 2. With this config... 40 | 3. Run '...' 41 | 4. See error... 42 | validations: 43 | required: true 44 | - type: textarea 45 | id: logs 46 | attributes: 47 | label: Relevant log output 48 | description: | 49 | If applicable, log output to help explain your problem. 50 | render: shell 51 | validations: 52 | required: false 53 | - type: textarea 54 | attributes: 55 | label: Additional Context 56 | description: | 57 | Links? References? Anything that will give us more context about the issue you are encountering! 58 | 59 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. 60 | validations: 61 | required: false 62 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: ✨ Feature 2 | description: Propose a straightforward extension of dbt-oss-template functionality 3 | title: "[Feature] <title>" 4 | labels: ["enhancement", "triage"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this feature request! 10 | - type: checkboxes 11 | attributes: 12 | label: Is this your first time submitting a feature request? 13 | description: > 14 | We want to make sure that features are distinct and discoverable, 15 | so that other members of the community can find them and offer their thoughts. 16 | options: 17 | - label: I have read the [expectations for open source contributors](https://docs.getdbt.com/docs/contributing/oss-expectations) 18 | required: true 19 | - label: I have searched the existing issues, and I could not find an existing issue for this feature 20 | required: true 21 | - label: I am requesting a straightforward extension of existing `tree-sitter-jinja2` functionality, rather than a Big Idea better suited to a discussion 22 | required: true 23 | - type: textarea 24 | attributes: 25 | label: Describe the feature 26 | description: A clear and concise description of what you want to happen. 27 | validations: 28 | required: true 29 | - type: textarea 30 | attributes: 31 | label: Describe alternatives you've considered 32 | description: | 33 | A clear and concise description of any alternative solutions or features you've considered. 34 | validations: 35 | required: false 36 | - type: textarea 37 | attributes: 38 | label: Who will this benefit? 39 | description: | 40 | What kind of use case will this feature be useful for? Please be specific and provide examples, this will help us prioritize properly. 41 | validations: 42 | required: false 43 | - type: input 44 | attributes: 45 | label: Are you interested in contributing this feature? 46 | description: Let us know if you want to write some code, and how we can help. 47 | validations: 48 | required: false 49 | - type: textarea 50 | attributes: 51 | label: Anything else? 52 | description: | 53 | Links? References? Anything that will give us more context about the feature you are suggesting! 54 | validations: 55 | required: false 56 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # toggles logging via `make <target-name> LOG=true` 2 | ifeq "$(LOG)" "" 3 | LOG=false 4 | endif 5 | 6 | ifeq "$(LOG)" "false" 7 | L=@ 8 | endif 9 | 10 | # system agnostic rm -f 11 | ifdef ComSpec 12 | RMF=del /F /Q 13 | else 14 | RMF=rm -f 15 | endif 16 | 17 | # system agnostic rm -rf 18 | ifdef ComSpec 19 | RMRF=rmdir /S /Q 20 | else 21 | RMRF=rm -rf 22 | endif 23 | 24 | # system agnostic find --delete 25 | define rm_all 26 | $(if $(ComSpec), del /S /Q $(1), find . -type f -name '$(1)' -delete) 27 | endef 28 | 29 | # system agnostic cp 30 | ifdef ComSpec 31 | CP=xcopy /R /H /Y 32 | else 33 | CP=cp 34 | endif 35 | 36 | # system agnostic command seprator 37 | ifdef ComSpec 38 | CMDSEP=& 39 | else 40 | CMDSEP=&& 41 | endif 42 | 43 | # system agnostic path separators 44 | ifdef ComSpec 45 | PATHSEP2=\\ 46 | else 47 | PATHSEP2=/ 48 | endif 49 | PATHSEP=$(strip $(PATHSEP2)) 50 | 51 | # system agnostic ls (mostly for debugging the makefile) 52 | ifdef ComSpec 53 | LS=dir 54 | else 55 | LS=ls 56 | endif 57 | 58 | # system agnostic renaming 59 | ifdef ComSpec 60 | RENAME=ren 61 | else 62 | RENAME=mv 63 | endif 64 | 65 | # system agnostic cat 66 | ifdef ComSpec 67 | CAT=type 68 | else 69 | CAT=cat 70 | endif 71 | 72 | # without args just build the project 73 | .PHONY: all 74 | all: build 75 | 76 | # installs npm dependencies 77 | node_modules/tree-sitter-cli/tree-sitter/: 78 | $(L)npm install 79 | 80 | .PHONY: install 81 | install: node_modules/tree-sitter-cli/tree-sitter/ 82 | $(L)python -m pip install --upgrade pip 83 | $(L)pip install wheel setuptools-dso==2.0a1 build 84 | 85 | # build tree-sitter 86 | .PHONY: build 87 | build: install 88 | $(L)npx tree-sitter generate 89 | 90 | # prepare to build bindings 91 | .PHONY: prebindings 92 | prebindings: build 93 | $(L)$(CAT) src$(PATHSEP)parser.c > bindings$(PATHSEP)python$(PATHSEP)include$(PATHSEP)parser.c $(CMDSEP) mkdir bindings$(PATHSEP)python$(PATHSEP)include$(PATHSEP)tree_sitter$(PATHSEP) $(CMDSEP) $(CP) src$(PATHSEP)tree_sitter$(PATHSEP)parser.h bindings$(PATHSEP)python$(PATHSEP)include$(PATHSEP)tree_sitter$(PATHSEP) 94 | 95 | # build bindings 96 | .PHONY: bindings 97 | bindings: prebindings 98 | $(L)cd bindings$(PATHSEP)python $(CMDSEP) python -m build --wheel 99 | 100 | # runs the tree-sitter unit tests 101 | .PHONY: test 102 | test: build 103 | $(L)npx tree-sitter test 104 | 105 | # docker must be running. build-wasm stage will print that error though 106 | .PHONY: build 107 | demo: build 108 | $(L)npx tree-sitter build-wasm \ 109 | $(CMDSEP) npx tree-sitter web-ui 110 | 111 | .PHONY: clean 112 | clean: 113 | $(L)$(RMRF) node_modules 114 | $(L)$(RMF) index.js 115 | $(L)$(RMRF) src 116 | $(L)$(RMRF) build 117 | $(L)$(call rm_all,*.wasm) 118 | $(L)$(call rm_all,*.gyp) 119 | $(L)$(RMRF) build 120 | $(L)$(RMRF) bindings$(PATHSEP)python$(PATHSEP)include 121 | $(L)$(RMRF) bindings$(PATHSEP)python$(PATHSEP)dist 122 | $(L)mkdir bindings$(PATHSEP)python$(PATHSEP)include 123 | $(L)echo # > bindings$(PATHSEP)python$(PATHSEP)include$(PATHSEP).gitignore 124 | -------------------------------------------------------------------------------- /test/corpus/fn_call_tests.txt: -------------------------------------------------------------------------------- 1 | ================== 2 | Ref with string literal 3 | ================== 4 | 5 | select * from {{ ref('my_table') }} 6 | 7 | --- 8 | 9 | (source_file 10 | (fn_call 11 | (identifier) 12 | (argument_list 13 | (lit_string) 14 | ) 15 | ) 16 | ) 17 | 18 | ================== 19 | Ref with bare words fails 20 | ================== 21 | 22 | select * from {{ ref(not_a_string) }} 23 | 24 | --- 25 | 26 | (source_file 27 | (fn_call 28 | (identifier) 29 | (argument_list 30 | (ERROR 31 | (identifier) 32 | ) 33 | ) 34 | ) 35 | ) 36 | 37 | ================== 38 | Config with one kwarg 39 | ================== 40 | 41 | {{ config(key='value') }} 42 | 43 | --- 44 | 45 | (source_file 46 | (fn_call 47 | (identifier) 48 | (argument_list 49 | (kwarg 50 | (identifier) 51 | (lit_string) 52 | ) 53 | ) 54 | ) 55 | ) 56 | 57 | ================== 58 | Config with two kwargs 59 | ================== 60 | 61 | {{ config(key='value', key2='value2') }} 62 | 63 | --- 64 | 65 | (source_file 66 | (fn_call 67 | (identifier) 68 | (argument_list 69 | (kwarg 70 | (identifier) 71 | (lit_string) 72 | ) 73 | (kwarg 74 | (identifier) 75 | (lit_string) 76 | ) 77 | ) 78 | ) 79 | ) 80 | 81 | ================== 82 | Fn with a kwarg, string lit, list, and dict 83 | ================== 84 | 85 | {{ config( 86 | key='value', 87 | 'lit', 88 | {'key':'value'}, 89 | ['a','b'] 90 | ) }} 91 | 92 | --- 93 | 94 | (source_file 95 | (fn_call 96 | (identifier) 97 | (argument_list 98 | (kwarg 99 | (identifier) 100 | (lit_string) 101 | ) 102 | (lit_string) 103 | (dict 104 | (pair 105 | (lit_string) 106 | (lit_string) 107 | ) 108 | ) 109 | (list 110 | (lit_string) 111 | (lit_string) 112 | ) 113 | ) 114 | ) 115 | ) 116 | 117 | ================== 118 | parses other fn names 119 | ================== 120 | 121 | {{ fn() }} 122 | 123 | --- 124 | 125 | (source_file 126 | (fn_call 127 | (identifier) 128 | (argument_list) 129 | ) 130 | ) 131 | 132 | ================== 133 | buried fn names 134 | ================== 135 | 136 | select 137 | field1, 138 | field2, 139 | field3 140 | from {{ ref('x') }} 141 | join {{ ref('y') }} 142 | 143 | --- 144 | 145 | (source_file 146 | (fn_call 147 | (identifier) 148 | (argument_list 149 | (lit_string) 150 | ) 151 | ) 152 | (fn_call 153 | (identifier) 154 | (argument_list 155 | (lit_string) 156 | ) 157 | ) 158 | ) 159 | 160 | ================== 161 | bool args 162 | ================== 163 | 164 | {{ fn(True) }} 165 | 166 | --- 167 | 168 | (source_file 169 | (fn_call 170 | (identifier) 171 | (argument_list 172 | (bool) 173 | ) 174 | ) 175 | ) 176 | 177 | ================== 178 | bool kwargs 179 | ================== 180 | 181 | {{ config(bind=False) }} 182 | 183 | --- 184 | 185 | (source_file 186 | (fn_call 187 | (identifier) 188 | (argument_list 189 | (kwarg 190 | (identifier) 191 | (bool) 192 | ) 193 | ) 194 | ) 195 | ) 196 | 197 | ================== 198 | True is an invalid fn name 199 | ================== 200 | 201 | {{ True() }} 202 | 203 | --- 204 | 205 | (source_file 206 | (ERROR 207 | (bool) 208 | ) 209 | ) 210 | -------------------------------------------------------------------------------- /grammar.js: -------------------------------------------------------------------------------- 1 | 2 | // Note: if you ever need to explicitly match line breaks, those are system specific. 3 | // use a regex like this \r\n?|\n to match on windows too. 4 | 5 | function commaSep1(rule) { 6 | return sep1(rule, ','); 7 | } 8 | 9 | function sep1(rule, separator) { 10 | return seq(rule, repeat(seq(separator, rule))) 11 | } 12 | 13 | module.exports = grammar ({ 14 | name: 'jinja2', 15 | 16 | rules: { 17 | source_file: $ => repeat( 18 | choice( 19 | $._jinja_value, 20 | $.jinja_expression, 21 | $._jinja_comment, 22 | $._text 23 | ) 24 | ), 25 | 26 | _jinja_value: $ => seq( 27 | '{{', 28 | $._expr, 29 | '}}' 30 | ), 31 | 32 | // This is awkward regex because we aren't parsing anything 33 | // in between the expression markers like _jinja_value does 34 | jinja_expression: $ => seq( 35 | '{%', 36 | new RegExp( 37 | '(' + // capture group 38 | '[^%]' + // any character that isn't a `%` 39 | '|' + // or 40 | '%[^}]' + // a `%` followed by any character that isn't `}` 41 | ')*' + // zero or more of the previous capture group 42 | '%}' // followed by a `%` then a `}` 43 | ) 44 | ), 45 | 46 | // comment regex is special because a comment can end 47 | // with #} ##} #######} etc. 48 | _jinja_comment: $ => seq( 49 | '{#', // comments start with `{#` 50 | new RegExp( 51 | '(' + // capture group 52 | '(' + // capture group 53 | '[^#]' + // any character that isn't `#` 54 | '|' + // or 55 | '#[^}]' + // a `#` character followed by another character that isn't `}` 56 | ')*' + // zero or more of the previous capture group 57 | ')#+}' // followed by at least one `#` and a `}` 58 | ) 59 | ), 60 | 61 | _expr: $ => choice( 62 | $.fn_call, 63 | $.list, 64 | $.dict, 65 | $.lit_string, 66 | $.bool, 67 | $.integer, 68 | $.float, 69 | ), 70 | 71 | fn_call: $ => seq( 72 | field('fn_name', $.identifier), 73 | field('argument_list', $.argument_list) 74 | ), 75 | 76 | argument_list: $ => seq( 77 | '(', 78 | optional(commaSep1( 79 | choice( 80 | $._expr, 81 | $.kwarg 82 | ) 83 | )), 84 | optional(','), 85 | ')' 86 | ), 87 | 88 | lit_string: $ => choice( 89 | seq( 90 | "'", // single quote string start 91 | /([^']|\\')*/, // either not a `'` or a `\` followed by a `'` zero or more times 92 | "'", // single quote string start 93 | ), 94 | seq( 95 | '"', // double quote string start 96 | /([^"]|\\")*/, // either not a `"` or a `\` followed by a `"` zero or more times 97 | '"', // double quote string start 98 | ) 99 | ), 100 | 101 | bool: $ => choice( 102 | 'True', 103 | 'False' 104 | ), 105 | 106 | list: $ => seq( 107 | '[', 108 | optional(commaSep1($._expr)), 109 | optional(','), 110 | ']' 111 | ), 112 | 113 | dict: $ => seq( 114 | '{', 115 | optional(commaSep1($.pair)), 116 | optional(','), 117 | '}' 118 | ), 119 | 120 | pair: $ => seq( 121 | field('key', $.lit_string), 122 | ':', 123 | field('value', $._expr) 124 | ), 125 | 126 | identifier: $ => $._identifier, 127 | 128 | // This regex is fine until we allow user-named variables and functions. 129 | // Once we do that we may want to allow Unicode identifiers like python does: /[_\p{XID_Start}][_\p{XID_Continue}]*/ 130 | _identifier: $ => token(new RegExp( 131 | '[a-zA-Z_]' + // starts with a lower or upper letter or an underscore 132 | '[a-zA-Z0-9_]*' // all following characters must be a lower or upper letter, digit, or underscore. 133 | )), 134 | 135 | kwarg: $ => seq( 136 | field("key", $.identifier), 137 | '=', 138 | field("value", $._expr), 139 | ), 140 | 141 | // matches everything but jinja 142 | _text: $ => new RegExp( 143 | '(' + // capture group 144 | '[^{]' + // match any character that is not `{` 145 | '|' + // or 146 | '[{][^{%#]' + // match a character that IS `{` and isn't followed by `{`, `%`, or`#` 147 | ')' + // end capture group 148 | '+' // one or more times. using this instead of * because tree-sitter can hang when matching the empty string. 149 | ), 150 | 151 | integer: $ => token( 152 | seq( 153 | optional(/[\+-]/), 154 | repeat1(/_?[0-9]+/), 155 | ) 156 | ), 157 | 158 | float: $ => { 159 | const digits = repeat1(/[0-9]+_?/); 160 | const exponent = seq(/[eE][\+-]?/, digits) 161 | const sign = /[\+-]/ 162 | 163 | return token( 164 | choice( 165 | seq(optional(sign), digits, '.', optional(digits), optional(exponent)), 166 | seq(optional(sign), optional(digits), '.', digits, optional(exponent)), 167 | seq(digits, exponent) 168 | ) 169 | ) 170 | }, 171 | } 172 | }); 173 | -------------------------------------------------------------------------------- /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 <stdbool.h> 9 | #include <stdint.h> 10 | #include <stdlib.h> 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 | typedef uint16_t TSStateId; 17 | 18 | #ifndef TREE_SITTER_API_H_ 19 | typedef uint16_t TSSymbol; 20 | typedef uint16_t TSFieldId; 21 | typedef struct TSLanguage TSLanguage; 22 | #endif 23 | 24 | typedef struct { 25 | TSFieldId field_id; 26 | uint8_t child_index; 27 | bool inherited; 28 | } TSFieldMapEntry; 29 | 30 | typedef struct { 31 | uint16_t index; 32 | uint16_t length; 33 | } TSFieldMapSlice; 34 | 35 | typedef struct { 36 | bool visible; 37 | bool named; 38 | bool supertype; 39 | } TSSymbolMetadata; 40 | 41 | typedef struct TSLexer TSLexer; 42 | 43 | struct TSLexer { 44 | int32_t lookahead; 45 | TSSymbol result_symbol; 46 | void (*advance)(TSLexer *, bool); 47 | void (*mark_end)(TSLexer *); 48 | uint32_t (*get_column)(TSLexer *); 49 | bool (*is_at_included_range_start)(const TSLexer *); 50 | bool (*eof)(const TSLexer *); 51 | }; 52 | 53 | typedef enum { 54 | TSParseActionTypeShift, 55 | TSParseActionTypeReduce, 56 | TSParseActionTypeAccept, 57 | TSParseActionTypeRecover, 58 | } TSParseActionType; 59 | 60 | typedef union { 61 | struct { 62 | uint8_t type; 63 | TSStateId state; 64 | bool extra; 65 | bool repetition; 66 | } shift; 67 | struct { 68 | uint8_t type; 69 | uint8_t child_count; 70 | TSSymbol symbol; 71 | int16_t dynamic_precedence; 72 | uint16_t production_id; 73 | } reduce; 74 | uint8_t type; 75 | } TSParseAction; 76 | 77 | typedef struct { 78 | uint16_t lex_state; 79 | uint16_t external_lex_state; 80 | } TSLexMode; 81 | 82 | typedef union { 83 | TSParseAction action; 84 | struct { 85 | uint8_t count; 86 | bool reusable; 87 | } entry; 88 | } TSParseActionEntry; 89 | 90 | struct TSLanguage { 91 | uint32_t version; 92 | uint32_t symbol_count; 93 | uint32_t alias_count; 94 | uint32_t token_count; 95 | uint32_t external_token_count; 96 | uint32_t state_count; 97 | uint32_t large_state_count; 98 | uint32_t production_id_count; 99 | uint32_t field_count; 100 | uint16_t max_alias_sequence_length; 101 | const uint16_t *parse_table; 102 | const uint16_t *small_parse_table; 103 | const uint32_t *small_parse_table_map; 104 | const TSParseActionEntry *parse_actions; 105 | const char * const *symbol_names; 106 | const char * const *field_names; 107 | const TSFieldMapSlice *field_map_slices; 108 | const TSFieldMapEntry *field_map_entries; 109 | const TSSymbolMetadata *symbol_metadata; 110 | const TSSymbol *public_symbol_map; 111 | const uint16_t *alias_map; 112 | const TSSymbol *alias_sequences; 113 | const TSLexMode *lex_modes; 114 | bool (*lex_fn)(TSLexer *, TSStateId); 115 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 116 | TSSymbol keyword_capture_token; 117 | struct { 118 | const bool *states; 119 | const TSSymbol *symbol_map; 120 | void *(*create)(void); 121 | void (*destroy)(void *); 122 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 123 | unsigned (*serialize)(void *, char *); 124 | void (*deserialize)(void *, const char *, unsigned); 125 | } external_scanner; 126 | const TSStateId *primary_state_ids; 127 | }; 128 | 129 | /* 130 | * Lexer Macros 131 | */ 132 | 133 | #define START_LEXER() \ 134 | bool result = false; \ 135 | bool skip = false; \ 136 | bool eof = false; \ 137 | int32_t lookahead; \ 138 | goto start; \ 139 | next_state: \ 140 | lexer->advance(lexer, skip); \ 141 | start: \ 142 | skip = false; \ 143 | lookahead = lexer->lookahead; 144 | 145 | #define ADVANCE(state_value) \ 146 | { \ 147 | state = state_value; \ 148 | goto next_state; \ 149 | } 150 | 151 | #define SKIP(state_value) \ 152 | { \ 153 | skip = true; \ 154 | state = state_value; \ 155 | goto next_state; \ 156 | } 157 | 158 | #define ACCEPT_TOKEN(symbol_value) \ 159 | result = true; \ 160 | lexer->result_symbol = symbol_value; \ 161 | lexer->mark_end(lexer); 162 | 163 | #define END_STATE() return result; 164 | 165 | /* 166 | * Parse Table Macros 167 | */ 168 | 169 | #define SMALL_STATE(id) id - LARGE_STATE_COUNT 170 | 171 | #define STATE(id) id 172 | 173 | #define ACTIONS(id) id 174 | 175 | #define SHIFT(state_value) \ 176 | {{ \ 177 | .shift = { \ 178 | .type = TSParseActionTypeShift, \ 179 | .state = state_value \ 180 | } \ 181 | }} 182 | 183 | #define SHIFT_REPEAT(state_value) \ 184 | {{ \ 185 | .shift = { \ 186 | .type = TSParseActionTypeShift, \ 187 | .state = state_value, \ 188 | .repetition = true \ 189 | } \ 190 | }} 191 | 192 | #define SHIFT_EXTRA() \ 193 | {{ \ 194 | .shift = { \ 195 | .type = TSParseActionTypeShift, \ 196 | .extra = true \ 197 | } \ 198 | }} 199 | 200 | #define REDUCE(symbol_val, child_count_val, ...) \ 201 | {{ \ 202 | .reduce = { \ 203 | .type = TSParseActionTypeReduce, \ 204 | .symbol = symbol_val, \ 205 | .child_count = child_count_val, \ 206 | __VA_ARGS__ \ 207 | }, \ 208 | }} 209 | 210 | #define RECOVER() \ 211 | {{ \ 212 | .type = TSParseActionTypeRecover \ 213 | }} 214 | 215 | #define ACCEPT_INPUT() \ 216 | {{ \ 217 | .type = TSParseActionTypeAccept \ 218 | }} 219 | 220 | #ifdef __cplusplus 221 | } 222 | #endif 223 | 224 | #endif // TREE_SITTER_PARSER_H_ 225 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to `tree-sitter-jinja2` 2 | 3 | `tree-sitter-jinja2` is a Jinja2 grammar for tree-sitter. At present, the jinja grammar described in this repo is highly simplified and incomplete. It is primarily intended to support dbt-extractor. It may be elaborated in the future. 4 | 5 | 6 | 1. [About this document](#about-this-document) 7 | 2. [Getting the code](#getting-the-code) 8 | 3. [Setting up an environment](#setting-up-an-environment) 9 | 4. [Running in development](#running-tree-sitter-jinja2-in-development) 10 | 5. [Testing](#testing) 11 | 6. [Debugging](#debugging) 12 | 7. [Adding or modifying a changelog entry](#adding-or-modifying-a-changelog-entry) 13 | 8. [Submitting a Pull Request](#submitting-a-pull-request) 14 | 9. [Troubleshooting Tips](#troubleshooting-tips) 15 | 16 | ## About this document 17 | 18 | There are many ways to contribute to the ongoing development of `tree-sitter-jinja2`, such as by participating in discussions and issues. We encourage you to first read our higher-level document: ["Expectations for Open Source Contributors"](https://docs.getdbt.com/docs/contributing/oss-expectations). 19 | 20 | The rest of this document serves as a more granular guide for contributing code changes to `tree-sitter-jinja2` (this repository). It is not intended as a guide for using `tree-sitter-jinja2`, and some pieces assume a level of familiarity with Python development (virtualenvs, `pip`, etc), JavaScript, and Node.js. Specific code snippets in this guide assume you are using macOS or Linux and are comfortable with the command line. 21 | 22 | ### Notes 23 | 24 | - **CLA:** Please note that anyone contributing code to `tree-sitter-jinja2` must sign the [Contributor License Agreement](https://docs.getdbt.com/docs/contributor-license-agreements). If you are unable to sign the CLA, the `tree-sitter-jinja2` maintainers will unfortunately be unable to merge any of your Pull Requests. We welcome you to participate in discussions, open issues, and comment on existing ones. 25 | - **Branches:** All pull requests from community contributors should target the `main` branch (default). 26 | - **Releases**: This repository is released on an as needed basis. 27 | 28 | ## Getting the code 29 | 30 | ### Installing git 31 | 32 | You will need `git` in order to download and modify the source code. 33 | 34 | ### External contributors 35 | 36 | If you are not a member of the `dbt-labs` GitHub organization, you can contribute to `tree-sitter-jinja2` by forking the `tree-sitter-jinja2` repository. For a detailed overview on forking, check out the [GitHub docs on forking](https://help.github.com/en/articles/fork-a-repo). In short, you will need to: 37 | 38 | 1. Fork the `tree-sitter-jinja2` repository 39 | 2. Clone your fork locally 40 | 3. Check out a new branch for your proposed changes 41 | 4. Push changes to your fork 42 | 5. Open a pull request against `dbt-labs/tree-sitter-jinja2` from your forked repository 43 | 44 | ### dbt Labs contributors 45 | 46 | If you are a member of the `dbt-labs` GitHub organization, you will have push access to the `tree-sitter-jinja2` repo. Rather than forking `tree-sitter-jinja2` to make your changes, just clone the repository, check out a new branch, and push directly to that branch. 47 | 48 | ## Building `tree-sitter-jinja2` 49 | 50 | ### Requirements 51 | 52 | In order to build `tree-sitter-jinja2`, you will need to have Python 3 and Node.js installed. 53 | 54 | 55 | ### Building `tree-sitter-jinja2` 56 | 57 | Once you have the requirements installed, you can move to the repo root directory and run the command `make build` to convert the grammar description into parser source code. The build output is C source code which can be found in the `src` subdirectory. 58 | 59 | ## Testing 60 | 61 | Once you're able to manually test that your code change is working as expected, it's important to run existing automated tests, as well as adding some new ones. These tests will ensure that: 62 | - Your code changes do not unexpectedly break other established functionality 63 | - Your code changes can handle all known edge cases 64 | - The functionality you're adding will _keep_ working in the future 65 | 66 | ### Test commands 67 | 68 | In the repo root directory, run the command `make test` to run the unit tests. 69 | 70 | ### Test 71 | 72 | Tests are defined by plain text files located in `tree-sitter-jinja2/tests/corpus`. A test file contains a sequence of named test cases, each with a jinja block and expected parse tree. 73 | 74 | For example, the following test case will appear in test output as `dict with bools`. It parses a jinja source file consisting of a block containing a simple dict. The resulting parse tree is compared to the expected parse tree defined below the jinja as an S-expression. If the actual parse tree matches the expected parse tree, the test passes. 75 | 76 | ``` 77 | ================== 78 | dict with bools 79 | ================== 80 | 81 | {{ {'x':True, 'y': False} }} 82 | 83 | --- 84 | 85 | (source_file 86 | (dict 87 | (pair 88 | (lit_string) 89 | (bool) 90 | ) 91 | (pair 92 | (lit_string) 93 | (bool) 94 | ) 95 | ) 96 | ) 97 | ``` 98 | 99 | ## Debugging 100 | 101 | See the tree-sitter documentation for information about debugging a grammar. 102 | 103 | 104 | ## Submitting a Pull Request 105 | 106 | Code can be merged into the current development branch `main` by opening a pull request. A `tree-sitter-jinja2` maintainer will review your PR. They may suggest code revision for style or clarity, or request that you add unit or integration test(s). These are good things! We believe that, with a little bit of help, anyone can contribute high-quality code. 107 | 108 | Automated tests run via GitHub Actions. If you're a first-time contributor, all tests (including code checks and unit tests) will require a maintainer to approve. Changes in the `tree-sitter-jinja2` repository trigger integration tests against Postgres. dbt Labs also provides CI environments in which to test changes to other adapters, triggered by PRs in those adapters' repositories, as well as periodic maintenance checks of each adapter in concert with the latest `tree-sitter-jinja2` code changes. 109 | 110 | Once all tests are passing and your PR has been approved, a `tree-sitter-jinja2` maintainer will merge your changes into the active development branch. And that's it! Happy developing :tada: 111 | 112 | ## Troubleshooting Tips 113 | - Sometimes, the content license agreement auto-check bot doesn't find a user's entry in its roster. If you need to force a rerun, add `@cla-bot check` in a comment on the pull request. 114 | -------------------------------------------------------------------------------- /src/node-types.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "argument_list", 4 | "named": true, 5 | "fields": {}, 6 | "children": { 7 | "multiple": true, 8 | "required": false, 9 | "types": [ 10 | { 11 | "type": "bool", 12 | "named": true 13 | }, 14 | { 15 | "type": "dict", 16 | "named": true 17 | }, 18 | { 19 | "type": "float", 20 | "named": true 21 | }, 22 | { 23 | "type": "fn_call", 24 | "named": true 25 | }, 26 | { 27 | "type": "integer", 28 | "named": true 29 | }, 30 | { 31 | "type": "kwarg", 32 | "named": true 33 | }, 34 | { 35 | "type": "list", 36 | "named": true 37 | }, 38 | { 39 | "type": "lit_string", 40 | "named": true 41 | } 42 | ] 43 | } 44 | }, 45 | { 46 | "type": "bool", 47 | "named": true, 48 | "fields": {} 49 | }, 50 | { 51 | "type": "dict", 52 | "named": true, 53 | "fields": {}, 54 | "children": { 55 | "multiple": true, 56 | "required": false, 57 | "types": [ 58 | { 59 | "type": "pair", 60 | "named": true 61 | } 62 | ] 63 | } 64 | }, 65 | { 66 | "type": "fn_call", 67 | "named": true, 68 | "fields": { 69 | "argument_list": { 70 | "multiple": false, 71 | "required": true, 72 | "types": [ 73 | { 74 | "type": "argument_list", 75 | "named": true 76 | } 77 | ] 78 | }, 79 | "fn_name": { 80 | "multiple": false, 81 | "required": true, 82 | "types": [ 83 | { 84 | "type": "identifier", 85 | "named": true 86 | } 87 | ] 88 | } 89 | } 90 | }, 91 | { 92 | "type": "identifier", 93 | "named": true, 94 | "fields": {} 95 | }, 96 | { 97 | "type": "jinja_expression", 98 | "named": true, 99 | "fields": {} 100 | }, 101 | { 102 | "type": "kwarg", 103 | "named": true, 104 | "fields": { 105 | "key": { 106 | "multiple": false, 107 | "required": true, 108 | "types": [ 109 | { 110 | "type": "identifier", 111 | "named": true 112 | } 113 | ] 114 | }, 115 | "value": { 116 | "multiple": false, 117 | "required": true, 118 | "types": [ 119 | { 120 | "type": "bool", 121 | "named": true 122 | }, 123 | { 124 | "type": "dict", 125 | "named": true 126 | }, 127 | { 128 | "type": "float", 129 | "named": true 130 | }, 131 | { 132 | "type": "fn_call", 133 | "named": true 134 | }, 135 | { 136 | "type": "integer", 137 | "named": true 138 | }, 139 | { 140 | "type": "list", 141 | "named": true 142 | }, 143 | { 144 | "type": "lit_string", 145 | "named": true 146 | } 147 | ] 148 | } 149 | } 150 | }, 151 | { 152 | "type": "list", 153 | "named": true, 154 | "fields": {}, 155 | "children": { 156 | "multiple": true, 157 | "required": false, 158 | "types": [ 159 | { 160 | "type": "bool", 161 | "named": true 162 | }, 163 | { 164 | "type": "dict", 165 | "named": true 166 | }, 167 | { 168 | "type": "float", 169 | "named": true 170 | }, 171 | { 172 | "type": "fn_call", 173 | "named": true 174 | }, 175 | { 176 | "type": "integer", 177 | "named": true 178 | }, 179 | { 180 | "type": "list", 181 | "named": true 182 | }, 183 | { 184 | "type": "lit_string", 185 | "named": true 186 | } 187 | ] 188 | } 189 | }, 190 | { 191 | "type": "lit_string", 192 | "named": true, 193 | "fields": {} 194 | }, 195 | { 196 | "type": "pair", 197 | "named": true, 198 | "fields": { 199 | "key": { 200 | "multiple": false, 201 | "required": true, 202 | "types": [ 203 | { 204 | "type": "lit_string", 205 | "named": true 206 | } 207 | ] 208 | }, 209 | "value": { 210 | "multiple": false, 211 | "required": true, 212 | "types": [ 213 | { 214 | "type": "bool", 215 | "named": true 216 | }, 217 | { 218 | "type": "dict", 219 | "named": true 220 | }, 221 | { 222 | "type": "float", 223 | "named": true 224 | }, 225 | { 226 | "type": "fn_call", 227 | "named": true 228 | }, 229 | { 230 | "type": "integer", 231 | "named": true 232 | }, 233 | { 234 | "type": "list", 235 | "named": true 236 | }, 237 | { 238 | "type": "lit_string", 239 | "named": true 240 | } 241 | ] 242 | } 243 | } 244 | }, 245 | { 246 | "type": "source_file", 247 | "named": true, 248 | "fields": {}, 249 | "children": { 250 | "multiple": true, 251 | "required": false, 252 | "types": [ 253 | { 254 | "type": "bool", 255 | "named": true 256 | }, 257 | { 258 | "type": "dict", 259 | "named": true 260 | }, 261 | { 262 | "type": "float", 263 | "named": true 264 | }, 265 | { 266 | "type": "fn_call", 267 | "named": true 268 | }, 269 | { 270 | "type": "integer", 271 | "named": true 272 | }, 273 | { 274 | "type": "jinja_expression", 275 | "named": true 276 | }, 277 | { 278 | "type": "list", 279 | "named": true 280 | }, 281 | { 282 | "type": "lit_string", 283 | "named": true 284 | } 285 | ] 286 | } 287 | }, 288 | { 289 | "type": "\"", 290 | "named": false 291 | }, 292 | { 293 | "type": "'", 294 | "named": false 295 | }, 296 | { 297 | "type": "(", 298 | "named": false 299 | }, 300 | { 301 | "type": ")", 302 | "named": false 303 | }, 304 | { 305 | "type": ",", 306 | "named": false 307 | }, 308 | { 309 | "type": ":", 310 | "named": false 311 | }, 312 | { 313 | "type": "=", 314 | "named": false 315 | }, 316 | { 317 | "type": "False", 318 | "named": false 319 | }, 320 | { 321 | "type": "True", 322 | "named": false 323 | }, 324 | { 325 | "type": "[", 326 | "named": false 327 | }, 328 | { 329 | "type": "]", 330 | "named": false 331 | }, 332 | { 333 | "type": "float", 334 | "named": true 335 | }, 336 | { 337 | "type": "integer", 338 | "named": true 339 | }, 340 | { 341 | "type": "{", 342 | "named": false 343 | }, 344 | { 345 | "type": "{#", 346 | "named": false 347 | }, 348 | { 349 | "type": "{%", 350 | "named": false 351 | }, 352 | { 353 | "type": "{{", 354 | "named": false 355 | }, 356 | { 357 | "type": "}", 358 | "named": false 359 | }, 360 | { 361 | "type": "}}", 362 | "named": false 363 | } 364 | ] -------------------------------------------------------------------------------- /.github/workflows/build_python.yml: -------------------------------------------------------------------------------- 1 | # **what?** 2 | # Minimal tests that we can build and install 3 | # 4 | # **why?** 5 | # Ensure it works after PR changes 6 | # 7 | # **when?** 8 | # On every pull request 9 | # 10 | 11 | name: tree-sitter-jinja2 12 | 13 | on: [pull_request] 14 | 15 | jobs: 16 | test: 17 | name: Test package 18 | runs-on: ${{ matrix.os }} 19 | strategy: 20 | matrix: 21 | os: [ubuntu-latest, macos-latest, windows-latest] 22 | python-version: [3.8] 23 | 24 | steps: 25 | - name: Checkout Repo 26 | uses: actions/checkout@v4 27 | 28 | - name: Setup npm 29 | uses: actions/setup-node@v4 30 | with: 31 | node-version: '16' 32 | 33 | - name: "Setup Python ${{ matrix.python-version }}" 34 | uses: actions/setup-python@v5 35 | with: 36 | python-version: "${{ matrix.python-version }}" 37 | 38 | - name: Test tree-sitter 39 | run: make test LOG=true 40 | 41 | generate-language-source: 42 | needs: [test] 43 | name: Generate language source files 44 | runs-on: ubuntu-latest 45 | 46 | steps: 47 | - name: Checkout Repo 48 | uses: actions/checkout@v4 49 | 50 | - name: Setup npm 51 | uses: actions/setup-node@v4 52 | with: 53 | node-version: '16' 54 | 55 | - name: Install dependencies 56 | run: npm install 57 | 58 | - name: Generate tree-sitter language source 59 | run: npx tree-sitter generate 60 | 61 | - name: Upload Artifact 62 | uses: actions/upload-artifact@v4 63 | with: 64 | name: language_source 65 | path: src/ 66 | 67 | build-sdist: 68 | needs: [generate-language-source] 69 | name: Build sdist 70 | runs-on: ubuntu-latest 71 | 72 | steps: 73 | - name: Checkout Repo 74 | uses: actions/checkout@v4 75 | 76 | - name: Set up Python 77 | uses: actions/setup-python@v5 78 | with: 79 | python-version: '3.9' 80 | 81 | - name: Display Python version 82 | run: python -c "import sys; print(sys.version)" 83 | 84 | - name: Download tree-sitter language source 85 | uses: actions/download-artifact@v4 86 | with: 87 | name: language_source 88 | path: bindings/python/include 89 | 90 | - name: Upgrade pip and build 91 | run: python -m pip install -U pip build 92 | 93 | - name: Creating source distribution 94 | run: python -m build bindings/python --sdist --outdir dist 95 | 96 | - name: Show sdist generated 97 | run: ls -lh dist 98 | 99 | - name: Upload Artifact 100 | uses: actions/upload-artifact@v4 101 | with: 102 | name: sdist 103 | path: dist/ 104 | 105 | build-manylinux: 106 | needs: [generate-language-source] 107 | name: "Build linux-py${{ matrix.tags.python-version }}" 108 | runs-on: ubuntu-latest 109 | strategy: 110 | matrix: 111 | tags: 112 | - version-tag: cp38-cp38 113 | python-version: "3.8" 114 | - version-tag: cp39-cp39 115 | python-version: "3.9" 116 | - version-tag: cp310-cp310 117 | python-version: "3.10" 118 | - version-tag: cp311-cp311 119 | python-version: "3.11" 120 | 121 | steps: 122 | - name: Checkout Repo 123 | uses: actions/checkout@v4 124 | 125 | - name: Download tree-sitter language source 126 | uses: actions/download-artifact@v4 127 | with: 128 | name: language_source 129 | path: bindings/python/include 130 | 131 | - name: Build manylinux wheels 132 | uses: RalfG/python-wheels-manylinux-build@v0.7.1-manylinux2014_x86_64 133 | with: 134 | python-versions: "${{ matrix.tags.version-tag }}" 135 | package-path: bindings/python/ 136 | 137 | - name: Copy manylinux wheel files to dist 138 | run: mkdir dist && cp bindings/python/dist/*manylinux*.whl dist/ 139 | 140 | - name: Show wheels generated 141 | run: ls -lh dist 142 | 143 | - name: Upload Artifact 144 | uses: actions/upload-artifact@v4 145 | with: 146 | name: "linux_py${{ matrix.tags.python-version }}" 147 | path: dist/ 148 | 149 | build-macos: 150 | needs: [generate-language-source] 151 | name: "Build macos-py${{ matrix.python-version }}" 152 | runs-on: macos-latest 153 | strategy: 154 | matrix: 155 | python-version: ["3.8", "3.9", "3.10", "3.11"] 156 | 157 | steps: 158 | - name: Checkout Repo 159 | uses: actions/checkout@v4 160 | 161 | - name: Set up Python 162 | uses: actions/setup-python@v5 163 | with: 164 | python-version: "${{ matrix.python-version }}" 165 | 166 | - name: Display Python version 167 | run: python -c "import sys; print(sys.version)" 168 | 169 | - name: Download tree-sitter language source 170 | uses: actions/download-artifact@v4 171 | with: 172 | name: language_source 173 | path: bindings/python/include 174 | 175 | - name: Upgrade pip and build 176 | run: python -m pip install -U pip build 177 | 178 | - name: Generate wheel 179 | run: python -m build bindings/python --wheel --outdir dist 180 | 181 | - name: Show wheels generated 182 | run: ls -lh dist/ 183 | 184 | - name: Upload Artifact 185 | uses: actions/upload-artifact@v4 186 | with: 187 | name: "macos_py${{ matrix.python-version }}" 188 | path: dist/ 189 | 190 | build-windows: 191 | needs: [generate-language-source] 192 | name: "Build windows-py${{ matrix.python-version }}" 193 | runs-on: windows-latest 194 | strategy: 195 | matrix: 196 | python-version: ["3.8", "3.9", "3.10", "3.11"] 197 | 198 | steps: 199 | - name: Checkout Repo 200 | uses: actions/checkout@v4 201 | 202 | - name: Set up Python 203 | uses: actions/setup-python@v5 204 | with: 205 | python-version: "${{ matrix.python-version }}" 206 | 207 | - name: Display Python version 208 | run: python -c "import sys; print(sys.version)" 209 | 210 | - name: Download tree-sitter language 211 | uses: actions/download-artifact@v4 212 | with: 213 | name: language_source 214 | path: bindings/python/include 215 | 216 | - name: Upgrade pip and build 217 | run: python -m pip install -U pip build 218 | 219 | - name: Generate wheel 220 | run: python -m build bindings/python --wheel --outdir dist 221 | 222 | - name: Show wheels generated 223 | run: ls -lh dist 224 | shell: bash 225 | 226 | - name: Upload Artifact 227 | uses: actions/upload-artifact@v4 228 | with: 229 | name: "windows_py${{ matrix.python-version }}" 230 | path: dist/ 231 | 232 | test-sdist: 233 | needs: [build-sdist] 234 | name: Test sdist 235 | runs-on: ubuntu-latest 236 | 237 | steps: 238 | - name: Checkout Repo 239 | uses: actions/checkout@v4 240 | 241 | - name: Download sdist 242 | uses: actions/download-artifact@v4 243 | with: 244 | name: sdist 245 | path: dist 246 | 247 | - name: Show sdist downloaded 248 | run: ls -lh dist 249 | 250 | - name: Set up Python 251 | uses: actions/setup-python@v5 252 | with: 253 | python-version: '3.9' 254 | 255 | - name: Display Python version 256 | run: python -c "import sys; print(sys.version)" 257 | 258 | - name: Upgrade pip 259 | run: python -m pip install -U pip wheel 260 | 261 | - name: Install sdist 262 | run: python -m pip install --find-links dist tree-sitter-jinja2 263 | 264 | test-wheels: 265 | name: "Test ${{ matrix.os.download_name }}-py${{ matrix.python-version }}" 266 | needs: [build-manylinux, build-macos, build-windows] 267 | runs-on: ${{ matrix.os.image_name }} 268 | strategy: 269 | matrix: 270 | os: 271 | - image_name: ubuntu-latest 272 | download_name: linux 273 | - image_name: macos-latest 274 | download_name: macos 275 | - image_name: windows-latest 276 | download_name: windows 277 | python-version: ["3.8", "3.9", "3.10", "3.11"] 278 | 279 | steps: 280 | - name: Checkout Repo 281 | uses: actions/checkout@v4 282 | 283 | - name: Set up Python 284 | uses: actions/setup-python@v5 285 | with: 286 | python-version: "${{ matrix.python-version }}" 287 | 288 | - name: Display Python version 289 | run: python -c "import sys; print(sys.version)" 290 | 291 | - name: Download wheel(s) 292 | uses: actions/download-artifact@v4 293 | with: 294 | name: "${{ matrix.os.download_name }}_py${{ matrix.python-version }}" 295 | path: dist 296 | 297 | - name: Show wheels downloaded 298 | run: ls -lh dist 299 | shell: bash 300 | 301 | - name: Upgrade pip 302 | run: python -m pip install -U pip wheel 303 | 304 | - name: Install wheel 305 | run: python -m pip install --find-links dist tree-sitter-jinja2 306 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2021 dbt Labs, Inc. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/grammar.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jinja2", 3 | "rules": { 4 | "source_file": { 5 | "type": "REPEAT", 6 | "content": { 7 | "type": "CHOICE", 8 | "members": [ 9 | { 10 | "type": "SYMBOL", 11 | "name": "_jinja_value" 12 | }, 13 | { 14 | "type": "SYMBOL", 15 | "name": "jinja_expression" 16 | }, 17 | { 18 | "type": "SYMBOL", 19 | "name": "_jinja_comment" 20 | }, 21 | { 22 | "type": "SYMBOL", 23 | "name": "_text" 24 | } 25 | ] 26 | } 27 | }, 28 | "_jinja_value": { 29 | "type": "SEQ", 30 | "members": [ 31 | { 32 | "type": "STRING", 33 | "value": "{{" 34 | }, 35 | { 36 | "type": "SYMBOL", 37 | "name": "_expr" 38 | }, 39 | { 40 | "type": "STRING", 41 | "value": "}}" 42 | } 43 | ] 44 | }, 45 | "jinja_expression": { 46 | "type": "SEQ", 47 | "members": [ 48 | { 49 | "type": "STRING", 50 | "value": "{%" 51 | }, 52 | { 53 | "type": "PATTERN", 54 | "value": "([^%]|%[^}])*%}" 55 | } 56 | ] 57 | }, 58 | "_jinja_comment": { 59 | "type": "SEQ", 60 | "members": [ 61 | { 62 | "type": "STRING", 63 | "value": "{#" 64 | }, 65 | { 66 | "type": "PATTERN", 67 | "value": "(([^#]|#[^}])*)#+}" 68 | } 69 | ] 70 | }, 71 | "_expr": { 72 | "type": "CHOICE", 73 | "members": [ 74 | { 75 | "type": "SYMBOL", 76 | "name": "fn_call" 77 | }, 78 | { 79 | "type": "SYMBOL", 80 | "name": "list" 81 | }, 82 | { 83 | "type": "SYMBOL", 84 | "name": "dict" 85 | }, 86 | { 87 | "type": "SYMBOL", 88 | "name": "lit_string" 89 | }, 90 | { 91 | "type": "SYMBOL", 92 | "name": "bool" 93 | }, 94 | { 95 | "type": "SYMBOL", 96 | "name": "integer" 97 | }, 98 | { 99 | "type": "SYMBOL", 100 | "name": "float" 101 | } 102 | ] 103 | }, 104 | "fn_call": { 105 | "type": "SEQ", 106 | "members": [ 107 | { 108 | "type": "FIELD", 109 | "name": "fn_name", 110 | "content": { 111 | "type": "SYMBOL", 112 | "name": "identifier" 113 | } 114 | }, 115 | { 116 | "type": "FIELD", 117 | "name": "argument_list", 118 | "content": { 119 | "type": "SYMBOL", 120 | "name": "argument_list" 121 | } 122 | } 123 | ] 124 | }, 125 | "argument_list": { 126 | "type": "SEQ", 127 | "members": [ 128 | { 129 | "type": "STRING", 130 | "value": "(" 131 | }, 132 | { 133 | "type": "CHOICE", 134 | "members": [ 135 | { 136 | "type": "SEQ", 137 | "members": [ 138 | { 139 | "type": "CHOICE", 140 | "members": [ 141 | { 142 | "type": "SYMBOL", 143 | "name": "_expr" 144 | }, 145 | { 146 | "type": "SYMBOL", 147 | "name": "kwarg" 148 | } 149 | ] 150 | }, 151 | { 152 | "type": "REPEAT", 153 | "content": { 154 | "type": "SEQ", 155 | "members": [ 156 | { 157 | "type": "STRING", 158 | "value": "," 159 | }, 160 | { 161 | "type": "CHOICE", 162 | "members": [ 163 | { 164 | "type": "SYMBOL", 165 | "name": "_expr" 166 | }, 167 | { 168 | "type": "SYMBOL", 169 | "name": "kwarg" 170 | } 171 | ] 172 | } 173 | ] 174 | } 175 | } 176 | ] 177 | }, 178 | { 179 | "type": "BLANK" 180 | } 181 | ] 182 | }, 183 | { 184 | "type": "CHOICE", 185 | "members": [ 186 | { 187 | "type": "STRING", 188 | "value": "," 189 | }, 190 | { 191 | "type": "BLANK" 192 | } 193 | ] 194 | }, 195 | { 196 | "type": "STRING", 197 | "value": ")" 198 | } 199 | ] 200 | }, 201 | "lit_string": { 202 | "type": "CHOICE", 203 | "members": [ 204 | { 205 | "type": "SEQ", 206 | "members": [ 207 | { 208 | "type": "STRING", 209 | "value": "'" 210 | }, 211 | { 212 | "type": "PATTERN", 213 | "value": "([^']|\\\\')*" 214 | }, 215 | { 216 | "type": "STRING", 217 | "value": "'" 218 | } 219 | ] 220 | }, 221 | { 222 | "type": "SEQ", 223 | "members": [ 224 | { 225 | "type": "STRING", 226 | "value": "\"" 227 | }, 228 | { 229 | "type": "PATTERN", 230 | "value": "([^\"]|\\\\\")*" 231 | }, 232 | { 233 | "type": "STRING", 234 | "value": "\"" 235 | } 236 | ] 237 | } 238 | ] 239 | }, 240 | "bool": { 241 | "type": "CHOICE", 242 | "members": [ 243 | { 244 | "type": "STRING", 245 | "value": "True" 246 | }, 247 | { 248 | "type": "STRING", 249 | "value": "False" 250 | } 251 | ] 252 | }, 253 | "list": { 254 | "type": "SEQ", 255 | "members": [ 256 | { 257 | "type": "STRING", 258 | "value": "[" 259 | }, 260 | { 261 | "type": "CHOICE", 262 | "members": [ 263 | { 264 | "type": "SEQ", 265 | "members": [ 266 | { 267 | "type": "SYMBOL", 268 | "name": "_expr" 269 | }, 270 | { 271 | "type": "REPEAT", 272 | "content": { 273 | "type": "SEQ", 274 | "members": [ 275 | { 276 | "type": "STRING", 277 | "value": "," 278 | }, 279 | { 280 | "type": "SYMBOL", 281 | "name": "_expr" 282 | } 283 | ] 284 | } 285 | } 286 | ] 287 | }, 288 | { 289 | "type": "BLANK" 290 | } 291 | ] 292 | }, 293 | { 294 | "type": "CHOICE", 295 | "members": [ 296 | { 297 | "type": "STRING", 298 | "value": "," 299 | }, 300 | { 301 | "type": "BLANK" 302 | } 303 | ] 304 | }, 305 | { 306 | "type": "STRING", 307 | "value": "]" 308 | } 309 | ] 310 | }, 311 | "dict": { 312 | "type": "SEQ", 313 | "members": [ 314 | { 315 | "type": "STRING", 316 | "value": "{" 317 | }, 318 | { 319 | "type": "CHOICE", 320 | "members": [ 321 | { 322 | "type": "SEQ", 323 | "members": [ 324 | { 325 | "type": "SYMBOL", 326 | "name": "pair" 327 | }, 328 | { 329 | "type": "REPEAT", 330 | "content": { 331 | "type": "SEQ", 332 | "members": [ 333 | { 334 | "type": "STRING", 335 | "value": "," 336 | }, 337 | { 338 | "type": "SYMBOL", 339 | "name": "pair" 340 | } 341 | ] 342 | } 343 | } 344 | ] 345 | }, 346 | { 347 | "type": "BLANK" 348 | } 349 | ] 350 | }, 351 | { 352 | "type": "CHOICE", 353 | "members": [ 354 | { 355 | "type": "STRING", 356 | "value": "," 357 | }, 358 | { 359 | "type": "BLANK" 360 | } 361 | ] 362 | }, 363 | { 364 | "type": "STRING", 365 | "value": "}" 366 | } 367 | ] 368 | }, 369 | "pair": { 370 | "type": "SEQ", 371 | "members": [ 372 | { 373 | "type": "FIELD", 374 | "name": "key", 375 | "content": { 376 | "type": "SYMBOL", 377 | "name": "lit_string" 378 | } 379 | }, 380 | { 381 | "type": "STRING", 382 | "value": ":" 383 | }, 384 | { 385 | "type": "FIELD", 386 | "name": "value", 387 | "content": { 388 | "type": "SYMBOL", 389 | "name": "_expr" 390 | } 391 | } 392 | ] 393 | }, 394 | "identifier": { 395 | "type": "SYMBOL", 396 | "name": "_identifier" 397 | }, 398 | "_identifier": { 399 | "type": "TOKEN", 400 | "content": { 401 | "type": "PATTERN", 402 | "value": "[a-zA-Z_][a-zA-Z0-9_]*" 403 | } 404 | }, 405 | "kwarg": { 406 | "type": "SEQ", 407 | "members": [ 408 | { 409 | "type": "FIELD", 410 | "name": "key", 411 | "content": { 412 | "type": "SYMBOL", 413 | "name": "identifier" 414 | } 415 | }, 416 | { 417 | "type": "STRING", 418 | "value": "=" 419 | }, 420 | { 421 | "type": "FIELD", 422 | "name": "value", 423 | "content": { 424 | "type": "SYMBOL", 425 | "name": "_expr" 426 | } 427 | } 428 | ] 429 | }, 430 | "_text": { 431 | "type": "PATTERN", 432 | "value": "([^{]|[{][^{%#])+" 433 | }, 434 | "integer": { 435 | "type": "TOKEN", 436 | "content": { 437 | "type": "SEQ", 438 | "members": [ 439 | { 440 | "type": "CHOICE", 441 | "members": [ 442 | { 443 | "type": "PATTERN", 444 | "value": "[\\+-]" 445 | }, 446 | { 447 | "type": "BLANK" 448 | } 449 | ] 450 | }, 451 | { 452 | "type": "REPEAT1", 453 | "content": { 454 | "type": "PATTERN", 455 | "value": "_?[0-9]+" 456 | } 457 | } 458 | ] 459 | } 460 | }, 461 | "float": { 462 | "type": "TOKEN", 463 | "content": { 464 | "type": "CHOICE", 465 | "members": [ 466 | { 467 | "type": "SEQ", 468 | "members": [ 469 | { 470 | "type": "CHOICE", 471 | "members": [ 472 | { 473 | "type": "PATTERN", 474 | "value": "[\\+-]" 475 | }, 476 | { 477 | "type": "BLANK" 478 | } 479 | ] 480 | }, 481 | { 482 | "type": "REPEAT1", 483 | "content": { 484 | "type": "PATTERN", 485 | "value": "[0-9]+_?" 486 | } 487 | }, 488 | { 489 | "type": "STRING", 490 | "value": "." 491 | }, 492 | { 493 | "type": "CHOICE", 494 | "members": [ 495 | { 496 | "type": "REPEAT1", 497 | "content": { 498 | "type": "PATTERN", 499 | "value": "[0-9]+_?" 500 | } 501 | }, 502 | { 503 | "type": "BLANK" 504 | } 505 | ] 506 | }, 507 | { 508 | "type": "CHOICE", 509 | "members": [ 510 | { 511 | "type": "SEQ", 512 | "members": [ 513 | { 514 | "type": "PATTERN", 515 | "value": "[eE][\\+-]?" 516 | }, 517 | { 518 | "type": "REPEAT1", 519 | "content": { 520 | "type": "PATTERN", 521 | "value": "[0-9]+_?" 522 | } 523 | } 524 | ] 525 | }, 526 | { 527 | "type": "BLANK" 528 | } 529 | ] 530 | } 531 | ] 532 | }, 533 | { 534 | "type": "SEQ", 535 | "members": [ 536 | { 537 | "type": "CHOICE", 538 | "members": [ 539 | { 540 | "type": "PATTERN", 541 | "value": "[\\+-]" 542 | }, 543 | { 544 | "type": "BLANK" 545 | } 546 | ] 547 | }, 548 | { 549 | "type": "CHOICE", 550 | "members": [ 551 | { 552 | "type": "REPEAT1", 553 | "content": { 554 | "type": "PATTERN", 555 | "value": "[0-9]+_?" 556 | } 557 | }, 558 | { 559 | "type": "BLANK" 560 | } 561 | ] 562 | }, 563 | { 564 | "type": "STRING", 565 | "value": "." 566 | }, 567 | { 568 | "type": "REPEAT1", 569 | "content": { 570 | "type": "PATTERN", 571 | "value": "[0-9]+_?" 572 | } 573 | }, 574 | { 575 | "type": "CHOICE", 576 | "members": [ 577 | { 578 | "type": "SEQ", 579 | "members": [ 580 | { 581 | "type": "PATTERN", 582 | "value": "[eE][\\+-]?" 583 | }, 584 | { 585 | "type": "REPEAT1", 586 | "content": { 587 | "type": "PATTERN", 588 | "value": "[0-9]+_?" 589 | } 590 | } 591 | ] 592 | }, 593 | { 594 | "type": "BLANK" 595 | } 596 | ] 597 | } 598 | ] 599 | }, 600 | { 601 | "type": "SEQ", 602 | "members": [ 603 | { 604 | "type": "REPEAT1", 605 | "content": { 606 | "type": "PATTERN", 607 | "value": "[0-9]+_?" 608 | } 609 | }, 610 | { 611 | "type": "SEQ", 612 | "members": [ 613 | { 614 | "type": "PATTERN", 615 | "value": "[eE][\\+-]?" 616 | }, 617 | { 618 | "type": "REPEAT1", 619 | "content": { 620 | "type": "PATTERN", 621 | "value": "[0-9]+_?" 622 | } 623 | } 624 | ] 625 | } 626 | ] 627 | } 628 | ] 629 | } 630 | } 631 | }, 632 | "extras": [ 633 | { 634 | "type": "PATTERN", 635 | "value": "\\s" 636 | } 637 | ], 638 | "conflicts": [], 639 | "precedences": [], 640 | "externals": [], 641 | "inline": [], 642 | "supertypes": [] 643 | } 644 | 645 | -------------------------------------------------------------------------------- /src/parser.c: -------------------------------------------------------------------------------- 1 | #include <tree_sitter/parser.h> 2 | 3 | #if defined(__GNUC__) || defined(__clang__) 4 | #pragma GCC diagnostic push 5 | #pragma GCC diagnostic ignored "-Wmissing-field-initializers" 6 | #endif 7 | 8 | #define LANGUAGE_VERSION 14 9 | #define STATE_COUNT 104 10 | #define LARGE_STATE_COUNT 2 11 | #define SYMBOL_COUNT 44 12 | #define ALIAS_COUNT 0 13 | #define TOKEN_COUNT 26 14 | #define EXTERNAL_TOKEN_COUNT 0 15 | #define FIELD_COUNT 4 16 | #define MAX_ALIAS_SEQUENCE_LENGTH 5 17 | #define PRODUCTION_ID_COUNT 3 18 | 19 | enum { 20 | anon_sym_LBRACE_LBRACE = 1, 21 | anon_sym_RBRACE_RBRACE = 2, 22 | anon_sym_LBRACE_PERCENT = 3, 23 | aux_sym_jinja_expression_token1 = 4, 24 | anon_sym_LBRACE_POUND = 5, 25 | aux_sym__jinja_comment_token1 = 6, 26 | anon_sym_LPAREN = 7, 27 | anon_sym_COMMA = 8, 28 | anon_sym_RPAREN = 9, 29 | anon_sym_SQUOTE = 10, 30 | aux_sym_lit_string_token1 = 11, 31 | anon_sym_DQUOTE = 12, 32 | aux_sym_lit_string_token2 = 13, 33 | anon_sym_True = 14, 34 | anon_sym_False = 15, 35 | anon_sym_LBRACK = 16, 36 | anon_sym_RBRACK = 17, 37 | anon_sym_LBRACE = 18, 38 | anon_sym_RBRACE = 19, 39 | anon_sym_COLON = 20, 40 | sym__identifier = 21, 41 | anon_sym_EQ = 22, 42 | sym__text = 23, 43 | sym_integer = 24, 44 | sym_float = 25, 45 | sym_source_file = 26, 46 | sym__jinja_value = 27, 47 | sym_jinja_expression = 28, 48 | sym__jinja_comment = 29, 49 | sym__expr = 30, 50 | sym_fn_call = 31, 51 | sym_argument_list = 32, 52 | sym_lit_string = 33, 53 | sym_bool = 34, 54 | sym_list = 35, 55 | sym_dict = 36, 56 | sym_pair = 37, 57 | sym_identifier = 38, 58 | sym_kwarg = 39, 59 | aux_sym_source_file_repeat1 = 40, 60 | aux_sym_argument_list_repeat1 = 41, 61 | aux_sym_list_repeat1 = 42, 62 | aux_sym_dict_repeat1 = 43, 63 | }; 64 | 65 | static const char * const ts_symbol_names[] = { 66 | [ts_builtin_sym_end] = "end", 67 | [anon_sym_LBRACE_LBRACE] = "{{", 68 | [anon_sym_RBRACE_RBRACE] = "}}", 69 | [anon_sym_LBRACE_PERCENT] = "{%", 70 | [aux_sym_jinja_expression_token1] = "jinja_expression_token1", 71 | [anon_sym_LBRACE_POUND] = "{#", 72 | [aux_sym__jinja_comment_token1] = "_jinja_comment_token1", 73 | [anon_sym_LPAREN] = "(", 74 | [anon_sym_COMMA] = ",", 75 | [anon_sym_RPAREN] = ")", 76 | [anon_sym_SQUOTE] = "'", 77 | [aux_sym_lit_string_token1] = "lit_string_token1", 78 | [anon_sym_DQUOTE] = "\"", 79 | [aux_sym_lit_string_token2] = "lit_string_token2", 80 | [anon_sym_True] = "True", 81 | [anon_sym_False] = "False", 82 | [anon_sym_LBRACK] = "[", 83 | [anon_sym_RBRACK] = "]", 84 | [anon_sym_LBRACE] = "{", 85 | [anon_sym_RBRACE] = "}", 86 | [anon_sym_COLON] = ":", 87 | [sym__identifier] = "_identifier", 88 | [anon_sym_EQ] = "=", 89 | [sym__text] = "_text", 90 | [sym_integer] = "integer", 91 | [sym_float] = "float", 92 | [sym_source_file] = "source_file", 93 | [sym__jinja_value] = "_jinja_value", 94 | [sym_jinja_expression] = "jinja_expression", 95 | [sym__jinja_comment] = "_jinja_comment", 96 | [sym__expr] = "_expr", 97 | [sym_fn_call] = "fn_call", 98 | [sym_argument_list] = "argument_list", 99 | [sym_lit_string] = "lit_string", 100 | [sym_bool] = "bool", 101 | [sym_list] = "list", 102 | [sym_dict] = "dict", 103 | [sym_pair] = "pair", 104 | [sym_identifier] = "identifier", 105 | [sym_kwarg] = "kwarg", 106 | [aux_sym_source_file_repeat1] = "source_file_repeat1", 107 | [aux_sym_argument_list_repeat1] = "argument_list_repeat1", 108 | [aux_sym_list_repeat1] = "list_repeat1", 109 | [aux_sym_dict_repeat1] = "dict_repeat1", 110 | }; 111 | 112 | static const TSSymbol ts_symbol_map[] = { 113 | [ts_builtin_sym_end] = ts_builtin_sym_end, 114 | [anon_sym_LBRACE_LBRACE] = anon_sym_LBRACE_LBRACE, 115 | [anon_sym_RBRACE_RBRACE] = anon_sym_RBRACE_RBRACE, 116 | [anon_sym_LBRACE_PERCENT] = anon_sym_LBRACE_PERCENT, 117 | [aux_sym_jinja_expression_token1] = aux_sym_jinja_expression_token1, 118 | [anon_sym_LBRACE_POUND] = anon_sym_LBRACE_POUND, 119 | [aux_sym__jinja_comment_token1] = aux_sym__jinja_comment_token1, 120 | [anon_sym_LPAREN] = anon_sym_LPAREN, 121 | [anon_sym_COMMA] = anon_sym_COMMA, 122 | [anon_sym_RPAREN] = anon_sym_RPAREN, 123 | [anon_sym_SQUOTE] = anon_sym_SQUOTE, 124 | [aux_sym_lit_string_token1] = aux_sym_lit_string_token1, 125 | [anon_sym_DQUOTE] = anon_sym_DQUOTE, 126 | [aux_sym_lit_string_token2] = aux_sym_lit_string_token2, 127 | [anon_sym_True] = anon_sym_True, 128 | [anon_sym_False] = anon_sym_False, 129 | [anon_sym_LBRACK] = anon_sym_LBRACK, 130 | [anon_sym_RBRACK] = anon_sym_RBRACK, 131 | [anon_sym_LBRACE] = anon_sym_LBRACE, 132 | [anon_sym_RBRACE] = anon_sym_RBRACE, 133 | [anon_sym_COLON] = anon_sym_COLON, 134 | [sym__identifier] = sym__identifier, 135 | [anon_sym_EQ] = anon_sym_EQ, 136 | [sym__text] = sym__text, 137 | [sym_integer] = sym_integer, 138 | [sym_float] = sym_float, 139 | [sym_source_file] = sym_source_file, 140 | [sym__jinja_value] = sym__jinja_value, 141 | [sym_jinja_expression] = sym_jinja_expression, 142 | [sym__jinja_comment] = sym__jinja_comment, 143 | [sym__expr] = sym__expr, 144 | [sym_fn_call] = sym_fn_call, 145 | [sym_argument_list] = sym_argument_list, 146 | [sym_lit_string] = sym_lit_string, 147 | [sym_bool] = sym_bool, 148 | [sym_list] = sym_list, 149 | [sym_dict] = sym_dict, 150 | [sym_pair] = sym_pair, 151 | [sym_identifier] = sym_identifier, 152 | [sym_kwarg] = sym_kwarg, 153 | [aux_sym_source_file_repeat1] = aux_sym_source_file_repeat1, 154 | [aux_sym_argument_list_repeat1] = aux_sym_argument_list_repeat1, 155 | [aux_sym_list_repeat1] = aux_sym_list_repeat1, 156 | [aux_sym_dict_repeat1] = aux_sym_dict_repeat1, 157 | }; 158 | 159 | static const TSSymbolMetadata ts_symbol_metadata[] = { 160 | [ts_builtin_sym_end] = { 161 | .visible = false, 162 | .named = true, 163 | }, 164 | [anon_sym_LBRACE_LBRACE] = { 165 | .visible = true, 166 | .named = false, 167 | }, 168 | [anon_sym_RBRACE_RBRACE] = { 169 | .visible = true, 170 | .named = false, 171 | }, 172 | [anon_sym_LBRACE_PERCENT] = { 173 | .visible = true, 174 | .named = false, 175 | }, 176 | [aux_sym_jinja_expression_token1] = { 177 | .visible = false, 178 | .named = false, 179 | }, 180 | [anon_sym_LBRACE_POUND] = { 181 | .visible = true, 182 | .named = false, 183 | }, 184 | [aux_sym__jinja_comment_token1] = { 185 | .visible = false, 186 | .named = false, 187 | }, 188 | [anon_sym_LPAREN] = { 189 | .visible = true, 190 | .named = false, 191 | }, 192 | [anon_sym_COMMA] = { 193 | .visible = true, 194 | .named = false, 195 | }, 196 | [anon_sym_RPAREN] = { 197 | .visible = true, 198 | .named = false, 199 | }, 200 | [anon_sym_SQUOTE] = { 201 | .visible = true, 202 | .named = false, 203 | }, 204 | [aux_sym_lit_string_token1] = { 205 | .visible = false, 206 | .named = false, 207 | }, 208 | [anon_sym_DQUOTE] = { 209 | .visible = true, 210 | .named = false, 211 | }, 212 | [aux_sym_lit_string_token2] = { 213 | .visible = false, 214 | .named = false, 215 | }, 216 | [anon_sym_True] = { 217 | .visible = true, 218 | .named = false, 219 | }, 220 | [anon_sym_False] = { 221 | .visible = true, 222 | .named = false, 223 | }, 224 | [anon_sym_LBRACK] = { 225 | .visible = true, 226 | .named = false, 227 | }, 228 | [anon_sym_RBRACK] = { 229 | .visible = true, 230 | .named = false, 231 | }, 232 | [anon_sym_LBRACE] = { 233 | .visible = true, 234 | .named = false, 235 | }, 236 | [anon_sym_RBRACE] = { 237 | .visible = true, 238 | .named = false, 239 | }, 240 | [anon_sym_COLON] = { 241 | .visible = true, 242 | .named = false, 243 | }, 244 | [sym__identifier] = { 245 | .visible = false, 246 | .named = true, 247 | }, 248 | [anon_sym_EQ] = { 249 | .visible = true, 250 | .named = false, 251 | }, 252 | [sym__text] = { 253 | .visible = false, 254 | .named = true, 255 | }, 256 | [sym_integer] = { 257 | .visible = true, 258 | .named = true, 259 | }, 260 | [sym_float] = { 261 | .visible = true, 262 | .named = true, 263 | }, 264 | [sym_source_file] = { 265 | .visible = true, 266 | .named = true, 267 | }, 268 | [sym__jinja_value] = { 269 | .visible = false, 270 | .named = true, 271 | }, 272 | [sym_jinja_expression] = { 273 | .visible = true, 274 | .named = true, 275 | }, 276 | [sym__jinja_comment] = { 277 | .visible = false, 278 | .named = true, 279 | }, 280 | [sym__expr] = { 281 | .visible = false, 282 | .named = true, 283 | }, 284 | [sym_fn_call] = { 285 | .visible = true, 286 | .named = true, 287 | }, 288 | [sym_argument_list] = { 289 | .visible = true, 290 | .named = true, 291 | }, 292 | [sym_lit_string] = { 293 | .visible = true, 294 | .named = true, 295 | }, 296 | [sym_bool] = { 297 | .visible = true, 298 | .named = true, 299 | }, 300 | [sym_list] = { 301 | .visible = true, 302 | .named = true, 303 | }, 304 | [sym_dict] = { 305 | .visible = true, 306 | .named = true, 307 | }, 308 | [sym_pair] = { 309 | .visible = true, 310 | .named = true, 311 | }, 312 | [sym_identifier] = { 313 | .visible = true, 314 | .named = true, 315 | }, 316 | [sym_kwarg] = { 317 | .visible = true, 318 | .named = true, 319 | }, 320 | [aux_sym_source_file_repeat1] = { 321 | .visible = false, 322 | .named = false, 323 | }, 324 | [aux_sym_argument_list_repeat1] = { 325 | .visible = false, 326 | .named = false, 327 | }, 328 | [aux_sym_list_repeat1] = { 329 | .visible = false, 330 | .named = false, 331 | }, 332 | [aux_sym_dict_repeat1] = { 333 | .visible = false, 334 | .named = false, 335 | }, 336 | }; 337 | 338 | enum { 339 | field_argument_list = 1, 340 | field_fn_name = 2, 341 | field_key = 3, 342 | field_value = 4, 343 | }; 344 | 345 | static const char * const ts_field_names[] = { 346 | [0] = NULL, 347 | [field_argument_list] = "argument_list", 348 | [field_fn_name] = "fn_name", 349 | [field_key] = "key", 350 | [field_value] = "value", 351 | }; 352 | 353 | static const TSFieldMapSlice ts_field_map_slices[PRODUCTION_ID_COUNT] = { 354 | [1] = {.index = 0, .length = 2}, 355 | [2] = {.index = 2, .length = 2}, 356 | }; 357 | 358 | static const TSFieldMapEntry ts_field_map_entries[] = { 359 | [0] = 360 | {field_argument_list, 1}, 361 | {field_fn_name, 0}, 362 | [2] = 363 | {field_key, 0}, 364 | {field_value, 2}, 365 | }; 366 | 367 | static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT][MAX_ALIAS_SEQUENCE_LENGTH] = { 368 | [0] = {0}, 369 | }; 370 | 371 | static const uint16_t ts_non_terminal_alias_map[] = { 372 | 0, 373 | }; 374 | 375 | static const TSStateId ts_primary_state_ids[STATE_COUNT] = { 376 | [0] = 0, 377 | [1] = 1, 378 | [2] = 2, 379 | [3] = 2, 380 | [4] = 4, 381 | [5] = 5, 382 | [6] = 6, 383 | [7] = 5, 384 | [8] = 4, 385 | [9] = 6, 386 | [10] = 10, 387 | [11] = 11, 388 | [12] = 11, 389 | [13] = 10, 390 | [14] = 14, 391 | [15] = 15, 392 | [16] = 16, 393 | [17] = 17, 394 | [18] = 18, 395 | [19] = 19, 396 | [20] = 20, 397 | [21] = 21, 398 | [22] = 21, 399 | [23] = 23, 400 | [24] = 24, 401 | [25] = 25, 402 | [26] = 25, 403 | [27] = 27, 404 | [28] = 24, 405 | [29] = 29, 406 | [30] = 30, 407 | [31] = 31, 408 | [32] = 32, 409 | [33] = 33, 410 | [34] = 34, 411 | [35] = 35, 412 | [36] = 36, 413 | [37] = 37, 414 | [38] = 38, 415 | [39] = 39, 416 | [40] = 40, 417 | [41] = 41, 418 | [42] = 42, 419 | [43] = 43, 420 | [44] = 44, 421 | [45] = 45, 422 | [46] = 46, 423 | [47] = 47, 424 | [48] = 48, 425 | [49] = 49, 426 | [50] = 50, 427 | [51] = 51, 428 | [52] = 52, 429 | [53] = 49, 430 | [54] = 54, 431 | [55] = 50, 432 | [56] = 56, 433 | [57] = 52, 434 | [58] = 56, 435 | [59] = 46, 436 | [60] = 60, 437 | [61] = 60, 438 | [62] = 43, 439 | [63] = 63, 440 | [64] = 64, 441 | [65] = 65, 442 | [66] = 41, 443 | [67] = 37, 444 | [68] = 44, 445 | [69] = 36, 446 | [70] = 30, 447 | [71] = 32, 448 | [72] = 34, 449 | [73] = 39, 450 | [74] = 42, 451 | [75] = 75, 452 | [76] = 45, 453 | [77] = 38, 454 | [78] = 33, 455 | [79] = 35, 456 | [80] = 31, 457 | [81] = 81, 458 | [82] = 63, 459 | [83] = 83, 460 | [84] = 84, 461 | [85] = 85, 462 | [86] = 86, 463 | [87] = 87, 464 | [88] = 88, 465 | [89] = 88, 466 | [90] = 87, 467 | [91] = 91, 468 | [92] = 92, 469 | [93] = 85, 470 | [94] = 94, 471 | [95] = 94, 472 | [96] = 96, 473 | [97] = 97, 474 | [98] = 98, 475 | [99] = 99, 476 | [100] = 86, 477 | [101] = 101, 478 | [102] = 98, 479 | [103] = 97, 480 | }; 481 | 482 | static bool ts_lex(TSLexer *lexer, TSStateId state) { 483 | START_LEXER(); 484 | eof = lexer->eof(lexer); 485 | switch (state) { 486 | case 0: 487 | if (eof) ADVANCE(20); 488 | if (lookahead == '"') ADVANCE(35); 489 | if (lookahead == '\'') ADVANCE(31); 490 | if (lookahead == '(') ADVANCE(28); 491 | if (lookahead == ')') ADVANCE(30); 492 | if (lookahead == ',') ADVANCE(29); 493 | if (lookahead == '.') ADVANCE(15); 494 | if (lookahead == ':') ADVANCE(46); 495 | if (lookahead == '=') ADVANCE(57); 496 | if (lookahead == 'F') ADVANCE(48); 497 | if (lookahead == 'T') ADVANCE(52); 498 | if (lookahead == '[') ADVANCE(41); 499 | if (lookahead == ']') ADVANCE(42); 500 | if (lookahead == '_') ADVANCE(55); 501 | if (lookahead == '{') ADVANCE(44); 502 | if (lookahead == '}') ADVANCE(45); 503 | if (('+' <= lookahead && lookahead <= '-')) ADVANCE(9); 504 | if (lookahead == '\t' || 505 | lookahead == '\n' || 506 | lookahead == '\r' || 507 | lookahead == ' ') SKIP(0) 508 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(60); 509 | if (('A' <= lookahead && lookahead <= 'Z') || 510 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 511 | END_STATE(); 512 | case 1: 513 | if (lookahead == '"') ADVANCE(35); 514 | if (lookahead == '\'') ADVANCE(31); 515 | if (lookahead == ')') ADVANCE(30); 516 | if (lookahead == ',') ADVANCE(29); 517 | if (lookahead == '.') ADVANCE(15); 518 | if (lookahead == ':') ADVANCE(46); 519 | if (lookahead == 'F') ADVANCE(48); 520 | if (lookahead == 'T') ADVANCE(52); 521 | if (lookahead == '[') ADVANCE(41); 522 | if (lookahead == ']') ADVANCE(42); 523 | if (lookahead == '_') ADVANCE(55); 524 | if (lookahead == '{') ADVANCE(43); 525 | if (lookahead == '}') ADVANCE(12); 526 | if (('+' <= lookahead && lookahead <= '-')) ADVANCE(9); 527 | if (lookahead == '\t' || 528 | lookahead == '\n' || 529 | lookahead == '\r' || 530 | lookahead == ' ') SKIP(1) 531 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(60); 532 | if (('A' <= lookahead && lookahead <= 'Z') || 533 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 534 | END_STATE(); 535 | case 2: 536 | if (lookahead == '#') ADVANCE(25); 537 | if (lookahead == '%') ADVANCE(23); 538 | if (lookahead == '{') ADVANCE(21); 539 | if (lookahead != 0) ADVANCE(59); 540 | END_STATE(); 541 | case 3: 542 | if (lookahead == '#') ADVANCE(6); 543 | if (lookahead == '}') ADVANCE(27); 544 | if (lookahead != 0) ADVANCE(5); 545 | END_STATE(); 546 | case 4: 547 | if (lookahead == '#') ADVANCE(6); 548 | if (lookahead == '\t' || 549 | lookahead == '\n' || 550 | lookahead == '\r' || 551 | lookahead == ' ') ADVANCE(4); 552 | if (lookahead != 0) ADVANCE(5); 553 | END_STATE(); 554 | case 5: 555 | if (lookahead == '#') ADVANCE(6); 556 | if (lookahead != 0) ADVANCE(5); 557 | END_STATE(); 558 | case 6: 559 | if (lookahead == '#') ADVANCE(3); 560 | if (lookahead == '}') ADVANCE(26); 561 | if (lookahead != 0) ADVANCE(5); 562 | END_STATE(); 563 | case 7: 564 | if (lookahead == '%') ADVANCE(13); 565 | if (lookahead == '\t' || 566 | lookahead == '\n' || 567 | lookahead == '\r' || 568 | lookahead == ' ') ADVANCE(7); 569 | if (lookahead != 0) ADVANCE(8); 570 | END_STATE(); 571 | case 8: 572 | if (lookahead == '%') ADVANCE(13); 573 | if (lookahead != 0) ADVANCE(8); 574 | END_STATE(); 575 | case 9: 576 | if (lookahead == '.') ADVANCE(15); 577 | if (lookahead == '_') ADVANCE(16); 578 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(61); 579 | END_STATE(); 580 | case 10: 581 | if (lookahead == '.') ADVANCE(65); 582 | if (lookahead == 'E' || 583 | lookahead == 'e') ADVANCE(14); 584 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(60); 585 | END_STATE(); 586 | case 11: 587 | if (lookahead == '.') ADVANCE(65); 588 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(61); 589 | END_STATE(); 590 | case 12: 591 | if (lookahead == '}') ADVANCE(22); 592 | END_STATE(); 593 | case 13: 594 | if (lookahead == '}') ADVANCE(24); 595 | if (lookahead != 0) ADVANCE(8); 596 | END_STATE(); 597 | case 14: 598 | if (lookahead == '+' || 599 | lookahead == '-') ADVANCE(17); 600 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(64); 601 | END_STATE(); 602 | case 15: 603 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(63); 604 | END_STATE(); 605 | case 16: 606 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(62); 607 | END_STATE(); 608 | case 17: 609 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(64); 610 | END_STATE(); 611 | case 18: 612 | if (lookahead != 0 && 613 | lookahead != '#' && 614 | lookahead != '%' && 615 | lookahead != '{') ADVANCE(59); 616 | END_STATE(); 617 | case 19: 618 | if (eof) ADVANCE(20); 619 | if (lookahead == '{') ADVANCE(2); 620 | if (lookahead == '\t' || 621 | lookahead == '\n' || 622 | lookahead == '\r' || 623 | lookahead == ' ') ADVANCE(58); 624 | if (lookahead != 0) ADVANCE(59); 625 | END_STATE(); 626 | case 20: 627 | ACCEPT_TOKEN(ts_builtin_sym_end); 628 | END_STATE(); 629 | case 21: 630 | ACCEPT_TOKEN(anon_sym_LBRACE_LBRACE); 631 | END_STATE(); 632 | case 22: 633 | ACCEPT_TOKEN(anon_sym_RBRACE_RBRACE); 634 | END_STATE(); 635 | case 23: 636 | ACCEPT_TOKEN(anon_sym_LBRACE_PERCENT); 637 | END_STATE(); 638 | case 24: 639 | ACCEPT_TOKEN(aux_sym_jinja_expression_token1); 640 | END_STATE(); 641 | case 25: 642 | ACCEPT_TOKEN(anon_sym_LBRACE_POUND); 643 | END_STATE(); 644 | case 26: 645 | ACCEPT_TOKEN(aux_sym__jinja_comment_token1); 646 | END_STATE(); 647 | case 27: 648 | ACCEPT_TOKEN(aux_sym__jinja_comment_token1); 649 | if (lookahead == '#') ADVANCE(6); 650 | if (lookahead != 0) ADVANCE(5); 651 | END_STATE(); 652 | case 28: 653 | ACCEPT_TOKEN(anon_sym_LPAREN); 654 | END_STATE(); 655 | case 29: 656 | ACCEPT_TOKEN(anon_sym_COMMA); 657 | END_STATE(); 658 | case 30: 659 | ACCEPT_TOKEN(anon_sym_RPAREN); 660 | END_STATE(); 661 | case 31: 662 | ACCEPT_TOKEN(anon_sym_SQUOTE); 663 | END_STATE(); 664 | case 32: 665 | ACCEPT_TOKEN(aux_sym_lit_string_token1); 666 | if (lookahead == '\\') ADVANCE(34); 667 | if (lookahead == '\t' || 668 | lookahead == '\n' || 669 | lookahead == '\r' || 670 | lookahead == ' ') ADVANCE(32); 671 | if (lookahead != 0 && 672 | lookahead != '\'') ADVANCE(33); 673 | END_STATE(); 674 | case 33: 675 | ACCEPT_TOKEN(aux_sym_lit_string_token1); 676 | if (lookahead == '\\') ADVANCE(34); 677 | if (lookahead != 0 && 678 | lookahead != '\'') ADVANCE(33); 679 | END_STATE(); 680 | case 34: 681 | ACCEPT_TOKEN(aux_sym_lit_string_token1); 682 | if (lookahead != 0 && 683 | lookahead != '\\') ADVANCE(33); 684 | if (lookahead == '\\') ADVANCE(34); 685 | END_STATE(); 686 | case 35: 687 | ACCEPT_TOKEN(anon_sym_DQUOTE); 688 | END_STATE(); 689 | case 36: 690 | ACCEPT_TOKEN(aux_sym_lit_string_token2); 691 | if (lookahead == '\\') ADVANCE(38); 692 | if (lookahead == '\t' || 693 | lookahead == '\n' || 694 | lookahead == '\r' || 695 | lookahead == ' ') ADVANCE(36); 696 | if (lookahead != 0 && 697 | lookahead != '"') ADVANCE(37); 698 | END_STATE(); 699 | case 37: 700 | ACCEPT_TOKEN(aux_sym_lit_string_token2); 701 | if (lookahead == '\\') ADVANCE(38); 702 | if (lookahead != 0 && 703 | lookahead != '"') ADVANCE(37); 704 | END_STATE(); 705 | case 38: 706 | ACCEPT_TOKEN(aux_sym_lit_string_token2); 707 | if (lookahead != 0 && 708 | lookahead != '\\') ADVANCE(37); 709 | if (lookahead == '\\') ADVANCE(38); 710 | END_STATE(); 711 | case 39: 712 | ACCEPT_TOKEN(anon_sym_True); 713 | if (('0' <= lookahead && lookahead <= '9') || 714 | ('A' <= lookahead && lookahead <= 'Z') || 715 | lookahead == '_' || 716 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 717 | END_STATE(); 718 | case 40: 719 | ACCEPT_TOKEN(anon_sym_False); 720 | if (('0' <= lookahead && lookahead <= '9') || 721 | ('A' <= lookahead && lookahead <= 'Z') || 722 | lookahead == '_' || 723 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 724 | END_STATE(); 725 | case 41: 726 | ACCEPT_TOKEN(anon_sym_LBRACK); 727 | END_STATE(); 728 | case 42: 729 | ACCEPT_TOKEN(anon_sym_RBRACK); 730 | END_STATE(); 731 | case 43: 732 | ACCEPT_TOKEN(anon_sym_LBRACE); 733 | END_STATE(); 734 | case 44: 735 | ACCEPT_TOKEN(anon_sym_LBRACE); 736 | if (lookahead == '#') ADVANCE(25); 737 | if (lookahead == '%') ADVANCE(23); 738 | if (lookahead == '{') ADVANCE(21); 739 | END_STATE(); 740 | case 45: 741 | ACCEPT_TOKEN(anon_sym_RBRACE); 742 | END_STATE(); 743 | case 46: 744 | ACCEPT_TOKEN(anon_sym_COLON); 745 | END_STATE(); 746 | case 47: 747 | ACCEPT_TOKEN(sym__identifier); 748 | if (lookahead == '_') ADVANCE(55); 749 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(47); 750 | if (('A' <= lookahead && lookahead <= 'Z') || 751 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 752 | END_STATE(); 753 | case 48: 754 | ACCEPT_TOKEN(sym__identifier); 755 | if (lookahead == 'a') ADVANCE(51); 756 | if (('0' <= lookahead && lookahead <= '9') || 757 | ('A' <= lookahead && lookahead <= 'Z') || 758 | lookahead == '_' || 759 | ('b' <= lookahead && lookahead <= 'z')) ADVANCE(56); 760 | END_STATE(); 761 | case 49: 762 | ACCEPT_TOKEN(sym__identifier); 763 | if (lookahead == 'e') ADVANCE(39); 764 | if (('0' <= lookahead && lookahead <= '9') || 765 | ('A' <= lookahead && lookahead <= 'Z') || 766 | lookahead == '_' || 767 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 768 | END_STATE(); 769 | case 50: 770 | ACCEPT_TOKEN(sym__identifier); 771 | if (lookahead == 'e') ADVANCE(40); 772 | if (('0' <= lookahead && lookahead <= '9') || 773 | ('A' <= lookahead && lookahead <= 'Z') || 774 | lookahead == '_' || 775 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 776 | END_STATE(); 777 | case 51: 778 | ACCEPT_TOKEN(sym__identifier); 779 | if (lookahead == 'l') ADVANCE(53); 780 | if (('0' <= lookahead && lookahead <= '9') || 781 | ('A' <= lookahead && lookahead <= 'Z') || 782 | lookahead == '_' || 783 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 784 | END_STATE(); 785 | case 52: 786 | ACCEPT_TOKEN(sym__identifier); 787 | if (lookahead == 'r') ADVANCE(54); 788 | if (('0' <= lookahead && lookahead <= '9') || 789 | ('A' <= lookahead && lookahead <= 'Z') || 790 | lookahead == '_' || 791 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 792 | END_STATE(); 793 | case 53: 794 | ACCEPT_TOKEN(sym__identifier); 795 | if (lookahead == 's') ADVANCE(50); 796 | if (('0' <= lookahead && lookahead <= '9') || 797 | ('A' <= lookahead && lookahead <= 'Z') || 798 | lookahead == '_' || 799 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 800 | END_STATE(); 801 | case 54: 802 | ACCEPT_TOKEN(sym__identifier); 803 | if (lookahead == 'u') ADVANCE(49); 804 | if (('0' <= lookahead && lookahead <= '9') || 805 | ('A' <= lookahead && lookahead <= 'Z') || 806 | lookahead == '_' || 807 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 808 | END_STATE(); 809 | case 55: 810 | ACCEPT_TOKEN(sym__identifier); 811 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(47); 812 | if (('A' <= lookahead && lookahead <= 'Z') || 813 | lookahead == '_' || 814 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 815 | END_STATE(); 816 | case 56: 817 | ACCEPT_TOKEN(sym__identifier); 818 | if (('0' <= lookahead && lookahead <= '9') || 819 | ('A' <= lookahead && lookahead <= 'Z') || 820 | lookahead == '_' || 821 | ('a' <= lookahead && lookahead <= 'z')) ADVANCE(56); 822 | END_STATE(); 823 | case 57: 824 | ACCEPT_TOKEN(anon_sym_EQ); 825 | END_STATE(); 826 | case 58: 827 | ACCEPT_TOKEN(sym__text); 828 | if (lookahead == '{') ADVANCE(2); 829 | if (lookahead == '\t' || 830 | lookahead == '\n' || 831 | lookahead == '\r' || 832 | lookahead == ' ') ADVANCE(58); 833 | if (lookahead != 0) ADVANCE(59); 834 | END_STATE(); 835 | case 59: 836 | ACCEPT_TOKEN(sym__text); 837 | if (lookahead == '{') ADVANCE(18); 838 | if (lookahead != 0) ADVANCE(59); 839 | END_STATE(); 840 | case 60: 841 | ACCEPT_TOKEN(sym_integer); 842 | if (lookahead == '.') ADVANCE(65); 843 | if (lookahead == '_') ADVANCE(10); 844 | if (lookahead == 'E' || 845 | lookahead == 'e') ADVANCE(14); 846 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(60); 847 | END_STATE(); 848 | case 61: 849 | ACCEPT_TOKEN(sym_integer); 850 | if (lookahead == '.') ADVANCE(65); 851 | if (lookahead == '_') ADVANCE(11); 852 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(61); 853 | END_STATE(); 854 | case 62: 855 | ACCEPT_TOKEN(sym_integer); 856 | if (lookahead == '_') ADVANCE(16); 857 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(62); 858 | END_STATE(); 859 | case 63: 860 | ACCEPT_TOKEN(sym_float); 861 | if (lookahead == '_') ADVANCE(65); 862 | if (lookahead == 'E' || 863 | lookahead == 'e') ADVANCE(14); 864 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(63); 865 | END_STATE(); 866 | case 64: 867 | ACCEPT_TOKEN(sym_float); 868 | if (lookahead == '_') ADVANCE(66); 869 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(64); 870 | END_STATE(); 871 | case 65: 872 | ACCEPT_TOKEN(sym_float); 873 | if (lookahead == 'E' || 874 | lookahead == 'e') ADVANCE(14); 875 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(63); 876 | END_STATE(); 877 | case 66: 878 | ACCEPT_TOKEN(sym_float); 879 | if (('0' <= lookahead && lookahead <= '9')) ADVANCE(64); 880 | END_STATE(); 881 | default: 882 | return false; 883 | } 884 | } 885 | 886 | static const TSLexMode ts_lex_modes[STATE_COUNT] = { 887 | [0] = {.lex_state = 0}, 888 | [1] = {.lex_state = 19}, 889 | [2] = {.lex_state = 1}, 890 | [3] = {.lex_state = 1}, 891 | [4] = {.lex_state = 1}, 892 | [5] = {.lex_state = 1}, 893 | [6] = {.lex_state = 1}, 894 | [7] = {.lex_state = 1}, 895 | [8] = {.lex_state = 1}, 896 | [9] = {.lex_state = 1}, 897 | [10] = {.lex_state = 1}, 898 | [11] = {.lex_state = 1}, 899 | [12] = {.lex_state = 1}, 900 | [13] = {.lex_state = 1}, 901 | [14] = {.lex_state = 1}, 902 | [15] = {.lex_state = 1}, 903 | [16] = {.lex_state = 1}, 904 | [17] = {.lex_state = 1}, 905 | [18] = {.lex_state = 1}, 906 | [19] = {.lex_state = 19}, 907 | [20] = {.lex_state = 19}, 908 | [21] = {.lex_state = 0}, 909 | [22] = {.lex_state = 0}, 910 | [23] = {.lex_state = 19}, 911 | [24] = {.lex_state = 0}, 912 | [25] = {.lex_state = 0}, 913 | [26] = {.lex_state = 0}, 914 | [27] = {.lex_state = 19}, 915 | [28] = {.lex_state = 0}, 916 | [29] = {.lex_state = 19}, 917 | [30] = {.lex_state = 1}, 918 | [31] = {.lex_state = 1}, 919 | [32] = {.lex_state = 1}, 920 | [33] = {.lex_state = 1}, 921 | [34] = {.lex_state = 1}, 922 | [35] = {.lex_state = 1}, 923 | [36] = {.lex_state = 1}, 924 | [37] = {.lex_state = 1}, 925 | [38] = {.lex_state = 1}, 926 | [39] = {.lex_state = 1}, 927 | [40] = {.lex_state = 0}, 928 | [41] = {.lex_state = 1}, 929 | [42] = {.lex_state = 1}, 930 | [43] = {.lex_state = 1}, 931 | [44] = {.lex_state = 1}, 932 | [45] = {.lex_state = 1}, 933 | [46] = {.lex_state = 0}, 934 | [47] = {.lex_state = 0}, 935 | [48] = {.lex_state = 0}, 936 | [49] = {.lex_state = 0}, 937 | [50] = {.lex_state = 0}, 938 | [51] = {.lex_state = 0}, 939 | [52] = {.lex_state = 0}, 940 | [53] = {.lex_state = 0}, 941 | [54] = {.lex_state = 0}, 942 | [55] = {.lex_state = 0}, 943 | [56] = {.lex_state = 0}, 944 | [57] = {.lex_state = 0}, 945 | [58] = {.lex_state = 0}, 946 | [59] = {.lex_state = 0}, 947 | [60] = {.lex_state = 0}, 948 | [61] = {.lex_state = 0}, 949 | [62] = {.lex_state = 0}, 950 | [63] = {.lex_state = 0}, 951 | [64] = {.lex_state = 0}, 952 | [65] = {.lex_state = 0}, 953 | [66] = {.lex_state = 0}, 954 | [67] = {.lex_state = 0}, 955 | [68] = {.lex_state = 0}, 956 | [69] = {.lex_state = 0}, 957 | [70] = {.lex_state = 0}, 958 | [71] = {.lex_state = 0}, 959 | [72] = {.lex_state = 0}, 960 | [73] = {.lex_state = 0}, 961 | [74] = {.lex_state = 0}, 962 | [75] = {.lex_state = 0}, 963 | [76] = {.lex_state = 0}, 964 | [77] = {.lex_state = 0}, 965 | [78] = {.lex_state = 0}, 966 | [79] = {.lex_state = 0}, 967 | [80] = {.lex_state = 0}, 968 | [81] = {.lex_state = 0}, 969 | [82] = {.lex_state = 0}, 970 | [83] = {.lex_state = 0}, 971 | [84] = {.lex_state = 0}, 972 | [85] = {.lex_state = 0}, 973 | [86] = {.lex_state = 0}, 974 | [87] = {.lex_state = 0}, 975 | [88] = {.lex_state = 0}, 976 | [89] = {.lex_state = 0}, 977 | [90] = {.lex_state = 0}, 978 | [91] = {.lex_state = 1}, 979 | [92] = {.lex_state = 0}, 980 | [93] = {.lex_state = 0}, 981 | [94] = {.lex_state = 0}, 982 | [95] = {.lex_state = 0}, 983 | [96] = {.lex_state = 7}, 984 | [97] = {.lex_state = 36}, 985 | [98] = {.lex_state = 32}, 986 | [99] = {.lex_state = 0}, 987 | [100] = {.lex_state = 0}, 988 | [101] = {.lex_state = 4}, 989 | [102] = {.lex_state = 32}, 990 | [103] = {.lex_state = 36}, 991 | }; 992 | 993 | static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { 994 | [0] = { 995 | [ts_builtin_sym_end] = ACTIONS(1), 996 | [anon_sym_LBRACE_LBRACE] = ACTIONS(1), 997 | [anon_sym_LBRACE_PERCENT] = ACTIONS(1), 998 | [anon_sym_LBRACE_POUND] = ACTIONS(1), 999 | [anon_sym_LPAREN] = ACTIONS(1), 1000 | [anon_sym_COMMA] = ACTIONS(1), 1001 | [anon_sym_RPAREN] = ACTIONS(1), 1002 | [anon_sym_SQUOTE] = ACTIONS(1), 1003 | [anon_sym_DQUOTE] = ACTIONS(1), 1004 | [anon_sym_True] = ACTIONS(1), 1005 | [anon_sym_False] = ACTIONS(1), 1006 | [anon_sym_LBRACK] = ACTIONS(1), 1007 | [anon_sym_RBRACK] = ACTIONS(1), 1008 | [anon_sym_LBRACE] = ACTIONS(1), 1009 | [anon_sym_RBRACE] = ACTIONS(1), 1010 | [anon_sym_COLON] = ACTIONS(1), 1011 | [sym__identifier] = ACTIONS(1), 1012 | [anon_sym_EQ] = ACTIONS(1), 1013 | [sym_integer] = ACTIONS(1), 1014 | [sym_float] = ACTIONS(1), 1015 | }, 1016 | [1] = { 1017 | [sym_source_file] = STATE(99), 1018 | [sym__jinja_value] = STATE(20), 1019 | [sym_jinja_expression] = STATE(20), 1020 | [sym__jinja_comment] = STATE(20), 1021 | [aux_sym_source_file_repeat1] = STATE(20), 1022 | [ts_builtin_sym_end] = ACTIONS(3), 1023 | [anon_sym_LBRACE_LBRACE] = ACTIONS(5), 1024 | [anon_sym_LBRACE_PERCENT] = ACTIONS(7), 1025 | [anon_sym_LBRACE_POUND] = ACTIONS(9), 1026 | [sym__text] = ACTIONS(11), 1027 | }, 1028 | }; 1029 | 1030 | static const uint16_t ts_small_parse_table[] = { 1031 | [0] = 12, 1032 | ACTIONS(13), 1, 1033 | anon_sym_COMMA, 1034 | ACTIONS(15), 1, 1035 | anon_sym_RPAREN, 1036 | ACTIONS(17), 1, 1037 | anon_sym_SQUOTE, 1038 | ACTIONS(19), 1, 1039 | anon_sym_DQUOTE, 1040 | ACTIONS(23), 1, 1041 | anon_sym_LBRACK, 1042 | ACTIONS(25), 1, 1043 | anon_sym_LBRACE, 1044 | ACTIONS(27), 1, 1045 | sym__identifier, 1046 | ACTIONS(29), 1, 1047 | sym_integer, 1048 | ACTIONS(31), 1, 1049 | sym_float, 1050 | STATE(54), 1, 1051 | sym_identifier, 1052 | ACTIONS(21), 2, 1053 | anon_sym_True, 1054 | anon_sym_False, 1055 | STATE(55), 7, 1056 | sym__expr, 1057 | sym_fn_call, 1058 | sym_lit_string, 1059 | sym_bool, 1060 | sym_list, 1061 | sym_dict, 1062 | sym_kwarg, 1063 | [44] = 12, 1064 | ACTIONS(17), 1, 1065 | anon_sym_SQUOTE, 1066 | ACTIONS(19), 1, 1067 | anon_sym_DQUOTE, 1068 | ACTIONS(23), 1, 1069 | anon_sym_LBRACK, 1070 | ACTIONS(25), 1, 1071 | anon_sym_LBRACE, 1072 | ACTIONS(27), 1, 1073 | sym__identifier, 1074 | ACTIONS(33), 1, 1075 | anon_sym_COMMA, 1076 | ACTIONS(35), 1, 1077 | anon_sym_RPAREN, 1078 | ACTIONS(37), 1, 1079 | sym_integer, 1080 | ACTIONS(39), 1, 1081 | sym_float, 1082 | STATE(54), 1, 1083 | sym_identifier, 1084 | ACTIONS(21), 2, 1085 | anon_sym_True, 1086 | anon_sym_False, 1087 | STATE(50), 7, 1088 | sym__expr, 1089 | sym_fn_call, 1090 | sym_lit_string, 1091 | sym_bool, 1092 | sym_list, 1093 | sym_dict, 1094 | sym_kwarg, 1095 | [88] = 12, 1096 | ACTIONS(17), 1, 1097 | anon_sym_SQUOTE, 1098 | ACTIONS(19), 1, 1099 | anon_sym_DQUOTE, 1100 | ACTIONS(23), 1, 1101 | anon_sym_LBRACK, 1102 | ACTIONS(25), 1, 1103 | anon_sym_LBRACE, 1104 | ACTIONS(27), 1, 1105 | sym__identifier, 1106 | ACTIONS(41), 1, 1107 | anon_sym_COMMA, 1108 | ACTIONS(43), 1, 1109 | anon_sym_RBRACK, 1110 | ACTIONS(45), 1, 1111 | sym_integer, 1112 | ACTIONS(47), 1, 1113 | sym_float, 1114 | STATE(82), 1, 1115 | sym_identifier, 1116 | ACTIONS(21), 2, 1117 | anon_sym_True, 1118 | anon_sym_False, 1119 | STATE(61), 6, 1120 | sym__expr, 1121 | sym_fn_call, 1122 | sym_lit_string, 1123 | sym_bool, 1124 | sym_list, 1125 | sym_dict, 1126 | [131] = 11, 1127 | ACTIONS(17), 1, 1128 | anon_sym_SQUOTE, 1129 | ACTIONS(19), 1, 1130 | anon_sym_DQUOTE, 1131 | ACTIONS(23), 1, 1132 | anon_sym_LBRACK, 1133 | ACTIONS(25), 1, 1134 | anon_sym_LBRACE, 1135 | ACTIONS(27), 1, 1136 | sym__identifier, 1137 | ACTIONS(49), 1, 1138 | anon_sym_RPAREN, 1139 | ACTIONS(51), 1, 1140 | sym_integer, 1141 | ACTIONS(53), 1, 1142 | sym_float, 1143 | STATE(54), 1, 1144 | sym_identifier, 1145 | ACTIONS(21), 2, 1146 | anon_sym_True, 1147 | anon_sym_False, 1148 | STATE(83), 7, 1149 | sym__expr, 1150 | sym_fn_call, 1151 | sym_lit_string, 1152 | sym_bool, 1153 | sym_list, 1154 | sym_dict, 1155 | sym_kwarg, 1156 | [172] = 11, 1157 | ACTIONS(17), 1, 1158 | anon_sym_SQUOTE, 1159 | ACTIONS(19), 1, 1160 | anon_sym_DQUOTE, 1161 | ACTIONS(23), 1, 1162 | anon_sym_LBRACK, 1163 | ACTIONS(25), 1, 1164 | anon_sym_LBRACE, 1165 | ACTIONS(27), 1, 1166 | sym__identifier, 1167 | ACTIONS(51), 1, 1168 | sym_integer, 1169 | ACTIONS(53), 1, 1170 | sym_float, 1171 | ACTIONS(55), 1, 1172 | anon_sym_RPAREN, 1173 | STATE(54), 1, 1174 | sym_identifier, 1175 | ACTIONS(21), 2, 1176 | anon_sym_True, 1177 | anon_sym_False, 1178 | STATE(83), 7, 1179 | sym__expr, 1180 | sym_fn_call, 1181 | sym_lit_string, 1182 | sym_bool, 1183 | sym_list, 1184 | sym_dict, 1185 | sym_kwarg, 1186 | [213] = 11, 1187 | ACTIONS(17), 1, 1188 | anon_sym_SQUOTE, 1189 | ACTIONS(19), 1, 1190 | anon_sym_DQUOTE, 1191 | ACTIONS(23), 1, 1192 | anon_sym_LBRACK, 1193 | ACTIONS(25), 1, 1194 | anon_sym_LBRACE, 1195 | ACTIONS(27), 1, 1196 | sym__identifier, 1197 | ACTIONS(51), 1, 1198 | sym_integer, 1199 | ACTIONS(53), 1, 1200 | sym_float, 1201 | ACTIONS(57), 1, 1202 | anon_sym_RPAREN, 1203 | STATE(54), 1, 1204 | sym_identifier, 1205 | ACTIONS(21), 2, 1206 | anon_sym_True, 1207 | anon_sym_False, 1208 | STATE(83), 7, 1209 | sym__expr, 1210 | sym_fn_call, 1211 | sym_lit_string, 1212 | sym_bool, 1213 | sym_list, 1214 | sym_dict, 1215 | sym_kwarg, 1216 | [254] = 12, 1217 | ACTIONS(17), 1, 1218 | anon_sym_SQUOTE, 1219 | ACTIONS(19), 1, 1220 | anon_sym_DQUOTE, 1221 | ACTIONS(23), 1, 1222 | anon_sym_LBRACK, 1223 | ACTIONS(25), 1, 1224 | anon_sym_LBRACE, 1225 | ACTIONS(27), 1, 1226 | sym__identifier, 1227 | ACTIONS(59), 1, 1228 | anon_sym_COMMA, 1229 | ACTIONS(61), 1, 1230 | anon_sym_RBRACK, 1231 | ACTIONS(63), 1, 1232 | sym_integer, 1233 | ACTIONS(65), 1, 1234 | sym_float, 1235 | STATE(82), 1, 1236 | sym_identifier, 1237 | ACTIONS(21), 2, 1238 | anon_sym_True, 1239 | anon_sym_False, 1240 | STATE(60), 6, 1241 | sym__expr, 1242 | sym_fn_call, 1243 | sym_lit_string, 1244 | sym_bool, 1245 | sym_list, 1246 | sym_dict, 1247 | [297] = 11, 1248 | ACTIONS(17), 1, 1249 | anon_sym_SQUOTE, 1250 | ACTIONS(19), 1, 1251 | anon_sym_DQUOTE, 1252 | ACTIONS(23), 1, 1253 | anon_sym_LBRACK, 1254 | ACTIONS(25), 1, 1255 | anon_sym_LBRACE, 1256 | ACTIONS(27), 1, 1257 | sym__identifier, 1258 | ACTIONS(51), 1, 1259 | sym_integer, 1260 | ACTIONS(53), 1, 1261 | sym_float, 1262 | ACTIONS(67), 1, 1263 | anon_sym_RPAREN, 1264 | STATE(54), 1, 1265 | sym_identifier, 1266 | ACTIONS(21), 2, 1267 | anon_sym_True, 1268 | anon_sym_False, 1269 | STATE(83), 7, 1270 | sym__expr, 1271 | sym_fn_call, 1272 | sym_lit_string, 1273 | sym_bool, 1274 | sym_list, 1275 | sym_dict, 1276 | sym_kwarg, 1277 | [338] = 11, 1278 | ACTIONS(17), 1, 1279 | anon_sym_SQUOTE, 1280 | ACTIONS(19), 1, 1281 | anon_sym_DQUOTE, 1282 | ACTIONS(23), 1, 1283 | anon_sym_LBRACK, 1284 | ACTIONS(25), 1, 1285 | anon_sym_LBRACE, 1286 | ACTIONS(27), 1, 1287 | sym__identifier, 1288 | ACTIONS(69), 1, 1289 | anon_sym_RBRACK, 1290 | ACTIONS(71), 1, 1291 | sym_integer, 1292 | ACTIONS(73), 1, 1293 | sym_float, 1294 | STATE(82), 1, 1295 | sym_identifier, 1296 | ACTIONS(21), 2, 1297 | anon_sym_True, 1298 | anon_sym_False, 1299 | STATE(75), 6, 1300 | sym__expr, 1301 | sym_fn_call, 1302 | sym_lit_string, 1303 | sym_bool, 1304 | sym_list, 1305 | sym_dict, 1306 | [378] = 11, 1307 | ACTIONS(17), 1, 1308 | anon_sym_SQUOTE, 1309 | ACTIONS(19), 1, 1310 | anon_sym_DQUOTE, 1311 | ACTIONS(23), 1, 1312 | anon_sym_LBRACK, 1313 | ACTIONS(25), 1, 1314 | anon_sym_LBRACE, 1315 | ACTIONS(27), 1, 1316 | sym__identifier, 1317 | ACTIONS(71), 1, 1318 | sym_integer, 1319 | ACTIONS(73), 1, 1320 | sym_float, 1321 | ACTIONS(75), 1, 1322 | anon_sym_RBRACK, 1323 | STATE(82), 1, 1324 | sym_identifier, 1325 | ACTIONS(21), 2, 1326 | anon_sym_True, 1327 | anon_sym_False, 1328 | STATE(75), 6, 1329 | sym__expr, 1330 | sym_fn_call, 1331 | sym_lit_string, 1332 | sym_bool, 1333 | sym_list, 1334 | sym_dict, 1335 | [418] = 11, 1336 | ACTIONS(17), 1, 1337 | anon_sym_SQUOTE, 1338 | ACTIONS(19), 1, 1339 | anon_sym_DQUOTE, 1340 | ACTIONS(23), 1, 1341 | anon_sym_LBRACK, 1342 | ACTIONS(25), 1, 1343 | anon_sym_LBRACE, 1344 | ACTIONS(27), 1, 1345 | sym__identifier, 1346 | ACTIONS(71), 1, 1347 | sym_integer, 1348 | ACTIONS(73), 1, 1349 | sym_float, 1350 | ACTIONS(77), 1, 1351 | anon_sym_RBRACK, 1352 | STATE(82), 1, 1353 | sym_identifier, 1354 | ACTIONS(21), 2, 1355 | anon_sym_True, 1356 | anon_sym_False, 1357 | STATE(75), 6, 1358 | sym__expr, 1359 | sym_fn_call, 1360 | sym_lit_string, 1361 | sym_bool, 1362 | sym_list, 1363 | sym_dict, 1364 | [458] = 11, 1365 | ACTIONS(17), 1, 1366 | anon_sym_SQUOTE, 1367 | ACTIONS(19), 1, 1368 | anon_sym_DQUOTE, 1369 | ACTIONS(23), 1, 1370 | anon_sym_LBRACK, 1371 | ACTIONS(25), 1, 1372 | anon_sym_LBRACE, 1373 | ACTIONS(27), 1, 1374 | sym__identifier, 1375 | ACTIONS(71), 1, 1376 | sym_integer, 1377 | ACTIONS(73), 1, 1378 | sym_float, 1379 | ACTIONS(79), 1, 1380 | anon_sym_RBRACK, 1381 | STATE(82), 1, 1382 | sym_identifier, 1383 | ACTIONS(21), 2, 1384 | anon_sym_True, 1385 | anon_sym_False, 1386 | STATE(75), 6, 1387 | sym__expr, 1388 | sym_fn_call, 1389 | sym_lit_string, 1390 | sym_bool, 1391 | sym_list, 1392 | sym_dict, 1393 | [498] = 10, 1394 | ACTIONS(17), 1, 1395 | anon_sym_SQUOTE, 1396 | ACTIONS(19), 1, 1397 | anon_sym_DQUOTE, 1398 | ACTIONS(23), 1, 1399 | anon_sym_LBRACK, 1400 | ACTIONS(25), 1, 1401 | anon_sym_LBRACE, 1402 | ACTIONS(27), 1, 1403 | sym__identifier, 1404 | ACTIONS(51), 1, 1405 | sym_integer, 1406 | ACTIONS(53), 1, 1407 | sym_float, 1408 | STATE(54), 1, 1409 | sym_identifier, 1410 | ACTIONS(21), 2, 1411 | anon_sym_True, 1412 | anon_sym_False, 1413 | STATE(83), 7, 1414 | sym__expr, 1415 | sym_fn_call, 1416 | sym_lit_string, 1417 | sym_bool, 1418 | sym_list, 1419 | sym_dict, 1420 | sym_kwarg, 1421 | [536] = 10, 1422 | ACTIONS(17), 1, 1423 | anon_sym_SQUOTE, 1424 | ACTIONS(19), 1, 1425 | anon_sym_DQUOTE, 1426 | ACTIONS(23), 1, 1427 | anon_sym_LBRACK, 1428 | ACTIONS(25), 1, 1429 | anon_sym_LBRACE, 1430 | ACTIONS(27), 1, 1431 | sym__identifier, 1432 | ACTIONS(71), 1, 1433 | sym_integer, 1434 | ACTIONS(73), 1, 1435 | sym_float, 1436 | STATE(82), 1, 1437 | sym_identifier, 1438 | ACTIONS(21), 2, 1439 | anon_sym_True, 1440 | anon_sym_False, 1441 | STATE(75), 6, 1442 | sym__expr, 1443 | sym_fn_call, 1444 | sym_lit_string, 1445 | sym_bool, 1446 | sym_list, 1447 | sym_dict, 1448 | [573] = 10, 1449 | ACTIONS(17), 1, 1450 | anon_sym_SQUOTE, 1451 | ACTIONS(19), 1, 1452 | anon_sym_DQUOTE, 1453 | ACTIONS(23), 1, 1454 | anon_sym_LBRACK, 1455 | ACTIONS(25), 1, 1456 | anon_sym_LBRACE, 1457 | ACTIONS(27), 1, 1458 | sym__identifier, 1459 | ACTIONS(81), 1, 1460 | sym_integer, 1461 | ACTIONS(83), 1, 1462 | sym_float, 1463 | STATE(82), 1, 1464 | sym_identifier, 1465 | ACTIONS(21), 2, 1466 | anon_sym_True, 1467 | anon_sym_False, 1468 | STATE(91), 6, 1469 | sym__expr, 1470 | sym_fn_call, 1471 | sym_lit_string, 1472 | sym_bool, 1473 | sym_list, 1474 | sym_dict, 1475 | [610] = 10, 1476 | ACTIONS(27), 1, 1477 | sym__identifier, 1478 | ACTIONS(85), 1, 1479 | anon_sym_SQUOTE, 1480 | ACTIONS(87), 1, 1481 | anon_sym_DQUOTE, 1482 | ACTIONS(91), 1, 1483 | anon_sym_LBRACK, 1484 | ACTIONS(93), 1, 1485 | anon_sym_LBRACE, 1486 | ACTIONS(95), 1, 1487 | sym_integer, 1488 | ACTIONS(97), 1, 1489 | sym_float, 1490 | STATE(63), 1, 1491 | sym_identifier, 1492 | ACTIONS(89), 2, 1493 | anon_sym_True, 1494 | anon_sym_False, 1495 | STATE(84), 6, 1496 | sym__expr, 1497 | sym_fn_call, 1498 | sym_lit_string, 1499 | sym_bool, 1500 | sym_list, 1501 | sym_dict, 1502 | [647] = 10, 1503 | ACTIONS(17), 1, 1504 | anon_sym_SQUOTE, 1505 | ACTIONS(19), 1, 1506 | anon_sym_DQUOTE, 1507 | ACTIONS(23), 1, 1508 | anon_sym_LBRACK, 1509 | ACTIONS(25), 1, 1510 | anon_sym_LBRACE, 1511 | ACTIONS(27), 1, 1512 | sym__identifier, 1513 | ACTIONS(99), 1, 1514 | sym_integer, 1515 | ACTIONS(101), 1, 1516 | sym_float, 1517 | STATE(82), 1, 1518 | sym_identifier, 1519 | ACTIONS(21), 2, 1520 | anon_sym_True, 1521 | anon_sym_False, 1522 | STATE(64), 6, 1523 | sym__expr, 1524 | sym_fn_call, 1525 | sym_lit_string, 1526 | sym_bool, 1527 | sym_list, 1528 | sym_dict, 1529 | [684] = 6, 1530 | ACTIONS(103), 1, 1531 | ts_builtin_sym_end, 1532 | ACTIONS(105), 1, 1533 | anon_sym_LBRACE_LBRACE, 1534 | ACTIONS(108), 1, 1535 | anon_sym_LBRACE_PERCENT, 1536 | ACTIONS(111), 1, 1537 | anon_sym_LBRACE_POUND, 1538 | ACTIONS(114), 1, 1539 | sym__text, 1540 | STATE(19), 4, 1541 | sym__jinja_value, 1542 | sym_jinja_expression, 1543 | sym__jinja_comment, 1544 | aux_sym_source_file_repeat1, 1545 | [706] = 6, 1546 | ACTIONS(5), 1, 1547 | anon_sym_LBRACE_LBRACE, 1548 | ACTIONS(7), 1, 1549 | anon_sym_LBRACE_PERCENT, 1550 | ACTIONS(9), 1, 1551 | anon_sym_LBRACE_POUND, 1552 | ACTIONS(117), 1, 1553 | ts_builtin_sym_end, 1554 | ACTIONS(119), 1, 1555 | sym__text, 1556 | STATE(19), 4, 1557 | sym__jinja_value, 1558 | sym_jinja_expression, 1559 | sym__jinja_comment, 1560 | aux_sym_source_file_repeat1, 1561 | [728] = 6, 1562 | ACTIONS(17), 1, 1563 | anon_sym_SQUOTE, 1564 | ACTIONS(19), 1, 1565 | anon_sym_DQUOTE, 1566 | ACTIONS(121), 1, 1567 | anon_sym_COMMA, 1568 | ACTIONS(123), 1, 1569 | anon_sym_RBRACE, 1570 | STATE(46), 1, 1571 | sym_pair, 1572 | STATE(92), 1, 1573 | sym_lit_string, 1574 | [747] = 6, 1575 | ACTIONS(17), 1, 1576 | anon_sym_SQUOTE, 1577 | ACTIONS(19), 1, 1578 | anon_sym_DQUOTE, 1579 | ACTIONS(125), 1, 1580 | anon_sym_COMMA, 1581 | ACTIONS(127), 1, 1582 | anon_sym_RBRACE, 1583 | STATE(59), 1, 1584 | sym_pair, 1585 | STATE(92), 1, 1586 | sym_lit_string, 1587 | [766] = 2, 1588 | ACTIONS(129), 2, 1589 | ts_builtin_sym_end, 1590 | sym__text, 1591 | ACTIONS(131), 3, 1592 | anon_sym_LBRACE_LBRACE, 1593 | anon_sym_LBRACE_PERCENT, 1594 | anon_sym_LBRACE_POUND, 1595 | [776] = 5, 1596 | ACTIONS(17), 1, 1597 | anon_sym_SQUOTE, 1598 | ACTIONS(19), 1, 1599 | anon_sym_DQUOTE, 1600 | ACTIONS(133), 1, 1601 | anon_sym_RBRACE, 1602 | STATE(65), 1, 1603 | sym_pair, 1604 | STATE(92), 1, 1605 | sym_lit_string, 1606 | [792] = 5, 1607 | ACTIONS(17), 1, 1608 | anon_sym_SQUOTE, 1609 | ACTIONS(19), 1, 1610 | anon_sym_DQUOTE, 1611 | ACTIONS(135), 1, 1612 | anon_sym_RBRACE, 1613 | STATE(65), 1, 1614 | sym_pair, 1615 | STATE(92), 1, 1616 | sym_lit_string, 1617 | [808] = 5, 1618 | ACTIONS(17), 1, 1619 | anon_sym_SQUOTE, 1620 | ACTIONS(19), 1, 1621 | anon_sym_DQUOTE, 1622 | ACTIONS(137), 1, 1623 | anon_sym_RBRACE, 1624 | STATE(65), 1, 1625 | sym_pair, 1626 | STATE(92), 1, 1627 | sym_lit_string, 1628 | [824] = 2, 1629 | ACTIONS(139), 2, 1630 | ts_builtin_sym_end, 1631 | sym__text, 1632 | ACTIONS(141), 3, 1633 | anon_sym_LBRACE_LBRACE, 1634 | anon_sym_LBRACE_PERCENT, 1635 | anon_sym_LBRACE_POUND, 1636 | [834] = 5, 1637 | ACTIONS(17), 1, 1638 | anon_sym_SQUOTE, 1639 | ACTIONS(19), 1, 1640 | anon_sym_DQUOTE, 1641 | ACTIONS(143), 1, 1642 | anon_sym_RBRACE, 1643 | STATE(65), 1, 1644 | sym_pair, 1645 | STATE(92), 1, 1646 | sym_lit_string, 1647 | [850] = 2, 1648 | ACTIONS(145), 2, 1649 | ts_builtin_sym_end, 1650 | sym__text, 1651 | ACTIONS(147), 3, 1652 | anon_sym_LBRACE_LBRACE, 1653 | anon_sym_LBRACE_PERCENT, 1654 | anon_sym_LBRACE_POUND, 1655 | [860] = 1, 1656 | ACTIONS(149), 5, 1657 | anon_sym_RBRACE_RBRACE, 1658 | anon_sym_COMMA, 1659 | anon_sym_RPAREN, 1660 | anon_sym_RBRACK, 1661 | anon_sym_COLON, 1662 | [868] = 1, 1663 | ACTIONS(151), 4, 1664 | anon_sym_RBRACE_RBRACE, 1665 | anon_sym_COMMA, 1666 | anon_sym_RPAREN, 1667 | anon_sym_RBRACK, 1668 | [875] = 1, 1669 | ACTIONS(153), 4, 1670 | anon_sym_RBRACE_RBRACE, 1671 | anon_sym_COMMA, 1672 | anon_sym_RPAREN, 1673 | anon_sym_RBRACK, 1674 | [882] = 1, 1675 | ACTIONS(155), 4, 1676 | anon_sym_RBRACE_RBRACE, 1677 | anon_sym_COMMA, 1678 | anon_sym_RPAREN, 1679 | anon_sym_RBRACK, 1680 | [889] = 1, 1681 | ACTIONS(157), 4, 1682 | anon_sym_RBRACE_RBRACE, 1683 | anon_sym_COMMA, 1684 | anon_sym_RPAREN, 1685 | anon_sym_RBRACK, 1686 | [896] = 1, 1687 | ACTIONS(159), 4, 1688 | anon_sym_RBRACE_RBRACE, 1689 | anon_sym_COMMA, 1690 | anon_sym_RPAREN, 1691 | anon_sym_RBRACK, 1692 | [903] = 1, 1693 | ACTIONS(161), 4, 1694 | anon_sym_RBRACE_RBRACE, 1695 | anon_sym_COMMA, 1696 | anon_sym_RPAREN, 1697 | anon_sym_RBRACK, 1698 | [910] = 1, 1699 | ACTIONS(163), 4, 1700 | anon_sym_RBRACE_RBRACE, 1701 | anon_sym_COMMA, 1702 | anon_sym_RPAREN, 1703 | anon_sym_RBRACK, 1704 | [917] = 1, 1705 | ACTIONS(165), 4, 1706 | anon_sym_RBRACE_RBRACE, 1707 | anon_sym_COMMA, 1708 | anon_sym_RPAREN, 1709 | anon_sym_RBRACK, 1710 | [924] = 1, 1711 | ACTIONS(167), 4, 1712 | anon_sym_RBRACE_RBRACE, 1713 | anon_sym_COMMA, 1714 | anon_sym_RPAREN, 1715 | anon_sym_RBRACK, 1716 | [931] = 4, 1717 | ACTIONS(17), 1, 1718 | anon_sym_SQUOTE, 1719 | ACTIONS(19), 1, 1720 | anon_sym_DQUOTE, 1721 | STATE(65), 1, 1722 | sym_pair, 1723 | STATE(92), 1, 1724 | sym_lit_string, 1725 | [944] = 1, 1726 | ACTIONS(169), 4, 1727 | anon_sym_RBRACE_RBRACE, 1728 | anon_sym_COMMA, 1729 | anon_sym_RPAREN, 1730 | anon_sym_RBRACK, 1731 | [951] = 1, 1732 | ACTIONS(171), 4, 1733 | anon_sym_RBRACE_RBRACE, 1734 | anon_sym_COMMA, 1735 | anon_sym_RPAREN, 1736 | anon_sym_RBRACK, 1737 | [958] = 1, 1738 | ACTIONS(173), 4, 1739 | anon_sym_RBRACE_RBRACE, 1740 | anon_sym_COMMA, 1741 | anon_sym_RPAREN, 1742 | anon_sym_RBRACK, 1743 | [965] = 1, 1744 | ACTIONS(175), 4, 1745 | anon_sym_RBRACE_RBRACE, 1746 | anon_sym_COMMA, 1747 | anon_sym_RPAREN, 1748 | anon_sym_RBRACK, 1749 | [972] = 1, 1750 | ACTIONS(177), 4, 1751 | anon_sym_RBRACE_RBRACE, 1752 | anon_sym_COMMA, 1753 | anon_sym_RPAREN, 1754 | anon_sym_RBRACK, 1755 | [979] = 3, 1756 | ACTIONS(179), 1, 1757 | anon_sym_COMMA, 1758 | ACTIONS(181), 1, 1759 | anon_sym_RBRACE, 1760 | STATE(57), 1, 1761 | aux_sym_dict_repeat1, 1762 | [989] = 3, 1763 | ACTIONS(183), 1, 1764 | anon_sym_COMMA, 1765 | ACTIONS(186), 1, 1766 | anon_sym_RPAREN, 1767 | STATE(47), 1, 1768 | aux_sym_argument_list_repeat1, 1769 | [999] = 3, 1770 | ACTIONS(188), 1, 1771 | anon_sym_COMMA, 1772 | ACTIONS(191), 1, 1773 | anon_sym_RBRACK, 1774 | STATE(48), 1, 1775 | aux_sym_list_repeat1, 1776 | [1009] = 3, 1777 | ACTIONS(55), 1, 1778 | anon_sym_RPAREN, 1779 | ACTIONS(193), 1, 1780 | anon_sym_COMMA, 1781 | STATE(47), 1, 1782 | aux_sym_argument_list_repeat1, 1783 | [1019] = 3, 1784 | ACTIONS(195), 1, 1785 | anon_sym_COMMA, 1786 | ACTIONS(197), 1, 1787 | anon_sym_RPAREN, 1788 | STATE(49), 1, 1789 | aux_sym_argument_list_repeat1, 1790 | [1029] = 3, 1791 | ACTIONS(199), 1, 1792 | anon_sym_COMMA, 1793 | ACTIONS(202), 1, 1794 | anon_sym_RBRACE, 1795 | STATE(51), 1, 1796 | aux_sym_dict_repeat1, 1797 | [1039] = 3, 1798 | ACTIONS(133), 1, 1799 | anon_sym_RBRACE, 1800 | ACTIONS(204), 1, 1801 | anon_sym_COMMA, 1802 | STATE(51), 1, 1803 | aux_sym_dict_repeat1, 1804 | [1049] = 3, 1805 | ACTIONS(67), 1, 1806 | anon_sym_RPAREN, 1807 | ACTIONS(206), 1, 1808 | anon_sym_COMMA, 1809 | STATE(47), 1, 1810 | aux_sym_argument_list_repeat1, 1811 | [1059] = 3, 1812 | ACTIONS(208), 1, 1813 | anon_sym_LPAREN, 1814 | ACTIONS(210), 1, 1815 | anon_sym_EQ, 1816 | STATE(36), 1, 1817 | sym_argument_list, 1818 | [1069] = 3, 1819 | ACTIONS(212), 1, 1820 | anon_sym_COMMA, 1821 | ACTIONS(214), 1, 1822 | anon_sym_RPAREN, 1823 | STATE(53), 1, 1824 | aux_sym_argument_list_repeat1, 1825 | [1079] = 3, 1826 | ACTIONS(75), 1, 1827 | anon_sym_RBRACK, 1828 | ACTIONS(216), 1, 1829 | anon_sym_COMMA, 1830 | STATE(48), 1, 1831 | aux_sym_list_repeat1, 1832 | [1089] = 3, 1833 | ACTIONS(143), 1, 1834 | anon_sym_RBRACE, 1835 | ACTIONS(218), 1, 1836 | anon_sym_COMMA, 1837 | STATE(51), 1, 1838 | aux_sym_dict_repeat1, 1839 | [1099] = 3, 1840 | ACTIONS(77), 1, 1841 | anon_sym_RBRACK, 1842 | ACTIONS(220), 1, 1843 | anon_sym_COMMA, 1844 | STATE(48), 1, 1845 | aux_sym_list_repeat1, 1846 | [1109] = 3, 1847 | ACTIONS(222), 1, 1848 | anon_sym_COMMA, 1849 | ACTIONS(224), 1, 1850 | anon_sym_RBRACE, 1851 | STATE(52), 1, 1852 | aux_sym_dict_repeat1, 1853 | [1119] = 3, 1854 | ACTIONS(226), 1, 1855 | anon_sym_COMMA, 1856 | ACTIONS(228), 1, 1857 | anon_sym_RBRACK, 1858 | STATE(56), 1, 1859 | aux_sym_list_repeat1, 1860 | [1129] = 3, 1861 | ACTIONS(230), 1, 1862 | anon_sym_COMMA, 1863 | ACTIONS(232), 1, 1864 | anon_sym_RBRACK, 1865 | STATE(58), 1, 1866 | aux_sym_list_repeat1, 1867 | [1139] = 1, 1868 | ACTIONS(173), 2, 1869 | anon_sym_COMMA, 1870 | anon_sym_RBRACE, 1871 | [1144] = 2, 1872 | ACTIONS(234), 1, 1873 | anon_sym_LPAREN, 1874 | STATE(69), 1, 1875 | sym_argument_list, 1876 | [1151] = 1, 1877 | ACTIONS(236), 2, 1878 | anon_sym_COMMA, 1879 | anon_sym_RPAREN, 1880 | [1156] = 1, 1881 | ACTIONS(202), 2, 1882 | anon_sym_COMMA, 1883 | anon_sym_RBRACE, 1884 | [1161] = 1, 1885 | ACTIONS(169), 2, 1886 | anon_sym_COMMA, 1887 | anon_sym_RBRACE, 1888 | [1166] = 1, 1889 | ACTIONS(163), 2, 1890 | anon_sym_COMMA, 1891 | anon_sym_RBRACE, 1892 | [1171] = 1, 1893 | ACTIONS(175), 2, 1894 | anon_sym_COMMA, 1895 | anon_sym_RBRACE, 1896 | [1176] = 1, 1897 | ACTIONS(161), 2, 1898 | anon_sym_COMMA, 1899 | anon_sym_RBRACE, 1900 | [1181] = 1, 1901 | ACTIONS(149), 2, 1902 | anon_sym_COMMA, 1903 | anon_sym_RBRACE, 1904 | [1186] = 1, 1905 | ACTIONS(153), 2, 1906 | anon_sym_COMMA, 1907 | anon_sym_RBRACE, 1908 | [1191] = 1, 1909 | ACTIONS(157), 2, 1910 | anon_sym_COMMA, 1911 | anon_sym_RBRACE, 1912 | [1196] = 1, 1913 | ACTIONS(167), 2, 1914 | anon_sym_COMMA, 1915 | anon_sym_RBRACE, 1916 | [1201] = 1, 1917 | ACTIONS(171), 2, 1918 | anon_sym_COMMA, 1919 | anon_sym_RBRACE, 1920 | [1206] = 1, 1921 | ACTIONS(191), 2, 1922 | anon_sym_COMMA, 1923 | anon_sym_RBRACK, 1924 | [1211] = 1, 1925 | ACTIONS(177), 2, 1926 | anon_sym_COMMA, 1927 | anon_sym_RBRACE, 1928 | [1216] = 1, 1929 | ACTIONS(165), 2, 1930 | anon_sym_COMMA, 1931 | anon_sym_RBRACE, 1932 | [1221] = 1, 1933 | ACTIONS(155), 2, 1934 | anon_sym_COMMA, 1935 | anon_sym_RBRACE, 1936 | [1226] = 1, 1937 | ACTIONS(159), 2, 1938 | anon_sym_COMMA, 1939 | anon_sym_RBRACE, 1940 | [1231] = 1, 1941 | ACTIONS(151), 2, 1942 | anon_sym_COMMA, 1943 | anon_sym_RBRACE, 1944 | [1236] = 1, 1945 | ACTIONS(238), 2, 1946 | anon_sym_LPAREN, 1947 | anon_sym_EQ, 1948 | [1241] = 2, 1949 | ACTIONS(208), 1, 1950 | anon_sym_LPAREN, 1951 | STATE(36), 1, 1952 | sym_argument_list, 1953 | [1248] = 1, 1954 | ACTIONS(186), 2, 1955 | anon_sym_COMMA, 1956 | anon_sym_RPAREN, 1957 | [1253] = 1, 1958 | ACTIONS(240), 2, 1959 | anon_sym_COMMA, 1960 | anon_sym_RBRACE, 1961 | [1258] = 1, 1962 | ACTIONS(242), 1, 1963 | anon_sym_DQUOTE, 1964 | [1262] = 1, 1965 | ACTIONS(228), 1, 1966 | anon_sym_RBRACK, 1967 | [1266] = 1, 1968 | ACTIONS(242), 1, 1969 | anon_sym_SQUOTE, 1970 | [1270] = 1, 1971 | ACTIONS(224), 1, 1972 | anon_sym_RBRACE, 1973 | [1274] = 1, 1974 | ACTIONS(181), 1, 1975 | anon_sym_RBRACE, 1976 | [1278] = 1, 1977 | ACTIONS(244), 1, 1978 | anon_sym_SQUOTE, 1979 | [1282] = 1, 1980 | ACTIONS(246), 1, 1981 | anon_sym_RBRACE_RBRACE, 1982 | [1286] = 1, 1983 | ACTIONS(248), 1, 1984 | anon_sym_COLON, 1985 | [1290] = 1, 1986 | ACTIONS(244), 1, 1987 | anon_sym_DQUOTE, 1988 | [1294] = 1, 1989 | ACTIONS(214), 1, 1990 | anon_sym_RPAREN, 1991 | [1298] = 1, 1992 | ACTIONS(197), 1, 1993 | anon_sym_RPAREN, 1994 | [1302] = 1, 1995 | ACTIONS(250), 1, 1996 | aux_sym_jinja_expression_token1, 1997 | [1306] = 1, 1998 | ACTIONS(252), 1, 1999 | aux_sym_lit_string_token2, 2000 | [1310] = 1, 2001 | ACTIONS(254), 1, 2002 | aux_sym_lit_string_token1, 2003 | [1314] = 1, 2004 | ACTIONS(256), 1, 2005 | ts_builtin_sym_end, 2006 | [1318] = 1, 2007 | ACTIONS(232), 1, 2008 | anon_sym_RBRACK, 2009 | [1322] = 1, 2010 | ACTIONS(258), 1, 2011 | aux_sym__jinja_comment_token1, 2012 | [1326] = 1, 2013 | ACTIONS(260), 1, 2014 | aux_sym_lit_string_token1, 2015 | [1330] = 1, 2016 | ACTIONS(262), 1, 2017 | aux_sym_lit_string_token2, 2018 | }; 2019 | 2020 | static const uint32_t ts_small_parse_table_map[] = { 2021 | [SMALL_STATE(2)] = 0, 2022 | [SMALL_STATE(3)] = 44, 2023 | [SMALL_STATE(4)] = 88, 2024 | [SMALL_STATE(5)] = 131, 2025 | [SMALL_STATE(6)] = 172, 2026 | [SMALL_STATE(7)] = 213, 2027 | [SMALL_STATE(8)] = 254, 2028 | [SMALL_STATE(9)] = 297, 2029 | [SMALL_STATE(10)] = 338, 2030 | [SMALL_STATE(11)] = 378, 2031 | [SMALL_STATE(12)] = 418, 2032 | [SMALL_STATE(13)] = 458, 2033 | [SMALL_STATE(14)] = 498, 2034 | [SMALL_STATE(15)] = 536, 2035 | [SMALL_STATE(16)] = 573, 2036 | [SMALL_STATE(17)] = 610, 2037 | [SMALL_STATE(18)] = 647, 2038 | [SMALL_STATE(19)] = 684, 2039 | [SMALL_STATE(20)] = 706, 2040 | [SMALL_STATE(21)] = 728, 2041 | [SMALL_STATE(22)] = 747, 2042 | [SMALL_STATE(23)] = 766, 2043 | [SMALL_STATE(24)] = 776, 2044 | [SMALL_STATE(25)] = 792, 2045 | [SMALL_STATE(26)] = 808, 2046 | [SMALL_STATE(27)] = 824, 2047 | [SMALL_STATE(28)] = 834, 2048 | [SMALL_STATE(29)] = 850, 2049 | [SMALL_STATE(30)] = 860, 2050 | [SMALL_STATE(31)] = 868, 2051 | [SMALL_STATE(32)] = 875, 2052 | [SMALL_STATE(33)] = 882, 2053 | [SMALL_STATE(34)] = 889, 2054 | [SMALL_STATE(35)] = 896, 2055 | [SMALL_STATE(36)] = 903, 2056 | [SMALL_STATE(37)] = 910, 2057 | [SMALL_STATE(38)] = 917, 2058 | [SMALL_STATE(39)] = 924, 2059 | [SMALL_STATE(40)] = 931, 2060 | [SMALL_STATE(41)] = 944, 2061 | [SMALL_STATE(42)] = 951, 2062 | [SMALL_STATE(43)] = 958, 2063 | [SMALL_STATE(44)] = 965, 2064 | [SMALL_STATE(45)] = 972, 2065 | [SMALL_STATE(46)] = 979, 2066 | [SMALL_STATE(47)] = 989, 2067 | [SMALL_STATE(48)] = 999, 2068 | [SMALL_STATE(49)] = 1009, 2069 | [SMALL_STATE(50)] = 1019, 2070 | [SMALL_STATE(51)] = 1029, 2071 | [SMALL_STATE(52)] = 1039, 2072 | [SMALL_STATE(53)] = 1049, 2073 | [SMALL_STATE(54)] = 1059, 2074 | [SMALL_STATE(55)] = 1069, 2075 | [SMALL_STATE(56)] = 1079, 2076 | [SMALL_STATE(57)] = 1089, 2077 | [SMALL_STATE(58)] = 1099, 2078 | [SMALL_STATE(59)] = 1109, 2079 | [SMALL_STATE(60)] = 1119, 2080 | [SMALL_STATE(61)] = 1129, 2081 | [SMALL_STATE(62)] = 1139, 2082 | [SMALL_STATE(63)] = 1144, 2083 | [SMALL_STATE(64)] = 1151, 2084 | [SMALL_STATE(65)] = 1156, 2085 | [SMALL_STATE(66)] = 1161, 2086 | [SMALL_STATE(67)] = 1166, 2087 | [SMALL_STATE(68)] = 1171, 2088 | [SMALL_STATE(69)] = 1176, 2089 | [SMALL_STATE(70)] = 1181, 2090 | [SMALL_STATE(71)] = 1186, 2091 | [SMALL_STATE(72)] = 1191, 2092 | [SMALL_STATE(73)] = 1196, 2093 | [SMALL_STATE(74)] = 1201, 2094 | [SMALL_STATE(75)] = 1206, 2095 | [SMALL_STATE(76)] = 1211, 2096 | [SMALL_STATE(77)] = 1216, 2097 | [SMALL_STATE(78)] = 1221, 2098 | [SMALL_STATE(79)] = 1226, 2099 | [SMALL_STATE(80)] = 1231, 2100 | [SMALL_STATE(81)] = 1236, 2101 | [SMALL_STATE(82)] = 1241, 2102 | [SMALL_STATE(83)] = 1248, 2103 | [SMALL_STATE(84)] = 1253, 2104 | [SMALL_STATE(85)] = 1258, 2105 | [SMALL_STATE(86)] = 1262, 2106 | [SMALL_STATE(87)] = 1266, 2107 | [SMALL_STATE(88)] = 1270, 2108 | [SMALL_STATE(89)] = 1274, 2109 | [SMALL_STATE(90)] = 1278, 2110 | [SMALL_STATE(91)] = 1282, 2111 | [SMALL_STATE(92)] = 1286, 2112 | [SMALL_STATE(93)] = 1290, 2113 | [SMALL_STATE(94)] = 1294, 2114 | [SMALL_STATE(95)] = 1298, 2115 | [SMALL_STATE(96)] = 1302, 2116 | [SMALL_STATE(97)] = 1306, 2117 | [SMALL_STATE(98)] = 1310, 2118 | [SMALL_STATE(99)] = 1314, 2119 | [SMALL_STATE(100)] = 1318, 2120 | [SMALL_STATE(101)] = 1322, 2121 | [SMALL_STATE(102)] = 1326, 2122 | [SMALL_STATE(103)] = 1330, 2123 | }; 2124 | 2125 | static const TSParseActionEntry ts_parse_actions[] = { 2126 | [0] = {.entry = {.count = 0, .reusable = false}}, 2127 | [1] = {.entry = {.count = 1, .reusable = false}}, RECOVER(), 2128 | [3] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 0), 2129 | [5] = {.entry = {.count = 1, .reusable = false}}, SHIFT(16), 2130 | [7] = {.entry = {.count = 1, .reusable = false}}, SHIFT(96), 2131 | [9] = {.entry = {.count = 1, .reusable = false}}, SHIFT(101), 2132 | [11] = {.entry = {.count = 1, .reusable = true}}, SHIFT(20), 2133 | [13] = {.entry = {.count = 1, .reusable = true}}, SHIFT(94), 2134 | [15] = {.entry = {.count = 1, .reusable = true}}, SHIFT(39), 2135 | [17] = {.entry = {.count = 1, .reusable = true}}, SHIFT(98), 2136 | [19] = {.entry = {.count = 1, .reusable = true}}, SHIFT(97), 2137 | [21] = {.entry = {.count = 1, .reusable = false}}, SHIFT(41), 2138 | [23] = {.entry = {.count = 1, .reusable = true}}, SHIFT(4), 2139 | [25] = {.entry = {.count = 1, .reusable = true}}, SHIFT(21), 2140 | [27] = {.entry = {.count = 1, .reusable = false}}, SHIFT(81), 2141 | [29] = {.entry = {.count = 1, .reusable = false}}, SHIFT(55), 2142 | [31] = {.entry = {.count = 1, .reusable = true}}, SHIFT(55), 2143 | [33] = {.entry = {.count = 1, .reusable = true}}, SHIFT(95), 2144 | [35] = {.entry = {.count = 1, .reusable = true}}, SHIFT(73), 2145 | [37] = {.entry = {.count = 1, .reusable = false}}, SHIFT(50), 2146 | [39] = {.entry = {.count = 1, .reusable = true}}, SHIFT(50), 2147 | [41] = {.entry = {.count = 1, .reusable = true}}, SHIFT(100), 2148 | [43] = {.entry = {.count = 1, .reusable = true}}, SHIFT(37), 2149 | [45] = {.entry = {.count = 1, .reusable = false}}, SHIFT(61), 2150 | [47] = {.entry = {.count = 1, .reusable = true}}, SHIFT(61), 2151 | [49] = {.entry = {.count = 1, .reusable = true}}, SHIFT(80), 2152 | [51] = {.entry = {.count = 1, .reusable = false}}, SHIFT(83), 2153 | [53] = {.entry = {.count = 1, .reusable = true}}, SHIFT(83), 2154 | [55] = {.entry = {.count = 1, .reusable = true}}, SHIFT(79), 2155 | [57] = {.entry = {.count = 1, .reusable = true}}, SHIFT(31), 2156 | [59] = {.entry = {.count = 1, .reusable = true}}, SHIFT(86), 2157 | [61] = {.entry = {.count = 1, .reusable = true}}, SHIFT(67), 2158 | [63] = {.entry = {.count = 1, .reusable = false}}, SHIFT(60), 2159 | [65] = {.entry = {.count = 1, .reusable = true}}, SHIFT(60), 2160 | [67] = {.entry = {.count = 1, .reusable = true}}, SHIFT(35), 2161 | [69] = {.entry = {.count = 1, .reusable = true}}, SHIFT(38), 2162 | [71] = {.entry = {.count = 1, .reusable = false}}, SHIFT(75), 2163 | [73] = {.entry = {.count = 1, .reusable = true}}, SHIFT(75), 2164 | [75] = {.entry = {.count = 1, .reusable = true}}, SHIFT(74), 2165 | [77] = {.entry = {.count = 1, .reusable = true}}, SHIFT(42), 2166 | [79] = {.entry = {.count = 1, .reusable = true}}, SHIFT(77), 2167 | [81] = {.entry = {.count = 1, .reusable = false}}, SHIFT(91), 2168 | [83] = {.entry = {.count = 1, .reusable = true}}, SHIFT(91), 2169 | [85] = {.entry = {.count = 1, .reusable = true}}, SHIFT(102), 2170 | [87] = {.entry = {.count = 1, .reusable = true}}, SHIFT(103), 2171 | [89] = {.entry = {.count = 1, .reusable = false}}, SHIFT(66), 2172 | [91] = {.entry = {.count = 1, .reusable = true}}, SHIFT(8), 2173 | [93] = {.entry = {.count = 1, .reusable = true}}, SHIFT(22), 2174 | [95] = {.entry = {.count = 1, .reusable = false}}, SHIFT(84), 2175 | [97] = {.entry = {.count = 1, .reusable = true}}, SHIFT(84), 2176 | [99] = {.entry = {.count = 1, .reusable = false}}, SHIFT(64), 2177 | [101] = {.entry = {.count = 1, .reusable = true}}, SHIFT(64), 2178 | [103] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_source_file_repeat1, 2), 2179 | [105] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_source_file_repeat1, 2), SHIFT_REPEAT(16), 2180 | [108] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_source_file_repeat1, 2), SHIFT_REPEAT(96), 2181 | [111] = {.entry = {.count = 2, .reusable = false}}, REDUCE(aux_sym_source_file_repeat1, 2), SHIFT_REPEAT(101), 2182 | [114] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_source_file_repeat1, 2), SHIFT_REPEAT(19), 2183 | [117] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 1), 2184 | [119] = {.entry = {.count = 1, .reusable = true}}, SHIFT(19), 2185 | [121] = {.entry = {.count = 1, .reusable = true}}, SHIFT(89), 2186 | [123] = {.entry = {.count = 1, .reusable = true}}, SHIFT(44), 2187 | [125] = {.entry = {.count = 1, .reusable = true}}, SHIFT(88), 2188 | [127] = {.entry = {.count = 1, .reusable = true}}, SHIFT(68), 2189 | [129] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__jinja_comment, 2), 2190 | [131] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__jinja_comment, 2), 2191 | [133] = {.entry = {.count = 1, .reusable = true}}, SHIFT(62), 2192 | [135] = {.entry = {.count = 1, .reusable = true}}, SHIFT(33), 2193 | [137] = {.entry = {.count = 1, .reusable = true}}, SHIFT(78), 2194 | [139] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym__jinja_value, 3), 2195 | [141] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym__jinja_value, 3), 2196 | [143] = {.entry = {.count = 1, .reusable = true}}, SHIFT(43), 2197 | [145] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_jinja_expression, 2), 2198 | [147] = {.entry = {.count = 1, .reusable = false}}, REDUCE(sym_jinja_expression, 2), 2199 | [149] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_lit_string, 3), 2200 | [151] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_argument_list, 5), 2201 | [153] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 3), 2202 | [155] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dict, 5), 2203 | [157] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dict, 3), 2204 | [159] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_argument_list, 4), 2205 | [161] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_fn_call, 2, .production_id = 1), 2206 | [163] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 2), 2207 | [165] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 5), 2208 | [167] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_argument_list, 2), 2209 | [169] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_bool, 1), 2210 | [171] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_list, 4), 2211 | [173] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dict, 4), 2212 | [175] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_dict, 2), 2213 | [177] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_argument_list, 3), 2214 | [179] = {.entry = {.count = 1, .reusable = true}}, SHIFT(28), 2215 | [181] = {.entry = {.count = 1, .reusable = true}}, SHIFT(34), 2216 | [183] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_argument_list_repeat1, 2), SHIFT_REPEAT(14), 2217 | [186] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_argument_list_repeat1, 2), 2218 | [188] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2), SHIFT_REPEAT(15), 2219 | [191] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_list_repeat1, 2), 2220 | [193] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5), 2221 | [195] = {.entry = {.count = 1, .reusable = true}}, SHIFT(6), 2222 | [197] = {.entry = {.count = 1, .reusable = true}}, SHIFT(76), 2223 | [199] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_dict_repeat1, 2), SHIFT_REPEAT(40), 2224 | [202] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_dict_repeat1, 2), 2225 | [204] = {.entry = {.count = 1, .reusable = true}}, SHIFT(26), 2226 | [206] = {.entry = {.count = 1, .reusable = true}}, SHIFT(7), 2227 | [208] = {.entry = {.count = 1, .reusable = true}}, SHIFT(2), 2228 | [210] = {.entry = {.count = 1, .reusable = true}}, SHIFT(18), 2229 | [212] = {.entry = {.count = 1, .reusable = true}}, SHIFT(9), 2230 | [214] = {.entry = {.count = 1, .reusable = true}}, SHIFT(45), 2231 | [216] = {.entry = {.count = 1, .reusable = true}}, SHIFT(13), 2232 | [218] = {.entry = {.count = 1, .reusable = true}}, SHIFT(25), 2233 | [220] = {.entry = {.count = 1, .reusable = true}}, SHIFT(10), 2234 | [222] = {.entry = {.count = 1, .reusable = true}}, SHIFT(24), 2235 | [224] = {.entry = {.count = 1, .reusable = true}}, SHIFT(72), 2236 | [226] = {.entry = {.count = 1, .reusable = true}}, SHIFT(11), 2237 | [228] = {.entry = {.count = 1, .reusable = true}}, SHIFT(71), 2238 | [230] = {.entry = {.count = 1, .reusable = true}}, SHIFT(12), 2239 | [232] = {.entry = {.count = 1, .reusable = true}}, SHIFT(32), 2240 | [234] = {.entry = {.count = 1, .reusable = true}}, SHIFT(3), 2241 | [236] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_kwarg, 3, .production_id = 2), 2242 | [238] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_identifier, 1), 2243 | [240] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_pair, 3, .production_id = 2), 2244 | [242] = {.entry = {.count = 1, .reusable = true}}, SHIFT(70), 2245 | [244] = {.entry = {.count = 1, .reusable = true}}, SHIFT(30), 2246 | [246] = {.entry = {.count = 1, .reusable = true}}, SHIFT(27), 2247 | [248] = {.entry = {.count = 1, .reusable = true}}, SHIFT(17), 2248 | [250] = {.entry = {.count = 1, .reusable = true}}, SHIFT(29), 2249 | [252] = {.entry = {.count = 1, .reusable = true}}, SHIFT(93), 2250 | [254] = {.entry = {.count = 1, .reusable = true}}, SHIFT(90), 2251 | [256] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(), 2252 | [258] = {.entry = {.count = 1, .reusable = true}}, SHIFT(23), 2253 | [260] = {.entry = {.count = 1, .reusable = true}}, SHIFT(87), 2254 | [262] = {.entry = {.count = 1, .reusable = true}}, SHIFT(85), 2255 | }; 2256 | 2257 | #ifdef __cplusplus 2258 | extern "C" { 2259 | #endif 2260 | #ifdef _WIN32 2261 | #define extern __declspec(dllexport) 2262 | #endif 2263 | 2264 | extern const TSLanguage *tree_sitter_jinja2(void) { 2265 | static const TSLanguage language = { 2266 | .version = LANGUAGE_VERSION, 2267 | .symbol_count = SYMBOL_COUNT, 2268 | .alias_count = ALIAS_COUNT, 2269 | .token_count = TOKEN_COUNT, 2270 | .external_token_count = EXTERNAL_TOKEN_COUNT, 2271 | .state_count = STATE_COUNT, 2272 | .large_state_count = LARGE_STATE_COUNT, 2273 | .production_id_count = PRODUCTION_ID_COUNT, 2274 | .field_count = FIELD_COUNT, 2275 | .max_alias_sequence_length = MAX_ALIAS_SEQUENCE_LENGTH, 2276 | .parse_table = &ts_parse_table[0][0], 2277 | .small_parse_table = ts_small_parse_table, 2278 | .small_parse_table_map = ts_small_parse_table_map, 2279 | .parse_actions = ts_parse_actions, 2280 | .symbol_names = ts_symbol_names, 2281 | .field_names = ts_field_names, 2282 | .field_map_slices = ts_field_map_slices, 2283 | .field_map_entries = ts_field_map_entries, 2284 | .symbol_metadata = ts_symbol_metadata, 2285 | .public_symbol_map = ts_symbol_map, 2286 | .alias_map = ts_non_terminal_alias_map, 2287 | .alias_sequences = &ts_alias_sequences[0][0], 2288 | .lex_modes = ts_lex_modes, 2289 | .lex_fn = ts_lex, 2290 | .primary_state_ids = ts_primary_state_ids, 2291 | }; 2292 | return &language; 2293 | } 2294 | #ifdef __cplusplus 2295 | } 2296 | #endif 2297 | --------------------------------------------------------------------------------