├── .editorconfig ├── .gitattributes ├── .gitignore ├── Cargo.toml ├── LICENSE ├── Makefile ├── Package.swift ├── README.md ├── binding.gyp ├── bindings ├── c │ ├── tree-sitter-jsonnet.h │ └── tree-sitter-jsonnet.pc.in ├── go │ ├── binding.go │ ├── binding_test.go │ └── go.mod ├── node │ ├── binding.cc │ ├── index.d.ts │ └── index.js ├── python │ └── tree_sitter_jsonnet │ │ ├── __init__.py │ │ ├── __init__.pyi │ │ ├── binding.c │ │ └── py.typed ├── rust │ ├── build.rs │ └── lib.rs └── swift │ └── TreeSitterJsonnet │ └── jsonnet.h ├── examples ├── doc_1.jsonnet ├── example.jsonnet └── syntax.jsonnet ├── grammar.js ├── package.json ├── pyproject.toml ├── queries ├── folds.scm ├── highlights.scm └── locals.scm ├── setup.py ├── src ├── grammar.json ├── node-types.json ├── parser.c ├── scanner.c └── tree_sitter │ ├── alloc.h │ ├── array.h │ └── parser.h └── test └── corpus ├── assert.txt ├── exprs.txt ├── fieldname.txt ├── forloop.txt ├── inoperator.txt ├── number.txt └── objlocal.txt /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | 9 | [*.{json,toml,yml,gyp}] 10 | indent_style = space 11 | indent_size = 2 12 | 13 | [*.js] 14 | indent_style = space 15 | indent_size = 2 16 | 17 | [*.rs] 18 | indent_style = space 19 | indent_size = 4 20 | 21 | [*.{c,cc,h}] 22 | indent_style = space 23 | indent_size = 4 24 | 25 | [*.{py,pyi}] 26 | indent_style = space 27 | indent_size = 4 28 | 29 | [*.swift] 30 | indent_style = space 31 | indent_size = 4 32 | 33 | [*.go] 34 | indent_style = tab 35 | indent_size = 8 36 | 37 | [Makefile] 38 | indent_style = tab 39 | indent_size = 8 40 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | 3 | src/*.json linguist-generated 4 | src/parser.c linguist-generated 5 | src/tree_sitter/* linguist-generated 6 | 7 | bindings/** linguist-generated 8 | binding.gyp linguist-generated 9 | setup.py linguist-generated 10 | Makefile linguist-generated 11 | Package.swift linguist-generated 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | node_modules 3 | build 4 | package-lock.json 5 | /target/ 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tree-sitter-jsonnet" 3 | description = "jsonnet grammar for the tree-sitter parsing library" 4 | version = "0.0.1" 5 | keywords = ["incremental", "parsing", "jsonnet"] 6 | categories = ["parsing", "text-editors"] 7 | repository = "https://github.com/tree-sitter/tree-sitter-jsonnet" 8 | edition = "2018" 9 | license = "MIT" 10 | 11 | build = "bindings/rust/build.rs" 12 | include = [ 13 | "bindings/rust/*", 14 | "grammar.js", 15 | "queries/*", 16 | "src/*", 17 | ] 18 | 19 | [lib] 20 | path = "bindings/rust/lib.rs" 21 | 22 | [dependencies] 23 | tree-sitter = "0.22.6" 24 | 25 | [build-dependencies] 26 | cc = "1.0" 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Sourcegraph 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ts := tree-sitter 2 | 3 | generate: 4 | ${ts} generate 5 | 6 | test: generate 7 | ${ts} test 8 | 9 | fmt: 10 | npx prettier --tab-width 4 -w grammar.js 11 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "TreeSitterJsonnet", 6 | products: [ 7 | .library(name: "TreeSitterJsonnet", targets: ["TreeSitterJsonnet"]), 8 | ], 9 | dependencies: [], 10 | targets: [ 11 | .target(name: "TreeSitterJsonnet", 12 | path: ".", 13 | exclude: [ 14 | "Cargo.toml", 15 | "Makefile", 16 | "binding.gyp", 17 | "bindings/c", 18 | "bindings/go", 19 | "bindings/node", 20 | "bindings/python", 21 | "bindings/rust", 22 | "prebuilds", 23 | "grammar.js", 24 | "package.json", 25 | "package-lock.json", 26 | "pyproject.toml", 27 | "setup.py", 28 | "test", 29 | "examples", 30 | ".editorconfig", 31 | ".github", 32 | ".gitignore", 33 | ".gitattributes", 34 | ".gitmodules", 35 | ], 36 | sources: [ 37 | "src/parser.c", 38 | // NOTE: if your language has an external scanner, add it here. 39 | ], 40 | resources: [ 41 | .copy("queries") 42 | ], 43 | publicHeadersPath: "bindings/swift", 44 | cSettings: [.headerSearchPath("src")]) 45 | ], 46 | cLanguageStandard: .c11 47 | ) 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-jsonnet 2 | tree-sitter grammar for JSONNET 3 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_jsonnet_binding", 5 | "dependencies": [ 6 | " 2 | 3 | typedef struct TSLanguage TSLanguage; 4 | 5 | extern "C" TSLanguage *tree_sitter_jsonnet(); 6 | 7 | // "tree-sitter", "language" hashed with BLAKE2 8 | const napi_type_tag LANGUAGE_TYPE_TAG = { 9 | 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16 10 | }; 11 | 12 | Napi::Object Init(Napi::Env env, Napi::Object exports) { 13 | exports["name"] = Napi::String::New(env, "jsonnet"); 14 | auto language = Napi::External::New(env, tree_sitter_jsonnet()); 15 | language.TypeTag(&LANGUAGE_TYPE_TAG); 16 | exports["language"] = language; 17 | return exports; 18 | } 19 | 20 | NODE_API_MODULE(tree_sitter_jsonnet_binding, Init) 21 | -------------------------------------------------------------------------------- /bindings/node/index.d.ts: -------------------------------------------------------------------------------- 1 | type BaseNode = { 2 | type: string; 3 | named: boolean; 4 | }; 5 | 6 | type ChildNode = { 7 | multiple: boolean; 8 | required: boolean; 9 | types: BaseNode[]; 10 | }; 11 | 12 | type NodeInfo = 13 | | (BaseNode & { 14 | subtypes: BaseNode[]; 15 | }) 16 | | (BaseNode & { 17 | fields: { [name: string]: ChildNode }; 18 | children: ChildNode[]; 19 | }); 20 | 21 | type Language = { 22 | name: string; 23 | language: unknown; 24 | nodeTypeInfo: NodeInfo[]; 25 | }; 26 | 27 | declare const language: Language; 28 | export = language; 29 | -------------------------------------------------------------------------------- /bindings/node/index.js: -------------------------------------------------------------------------------- 1 | const root = require("path").join(__dirname, "..", ".."); 2 | 3 | module.exports = require("node-gyp-build")(root); 4 | 5 | try { 6 | module.exports.nodeTypeInfo = require("../../src/node-types.json"); 7 | } catch (_) {} 8 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_jsonnet/__init__.py: -------------------------------------------------------------------------------- 1 | "Jsonnet grammar for tree-sitter" 2 | 3 | from ._binding import language 4 | 5 | __all__ = ["language"] 6 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_jsonnet/__init__.pyi: -------------------------------------------------------------------------------- 1 | def language() -> int: ... 2 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_jsonnet/binding.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct TSLanguage TSLanguage; 4 | 5 | TSLanguage *tree_sitter_jsonnet(void); 6 | 7 | static PyObject* _binding_language(PyObject *self, PyObject *args) { 8 | return PyLong_FromVoidPtr(tree_sitter_jsonnet()); 9 | } 10 | 11 | static PyMethodDef methods[] = { 12 | {"language", _binding_language, METH_NOARGS, 13 | "Get the tree-sitter language for this grammar."}, 14 | {NULL, NULL, 0, NULL} 15 | }; 16 | 17 | static struct PyModuleDef module = { 18 | .m_base = PyModuleDef_HEAD_INIT, 19 | .m_name = "_binding", 20 | .m_doc = NULL, 21 | .m_size = -1, 22 | .m_methods = methods 23 | }; 24 | 25 | PyMODINIT_FUNC PyInit__binding(void) { 26 | return PyModule_Create(&module); 27 | } 28 | -------------------------------------------------------------------------------- /bindings/python/tree_sitter_jsonnet/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sourcegraph/tree-sitter-jsonnet/ddd075f1939aed8147b7aa67f042eda3fce22790/bindings/python/tree_sitter_jsonnet/py.typed -------------------------------------------------------------------------------- /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 | #[cfg(target_env = "msvc")] 11 | c_config.flag("-utf-8"); 12 | 13 | let parser_path = src_dir.join("parser.c"); 14 | c_config.file(&parser_path); 15 | 16 | let scanner_path = src_dir.join("scanner.c"); 17 | c_config.file(&scanner_path); 18 | println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); 19 | 20 | c_config.compile("parser"); 21 | println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); 22 | } 23 | -------------------------------------------------------------------------------- /bindings/rust/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides jsonnet language support for the [tree-sitter][] parsing library. 2 | //! 3 | //! Typically, you will use the [language][language func] function to add this language to a 4 | //! tree-sitter [Parser][], and then use the parser to parse some code: 5 | //! 6 | //! ``` 7 | //! let code = ""; 8 | //! let mut parser = tree_sitter::Parser::new(); 9 | //! parser.set_language(&tree_sitter_jsonnet::language()).expect("Error loading jsonnet 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_jsonnet() -> 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_jsonnet() } 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: &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 jsonnet language"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /bindings/swift/TreeSitterJsonnet/jsonnet.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_JSONNET_H_ 2 | #define TREE_SITTER_JSONNET_H_ 3 | 4 | typedef struct TSLanguage TSLanguage; 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | const TSLanguage *tree_sitter_jsonnet(void); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif // TREE_SITTER_JSONNET_H_ 17 | -------------------------------------------------------------------------------- /examples/doc_1.jsonnet: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2015 Google Inc. All rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Define a local function. 18 | // Default arguments are like Python: 19 | local my_function(x, y=10) = x + y; 20 | 21 | // Define a local multiline function. 22 | local multiline_function(x) = 23 | // One can nest locals. 24 | local temp = x * 2; 25 | // Every local ends with a semi-colon. 26 | [temp, temp + 1]; 27 | 28 | local object = { 29 | // A method 30 | my_method(x): x * x, 31 | }; 32 | 33 | { 34 | // Functions are first class citizens. 35 | call_inline_function: 36 | (function(x) x * x)(5), 37 | 38 | call_multiline_function: multiline_function(4), 39 | 40 | // Using the variable fetches the function, 41 | // the parens call the function. 42 | call: my_function(true), 43 | 44 | // Like python, parameters can be named at 45 | // call time. 46 | named_params: my_function(x=2), 47 | // This allows changing their order 48 | named_params2: my_function(y=3, x=2), 49 | 50 | // object.my_method returns the function, 51 | // which is then called like any other. 52 | call_method1: object.my_method(3), 53 | 54 | standard_lib: 55 | std.join(' ', std.split('foo/bar', '/')), 56 | 57 | len: [ 58 | std.length('hello'), 59 | std.length([1, 2, 3]), 60 | ], 61 | } 62 | -------------------------------------------------------------------------------- /examples/example.jsonnet: -------------------------------------------------------------------------------- 1 | hello 2 | -------------------------------------------------------------------------------- /examples/syntax.jsonnet: -------------------------------------------------------------------------------- 1 | // Example file with all(?) possible components from the syntax 2 | 3 | local object = { 4 | 'null': null, 5 | 'true': true, 6 | 'false': false, 7 | string: 'string', 8 | number: 5, 9 | array: [ 10 | null, 11 | true, 12 | false, 13 | 'string', 14 | 1.5, 15 | ], 16 | 17 | forloop: [ 18 | i 19 | for i in std.range(0, 9) 20 | ], 21 | 22 | objforloop: { 23 | ['index' + i]: i 24 | for i in std.range(0, 9) 25 | if (i % 2) == 0 // binaryop: multiplicative and equality 26 | }, 27 | 28 | fieldaccess: self.string, 29 | indexing: self.forloop[self.number], 30 | indexing_obj: self.objforloop['index' + '0'], 31 | indexing_slice: self.forloop[2:8:2], 32 | 33 | binaryop_equality: self.string == 'string', 34 | conditional_in_parenthesis: 35 | (if self.binaryop_equality && true // binaryop: AND 36 | then 'condition true' 37 | else 'condition false'), 38 | 39 | local objlocal = false || true, // binaryop: OR 40 | unaryop: !objlocal, 41 | 42 | anonymous_function:: function(arg, default='v') arg + default, 43 | regular_func(arg):: $.string + ' ' + arg, 44 | 45 | assert true : 'assert instide object', 46 | 47 | 'import':: import 'file.json', 48 | 'importstr':: import 'file.txt', 49 | err:: error 'message', 50 | }; 51 | 52 | assert true : 'assert outside object'; 53 | 54 | object + { 55 | fieldaccess_super: super.number, 56 | indexing_super: super.array[2 * 2], // binaryop: multiplicative 57 | 58 | functioncall_1: super.anonymous_function('echo 1'), 59 | 60 | functioncall_2: self.regular_func(arg='echo 2') tailstrict, 61 | 62 | local localfunc(arg) = { 63 | local notarg = 'value', 64 | a: notarg, // not a parameter reference 65 | b: arg, // parameter reference 66 | [arg]: arg, // parameter reference in fieldname 67 | }, 68 | functioncall_3: localfunc('echo 3'), // function reference 69 | 70 | in_super: 'keynotfound' in super, 71 | 72 | array+: ['another item'], 73 | objforloop+: { another: 'item' }, 74 | 75 | ['fieldname_expr' + (5 - object.objforloop.index2)]: 'value', 76 | [if object.string == 'string' then 'conditional_key']: 'value', 77 | } 78 | -------------------------------------------------------------------------------- /grammar.js: -------------------------------------------------------------------------------- 1 | const PREC = { 2 | // The priorities below are taken from the spec here: 3 | // https://jsonnet.org/ref/spec.html#associativity_precedence 4 | // The order is reversed though: In the spec, '1' means high priority 5 | // but with tree-sitter it means low priority. 6 | application_indexing: 13, 7 | unary: 12, 8 | multiplicative: 11, 9 | additive: 10, 10 | bitshift: 9, 11 | comparison: 8, 12 | equality: 7, 13 | bitand: 6, 14 | bitxor: 5, 15 | bitor: 4, 16 | and: 3, 17 | or: 2, 18 | // This is not in the spec, which is why we go from 2 to 13 above 19 | // while in the spec it is going from 1 to 12. 20 | member: 1, 21 | }; 22 | 23 | module.exports = grammar({ 24 | name: "jsonnet", 25 | extras: ($) => [/\s/, $.comment], 26 | externals: ($) => [$._string_start, $._string_content, $._string_end], 27 | word: ($) => $._ident, 28 | inline: ($) => [$.h, $.objinside], 29 | conflicts: () => [], 30 | 31 | rules: { 32 | document: ($) => $._expr, 33 | 34 | comment: () => 35 | token( 36 | choice( 37 | seq("//", /.*/), 38 | seq("#", /.*/), 39 | seq("/*", /[^*]*\*+([^/*][^*]*\*+)*/, "/"), 40 | ), 41 | ), 42 | 43 | _expr: ($) => 44 | choice( 45 | $.null, 46 | $.true, 47 | $.false, 48 | $.self, 49 | $.dollar, 50 | $.string, 51 | $.number, 52 | $.object, 53 | $.array, 54 | $.forloop, 55 | $.fieldaccess, 56 | $.indexing, 57 | $.fieldaccess_super, 58 | $.indexing_super, 59 | $.functioncall, 60 | $.id, 61 | $.local_bind, 62 | $.conditional, 63 | $.binary, 64 | $.unary, 65 | $.implicit_plus, 66 | $.anonymous_function, 67 | $._assert_expr, 68 | $.import, 69 | $.importstr, 70 | $.error, 71 | $.in_super, 72 | $.parenthesis, 73 | ), 74 | 75 | // Literals 76 | null: () => "null", 77 | true: () => "true", 78 | false: () => "false", 79 | 80 | // Keywords 81 | self: () => "self", 82 | dollar: () => "$", 83 | super: () => "super", 84 | local: () => "local", 85 | tailstrict: () => "tailstrict", 86 | 87 | // Types 88 | number: ($) => $._number, 89 | string: ($) => $._string, 90 | object: ($) => seq("{", optional($.objinside), "}"), 91 | array: ($) => seq("[", commaSep($._expr, true), "]"), 92 | 93 | forloop: ($) => 94 | seq( 95 | "[", 96 | $._expr, 97 | optional(","), 98 | $.forspec, 99 | optional($.compspec), 100 | "]", 101 | ), 102 | 103 | fieldaccess: ($) => 104 | prec( 105 | PREC.application_indexing, 106 | seq($._expr, ".", field("last", $.id)), 107 | ), 108 | 109 | indexing: ($) => 110 | prec( 111 | PREC.application_indexing, 112 | seq( 113 | $._expr, 114 | "[", 115 | optional($._expr), 116 | optional( 117 | seq( 118 | ":", 119 | optional($._expr), 120 | optional(seq(":", optional($._expr))), 121 | ), 122 | ), 123 | "]", 124 | ), 125 | ), 126 | 127 | fieldaccess_super: ($) => seq($.super, ".", $.id), 128 | indexing_super: ($) => seq($.super, "[", $._expr, "]"), 129 | 130 | functioncall: ($) => 131 | prec( 132 | PREC.application_indexing, 133 | seq( 134 | $._expr, 135 | "(", 136 | optional($.args), 137 | ")", 138 | optional($.tailstrict), 139 | ), 140 | ), 141 | 142 | id: ($) => $._ident, 143 | // This use of an intermediate rule for identifiers is to 144 | // overcome some limitations in ocaml-tree-sitter-semgrep. 145 | // Indeed, ocaml-tree-sitter-semgrep can't override terminals (here was id) 146 | // that are also mentioned in the 'word:' directive. 147 | _ident: () => /[_a-zA-Z][_a-zA-Z0-9]*/, 148 | 149 | local_bind: ($) => 150 | prec.right(seq($.local, commaSep1($.bind, false), ";", $._expr)), 151 | 152 | conditional: ($) => 153 | prec.right( 154 | seq( 155 | "if", 156 | field("condition", $._expr), 157 | "then", 158 | field("consequence", $._expr), 159 | optional(seq("else", field("alternative", $._expr))), 160 | ), 161 | ), 162 | 163 | multiplicative: () => choice("*", "/", "%"), 164 | additive: () => choice("+", "-"), 165 | bitshift: () => choice("<<", ">>"), 166 | comparison: () => choice("<", "<=", ">", ">=", "in"), 167 | equality: () => choice("==", "!="), 168 | bitand: () => "&", 169 | bitxor: () => "^", 170 | bitor: () => "|", 171 | and: () => "&&", 172 | or: () => "||", 173 | 174 | binary: ($) => { 175 | const table = [ 176 | [PREC.multiplicative, $.multiplicative], 177 | [PREC.additive, $.additive], 178 | [PREC.bitshift, $.bitshift], 179 | [PREC.comparison, $.comparison], 180 | [PREC.equality, $.equality], 181 | [PREC.bitand, $.bitand], 182 | [PREC.bitxor, $.bitxor], 183 | [PREC.bitor, $.bitor], 184 | [PREC.and, $.and], 185 | [PREC.or, $.or], 186 | ]; 187 | return choice( 188 | ...table.map(([precedence, operator]) => 189 | prec.left( 190 | precedence, 191 | seq( 192 | field("left", $._expr), 193 | field("operator", operator), 194 | field("right", $._expr), 195 | ), 196 | ), 197 | ), 198 | ); 199 | }, 200 | 201 | unary: ($) => 202 | prec( 203 | PREC.unary, 204 | seq(field("operator", $.unaryop), field("argument", $._expr)), 205 | ), 206 | 207 | unaryop: () => choice("-", "+", "!", "~"), 208 | 209 | implicit_plus: ($) => seq($._expr, $.object), 210 | 211 | anonymous_function: ($) => 212 | prec.right( 213 | seq( 214 | "function", 215 | "(", 216 | optional(field("params", $.params)), 217 | ")", 218 | field("body", $._expr), 219 | ), 220 | ), 221 | 222 | _assert_expr: ($) => prec.right(seq($.assert, ";", $._expr)), 223 | 224 | // import string 225 | import: ($) => seq("import", $.string), 226 | 227 | // importstr string 228 | importstr: ($) => seq("importstr", $.string), 229 | 230 | // error expr 231 | error: ($) => prec.right(seq("error", $._expr)), 232 | 233 | in_super: ($) => prec(PREC.comparison, seq($._expr, "in", $.super)), 234 | 235 | parenthesis: ($) => seq("(", $._expr, ")"), 236 | 237 | objinside: ($) => 238 | choice( 239 | // seq($.member, repeat(seq(",", $.member)), optional(",")), 240 | commaSep1($.member, true), 241 | $.objforloop, 242 | ), 243 | 244 | objforloop: ($) => 245 | seq( 246 | repeat(seq($.objlocal, ",")), 247 | $.field, 248 | repeat(seq(",", $.objlocal)), 249 | optional(","), 250 | $.forspec, 251 | optional($.compspec), 252 | ), 253 | 254 | member: ($) => 255 | prec.right(PREC.member, choice($.objlocal, $.assert, $.field)), 256 | 257 | field: ($) => 258 | choice( 259 | seq($.fieldname, optional("+"), $.h, $._expr), 260 | seq( 261 | field("function", $.fieldname), 262 | "(", 263 | optional($.params), 264 | ")", 265 | $.h, 266 | $._expr, 267 | ), 268 | ), 269 | 270 | h: () => choice(":", "::", ":::"), 271 | 272 | objlocal: ($) => seq($.local, $.bind), 273 | 274 | compspec: ($) => repeat1(choice($.forspec, $.ifspec)), 275 | forspec: ($) => seq("for", $.id, "in", $._expr), 276 | ifspec: ($) => seq("if", $._expr), 277 | 278 | fieldname: ($) => 279 | prec.right(choice($.id, $.string, seq("[", $._expr, "]"))), 280 | 281 | // assert in objects 282 | assert: ($) => seq("assert", $._expr, optional(seq(":", $._expr))), 283 | 284 | bind: ($) => 285 | choice( 286 | seq($.id, "=", $._expr), 287 | prec.right( 288 | seq( 289 | field("function", $.id), 290 | "(", 291 | optional(field("params", $.params)), 292 | ")", 293 | "=", 294 | field("body", $._expr), 295 | ), 296 | ), 297 | ), 298 | 299 | args: ($) => 300 | choice( 301 | seq( 302 | $._expr, 303 | repeat(seq(",", $._expr)), 304 | repeat(seq(",", $.named_argument)), 305 | optional(","), 306 | ), 307 | seq( 308 | $.named_argument, 309 | repeat(seq(",", $.named_argument)), 310 | optional(","), 311 | ), 312 | ), 313 | named_argument: ($) => seq($.id, "=", $._expr), 314 | 315 | params: ($) => commaSep1($.param, true), 316 | param: ($) => 317 | seq( 318 | field("identifier", $.id), 319 | optional(seq("=", field("value", $._expr))), 320 | ), 321 | 322 | // COPIED FROM: tree-sitter-json 323 | _number: () => { 324 | const hex_literal = seq(choice("0x", "0X"), /[\da-fA-F]+/); 325 | 326 | const decimal_digits = /\d+/; 327 | const signed_integer = seq( 328 | optional(choice("-", "+")), 329 | decimal_digits, 330 | ); 331 | const exponent_part = seq(choice("e", "E"), signed_integer); 332 | 333 | const binary_literal = seq(choice("0b", "0B"), /[0-1]+/); 334 | 335 | const octal_literal = seq(choice("0o", "0O"), /[0-7]+/); 336 | 337 | const decimal_integer_literal = seq( 338 | optional(choice("-", "+")), 339 | choice("0", seq(/[1-9]/, optional(decimal_digits))), 340 | ); 341 | 342 | const decimal_literal = choice( 343 | seq( 344 | decimal_integer_literal, 345 | ".", 346 | optional(decimal_digits), 347 | optional(exponent_part), 348 | ), 349 | seq(".", decimal_digits, optional(exponent_part)), 350 | seq(decimal_integer_literal, optional(exponent_part)), 351 | ); 352 | 353 | return token( 354 | choice( 355 | hex_literal, 356 | decimal_literal, 357 | binary_literal, 358 | octal_literal, 359 | ), 360 | ); 361 | }, 362 | 363 | _string: ($) => 364 | choice( 365 | // Single Quotes 366 | seq( 367 | optional("@"), 368 | alias($._single, $.string_start), 369 | alias($._single, $.string_end), 370 | ), 371 | seq( 372 | optional("@"), 373 | alias($._single, $.string_start), 374 | alias($._str_single, $.string_content), 375 | alias($._single, $.string_end), 376 | ), 377 | // Double Quotes 378 | seq( 379 | optional("@"), 380 | alias($._double, $.string_start), 381 | alias($._double, $.string_end), 382 | ), 383 | seq( 384 | optional("@"), 385 | alias($._double, $.string_start), 386 | alias($._str_double, $.string_content), 387 | alias($._double, $.string_end), 388 | ), 389 | // ||| Quotes 390 | seq( 391 | optional("@"), 392 | alias($._string_start, $.string_start), 393 | alias($._string_content, $.string_content), 394 | alias($._string_end, $.string_end), 395 | ), 396 | ), 397 | 398 | _single: () => "'", 399 | _double: () => '"', 400 | 401 | _str_double: ($) => 402 | repeat1( 403 | choice( 404 | token.immediate(prec(1, /[^\\"\n]+/)), 405 | $.escape_sequence, 406 | ), 407 | ), 408 | 409 | _str_single: ($) => 410 | repeat1( 411 | choice( 412 | token.immediate(prec(1, /[^\\'\n]+/)), 413 | $.escape_sequence, 414 | ), 415 | ), 416 | 417 | escape_sequence: () => 418 | token.immediate(seq("\\", /(\"|\\|\/|b|f|n|r|t|u)/)), 419 | }, 420 | }); 421 | 422 | function commaSep1(rule, trailing) { 423 | if (trailing) { 424 | return seq(rule, repeat(seq(",", rule)), optional(",")); 425 | } else { 426 | return seq(rule, repeat(seq(",", rule))); 427 | } 428 | } 429 | 430 | function commaSep(rule, trailing) { 431 | return optional(commaSep1(rule, trailing)); 432 | } 433 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-jsonnet", 3 | "version": "0.0.1", 4 | "description": "jsonnet grammar for tree-sitter", 5 | "main": "bindings/node", 6 | "types": "bindings/node", 7 | "keywords": [ 8 | "parsing", 9 | "incremental" 10 | ], 11 | "files": [ 12 | "grammar.js", 13 | "binding.gyp", 14 | "prebuilds/**", 15 | "bindings/node/*", 16 | "queries/*", 17 | "src/**" 18 | ], 19 | "dependencies": { 20 | "node-addon-api": "^7.1.0", 21 | "node-gyp-build": "^4.8.0" 22 | }, 23 | "peerDependencies": { 24 | "tree-sitter": "^0.21.0" 25 | }, 26 | "peerDependenciesMeta": { 27 | "tree_sitter": { 28 | "optional": true 29 | } 30 | }, 31 | "devDependencies": { 32 | "tree-sitter-cli": "^0.22.6", 33 | "prebuildify": "^6.0.0" 34 | }, 35 | "scripts": { 36 | "build_init": "tree-sitter generate && node-gyp configure && node-gyp build", 37 | "build": "tree-sitter generate && node-gyp build", 38 | "test": "tree-sitter test", 39 | "build-test": "tree-sitter generate && node-gyp build && tree-sitter test", 40 | "install": "node-gyp-build", 41 | "prebuildify": "prebuildify --napi --strip" 42 | }, 43 | "tree-sitter": [ 44 | { 45 | "scope": "source.jsonnet", 46 | "file-types": [ 47 | "jsonnet" 48 | ], 49 | "injection-regex": "jsonnet" 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "tree-sitter-jsonnet" 7 | description = "Jsonnet grammar for tree-sitter" 8 | version = "0.0.1" 9 | keywords = ["incremental", "parsing", "tree-sitter", "jsonnet"] 10 | classifiers = [ 11 | "Intended Audience :: Developers", 12 | "License :: OSI Approved :: MIT License", 13 | "Topic :: Software Development :: Compilers", 14 | "Topic :: Text Processing :: Linguistic", 15 | "Typing :: Typed" 16 | ] 17 | requires-python = ">=3.8" 18 | license.text = "MIT" 19 | readme = "README.md" 20 | 21 | [project.urls] 22 | Homepage = "https://github.com/tree-sitter/tree-sitter-jsonnet" 23 | 24 | [project.optional-dependencies] 25 | core = ["tree-sitter~=0.21"] 26 | 27 | [tool.cibuildwheel] 28 | build = "cp38-*" 29 | build-frontend = "build" 30 | -------------------------------------------------------------------------------- /queries/folds.scm: -------------------------------------------------------------------------------- 1 | [ 2 | (field) 3 | (object) 4 | (array) 5 | (parenthesis) 6 | (bind) 7 | ; (params) 8 | ; (args) 9 | ; (conditional) 10 | ] @fold 11 | -------------------------------------------------------------------------------- /queries/highlights.scm: -------------------------------------------------------------------------------- 1 | (id) @variable 2 | (comment) @comment 3 | 4 | ; Literals 5 | (null) @constant.builtin 6 | (string) @string 7 | (number) @number 8 | [ 9 | (true) 10 | (false) 11 | ] @boolean 12 | 13 | ; Keywords 14 | "for" @repeat 15 | "in" @keyword.operator 16 | "function" @keyword.function 17 | [ 18 | "if" 19 | "then" 20 | "else" 21 | ] @conditional 22 | [ 23 | (local) 24 | (tailstrict) 25 | "function" 26 | "assert" 27 | "error" 28 | ] @keyword 29 | 30 | [ 31 | (dollar) 32 | (self) 33 | (super) 34 | ] @variable.builtin 35 | ((id) @variable.builtin 36 | (#eq? @variable.builtin "std")) 37 | 38 | ; Operators 39 | [ 40 | (multiplicative) 41 | (additive) 42 | (bitshift) 43 | (comparison) 44 | (equality) 45 | (bitand) 46 | (bitxor) 47 | (bitor) 48 | (and) 49 | (or) 50 | (unaryop) 51 | ] @operator 52 | 53 | ; Punctuation 54 | [ 55 | "[" 56 | "]" 57 | "{" 58 | "}" 59 | "(" 60 | ")" 61 | ] @punctuation.bracket 62 | 63 | [ 64 | "." 65 | "," 66 | ";" 67 | ":" 68 | ] @punctuation.delimiter 69 | 70 | [ 71 | "::" 72 | ":::" 73 | ] @punctuation.special 74 | 75 | (field 76 | (fieldname) "+" @punctuation.special) 77 | 78 | ; Imports 79 | [ 80 | (import) 81 | (importstr) 82 | ] @include 83 | 84 | ; References 85 | 86 | ; Make reference same color as parameter 87 | ; (may incur performance issues on big files) 88 | ; Depends on locals.scm 89 | ((id) @parameter.reference 90 | (#is? @parameter.reference parameter)) 91 | 92 | ((id) @function.reference 93 | (#is? @function.reference function)) 94 | 95 | ((id) @var.reference 96 | (#is? @var.reference var)) 97 | ((id) @define 98 | (#is? @var.reference var)) 99 | 100 | ; References do not apply to static field IDs 101 | ; Workaround for `(#is-not? local)` not supported 102 | (fieldname (id) @field) 103 | (fieldname (string 104 | (string_start) @text.strong 105 | (string_content) @field 106 | (string_end) @text.strong 107 | )) 108 | 109 | ; But it does apply if ID in an expression 110 | (fieldname 111 | ("[" 112 | (id) @parameter.reference 113 | "]" 114 | (#is? @parameter.reference parameter))) 115 | (fieldname 116 | ("[" 117 | (id) @define 118 | "]" 119 | (#is? @var.reference var))) 120 | 121 | ; Functions 122 | (field 123 | function: (fieldname (id) @function)) 124 | (field 125 | function: (fieldname 126 | (string 127 | (string_start) @text.strong 128 | (string_content) @function 129 | (string_end) @text.strong 130 | ))) 131 | (param 132 | identifier: (id) @parameter) 133 | 134 | (bind (id) @define) 135 | (bind function: (id) @function) 136 | 137 | ; Function call 138 | (functioncall 139 | (fieldaccess 140 | last: (id) @function.call 141 | )? 142 | (fieldaccess_super 143 | (id) @function.call 144 | )? 145 | (id)? @function.call 146 | "(" 147 | (args 148 | (named_argument 149 | (id) @parameter 150 | ) 151 | )? 152 | ")" 153 | ) 154 | 155 | ; Emphasize implicit plus usage 156 | (implicit_plus 157 | (_ "}"? @text.danger) 158 | (object 159 | "{" @text.danger 160 | ) 161 | ) 162 | 163 | ; ERROR 164 | (ERROR) @error 165 | -------------------------------------------------------------------------------- /queries/locals.scm: -------------------------------------------------------------------------------- 1 | (parenthesis) @scope 2 | (anonymous_function) @scope 3 | (object) @scope 4 | (field) @scope 5 | (local_bind) @scope 6 | 7 | (field 8 | function: (fieldname (id) @definition.function) 9 | (#set! "definition.function.scope" "parent") 10 | ) 11 | 12 | (bind (id) @definition.var) 13 | (bind function: (id) @definition.function) 14 | 15 | (param (id) @definition.parameter) 16 | 17 | (id) @reference 18 | ;(fieldname (id) (#is-not? local)) 19 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from os.path import isdir, join 2 | from platform import system 3 | 4 | from setuptools import Extension, find_packages, setup 5 | from setuptools.command.build import build 6 | from wheel.bdist_wheel import bdist_wheel 7 | 8 | 9 | class Build(build): 10 | def run(self): 11 | if isdir("queries"): 12 | dest = join(self.build_lib, "tree_sitter_jsonnet", "queries") 13 | self.copy_tree("queries", dest) 14 | super().run() 15 | 16 | 17 | class BdistWheel(bdist_wheel): 18 | def get_tag(self): 19 | python, abi, platform = super().get_tag() 20 | if python.startswith("cp"): 21 | python, abi = "cp38", "abi3" 22 | return python, abi, platform 23 | 24 | 25 | setup( 26 | packages=find_packages("bindings/python"), 27 | package_dir={"": "bindings/python"}, 28 | package_data={ 29 | "tree_sitter_jsonnet": ["*.pyi", "py.typed"], 30 | "tree_sitter_jsonnet.queries": ["*.scm"], 31 | }, 32 | ext_package="tree_sitter_jsonnet", 33 | ext_modules=[ 34 | Extension( 35 | name="_binding", 36 | sources=[ 37 | "bindings/python/tree_sitter_jsonnet/binding.c", 38 | "src/parser.c", 39 | # NOTE: if your language uses an external scanner, add it here. 40 | ], 41 | extra_compile_args=[ 42 | "-std=c11", 43 | ] if system() != "Windows" else [ 44 | "/std:c11", 45 | "/utf-8", 46 | ], 47 | define_macros=[ 48 | ("Py_LIMITED_API", "0x03080000"), 49 | ("PY_SSIZE_T_CLEAN", None) 50 | ], 51 | include_dirs=["src"], 52 | py_limited_api=True, 53 | ) 54 | ], 55 | cmdclass={ 56 | "build": Build, 57 | "bdist_wheel": BdistWheel 58 | }, 59 | zip_safe=False 60 | ) 61 | -------------------------------------------------------------------------------- /src/grammar.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsonnet", 3 | "word": "_ident", 4 | "rules": { 5 | "document": { 6 | "type": "SYMBOL", 7 | "name": "_expr" 8 | }, 9 | "comment": { 10 | "type": "TOKEN", 11 | "content": { 12 | "type": "CHOICE", 13 | "members": [ 14 | { 15 | "type": "SEQ", 16 | "members": [ 17 | { 18 | "type": "STRING", 19 | "value": "//" 20 | }, 21 | { 22 | "type": "PATTERN", 23 | "value": ".*" 24 | } 25 | ] 26 | }, 27 | { 28 | "type": "SEQ", 29 | "members": [ 30 | { 31 | "type": "STRING", 32 | "value": "#" 33 | }, 34 | { 35 | "type": "PATTERN", 36 | "value": ".*" 37 | } 38 | ] 39 | }, 40 | { 41 | "type": "SEQ", 42 | "members": [ 43 | { 44 | "type": "STRING", 45 | "value": "/*" 46 | }, 47 | { 48 | "type": "PATTERN", 49 | "value": "[^*]*\\*+([^/*][^*]*\\*+)*" 50 | }, 51 | { 52 | "type": "STRING", 53 | "value": "/" 54 | } 55 | ] 56 | } 57 | ] 58 | } 59 | }, 60 | "_expr": { 61 | "type": "CHOICE", 62 | "members": [ 63 | { 64 | "type": "SYMBOL", 65 | "name": "null" 66 | }, 67 | { 68 | "type": "SYMBOL", 69 | "name": "true" 70 | }, 71 | { 72 | "type": "SYMBOL", 73 | "name": "false" 74 | }, 75 | { 76 | "type": "SYMBOL", 77 | "name": "self" 78 | }, 79 | { 80 | "type": "SYMBOL", 81 | "name": "dollar" 82 | }, 83 | { 84 | "type": "SYMBOL", 85 | "name": "string" 86 | }, 87 | { 88 | "type": "SYMBOL", 89 | "name": "number" 90 | }, 91 | { 92 | "type": "SYMBOL", 93 | "name": "object" 94 | }, 95 | { 96 | "type": "SYMBOL", 97 | "name": "array" 98 | }, 99 | { 100 | "type": "SYMBOL", 101 | "name": "forloop" 102 | }, 103 | { 104 | "type": "SYMBOL", 105 | "name": "fieldaccess" 106 | }, 107 | { 108 | "type": "SYMBOL", 109 | "name": "indexing" 110 | }, 111 | { 112 | "type": "SYMBOL", 113 | "name": "fieldaccess_super" 114 | }, 115 | { 116 | "type": "SYMBOL", 117 | "name": "indexing_super" 118 | }, 119 | { 120 | "type": "SYMBOL", 121 | "name": "functioncall" 122 | }, 123 | { 124 | "type": "SYMBOL", 125 | "name": "id" 126 | }, 127 | { 128 | "type": "SYMBOL", 129 | "name": "local_bind" 130 | }, 131 | { 132 | "type": "SYMBOL", 133 | "name": "conditional" 134 | }, 135 | { 136 | "type": "SYMBOL", 137 | "name": "binary" 138 | }, 139 | { 140 | "type": "SYMBOL", 141 | "name": "unary" 142 | }, 143 | { 144 | "type": "SYMBOL", 145 | "name": "implicit_plus" 146 | }, 147 | { 148 | "type": "SYMBOL", 149 | "name": "anonymous_function" 150 | }, 151 | { 152 | "type": "SYMBOL", 153 | "name": "_assert_expr" 154 | }, 155 | { 156 | "type": "SYMBOL", 157 | "name": "import" 158 | }, 159 | { 160 | "type": "SYMBOL", 161 | "name": "importstr" 162 | }, 163 | { 164 | "type": "SYMBOL", 165 | "name": "error" 166 | }, 167 | { 168 | "type": "SYMBOL", 169 | "name": "in_super" 170 | }, 171 | { 172 | "type": "SYMBOL", 173 | "name": "parenthesis" 174 | } 175 | ] 176 | }, 177 | "null": { 178 | "type": "STRING", 179 | "value": "null" 180 | }, 181 | "true": { 182 | "type": "STRING", 183 | "value": "true" 184 | }, 185 | "false": { 186 | "type": "STRING", 187 | "value": "false" 188 | }, 189 | "self": { 190 | "type": "STRING", 191 | "value": "self" 192 | }, 193 | "dollar": { 194 | "type": "STRING", 195 | "value": "$" 196 | }, 197 | "super": { 198 | "type": "STRING", 199 | "value": "super" 200 | }, 201 | "local": { 202 | "type": "STRING", 203 | "value": "local" 204 | }, 205 | "tailstrict": { 206 | "type": "STRING", 207 | "value": "tailstrict" 208 | }, 209 | "number": { 210 | "type": "SYMBOL", 211 | "name": "_number" 212 | }, 213 | "string": { 214 | "type": "SYMBOL", 215 | "name": "_string" 216 | }, 217 | "object": { 218 | "type": "SEQ", 219 | "members": [ 220 | { 221 | "type": "STRING", 222 | "value": "{" 223 | }, 224 | { 225 | "type": "CHOICE", 226 | "members": [ 227 | { 228 | "type": "SYMBOL", 229 | "name": "objinside" 230 | }, 231 | { 232 | "type": "BLANK" 233 | } 234 | ] 235 | }, 236 | { 237 | "type": "STRING", 238 | "value": "}" 239 | } 240 | ] 241 | }, 242 | "array": { 243 | "type": "SEQ", 244 | "members": [ 245 | { 246 | "type": "STRING", 247 | "value": "[" 248 | }, 249 | { 250 | "type": "CHOICE", 251 | "members": [ 252 | { 253 | "type": "SEQ", 254 | "members": [ 255 | { 256 | "type": "SYMBOL", 257 | "name": "_expr" 258 | }, 259 | { 260 | "type": "REPEAT", 261 | "content": { 262 | "type": "SEQ", 263 | "members": [ 264 | { 265 | "type": "STRING", 266 | "value": "," 267 | }, 268 | { 269 | "type": "SYMBOL", 270 | "name": "_expr" 271 | } 272 | ] 273 | } 274 | }, 275 | { 276 | "type": "CHOICE", 277 | "members": [ 278 | { 279 | "type": "STRING", 280 | "value": "," 281 | }, 282 | { 283 | "type": "BLANK" 284 | } 285 | ] 286 | } 287 | ] 288 | }, 289 | { 290 | "type": "BLANK" 291 | } 292 | ] 293 | }, 294 | { 295 | "type": "STRING", 296 | "value": "]" 297 | } 298 | ] 299 | }, 300 | "forloop": { 301 | "type": "SEQ", 302 | "members": [ 303 | { 304 | "type": "STRING", 305 | "value": "[" 306 | }, 307 | { 308 | "type": "SYMBOL", 309 | "name": "_expr" 310 | }, 311 | { 312 | "type": "CHOICE", 313 | "members": [ 314 | { 315 | "type": "STRING", 316 | "value": "," 317 | }, 318 | { 319 | "type": "BLANK" 320 | } 321 | ] 322 | }, 323 | { 324 | "type": "SYMBOL", 325 | "name": "forspec" 326 | }, 327 | { 328 | "type": "CHOICE", 329 | "members": [ 330 | { 331 | "type": "SYMBOL", 332 | "name": "compspec" 333 | }, 334 | { 335 | "type": "BLANK" 336 | } 337 | ] 338 | }, 339 | { 340 | "type": "STRING", 341 | "value": "]" 342 | } 343 | ] 344 | }, 345 | "fieldaccess": { 346 | "type": "PREC", 347 | "value": 13, 348 | "content": { 349 | "type": "SEQ", 350 | "members": [ 351 | { 352 | "type": "SYMBOL", 353 | "name": "_expr" 354 | }, 355 | { 356 | "type": "STRING", 357 | "value": "." 358 | }, 359 | { 360 | "type": "FIELD", 361 | "name": "last", 362 | "content": { 363 | "type": "SYMBOL", 364 | "name": "id" 365 | } 366 | } 367 | ] 368 | } 369 | }, 370 | "indexing": { 371 | "type": "PREC", 372 | "value": 13, 373 | "content": { 374 | "type": "SEQ", 375 | "members": [ 376 | { 377 | "type": "SYMBOL", 378 | "name": "_expr" 379 | }, 380 | { 381 | "type": "STRING", 382 | "value": "[" 383 | }, 384 | { 385 | "type": "CHOICE", 386 | "members": [ 387 | { 388 | "type": "SYMBOL", 389 | "name": "_expr" 390 | }, 391 | { 392 | "type": "BLANK" 393 | } 394 | ] 395 | }, 396 | { 397 | "type": "CHOICE", 398 | "members": [ 399 | { 400 | "type": "SEQ", 401 | "members": [ 402 | { 403 | "type": "STRING", 404 | "value": ":" 405 | }, 406 | { 407 | "type": "CHOICE", 408 | "members": [ 409 | { 410 | "type": "SYMBOL", 411 | "name": "_expr" 412 | }, 413 | { 414 | "type": "BLANK" 415 | } 416 | ] 417 | }, 418 | { 419 | "type": "CHOICE", 420 | "members": [ 421 | { 422 | "type": "SEQ", 423 | "members": [ 424 | { 425 | "type": "STRING", 426 | "value": ":" 427 | }, 428 | { 429 | "type": "CHOICE", 430 | "members": [ 431 | { 432 | "type": "SYMBOL", 433 | "name": "_expr" 434 | }, 435 | { 436 | "type": "BLANK" 437 | } 438 | ] 439 | } 440 | ] 441 | }, 442 | { 443 | "type": "BLANK" 444 | } 445 | ] 446 | } 447 | ] 448 | }, 449 | { 450 | "type": "BLANK" 451 | } 452 | ] 453 | }, 454 | { 455 | "type": "STRING", 456 | "value": "]" 457 | } 458 | ] 459 | } 460 | }, 461 | "fieldaccess_super": { 462 | "type": "SEQ", 463 | "members": [ 464 | { 465 | "type": "SYMBOL", 466 | "name": "super" 467 | }, 468 | { 469 | "type": "STRING", 470 | "value": "." 471 | }, 472 | { 473 | "type": "SYMBOL", 474 | "name": "id" 475 | } 476 | ] 477 | }, 478 | "indexing_super": { 479 | "type": "SEQ", 480 | "members": [ 481 | { 482 | "type": "SYMBOL", 483 | "name": "super" 484 | }, 485 | { 486 | "type": "STRING", 487 | "value": "[" 488 | }, 489 | { 490 | "type": "SYMBOL", 491 | "name": "_expr" 492 | }, 493 | { 494 | "type": "STRING", 495 | "value": "]" 496 | } 497 | ] 498 | }, 499 | "functioncall": { 500 | "type": "PREC", 501 | "value": 13, 502 | "content": { 503 | "type": "SEQ", 504 | "members": [ 505 | { 506 | "type": "SYMBOL", 507 | "name": "_expr" 508 | }, 509 | { 510 | "type": "STRING", 511 | "value": "(" 512 | }, 513 | { 514 | "type": "CHOICE", 515 | "members": [ 516 | { 517 | "type": "SYMBOL", 518 | "name": "args" 519 | }, 520 | { 521 | "type": "BLANK" 522 | } 523 | ] 524 | }, 525 | { 526 | "type": "STRING", 527 | "value": ")" 528 | }, 529 | { 530 | "type": "CHOICE", 531 | "members": [ 532 | { 533 | "type": "SYMBOL", 534 | "name": "tailstrict" 535 | }, 536 | { 537 | "type": "BLANK" 538 | } 539 | ] 540 | } 541 | ] 542 | } 543 | }, 544 | "id": { 545 | "type": "SYMBOL", 546 | "name": "_ident" 547 | }, 548 | "_ident": { 549 | "type": "PATTERN", 550 | "value": "[_a-zA-Z][_a-zA-Z0-9]*" 551 | }, 552 | "local_bind": { 553 | "type": "PREC_RIGHT", 554 | "value": 0, 555 | "content": { 556 | "type": "SEQ", 557 | "members": [ 558 | { 559 | "type": "SYMBOL", 560 | "name": "local" 561 | }, 562 | { 563 | "type": "SEQ", 564 | "members": [ 565 | { 566 | "type": "SYMBOL", 567 | "name": "bind" 568 | }, 569 | { 570 | "type": "REPEAT", 571 | "content": { 572 | "type": "SEQ", 573 | "members": [ 574 | { 575 | "type": "STRING", 576 | "value": "," 577 | }, 578 | { 579 | "type": "SYMBOL", 580 | "name": "bind" 581 | } 582 | ] 583 | } 584 | } 585 | ] 586 | }, 587 | { 588 | "type": "STRING", 589 | "value": ";" 590 | }, 591 | { 592 | "type": "SYMBOL", 593 | "name": "_expr" 594 | } 595 | ] 596 | } 597 | }, 598 | "conditional": { 599 | "type": "PREC_RIGHT", 600 | "value": 0, 601 | "content": { 602 | "type": "SEQ", 603 | "members": [ 604 | { 605 | "type": "STRING", 606 | "value": "if" 607 | }, 608 | { 609 | "type": "FIELD", 610 | "name": "condition", 611 | "content": { 612 | "type": "SYMBOL", 613 | "name": "_expr" 614 | } 615 | }, 616 | { 617 | "type": "STRING", 618 | "value": "then" 619 | }, 620 | { 621 | "type": "FIELD", 622 | "name": "consequence", 623 | "content": { 624 | "type": "SYMBOL", 625 | "name": "_expr" 626 | } 627 | }, 628 | { 629 | "type": "CHOICE", 630 | "members": [ 631 | { 632 | "type": "SEQ", 633 | "members": [ 634 | { 635 | "type": "STRING", 636 | "value": "else" 637 | }, 638 | { 639 | "type": "FIELD", 640 | "name": "alternative", 641 | "content": { 642 | "type": "SYMBOL", 643 | "name": "_expr" 644 | } 645 | } 646 | ] 647 | }, 648 | { 649 | "type": "BLANK" 650 | } 651 | ] 652 | } 653 | ] 654 | } 655 | }, 656 | "multiplicative": { 657 | "type": "CHOICE", 658 | "members": [ 659 | { 660 | "type": "STRING", 661 | "value": "*" 662 | }, 663 | { 664 | "type": "STRING", 665 | "value": "/" 666 | }, 667 | { 668 | "type": "STRING", 669 | "value": "%" 670 | } 671 | ] 672 | }, 673 | "additive": { 674 | "type": "CHOICE", 675 | "members": [ 676 | { 677 | "type": "STRING", 678 | "value": "+" 679 | }, 680 | { 681 | "type": "STRING", 682 | "value": "-" 683 | } 684 | ] 685 | }, 686 | "bitshift": { 687 | "type": "CHOICE", 688 | "members": [ 689 | { 690 | "type": "STRING", 691 | "value": "<<" 692 | }, 693 | { 694 | "type": "STRING", 695 | "value": ">>" 696 | } 697 | ] 698 | }, 699 | "comparison": { 700 | "type": "CHOICE", 701 | "members": [ 702 | { 703 | "type": "STRING", 704 | "value": "<" 705 | }, 706 | { 707 | "type": "STRING", 708 | "value": "<=" 709 | }, 710 | { 711 | "type": "STRING", 712 | "value": ">" 713 | }, 714 | { 715 | "type": "STRING", 716 | "value": ">=" 717 | }, 718 | { 719 | "type": "STRING", 720 | "value": "in" 721 | } 722 | ] 723 | }, 724 | "equality": { 725 | "type": "CHOICE", 726 | "members": [ 727 | { 728 | "type": "STRING", 729 | "value": "==" 730 | }, 731 | { 732 | "type": "STRING", 733 | "value": "!=" 734 | } 735 | ] 736 | }, 737 | "bitand": { 738 | "type": "STRING", 739 | "value": "&" 740 | }, 741 | "bitxor": { 742 | "type": "STRING", 743 | "value": "^" 744 | }, 745 | "bitor": { 746 | "type": "STRING", 747 | "value": "|" 748 | }, 749 | "and": { 750 | "type": "STRING", 751 | "value": "&&" 752 | }, 753 | "or": { 754 | "type": "STRING", 755 | "value": "||" 756 | }, 757 | "binary": { 758 | "type": "CHOICE", 759 | "members": [ 760 | { 761 | "type": "PREC_LEFT", 762 | "value": 11, 763 | "content": { 764 | "type": "SEQ", 765 | "members": [ 766 | { 767 | "type": "FIELD", 768 | "name": "left", 769 | "content": { 770 | "type": "SYMBOL", 771 | "name": "_expr" 772 | } 773 | }, 774 | { 775 | "type": "FIELD", 776 | "name": "operator", 777 | "content": { 778 | "type": "SYMBOL", 779 | "name": "multiplicative" 780 | } 781 | }, 782 | { 783 | "type": "FIELD", 784 | "name": "right", 785 | "content": { 786 | "type": "SYMBOL", 787 | "name": "_expr" 788 | } 789 | } 790 | ] 791 | } 792 | }, 793 | { 794 | "type": "PREC_LEFT", 795 | "value": 10, 796 | "content": { 797 | "type": "SEQ", 798 | "members": [ 799 | { 800 | "type": "FIELD", 801 | "name": "left", 802 | "content": { 803 | "type": "SYMBOL", 804 | "name": "_expr" 805 | } 806 | }, 807 | { 808 | "type": "FIELD", 809 | "name": "operator", 810 | "content": { 811 | "type": "SYMBOL", 812 | "name": "additive" 813 | } 814 | }, 815 | { 816 | "type": "FIELD", 817 | "name": "right", 818 | "content": { 819 | "type": "SYMBOL", 820 | "name": "_expr" 821 | } 822 | } 823 | ] 824 | } 825 | }, 826 | { 827 | "type": "PREC_LEFT", 828 | "value": 9, 829 | "content": { 830 | "type": "SEQ", 831 | "members": [ 832 | { 833 | "type": "FIELD", 834 | "name": "left", 835 | "content": { 836 | "type": "SYMBOL", 837 | "name": "_expr" 838 | } 839 | }, 840 | { 841 | "type": "FIELD", 842 | "name": "operator", 843 | "content": { 844 | "type": "SYMBOL", 845 | "name": "bitshift" 846 | } 847 | }, 848 | { 849 | "type": "FIELD", 850 | "name": "right", 851 | "content": { 852 | "type": "SYMBOL", 853 | "name": "_expr" 854 | } 855 | } 856 | ] 857 | } 858 | }, 859 | { 860 | "type": "PREC_LEFT", 861 | "value": 8, 862 | "content": { 863 | "type": "SEQ", 864 | "members": [ 865 | { 866 | "type": "FIELD", 867 | "name": "left", 868 | "content": { 869 | "type": "SYMBOL", 870 | "name": "_expr" 871 | } 872 | }, 873 | { 874 | "type": "FIELD", 875 | "name": "operator", 876 | "content": { 877 | "type": "SYMBOL", 878 | "name": "comparison" 879 | } 880 | }, 881 | { 882 | "type": "FIELD", 883 | "name": "right", 884 | "content": { 885 | "type": "SYMBOL", 886 | "name": "_expr" 887 | } 888 | } 889 | ] 890 | } 891 | }, 892 | { 893 | "type": "PREC_LEFT", 894 | "value": 7, 895 | "content": { 896 | "type": "SEQ", 897 | "members": [ 898 | { 899 | "type": "FIELD", 900 | "name": "left", 901 | "content": { 902 | "type": "SYMBOL", 903 | "name": "_expr" 904 | } 905 | }, 906 | { 907 | "type": "FIELD", 908 | "name": "operator", 909 | "content": { 910 | "type": "SYMBOL", 911 | "name": "equality" 912 | } 913 | }, 914 | { 915 | "type": "FIELD", 916 | "name": "right", 917 | "content": { 918 | "type": "SYMBOL", 919 | "name": "_expr" 920 | } 921 | } 922 | ] 923 | } 924 | }, 925 | { 926 | "type": "PREC_LEFT", 927 | "value": 6, 928 | "content": { 929 | "type": "SEQ", 930 | "members": [ 931 | { 932 | "type": "FIELD", 933 | "name": "left", 934 | "content": { 935 | "type": "SYMBOL", 936 | "name": "_expr" 937 | } 938 | }, 939 | { 940 | "type": "FIELD", 941 | "name": "operator", 942 | "content": { 943 | "type": "SYMBOL", 944 | "name": "bitand" 945 | } 946 | }, 947 | { 948 | "type": "FIELD", 949 | "name": "right", 950 | "content": { 951 | "type": "SYMBOL", 952 | "name": "_expr" 953 | } 954 | } 955 | ] 956 | } 957 | }, 958 | { 959 | "type": "PREC_LEFT", 960 | "value": 5, 961 | "content": { 962 | "type": "SEQ", 963 | "members": [ 964 | { 965 | "type": "FIELD", 966 | "name": "left", 967 | "content": { 968 | "type": "SYMBOL", 969 | "name": "_expr" 970 | } 971 | }, 972 | { 973 | "type": "FIELD", 974 | "name": "operator", 975 | "content": { 976 | "type": "SYMBOL", 977 | "name": "bitxor" 978 | } 979 | }, 980 | { 981 | "type": "FIELD", 982 | "name": "right", 983 | "content": { 984 | "type": "SYMBOL", 985 | "name": "_expr" 986 | } 987 | } 988 | ] 989 | } 990 | }, 991 | { 992 | "type": "PREC_LEFT", 993 | "value": 4, 994 | "content": { 995 | "type": "SEQ", 996 | "members": [ 997 | { 998 | "type": "FIELD", 999 | "name": "left", 1000 | "content": { 1001 | "type": "SYMBOL", 1002 | "name": "_expr" 1003 | } 1004 | }, 1005 | { 1006 | "type": "FIELD", 1007 | "name": "operator", 1008 | "content": { 1009 | "type": "SYMBOL", 1010 | "name": "bitor" 1011 | } 1012 | }, 1013 | { 1014 | "type": "FIELD", 1015 | "name": "right", 1016 | "content": { 1017 | "type": "SYMBOL", 1018 | "name": "_expr" 1019 | } 1020 | } 1021 | ] 1022 | } 1023 | }, 1024 | { 1025 | "type": "PREC_LEFT", 1026 | "value": 3, 1027 | "content": { 1028 | "type": "SEQ", 1029 | "members": [ 1030 | { 1031 | "type": "FIELD", 1032 | "name": "left", 1033 | "content": { 1034 | "type": "SYMBOL", 1035 | "name": "_expr" 1036 | } 1037 | }, 1038 | { 1039 | "type": "FIELD", 1040 | "name": "operator", 1041 | "content": { 1042 | "type": "SYMBOL", 1043 | "name": "and" 1044 | } 1045 | }, 1046 | { 1047 | "type": "FIELD", 1048 | "name": "right", 1049 | "content": { 1050 | "type": "SYMBOL", 1051 | "name": "_expr" 1052 | } 1053 | } 1054 | ] 1055 | } 1056 | }, 1057 | { 1058 | "type": "PREC_LEFT", 1059 | "value": 2, 1060 | "content": { 1061 | "type": "SEQ", 1062 | "members": [ 1063 | { 1064 | "type": "FIELD", 1065 | "name": "left", 1066 | "content": { 1067 | "type": "SYMBOL", 1068 | "name": "_expr" 1069 | } 1070 | }, 1071 | { 1072 | "type": "FIELD", 1073 | "name": "operator", 1074 | "content": { 1075 | "type": "SYMBOL", 1076 | "name": "or" 1077 | } 1078 | }, 1079 | { 1080 | "type": "FIELD", 1081 | "name": "right", 1082 | "content": { 1083 | "type": "SYMBOL", 1084 | "name": "_expr" 1085 | } 1086 | } 1087 | ] 1088 | } 1089 | } 1090 | ] 1091 | }, 1092 | "unary": { 1093 | "type": "PREC", 1094 | "value": 12, 1095 | "content": { 1096 | "type": "SEQ", 1097 | "members": [ 1098 | { 1099 | "type": "FIELD", 1100 | "name": "operator", 1101 | "content": { 1102 | "type": "SYMBOL", 1103 | "name": "unaryop" 1104 | } 1105 | }, 1106 | { 1107 | "type": "FIELD", 1108 | "name": "argument", 1109 | "content": { 1110 | "type": "SYMBOL", 1111 | "name": "_expr" 1112 | } 1113 | } 1114 | ] 1115 | } 1116 | }, 1117 | "unaryop": { 1118 | "type": "CHOICE", 1119 | "members": [ 1120 | { 1121 | "type": "STRING", 1122 | "value": "-" 1123 | }, 1124 | { 1125 | "type": "STRING", 1126 | "value": "+" 1127 | }, 1128 | { 1129 | "type": "STRING", 1130 | "value": "!" 1131 | }, 1132 | { 1133 | "type": "STRING", 1134 | "value": "~" 1135 | } 1136 | ] 1137 | }, 1138 | "implicit_plus": { 1139 | "type": "SEQ", 1140 | "members": [ 1141 | { 1142 | "type": "SYMBOL", 1143 | "name": "_expr" 1144 | }, 1145 | { 1146 | "type": "SYMBOL", 1147 | "name": "object" 1148 | } 1149 | ] 1150 | }, 1151 | "anonymous_function": { 1152 | "type": "PREC_RIGHT", 1153 | "value": 0, 1154 | "content": { 1155 | "type": "SEQ", 1156 | "members": [ 1157 | { 1158 | "type": "STRING", 1159 | "value": "function" 1160 | }, 1161 | { 1162 | "type": "STRING", 1163 | "value": "(" 1164 | }, 1165 | { 1166 | "type": "CHOICE", 1167 | "members": [ 1168 | { 1169 | "type": "FIELD", 1170 | "name": "params", 1171 | "content": { 1172 | "type": "SYMBOL", 1173 | "name": "params" 1174 | } 1175 | }, 1176 | { 1177 | "type": "BLANK" 1178 | } 1179 | ] 1180 | }, 1181 | { 1182 | "type": "STRING", 1183 | "value": ")" 1184 | }, 1185 | { 1186 | "type": "FIELD", 1187 | "name": "body", 1188 | "content": { 1189 | "type": "SYMBOL", 1190 | "name": "_expr" 1191 | } 1192 | } 1193 | ] 1194 | } 1195 | }, 1196 | "_assert_expr": { 1197 | "type": "PREC_RIGHT", 1198 | "value": 0, 1199 | "content": { 1200 | "type": "SEQ", 1201 | "members": [ 1202 | { 1203 | "type": "SYMBOL", 1204 | "name": "assert" 1205 | }, 1206 | { 1207 | "type": "STRING", 1208 | "value": ";" 1209 | }, 1210 | { 1211 | "type": "SYMBOL", 1212 | "name": "_expr" 1213 | } 1214 | ] 1215 | } 1216 | }, 1217 | "import": { 1218 | "type": "SEQ", 1219 | "members": [ 1220 | { 1221 | "type": "STRING", 1222 | "value": "import" 1223 | }, 1224 | { 1225 | "type": "SYMBOL", 1226 | "name": "string" 1227 | } 1228 | ] 1229 | }, 1230 | "importstr": { 1231 | "type": "SEQ", 1232 | "members": [ 1233 | { 1234 | "type": "STRING", 1235 | "value": "importstr" 1236 | }, 1237 | { 1238 | "type": "SYMBOL", 1239 | "name": "string" 1240 | } 1241 | ] 1242 | }, 1243 | "error": { 1244 | "type": "PREC_RIGHT", 1245 | "value": 0, 1246 | "content": { 1247 | "type": "SEQ", 1248 | "members": [ 1249 | { 1250 | "type": "STRING", 1251 | "value": "error" 1252 | }, 1253 | { 1254 | "type": "SYMBOL", 1255 | "name": "_expr" 1256 | } 1257 | ] 1258 | } 1259 | }, 1260 | "in_super": { 1261 | "type": "PREC", 1262 | "value": 8, 1263 | "content": { 1264 | "type": "SEQ", 1265 | "members": [ 1266 | { 1267 | "type": "SYMBOL", 1268 | "name": "_expr" 1269 | }, 1270 | { 1271 | "type": "STRING", 1272 | "value": "in" 1273 | }, 1274 | { 1275 | "type": "SYMBOL", 1276 | "name": "super" 1277 | } 1278 | ] 1279 | } 1280 | }, 1281 | "parenthesis": { 1282 | "type": "SEQ", 1283 | "members": [ 1284 | { 1285 | "type": "STRING", 1286 | "value": "(" 1287 | }, 1288 | { 1289 | "type": "SYMBOL", 1290 | "name": "_expr" 1291 | }, 1292 | { 1293 | "type": "STRING", 1294 | "value": ")" 1295 | } 1296 | ] 1297 | }, 1298 | "objinside": { 1299 | "type": "CHOICE", 1300 | "members": [ 1301 | { 1302 | "type": "SEQ", 1303 | "members": [ 1304 | { 1305 | "type": "SYMBOL", 1306 | "name": "member" 1307 | }, 1308 | { 1309 | "type": "REPEAT", 1310 | "content": { 1311 | "type": "SEQ", 1312 | "members": [ 1313 | { 1314 | "type": "STRING", 1315 | "value": "," 1316 | }, 1317 | { 1318 | "type": "SYMBOL", 1319 | "name": "member" 1320 | } 1321 | ] 1322 | } 1323 | }, 1324 | { 1325 | "type": "CHOICE", 1326 | "members": [ 1327 | { 1328 | "type": "STRING", 1329 | "value": "," 1330 | }, 1331 | { 1332 | "type": "BLANK" 1333 | } 1334 | ] 1335 | } 1336 | ] 1337 | }, 1338 | { 1339 | "type": "SYMBOL", 1340 | "name": "objforloop" 1341 | } 1342 | ] 1343 | }, 1344 | "objforloop": { 1345 | "type": "SEQ", 1346 | "members": [ 1347 | { 1348 | "type": "REPEAT", 1349 | "content": { 1350 | "type": "SEQ", 1351 | "members": [ 1352 | { 1353 | "type": "SYMBOL", 1354 | "name": "objlocal" 1355 | }, 1356 | { 1357 | "type": "STRING", 1358 | "value": "," 1359 | } 1360 | ] 1361 | } 1362 | }, 1363 | { 1364 | "type": "SYMBOL", 1365 | "name": "field" 1366 | }, 1367 | { 1368 | "type": "REPEAT", 1369 | "content": { 1370 | "type": "SEQ", 1371 | "members": [ 1372 | { 1373 | "type": "STRING", 1374 | "value": "," 1375 | }, 1376 | { 1377 | "type": "SYMBOL", 1378 | "name": "objlocal" 1379 | } 1380 | ] 1381 | } 1382 | }, 1383 | { 1384 | "type": "CHOICE", 1385 | "members": [ 1386 | { 1387 | "type": "STRING", 1388 | "value": "," 1389 | }, 1390 | { 1391 | "type": "BLANK" 1392 | } 1393 | ] 1394 | }, 1395 | { 1396 | "type": "SYMBOL", 1397 | "name": "forspec" 1398 | }, 1399 | { 1400 | "type": "CHOICE", 1401 | "members": [ 1402 | { 1403 | "type": "SYMBOL", 1404 | "name": "compspec" 1405 | }, 1406 | { 1407 | "type": "BLANK" 1408 | } 1409 | ] 1410 | } 1411 | ] 1412 | }, 1413 | "member": { 1414 | "type": "PREC_RIGHT", 1415 | "value": 1, 1416 | "content": { 1417 | "type": "CHOICE", 1418 | "members": [ 1419 | { 1420 | "type": "SYMBOL", 1421 | "name": "objlocal" 1422 | }, 1423 | { 1424 | "type": "SYMBOL", 1425 | "name": "assert" 1426 | }, 1427 | { 1428 | "type": "SYMBOL", 1429 | "name": "field" 1430 | } 1431 | ] 1432 | } 1433 | }, 1434 | "field": { 1435 | "type": "CHOICE", 1436 | "members": [ 1437 | { 1438 | "type": "SEQ", 1439 | "members": [ 1440 | { 1441 | "type": "SYMBOL", 1442 | "name": "fieldname" 1443 | }, 1444 | { 1445 | "type": "CHOICE", 1446 | "members": [ 1447 | { 1448 | "type": "STRING", 1449 | "value": "+" 1450 | }, 1451 | { 1452 | "type": "BLANK" 1453 | } 1454 | ] 1455 | }, 1456 | { 1457 | "type": "SYMBOL", 1458 | "name": "h" 1459 | }, 1460 | { 1461 | "type": "SYMBOL", 1462 | "name": "_expr" 1463 | } 1464 | ] 1465 | }, 1466 | { 1467 | "type": "SEQ", 1468 | "members": [ 1469 | { 1470 | "type": "FIELD", 1471 | "name": "function", 1472 | "content": { 1473 | "type": "SYMBOL", 1474 | "name": "fieldname" 1475 | } 1476 | }, 1477 | { 1478 | "type": "STRING", 1479 | "value": "(" 1480 | }, 1481 | { 1482 | "type": "CHOICE", 1483 | "members": [ 1484 | { 1485 | "type": "SYMBOL", 1486 | "name": "params" 1487 | }, 1488 | { 1489 | "type": "BLANK" 1490 | } 1491 | ] 1492 | }, 1493 | { 1494 | "type": "STRING", 1495 | "value": ")" 1496 | }, 1497 | { 1498 | "type": "SYMBOL", 1499 | "name": "h" 1500 | }, 1501 | { 1502 | "type": "SYMBOL", 1503 | "name": "_expr" 1504 | } 1505 | ] 1506 | } 1507 | ] 1508 | }, 1509 | "h": { 1510 | "type": "CHOICE", 1511 | "members": [ 1512 | { 1513 | "type": "STRING", 1514 | "value": ":" 1515 | }, 1516 | { 1517 | "type": "STRING", 1518 | "value": "::" 1519 | }, 1520 | { 1521 | "type": "STRING", 1522 | "value": ":::" 1523 | } 1524 | ] 1525 | }, 1526 | "objlocal": { 1527 | "type": "SEQ", 1528 | "members": [ 1529 | { 1530 | "type": "SYMBOL", 1531 | "name": "local" 1532 | }, 1533 | { 1534 | "type": "SYMBOL", 1535 | "name": "bind" 1536 | } 1537 | ] 1538 | }, 1539 | "compspec": { 1540 | "type": "REPEAT1", 1541 | "content": { 1542 | "type": "CHOICE", 1543 | "members": [ 1544 | { 1545 | "type": "SYMBOL", 1546 | "name": "forspec" 1547 | }, 1548 | { 1549 | "type": "SYMBOL", 1550 | "name": "ifspec" 1551 | } 1552 | ] 1553 | } 1554 | }, 1555 | "forspec": { 1556 | "type": "SEQ", 1557 | "members": [ 1558 | { 1559 | "type": "STRING", 1560 | "value": "for" 1561 | }, 1562 | { 1563 | "type": "SYMBOL", 1564 | "name": "id" 1565 | }, 1566 | { 1567 | "type": "STRING", 1568 | "value": "in" 1569 | }, 1570 | { 1571 | "type": "SYMBOL", 1572 | "name": "_expr" 1573 | } 1574 | ] 1575 | }, 1576 | "ifspec": { 1577 | "type": "SEQ", 1578 | "members": [ 1579 | { 1580 | "type": "STRING", 1581 | "value": "if" 1582 | }, 1583 | { 1584 | "type": "SYMBOL", 1585 | "name": "_expr" 1586 | } 1587 | ] 1588 | }, 1589 | "fieldname": { 1590 | "type": "PREC_RIGHT", 1591 | "value": 0, 1592 | "content": { 1593 | "type": "CHOICE", 1594 | "members": [ 1595 | { 1596 | "type": "SYMBOL", 1597 | "name": "id" 1598 | }, 1599 | { 1600 | "type": "SYMBOL", 1601 | "name": "string" 1602 | }, 1603 | { 1604 | "type": "SEQ", 1605 | "members": [ 1606 | { 1607 | "type": "STRING", 1608 | "value": "[" 1609 | }, 1610 | { 1611 | "type": "SYMBOL", 1612 | "name": "_expr" 1613 | }, 1614 | { 1615 | "type": "STRING", 1616 | "value": "]" 1617 | } 1618 | ] 1619 | } 1620 | ] 1621 | } 1622 | }, 1623 | "assert": { 1624 | "type": "SEQ", 1625 | "members": [ 1626 | { 1627 | "type": "STRING", 1628 | "value": "assert" 1629 | }, 1630 | { 1631 | "type": "SYMBOL", 1632 | "name": "_expr" 1633 | }, 1634 | { 1635 | "type": "CHOICE", 1636 | "members": [ 1637 | { 1638 | "type": "SEQ", 1639 | "members": [ 1640 | { 1641 | "type": "STRING", 1642 | "value": ":" 1643 | }, 1644 | { 1645 | "type": "SYMBOL", 1646 | "name": "_expr" 1647 | } 1648 | ] 1649 | }, 1650 | { 1651 | "type": "BLANK" 1652 | } 1653 | ] 1654 | } 1655 | ] 1656 | }, 1657 | "bind": { 1658 | "type": "CHOICE", 1659 | "members": [ 1660 | { 1661 | "type": "SEQ", 1662 | "members": [ 1663 | { 1664 | "type": "SYMBOL", 1665 | "name": "id" 1666 | }, 1667 | { 1668 | "type": "STRING", 1669 | "value": "=" 1670 | }, 1671 | { 1672 | "type": "SYMBOL", 1673 | "name": "_expr" 1674 | } 1675 | ] 1676 | }, 1677 | { 1678 | "type": "PREC_RIGHT", 1679 | "value": 0, 1680 | "content": { 1681 | "type": "SEQ", 1682 | "members": [ 1683 | { 1684 | "type": "FIELD", 1685 | "name": "function", 1686 | "content": { 1687 | "type": "SYMBOL", 1688 | "name": "id" 1689 | } 1690 | }, 1691 | { 1692 | "type": "STRING", 1693 | "value": "(" 1694 | }, 1695 | { 1696 | "type": "CHOICE", 1697 | "members": [ 1698 | { 1699 | "type": "FIELD", 1700 | "name": "params", 1701 | "content": { 1702 | "type": "SYMBOL", 1703 | "name": "params" 1704 | } 1705 | }, 1706 | { 1707 | "type": "BLANK" 1708 | } 1709 | ] 1710 | }, 1711 | { 1712 | "type": "STRING", 1713 | "value": ")" 1714 | }, 1715 | { 1716 | "type": "STRING", 1717 | "value": "=" 1718 | }, 1719 | { 1720 | "type": "FIELD", 1721 | "name": "body", 1722 | "content": { 1723 | "type": "SYMBOL", 1724 | "name": "_expr" 1725 | } 1726 | } 1727 | ] 1728 | } 1729 | } 1730 | ] 1731 | }, 1732 | "args": { 1733 | "type": "CHOICE", 1734 | "members": [ 1735 | { 1736 | "type": "SEQ", 1737 | "members": [ 1738 | { 1739 | "type": "SYMBOL", 1740 | "name": "_expr" 1741 | }, 1742 | { 1743 | "type": "REPEAT", 1744 | "content": { 1745 | "type": "SEQ", 1746 | "members": [ 1747 | { 1748 | "type": "STRING", 1749 | "value": "," 1750 | }, 1751 | { 1752 | "type": "SYMBOL", 1753 | "name": "_expr" 1754 | } 1755 | ] 1756 | } 1757 | }, 1758 | { 1759 | "type": "REPEAT", 1760 | "content": { 1761 | "type": "SEQ", 1762 | "members": [ 1763 | { 1764 | "type": "STRING", 1765 | "value": "," 1766 | }, 1767 | { 1768 | "type": "SYMBOL", 1769 | "name": "named_argument" 1770 | } 1771 | ] 1772 | } 1773 | }, 1774 | { 1775 | "type": "CHOICE", 1776 | "members": [ 1777 | { 1778 | "type": "STRING", 1779 | "value": "," 1780 | }, 1781 | { 1782 | "type": "BLANK" 1783 | } 1784 | ] 1785 | } 1786 | ] 1787 | }, 1788 | { 1789 | "type": "SEQ", 1790 | "members": [ 1791 | { 1792 | "type": "SYMBOL", 1793 | "name": "named_argument" 1794 | }, 1795 | { 1796 | "type": "REPEAT", 1797 | "content": { 1798 | "type": "SEQ", 1799 | "members": [ 1800 | { 1801 | "type": "STRING", 1802 | "value": "," 1803 | }, 1804 | { 1805 | "type": "SYMBOL", 1806 | "name": "named_argument" 1807 | } 1808 | ] 1809 | } 1810 | }, 1811 | { 1812 | "type": "CHOICE", 1813 | "members": [ 1814 | { 1815 | "type": "STRING", 1816 | "value": "," 1817 | }, 1818 | { 1819 | "type": "BLANK" 1820 | } 1821 | ] 1822 | } 1823 | ] 1824 | } 1825 | ] 1826 | }, 1827 | "named_argument": { 1828 | "type": "SEQ", 1829 | "members": [ 1830 | { 1831 | "type": "SYMBOL", 1832 | "name": "id" 1833 | }, 1834 | { 1835 | "type": "STRING", 1836 | "value": "=" 1837 | }, 1838 | { 1839 | "type": "SYMBOL", 1840 | "name": "_expr" 1841 | } 1842 | ] 1843 | }, 1844 | "params": { 1845 | "type": "SEQ", 1846 | "members": [ 1847 | { 1848 | "type": "SYMBOL", 1849 | "name": "param" 1850 | }, 1851 | { 1852 | "type": "REPEAT", 1853 | "content": { 1854 | "type": "SEQ", 1855 | "members": [ 1856 | { 1857 | "type": "STRING", 1858 | "value": "," 1859 | }, 1860 | { 1861 | "type": "SYMBOL", 1862 | "name": "param" 1863 | } 1864 | ] 1865 | } 1866 | }, 1867 | { 1868 | "type": "CHOICE", 1869 | "members": [ 1870 | { 1871 | "type": "STRING", 1872 | "value": "," 1873 | }, 1874 | { 1875 | "type": "BLANK" 1876 | } 1877 | ] 1878 | } 1879 | ] 1880 | }, 1881 | "param": { 1882 | "type": "SEQ", 1883 | "members": [ 1884 | { 1885 | "type": "FIELD", 1886 | "name": "identifier", 1887 | "content": { 1888 | "type": "SYMBOL", 1889 | "name": "id" 1890 | } 1891 | }, 1892 | { 1893 | "type": "CHOICE", 1894 | "members": [ 1895 | { 1896 | "type": "SEQ", 1897 | "members": [ 1898 | { 1899 | "type": "STRING", 1900 | "value": "=" 1901 | }, 1902 | { 1903 | "type": "FIELD", 1904 | "name": "value", 1905 | "content": { 1906 | "type": "SYMBOL", 1907 | "name": "_expr" 1908 | } 1909 | } 1910 | ] 1911 | }, 1912 | { 1913 | "type": "BLANK" 1914 | } 1915 | ] 1916 | } 1917 | ] 1918 | }, 1919 | "_number": { 1920 | "type": "TOKEN", 1921 | "content": { 1922 | "type": "CHOICE", 1923 | "members": [ 1924 | { 1925 | "type": "SEQ", 1926 | "members": [ 1927 | { 1928 | "type": "CHOICE", 1929 | "members": [ 1930 | { 1931 | "type": "STRING", 1932 | "value": "0x" 1933 | }, 1934 | { 1935 | "type": "STRING", 1936 | "value": "0X" 1937 | } 1938 | ] 1939 | }, 1940 | { 1941 | "type": "PATTERN", 1942 | "value": "[\\da-fA-F]+" 1943 | } 1944 | ] 1945 | }, 1946 | { 1947 | "type": "CHOICE", 1948 | "members": [ 1949 | { 1950 | "type": "SEQ", 1951 | "members": [ 1952 | { 1953 | "type": "SEQ", 1954 | "members": [ 1955 | { 1956 | "type": "CHOICE", 1957 | "members": [ 1958 | { 1959 | "type": "CHOICE", 1960 | "members": [ 1961 | { 1962 | "type": "STRING", 1963 | "value": "-" 1964 | }, 1965 | { 1966 | "type": "STRING", 1967 | "value": "+" 1968 | } 1969 | ] 1970 | }, 1971 | { 1972 | "type": "BLANK" 1973 | } 1974 | ] 1975 | }, 1976 | { 1977 | "type": "CHOICE", 1978 | "members": [ 1979 | { 1980 | "type": "STRING", 1981 | "value": "0" 1982 | }, 1983 | { 1984 | "type": "SEQ", 1985 | "members": [ 1986 | { 1987 | "type": "PATTERN", 1988 | "value": "[1-9]" 1989 | }, 1990 | { 1991 | "type": "CHOICE", 1992 | "members": [ 1993 | { 1994 | "type": "PATTERN", 1995 | "value": "\\d+" 1996 | }, 1997 | { 1998 | "type": "BLANK" 1999 | } 2000 | ] 2001 | } 2002 | ] 2003 | } 2004 | ] 2005 | } 2006 | ] 2007 | }, 2008 | { 2009 | "type": "STRING", 2010 | "value": "." 2011 | }, 2012 | { 2013 | "type": "CHOICE", 2014 | "members": [ 2015 | { 2016 | "type": "PATTERN", 2017 | "value": "\\d+" 2018 | }, 2019 | { 2020 | "type": "BLANK" 2021 | } 2022 | ] 2023 | }, 2024 | { 2025 | "type": "CHOICE", 2026 | "members": [ 2027 | { 2028 | "type": "SEQ", 2029 | "members": [ 2030 | { 2031 | "type": "CHOICE", 2032 | "members": [ 2033 | { 2034 | "type": "STRING", 2035 | "value": "e" 2036 | }, 2037 | { 2038 | "type": "STRING", 2039 | "value": "E" 2040 | } 2041 | ] 2042 | }, 2043 | { 2044 | "type": "SEQ", 2045 | "members": [ 2046 | { 2047 | "type": "CHOICE", 2048 | "members": [ 2049 | { 2050 | "type": "CHOICE", 2051 | "members": [ 2052 | { 2053 | "type": "STRING", 2054 | "value": "-" 2055 | }, 2056 | { 2057 | "type": "STRING", 2058 | "value": "+" 2059 | } 2060 | ] 2061 | }, 2062 | { 2063 | "type": "BLANK" 2064 | } 2065 | ] 2066 | }, 2067 | { 2068 | "type": "PATTERN", 2069 | "value": "\\d+" 2070 | } 2071 | ] 2072 | } 2073 | ] 2074 | }, 2075 | { 2076 | "type": "BLANK" 2077 | } 2078 | ] 2079 | } 2080 | ] 2081 | }, 2082 | { 2083 | "type": "SEQ", 2084 | "members": [ 2085 | { 2086 | "type": "STRING", 2087 | "value": "." 2088 | }, 2089 | { 2090 | "type": "PATTERN", 2091 | "value": "\\d+" 2092 | }, 2093 | { 2094 | "type": "CHOICE", 2095 | "members": [ 2096 | { 2097 | "type": "SEQ", 2098 | "members": [ 2099 | { 2100 | "type": "CHOICE", 2101 | "members": [ 2102 | { 2103 | "type": "STRING", 2104 | "value": "e" 2105 | }, 2106 | { 2107 | "type": "STRING", 2108 | "value": "E" 2109 | } 2110 | ] 2111 | }, 2112 | { 2113 | "type": "SEQ", 2114 | "members": [ 2115 | { 2116 | "type": "CHOICE", 2117 | "members": [ 2118 | { 2119 | "type": "CHOICE", 2120 | "members": [ 2121 | { 2122 | "type": "STRING", 2123 | "value": "-" 2124 | }, 2125 | { 2126 | "type": "STRING", 2127 | "value": "+" 2128 | } 2129 | ] 2130 | }, 2131 | { 2132 | "type": "BLANK" 2133 | } 2134 | ] 2135 | }, 2136 | { 2137 | "type": "PATTERN", 2138 | "value": "\\d+" 2139 | } 2140 | ] 2141 | } 2142 | ] 2143 | }, 2144 | { 2145 | "type": "BLANK" 2146 | } 2147 | ] 2148 | } 2149 | ] 2150 | }, 2151 | { 2152 | "type": "SEQ", 2153 | "members": [ 2154 | { 2155 | "type": "SEQ", 2156 | "members": [ 2157 | { 2158 | "type": "CHOICE", 2159 | "members": [ 2160 | { 2161 | "type": "CHOICE", 2162 | "members": [ 2163 | { 2164 | "type": "STRING", 2165 | "value": "-" 2166 | }, 2167 | { 2168 | "type": "STRING", 2169 | "value": "+" 2170 | } 2171 | ] 2172 | }, 2173 | { 2174 | "type": "BLANK" 2175 | } 2176 | ] 2177 | }, 2178 | { 2179 | "type": "CHOICE", 2180 | "members": [ 2181 | { 2182 | "type": "STRING", 2183 | "value": "0" 2184 | }, 2185 | { 2186 | "type": "SEQ", 2187 | "members": [ 2188 | { 2189 | "type": "PATTERN", 2190 | "value": "[1-9]" 2191 | }, 2192 | { 2193 | "type": "CHOICE", 2194 | "members": [ 2195 | { 2196 | "type": "PATTERN", 2197 | "value": "\\d+" 2198 | }, 2199 | { 2200 | "type": "BLANK" 2201 | } 2202 | ] 2203 | } 2204 | ] 2205 | } 2206 | ] 2207 | } 2208 | ] 2209 | }, 2210 | { 2211 | "type": "CHOICE", 2212 | "members": [ 2213 | { 2214 | "type": "SEQ", 2215 | "members": [ 2216 | { 2217 | "type": "CHOICE", 2218 | "members": [ 2219 | { 2220 | "type": "STRING", 2221 | "value": "e" 2222 | }, 2223 | { 2224 | "type": "STRING", 2225 | "value": "E" 2226 | } 2227 | ] 2228 | }, 2229 | { 2230 | "type": "SEQ", 2231 | "members": [ 2232 | { 2233 | "type": "CHOICE", 2234 | "members": [ 2235 | { 2236 | "type": "CHOICE", 2237 | "members": [ 2238 | { 2239 | "type": "STRING", 2240 | "value": "-" 2241 | }, 2242 | { 2243 | "type": "STRING", 2244 | "value": "+" 2245 | } 2246 | ] 2247 | }, 2248 | { 2249 | "type": "BLANK" 2250 | } 2251 | ] 2252 | }, 2253 | { 2254 | "type": "PATTERN", 2255 | "value": "\\d+" 2256 | } 2257 | ] 2258 | } 2259 | ] 2260 | }, 2261 | { 2262 | "type": "BLANK" 2263 | } 2264 | ] 2265 | } 2266 | ] 2267 | } 2268 | ] 2269 | }, 2270 | { 2271 | "type": "SEQ", 2272 | "members": [ 2273 | { 2274 | "type": "CHOICE", 2275 | "members": [ 2276 | { 2277 | "type": "STRING", 2278 | "value": "0b" 2279 | }, 2280 | { 2281 | "type": "STRING", 2282 | "value": "0B" 2283 | } 2284 | ] 2285 | }, 2286 | { 2287 | "type": "PATTERN", 2288 | "value": "[0-1]+" 2289 | } 2290 | ] 2291 | }, 2292 | { 2293 | "type": "SEQ", 2294 | "members": [ 2295 | { 2296 | "type": "CHOICE", 2297 | "members": [ 2298 | { 2299 | "type": "STRING", 2300 | "value": "0o" 2301 | }, 2302 | { 2303 | "type": "STRING", 2304 | "value": "0O" 2305 | } 2306 | ] 2307 | }, 2308 | { 2309 | "type": "PATTERN", 2310 | "value": "[0-7]+" 2311 | } 2312 | ] 2313 | } 2314 | ] 2315 | } 2316 | }, 2317 | "_string": { 2318 | "type": "CHOICE", 2319 | "members": [ 2320 | { 2321 | "type": "SEQ", 2322 | "members": [ 2323 | { 2324 | "type": "CHOICE", 2325 | "members": [ 2326 | { 2327 | "type": "STRING", 2328 | "value": "@" 2329 | }, 2330 | { 2331 | "type": "BLANK" 2332 | } 2333 | ] 2334 | }, 2335 | { 2336 | "type": "ALIAS", 2337 | "content": { 2338 | "type": "SYMBOL", 2339 | "name": "_single" 2340 | }, 2341 | "named": true, 2342 | "value": "string_start" 2343 | }, 2344 | { 2345 | "type": "ALIAS", 2346 | "content": { 2347 | "type": "SYMBOL", 2348 | "name": "_single" 2349 | }, 2350 | "named": true, 2351 | "value": "string_end" 2352 | } 2353 | ] 2354 | }, 2355 | { 2356 | "type": "SEQ", 2357 | "members": [ 2358 | { 2359 | "type": "CHOICE", 2360 | "members": [ 2361 | { 2362 | "type": "STRING", 2363 | "value": "@" 2364 | }, 2365 | { 2366 | "type": "BLANK" 2367 | } 2368 | ] 2369 | }, 2370 | { 2371 | "type": "ALIAS", 2372 | "content": { 2373 | "type": "SYMBOL", 2374 | "name": "_single" 2375 | }, 2376 | "named": true, 2377 | "value": "string_start" 2378 | }, 2379 | { 2380 | "type": "ALIAS", 2381 | "content": { 2382 | "type": "SYMBOL", 2383 | "name": "_str_single" 2384 | }, 2385 | "named": true, 2386 | "value": "string_content" 2387 | }, 2388 | { 2389 | "type": "ALIAS", 2390 | "content": { 2391 | "type": "SYMBOL", 2392 | "name": "_single" 2393 | }, 2394 | "named": true, 2395 | "value": "string_end" 2396 | } 2397 | ] 2398 | }, 2399 | { 2400 | "type": "SEQ", 2401 | "members": [ 2402 | { 2403 | "type": "CHOICE", 2404 | "members": [ 2405 | { 2406 | "type": "STRING", 2407 | "value": "@" 2408 | }, 2409 | { 2410 | "type": "BLANK" 2411 | } 2412 | ] 2413 | }, 2414 | { 2415 | "type": "ALIAS", 2416 | "content": { 2417 | "type": "SYMBOL", 2418 | "name": "_double" 2419 | }, 2420 | "named": true, 2421 | "value": "string_start" 2422 | }, 2423 | { 2424 | "type": "ALIAS", 2425 | "content": { 2426 | "type": "SYMBOL", 2427 | "name": "_double" 2428 | }, 2429 | "named": true, 2430 | "value": "string_end" 2431 | } 2432 | ] 2433 | }, 2434 | { 2435 | "type": "SEQ", 2436 | "members": [ 2437 | { 2438 | "type": "CHOICE", 2439 | "members": [ 2440 | { 2441 | "type": "STRING", 2442 | "value": "@" 2443 | }, 2444 | { 2445 | "type": "BLANK" 2446 | } 2447 | ] 2448 | }, 2449 | { 2450 | "type": "ALIAS", 2451 | "content": { 2452 | "type": "SYMBOL", 2453 | "name": "_double" 2454 | }, 2455 | "named": true, 2456 | "value": "string_start" 2457 | }, 2458 | { 2459 | "type": "ALIAS", 2460 | "content": { 2461 | "type": "SYMBOL", 2462 | "name": "_str_double" 2463 | }, 2464 | "named": true, 2465 | "value": "string_content" 2466 | }, 2467 | { 2468 | "type": "ALIAS", 2469 | "content": { 2470 | "type": "SYMBOL", 2471 | "name": "_double" 2472 | }, 2473 | "named": true, 2474 | "value": "string_end" 2475 | } 2476 | ] 2477 | }, 2478 | { 2479 | "type": "SEQ", 2480 | "members": [ 2481 | { 2482 | "type": "CHOICE", 2483 | "members": [ 2484 | { 2485 | "type": "STRING", 2486 | "value": "@" 2487 | }, 2488 | { 2489 | "type": "BLANK" 2490 | } 2491 | ] 2492 | }, 2493 | { 2494 | "type": "ALIAS", 2495 | "content": { 2496 | "type": "SYMBOL", 2497 | "name": "_string_start" 2498 | }, 2499 | "named": true, 2500 | "value": "string_start" 2501 | }, 2502 | { 2503 | "type": "ALIAS", 2504 | "content": { 2505 | "type": "SYMBOL", 2506 | "name": "_string_content" 2507 | }, 2508 | "named": true, 2509 | "value": "string_content" 2510 | }, 2511 | { 2512 | "type": "ALIAS", 2513 | "content": { 2514 | "type": "SYMBOL", 2515 | "name": "_string_end" 2516 | }, 2517 | "named": true, 2518 | "value": "string_end" 2519 | } 2520 | ] 2521 | } 2522 | ] 2523 | }, 2524 | "_single": { 2525 | "type": "STRING", 2526 | "value": "'" 2527 | }, 2528 | "_double": { 2529 | "type": "STRING", 2530 | "value": "\"" 2531 | }, 2532 | "_str_double": { 2533 | "type": "REPEAT1", 2534 | "content": { 2535 | "type": "CHOICE", 2536 | "members": [ 2537 | { 2538 | "type": "IMMEDIATE_TOKEN", 2539 | "content": { 2540 | "type": "PREC", 2541 | "value": 1, 2542 | "content": { 2543 | "type": "PATTERN", 2544 | "value": "[^\\\\\"\\n]+" 2545 | } 2546 | } 2547 | }, 2548 | { 2549 | "type": "SYMBOL", 2550 | "name": "escape_sequence" 2551 | } 2552 | ] 2553 | } 2554 | }, 2555 | "_str_single": { 2556 | "type": "REPEAT1", 2557 | "content": { 2558 | "type": "CHOICE", 2559 | "members": [ 2560 | { 2561 | "type": "IMMEDIATE_TOKEN", 2562 | "content": { 2563 | "type": "PREC", 2564 | "value": 1, 2565 | "content": { 2566 | "type": "PATTERN", 2567 | "value": "[^\\\\'\\n]+" 2568 | } 2569 | } 2570 | }, 2571 | { 2572 | "type": "SYMBOL", 2573 | "name": "escape_sequence" 2574 | } 2575 | ] 2576 | } 2577 | }, 2578 | "escape_sequence": { 2579 | "type": "IMMEDIATE_TOKEN", 2580 | "content": { 2581 | "type": "SEQ", 2582 | "members": [ 2583 | { 2584 | "type": "STRING", 2585 | "value": "\\" 2586 | }, 2587 | { 2588 | "type": "PATTERN", 2589 | "value": "(\\\"|\\\\|\\/|b|f|n|r|t|u)" 2590 | } 2591 | ] 2592 | } 2593 | } 2594 | }, 2595 | "extras": [ 2596 | { 2597 | "type": "PATTERN", 2598 | "value": "\\s" 2599 | }, 2600 | { 2601 | "type": "SYMBOL", 2602 | "name": "comment" 2603 | } 2604 | ], 2605 | "conflicts": [], 2606 | "precedences": [], 2607 | "externals": [ 2608 | { 2609 | "type": "SYMBOL", 2610 | "name": "_string_start" 2611 | }, 2612 | { 2613 | "type": "SYMBOL", 2614 | "name": "_string_content" 2615 | }, 2616 | { 2617 | "type": "SYMBOL", 2618 | "name": "_string_end" 2619 | } 2620 | ], 2621 | "inline": [ 2622 | "h", 2623 | "objinside" 2624 | ], 2625 | "supertypes": [] 2626 | } 2627 | -------------------------------------------------------------------------------- /src/scanner.c: -------------------------------------------------------------------------------- 1 | // https://github.com/Azganoth/tree-sitter-lua/blob/master/src/scanner.cc 2 | // https://github.com/MunifTanjim/tree-sitter-lua/ 3 | // and now here 4 | 5 | #include 6 | #include 7 | #include "tree_sitter/parser.h" 8 | 9 | enum TokenType { 10 | STRING_START, 11 | STRING_CONTENT, 12 | STRING_END, 13 | }; 14 | 15 | static inline void consume(TSLexer *lexer) { lexer->advance(lexer, false); } 16 | static inline void skip(TSLexer *lexer) { lexer->advance(lexer, true); } 17 | 18 | static inline bool consume_char(char c, TSLexer *lexer) { 19 | if (lexer->lookahead != c) { 20 | return false; 21 | } 22 | 23 | consume(lexer); 24 | return true; 25 | } 26 | 27 | static inline uint8_t consume_and_count_char(char c, TSLexer *lexer) { 28 | uint8_t count = 0; 29 | while (lexer->lookahead == c) { 30 | ++count; 31 | consume(lexer); 32 | } 33 | return count; 34 | } 35 | 36 | static inline void skip_whitespaces(TSLexer *lexer) { 37 | while (iswspace(lexer->lookahead)) { 38 | skip(lexer); 39 | } 40 | } 41 | 42 | void *tree_sitter_jsonnet_external_scanner_create() { return NULL; } 43 | void tree_sitter_jsonnet_external_scanner_destroy(void *payload) {} 44 | 45 | enum InsideNode { INSIDE_NONE, INSIDE_STRING }; 46 | 47 | uint8_t inside_node = INSIDE_NONE; 48 | char ending_char = 0; 49 | uint8_t level_count = 0; 50 | 51 | static inline void reset_state() { 52 | inside_node = INSIDE_NONE; 53 | ending_char = 0; 54 | level_count = 0; 55 | } 56 | 57 | unsigned tree_sitter_jsonnet_external_scanner_serialize(void *payload, char *buffer) { 58 | buffer[0] = inside_node; 59 | buffer[1] = ending_char; 60 | buffer[2] = level_count; 61 | return 3; 62 | } 63 | 64 | void tree_sitter_jsonnet_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) { 65 | if (length == 0) return; 66 | inside_node = buffer[0]; 67 | if (length == 1) return; 68 | ending_char = buffer[1]; 69 | if (length == 2) return; 70 | level_count = buffer[2]; 71 | } 72 | 73 | static bool scan_block_start(TSLexer *lexer) { 74 | if (consume_char('|', lexer) && consume_char('|', lexer) && consume_char('|', lexer)) { 75 | return true; 76 | } 77 | 78 | return false; 79 | } 80 | 81 | static bool scan_block_end(TSLexer *lexer) { 82 | if (consume_char('|', lexer) && consume_char('|', lexer) && consume_char('|', lexer)) { 83 | return true; 84 | } 85 | 86 | return false; 87 | } 88 | 89 | static bool scan_block_content(TSLexer *lexer) { 90 | while (lexer->lookahead != 0) { 91 | if (lexer->lookahead == '|') { 92 | lexer->mark_end(lexer); 93 | 94 | if (scan_block_end(lexer)) { 95 | return true; 96 | } 97 | } else { 98 | consume(lexer); 99 | } 100 | } 101 | 102 | return false; 103 | } 104 | 105 | static bool scan_string_start(TSLexer *lexer) { 106 | if (lexer->lookahead == '"' || lexer->lookahead == '\'') { 107 | inside_node = INSIDE_STRING; 108 | ending_char = lexer->lookahead; 109 | consume(lexer); 110 | return true; 111 | } 112 | 113 | if (scan_block_start(lexer)) { 114 | inside_node = INSIDE_STRING; 115 | return true; 116 | } 117 | 118 | return false; 119 | } 120 | 121 | static bool scan_string_end(TSLexer *lexer) { 122 | if (ending_char == 0) { // block string 123 | return scan_block_end(lexer); 124 | } 125 | 126 | if (consume_char(ending_char, lexer)) { 127 | return true; 128 | } 129 | 130 | return false; 131 | } 132 | 133 | static bool scan_string_content(TSLexer *lexer) { 134 | if (ending_char == 0) { // block string 135 | return scan_block_content(lexer); 136 | } 137 | 138 | while (lexer->lookahead != '\n' && lexer->lookahead != 0 && lexer->lookahead != ending_char) { 139 | while (consume_char('\\', lexer) && consume_char('z', lexer)) continue; 140 | 141 | if (lexer->lookahead == 0) { 142 | return true; 143 | } 144 | 145 | consume(lexer); 146 | } 147 | 148 | return true; 149 | } 150 | 151 | bool tree_sitter_jsonnet_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) { 152 | if (inside_node == INSIDE_STRING) { 153 | if (valid_symbols[STRING_END] && scan_string_end(lexer)) { 154 | reset_state(); 155 | lexer->result_symbol = STRING_END; 156 | return true; 157 | } 158 | 159 | if (valid_symbols[STRING_CONTENT] && scan_string_content(lexer)) { 160 | lexer->result_symbol = STRING_CONTENT; 161 | return true; 162 | } 163 | 164 | return false; 165 | } 166 | 167 | skip_whitespaces(lexer); 168 | 169 | if (valid_symbols[STRING_START] && scan_string_start(lexer)) { 170 | lexer->result_symbol = STRING_START; 171 | return true; 172 | } 173 | 174 | 175 | return false; 176 | } 177 | -------------------------------------------------------------------------------- /src/tree_sitter/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ALLOC_H_ 2 | #define TREE_SITTER_ALLOC_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | // Allow clients to override allocation functions 13 | #ifdef TREE_SITTER_REUSE_ALLOCATOR 14 | 15 | extern void *(*ts_current_malloc)(size_t); 16 | extern void *(*ts_current_calloc)(size_t, size_t); 17 | extern void *(*ts_current_realloc)(void *, size_t); 18 | extern void (*ts_current_free)(void *); 19 | 20 | #ifndef ts_malloc 21 | #define ts_malloc ts_current_malloc 22 | #endif 23 | #ifndef ts_calloc 24 | #define ts_calloc ts_current_calloc 25 | #endif 26 | #ifndef ts_realloc 27 | #define ts_realloc ts_current_realloc 28 | #endif 29 | #ifndef ts_free 30 | #define ts_free ts_current_free 31 | #endif 32 | 33 | #else 34 | 35 | #ifndef ts_malloc 36 | #define ts_malloc malloc 37 | #endif 38 | #ifndef ts_calloc 39 | #define ts_calloc calloc 40 | #endif 41 | #ifndef ts_realloc 42 | #define ts_realloc realloc 43 | #endif 44 | #ifndef ts_free 45 | #define ts_free free 46 | #endif 47 | 48 | #endif 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif // TREE_SITTER_ALLOC_H_ 55 | -------------------------------------------------------------------------------- /src/tree_sitter/array.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ARRAY_H_ 2 | #define TREE_SITTER_ARRAY_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "./alloc.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef _MSC_VER 17 | #pragma warning(disable : 4101) 18 | #elif defined(__GNUC__) || defined(__clang__) 19 | #pragma GCC diagnostic push 20 | #pragma GCC diagnostic ignored "-Wunused-variable" 21 | #endif 22 | 23 | #define Array(T) \ 24 | struct { \ 25 | T *contents; \ 26 | uint32_t size; \ 27 | uint32_t capacity; \ 28 | } 29 | 30 | /// Initialize an array. 31 | #define array_init(self) \ 32 | ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) 33 | 34 | /// Create an empty array. 35 | #define array_new() \ 36 | { NULL, 0, 0 } 37 | 38 | /// Get a pointer to the element at a given `index` in the array. 39 | #define array_get(self, _index) \ 40 | (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) 41 | 42 | /// Get a pointer to the first element in the array. 43 | #define array_front(self) array_get(self, 0) 44 | 45 | /// Get a pointer to the last element in the array. 46 | #define array_back(self) array_get(self, (self)->size - 1) 47 | 48 | /// Clear the array, setting its size to zero. Note that this does not free any 49 | /// memory allocated for the array's contents. 50 | #define array_clear(self) ((self)->size = 0) 51 | 52 | /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is 53 | /// less than the array's current capacity, this function has no effect. 54 | #define array_reserve(self, new_capacity) \ 55 | _array__reserve((Array *)(self), array_elem_size(self), new_capacity) 56 | 57 | /// Free any memory allocated for this array. Note that this does not free any 58 | /// memory allocated for the array's contents. 59 | #define array_delete(self) _array__delete((Array *)(self)) 60 | 61 | /// Push a new `element` onto the end of the array. 62 | #define array_push(self, element) \ 63 | (_array__grow((Array *)(self), 1, array_elem_size(self)), \ 64 | (self)->contents[(self)->size++] = (element)) 65 | 66 | /// Increase the array's size by `count` elements. 67 | /// New elements are zero-initialized. 68 | #define array_grow_by(self, count) \ 69 | do { \ 70 | if ((count) == 0) break; \ 71 | _array__grow((Array *)(self), count, array_elem_size(self)); \ 72 | memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ 73 | (self)->size += (count); \ 74 | } while (0) 75 | 76 | /// Append all elements from one array to the end of another. 77 | #define array_push_all(self, other) \ 78 | array_extend((self), (other)->size, (other)->contents) 79 | 80 | /// Append `count` elements to the end of the array, reading their values from the 81 | /// `contents` pointer. 82 | #define array_extend(self, count, contents) \ 83 | _array__splice( \ 84 | (Array *)(self), array_elem_size(self), (self)->size, \ 85 | 0, count, contents \ 86 | ) 87 | 88 | /// Remove `old_count` elements from the array starting at the given `index`. At 89 | /// the same index, insert `new_count` new elements, reading their values from the 90 | /// `new_contents` pointer. 91 | #define array_splice(self, _index, old_count, new_count, new_contents) \ 92 | _array__splice( \ 93 | (Array *)(self), array_elem_size(self), _index, \ 94 | old_count, new_count, new_contents \ 95 | ) 96 | 97 | /// Insert one `element` into the array at the given `index`. 98 | #define array_insert(self, _index, element) \ 99 | _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element)) 100 | 101 | /// Remove one element from the array at the given `index`. 102 | #define array_erase(self, _index) \ 103 | _array__erase((Array *)(self), array_elem_size(self), _index) 104 | 105 | /// Pop the last element off the array, returning the element by value. 106 | #define array_pop(self) ((self)->contents[--(self)->size]) 107 | 108 | /// Assign the contents of one array to another, reallocating if necessary. 109 | #define array_assign(self, other) \ 110 | _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self)) 111 | 112 | /// Swap one array with another 113 | #define array_swap(self, other) \ 114 | _array__swap((Array *)(self), (Array *)(other)) 115 | 116 | /// Get the size of the array contents 117 | #define array_elem_size(self) (sizeof *(self)->contents) 118 | 119 | /// Search a sorted array for a given `needle` value, using the given `compare` 120 | /// callback to determine the order. 121 | /// 122 | /// If an existing element is found to be equal to `needle`, then the `index` 123 | /// out-parameter is set to the existing value's index, and the `exists` 124 | /// out-parameter is set to true. Otherwise, `index` is set to an index where 125 | /// `needle` should be inserted in order to preserve the sorting, and `exists` 126 | /// is set to false. 127 | #define array_search_sorted_with(self, compare, needle, _index, _exists) \ 128 | _array__search_sorted(self, 0, compare, , needle, _index, _exists) 129 | 130 | /// Search a sorted array for a given `needle` value, using integer comparisons 131 | /// of a given struct field (specified with a leading dot) to determine the order. 132 | /// 133 | /// See also `array_search_sorted_with`. 134 | #define array_search_sorted_by(self, field, needle, _index, _exists) \ 135 | _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) 136 | 137 | /// Insert a given `value` into a sorted array, using the given `compare` 138 | /// callback to determine the order. 139 | #define array_insert_sorted_with(self, compare, value) \ 140 | do { \ 141 | unsigned _index, _exists; \ 142 | array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ 143 | if (!_exists) array_insert(self, _index, value); \ 144 | } while (0) 145 | 146 | /// Insert a given `value` into a sorted array, using integer comparisons of 147 | /// a given struct field (specified with a leading dot) to determine the order. 148 | /// 149 | /// See also `array_search_sorted_by`. 150 | #define array_insert_sorted_by(self, field, value) \ 151 | do { \ 152 | unsigned _index, _exists; \ 153 | array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ 154 | if (!_exists) array_insert(self, _index, value); \ 155 | } while (0) 156 | 157 | // Private 158 | 159 | typedef Array(void) Array; 160 | 161 | /// This is not what you're looking for, see `array_delete`. 162 | static inline void _array__delete(Array *self) { 163 | if (self->contents) { 164 | ts_free(self->contents); 165 | self->contents = NULL; 166 | self->size = 0; 167 | self->capacity = 0; 168 | } 169 | } 170 | 171 | /// This is not what you're looking for, see `array_erase`. 172 | static inline void _array__erase(Array *self, size_t element_size, 173 | uint32_t index) { 174 | assert(index < self->size); 175 | char *contents = (char *)self->contents; 176 | memmove(contents + index * element_size, contents + (index + 1) * element_size, 177 | (self->size - index - 1) * element_size); 178 | self->size--; 179 | } 180 | 181 | /// This is not what you're looking for, see `array_reserve`. 182 | static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) { 183 | if (new_capacity > self->capacity) { 184 | if (self->contents) { 185 | self->contents = ts_realloc(self->contents, new_capacity * element_size); 186 | } else { 187 | self->contents = ts_malloc(new_capacity * element_size); 188 | } 189 | self->capacity = new_capacity; 190 | } 191 | } 192 | 193 | /// This is not what you're looking for, see `array_assign`. 194 | static inline void _array__assign(Array *self, const Array *other, size_t element_size) { 195 | _array__reserve(self, element_size, other->size); 196 | self->size = other->size; 197 | memcpy(self->contents, other->contents, self->size * element_size); 198 | } 199 | 200 | /// This is not what you're looking for, see `array_swap`. 201 | static inline void _array__swap(Array *self, Array *other) { 202 | Array swap = *other; 203 | *other = *self; 204 | *self = swap; 205 | } 206 | 207 | /// This is not what you're looking for, see `array_push` or `array_grow_by`. 208 | static inline void _array__grow(Array *self, uint32_t count, size_t element_size) { 209 | uint32_t new_size = self->size + count; 210 | if (new_size > self->capacity) { 211 | uint32_t new_capacity = self->capacity * 2; 212 | if (new_capacity < 8) new_capacity = 8; 213 | if (new_capacity < new_size) new_capacity = new_size; 214 | _array__reserve(self, element_size, new_capacity); 215 | } 216 | } 217 | 218 | /// This is not what you're looking for, see `array_splice`. 219 | static inline void _array__splice(Array *self, size_t element_size, 220 | uint32_t index, uint32_t old_count, 221 | uint32_t new_count, const void *elements) { 222 | uint32_t new_size = self->size + new_count - old_count; 223 | uint32_t old_end = index + old_count; 224 | uint32_t new_end = index + new_count; 225 | assert(old_end <= self->size); 226 | 227 | _array__reserve(self, element_size, new_size); 228 | 229 | char *contents = (char *)self->contents; 230 | if (self->size > old_end) { 231 | memmove( 232 | contents + new_end * element_size, 233 | contents + old_end * element_size, 234 | (self->size - old_end) * element_size 235 | ); 236 | } 237 | if (new_count > 0) { 238 | if (elements) { 239 | memcpy( 240 | (contents + index * element_size), 241 | elements, 242 | new_count * element_size 243 | ); 244 | } else { 245 | memset( 246 | (contents + index * element_size), 247 | 0, 248 | new_count * element_size 249 | ); 250 | } 251 | } 252 | self->size += new_count - old_count; 253 | } 254 | 255 | /// A binary search routine, based on Rust's `std::slice::binary_search_by`. 256 | /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. 257 | #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ 258 | do { \ 259 | *(_index) = start; \ 260 | *(_exists) = false; \ 261 | uint32_t size = (self)->size - *(_index); \ 262 | if (size == 0) break; \ 263 | int comparison; \ 264 | while (size > 1) { \ 265 | uint32_t half_size = size / 2; \ 266 | uint32_t mid_index = *(_index) + half_size; \ 267 | comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ 268 | if (comparison <= 0) *(_index) = mid_index; \ 269 | size -= half_size; \ 270 | } \ 271 | comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ 272 | if (comparison == 0) *(_exists) = true; \ 273 | else if (comparison < 0) *(_index) += 1; \ 274 | } while (0) 275 | 276 | /// Helper macro for the `_sorted_by` routines below. This takes the left (existing) 277 | /// parameter by reference in order to work with the generic sorting function above. 278 | #define _compare_int(a, b) ((int)*(a) - (int)(b)) 279 | 280 | #ifdef _MSC_VER 281 | #pragma warning(default : 4101) 282 | #elif defined(__GNUC__) || defined(__clang__) 283 | #pragma GCC diagnostic pop 284 | #endif 285 | 286 | #ifdef __cplusplus 287 | } 288 | #endif 289 | 290 | #endif // TREE_SITTER_ARRAY_H_ 291 | -------------------------------------------------------------------------------- /src/tree_sitter/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_PARSER_H_ 2 | #define TREE_SITTER_PARSER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define ts_builtin_sym_error ((TSSymbol)-1) 13 | #define ts_builtin_sym_end 0 14 | #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 15 | 16 | #ifndef TREE_SITTER_API_H_ 17 | typedef uint16_t TSStateId; 18 | typedef uint16_t TSSymbol; 19 | typedef uint16_t TSFieldId; 20 | typedef struct TSLanguage TSLanguage; 21 | #endif 22 | 23 | typedef struct { 24 | TSFieldId field_id; 25 | uint8_t child_index; 26 | bool inherited; 27 | } TSFieldMapEntry; 28 | 29 | typedef struct { 30 | uint16_t index; 31 | uint16_t length; 32 | } TSFieldMapSlice; 33 | 34 | typedef struct { 35 | bool visible; 36 | bool named; 37 | bool supertype; 38 | } TSSymbolMetadata; 39 | 40 | typedef struct TSLexer TSLexer; 41 | 42 | struct TSLexer { 43 | int32_t lookahead; 44 | TSSymbol result_symbol; 45 | void (*advance)(TSLexer *, bool); 46 | void (*mark_end)(TSLexer *); 47 | uint32_t (*get_column)(TSLexer *); 48 | bool (*is_at_included_range_start)(const TSLexer *); 49 | bool (*eof)(const TSLexer *); 50 | }; 51 | 52 | typedef enum { 53 | TSParseActionTypeShift, 54 | TSParseActionTypeReduce, 55 | TSParseActionTypeAccept, 56 | TSParseActionTypeRecover, 57 | } TSParseActionType; 58 | 59 | typedef union { 60 | struct { 61 | uint8_t type; 62 | TSStateId state; 63 | bool extra; 64 | bool repetition; 65 | } shift; 66 | struct { 67 | uint8_t type; 68 | uint8_t child_count; 69 | TSSymbol symbol; 70 | int16_t dynamic_precedence; 71 | uint16_t production_id; 72 | } reduce; 73 | uint8_t type; 74 | } TSParseAction; 75 | 76 | typedef struct { 77 | uint16_t lex_state; 78 | uint16_t external_lex_state; 79 | } TSLexMode; 80 | 81 | typedef union { 82 | TSParseAction action; 83 | struct { 84 | uint8_t count; 85 | bool reusable; 86 | } entry; 87 | } TSParseActionEntry; 88 | 89 | typedef struct { 90 | int32_t start; 91 | int32_t end; 92 | } TSCharacterRange; 93 | 94 | struct TSLanguage { 95 | uint32_t version; 96 | uint32_t symbol_count; 97 | uint32_t alias_count; 98 | uint32_t token_count; 99 | uint32_t external_token_count; 100 | uint32_t state_count; 101 | uint32_t large_state_count; 102 | uint32_t production_id_count; 103 | uint32_t field_count; 104 | uint16_t max_alias_sequence_length; 105 | const uint16_t *parse_table; 106 | const uint16_t *small_parse_table; 107 | const uint32_t *small_parse_table_map; 108 | const TSParseActionEntry *parse_actions; 109 | const char * const *symbol_names; 110 | const char * const *field_names; 111 | const TSFieldMapSlice *field_map_slices; 112 | const TSFieldMapEntry *field_map_entries; 113 | const TSSymbolMetadata *symbol_metadata; 114 | const TSSymbol *public_symbol_map; 115 | const uint16_t *alias_map; 116 | const TSSymbol *alias_sequences; 117 | const TSLexMode *lex_modes; 118 | bool (*lex_fn)(TSLexer *, TSStateId); 119 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 120 | TSSymbol keyword_capture_token; 121 | struct { 122 | const bool *states; 123 | const TSSymbol *symbol_map; 124 | void *(*create)(void); 125 | void (*destroy)(void *); 126 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 127 | unsigned (*serialize)(void *, char *); 128 | void (*deserialize)(void *, const char *, unsigned); 129 | } external_scanner; 130 | const TSStateId *primary_state_ids; 131 | }; 132 | 133 | static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { 134 | uint32_t index = 0; 135 | uint32_t size = len - index; 136 | while (size > 1) { 137 | uint32_t half_size = size / 2; 138 | uint32_t mid_index = index + half_size; 139 | TSCharacterRange *range = &ranges[mid_index]; 140 | if (lookahead >= range->start && lookahead <= range->end) { 141 | return true; 142 | } else if (lookahead > range->end) { 143 | index = mid_index; 144 | } 145 | size -= half_size; 146 | } 147 | TSCharacterRange *range = &ranges[index]; 148 | return (lookahead >= range->start && lookahead <= range->end); 149 | } 150 | 151 | /* 152 | * Lexer Macros 153 | */ 154 | 155 | #ifdef _MSC_VER 156 | #define UNUSED __pragma(warning(suppress : 4101)) 157 | #else 158 | #define UNUSED __attribute__((unused)) 159 | #endif 160 | 161 | #define START_LEXER() \ 162 | bool result = false; \ 163 | bool skip = false; \ 164 | UNUSED \ 165 | bool eof = false; \ 166 | int32_t lookahead; \ 167 | goto start; \ 168 | next_state: \ 169 | lexer->advance(lexer, skip); \ 170 | start: \ 171 | skip = false; \ 172 | lookahead = lexer->lookahead; 173 | 174 | #define ADVANCE(state_value) \ 175 | { \ 176 | state = state_value; \ 177 | goto next_state; \ 178 | } 179 | 180 | #define ADVANCE_MAP(...) \ 181 | { \ 182 | static const uint16_t map[] = { __VA_ARGS__ }; \ 183 | for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ 184 | if (map[i] == lookahead) { \ 185 | state = map[i + 1]; \ 186 | goto next_state; \ 187 | } \ 188 | } \ 189 | } 190 | 191 | #define SKIP(state_value) \ 192 | { \ 193 | skip = true; \ 194 | state = state_value; \ 195 | goto next_state; \ 196 | } 197 | 198 | #define ACCEPT_TOKEN(symbol_value) \ 199 | result = true; \ 200 | lexer->result_symbol = symbol_value; \ 201 | lexer->mark_end(lexer); 202 | 203 | #define END_STATE() return result; 204 | 205 | /* 206 | * Parse Table Macros 207 | */ 208 | 209 | #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) 210 | 211 | #define STATE(id) id 212 | 213 | #define ACTIONS(id) id 214 | 215 | #define SHIFT(state_value) \ 216 | {{ \ 217 | .shift = { \ 218 | .type = TSParseActionTypeShift, \ 219 | .state = (state_value) \ 220 | } \ 221 | }} 222 | 223 | #define SHIFT_REPEAT(state_value) \ 224 | {{ \ 225 | .shift = { \ 226 | .type = TSParseActionTypeShift, \ 227 | .state = (state_value), \ 228 | .repetition = true \ 229 | } \ 230 | }} 231 | 232 | #define SHIFT_EXTRA() \ 233 | {{ \ 234 | .shift = { \ 235 | .type = TSParseActionTypeShift, \ 236 | .extra = true \ 237 | } \ 238 | }} 239 | 240 | #define REDUCE(symbol_name, children, precedence, prod_id) \ 241 | {{ \ 242 | .reduce = { \ 243 | .type = TSParseActionTypeReduce, \ 244 | .symbol = symbol_name, \ 245 | .child_count = children, \ 246 | .dynamic_precedence = precedence, \ 247 | .production_id = prod_id \ 248 | }, \ 249 | }} 250 | 251 | #define RECOVER() \ 252 | {{ \ 253 | .type = TSParseActionTypeRecover \ 254 | }} 255 | 256 | #define ACCEPT_INPUT() \ 257 | {{ \ 258 | .type = TSParseActionTypeAccept \ 259 | }} 260 | 261 | #ifdef __cplusplus 262 | } 263 | #endif 264 | 265 | #endif // TREE_SITTER_PARSER_H_ 266 | -------------------------------------------------------------------------------- /test/corpus/assert.txt: -------------------------------------------------------------------------------- 1 | === 2 | Assert at root 3 | === 4 | 5 | assert true : 'message'; 6 | {} 7 | 8 | --- 9 | 10 | (document 11 | (assert 12 | (true) 13 | (string 14 | (string_start) 15 | (string_content) 16 | (string_end))) 17 | (object)) 18 | === 19 | Assert in object 20 | === 21 | 22 | { 23 | assert true : 'message' 24 | } 25 | 26 | --- 27 | 28 | (document 29 | (object 30 | (member 31 | (assert 32 | (true) 33 | (string 34 | (string_start) 35 | (string_content) 36 | (string_end)))))) 37 | -------------------------------------------------------------------------------- /test/corpus/exprs.txt: -------------------------------------------------------------------------------- 1 | ====================== 2 | Indexing priority 3 | ====================== 4 | 5 | "Hello" + xxx.name 6 | 7 | --- 8 | 9 | (document 10 | (binary 11 | left: (string (string_start) (string_content) (string_end)) 12 | operator: (additive) 13 | right: (fieldaccess (id) last: (id)) 14 | )) 15 | 16 | ====================== 17 | Indexing priority 2 18 | ====================== 19 | 20 | "Hello" + xxx[name] 21 | 22 | --- 23 | 24 | (document 25 | (binary 26 | left: (string (string_start) (string_content) (string_end)) 27 | operator: (additive) 28 | right: (indexing (id) (id)) 29 | )) 30 | 31 | ====================== 32 | Indexing priority 3 33 | ====================== 34 | 35 | "Hello" + super.name 36 | 37 | --- 38 | 39 | (document 40 | (binary 41 | left: (string (string_start) (string_content) (string_end)) 42 | operator: (additive) 43 | right: (fieldaccess_super (super) (id)) 44 | )) 45 | 46 | ====================== 47 | Indexing priority 4 48 | ====================== 49 | 50 | "Hello" + super['name'] 51 | 52 | --- 53 | 54 | (document 55 | (binary 56 | left: (string (string_start) (string_content) (string_end)) 57 | operator: (additive) 58 | right: (indexing_super 59 | (super) 60 | (string 61 | (string_start) 62 | (string_content) 63 | (string_end))) 64 | )) 65 | 66 | ====================== 67 | Parses example 2 68 | ====================== 69 | 70 | { 71 | person1: { 72 | name: "Alice", 73 | welcome: "Hello " + self.name + "!", 74 | }, 75 | person2: self.person1 { name: "Bob" }, 76 | } 77 | 78 | --- 79 | (document 80 | (object 81 | (member 82 | (field (fieldname (id)) 83 | (object 84 | (member 85 | (field (fieldname (id)) 86 | (string (string_start) (string_content) (string_end)) 87 | )) 88 | (member 89 | (field (fieldname (id)) 90 | (binary 91 | left: 92 | (binary 93 | left: (string (string_start) (string_content) (string_end)) 94 | operator: (additive) 95 | right: (fieldaccess (self) last: (id))) 96 | operator: (additive) 97 | right: (string (string_start) (string_content) (string_end)) 98 | ))) 99 | ))) 100 | (member 101 | (field (fieldname (id)) 102 | (implicit_plus 103 | (fieldaccess (self) last: (id)) 104 | (object 105 | (member 106 | (field (fieldname (id)) 107 | (string (string_start) (string_content) (string_end)) 108 | )))))))) 109 | 110 | ================================= 111 | should parse basic call foo(1,2) 112 | ================================= 113 | 114 | { 115 | x1: foo(1,2) 116 | } 117 | 118 | --- 119 | 120 | (document 121 | (object 122 | (member (field (fieldname (id)) 123 | (functioncall 124 | (id) 125 | (args (number) 126 | (number))) 127 | )))) 128 | 129 | ================================= 130 | should parse basic call foo(1,2,3) 131 | ================================= 132 | 133 | { 134 | x1: foo(1,2,3) 135 | } 136 | 137 | --- 138 | 139 | (document 140 | (object 141 | (member (field (fieldname (id)) 142 | (functioncall 143 | (id) 144 | (args (number) 145 | (number) 146 | (number))) 147 | )))) 148 | 149 | ================================= 150 | should parse tailstrict 151 | ================================= 152 | 153 | { 154 | x1: foo(1,2,3) tailstrict 155 | } 156 | 157 | --- 158 | 159 | (document 160 | (object 161 | (member (field (fieldname (id)) 162 | (functioncall 163 | (id) 164 | (args (number) 165 | (number) 166 | (number)) 167 | (tailstrict)) 168 | )))) 169 | 170 | ================================= 171 | should parse if-then-else 172 | ================================= 173 | 174 | if x > 0 then x + 2 else x - 2 175 | 176 | --- 177 | (document 178 | (conditional 179 | condition: 180 | (binary 181 | left: (id) 182 | operator: (comparison) 183 | right: (number)) 184 | consequence: 185 | (binary 186 | left: (id) 187 | operator: (additive) 188 | right: (number)) 189 | alternative: 190 | (binary 191 | left: (id) 192 | operator: (additive) 193 | right: (number)))) 194 | 195 | ================================= 196 | if-then-else vs local priority 197 | ================================= 198 | 199 | local a = if x > 0 then x + 2 else x - 2; a + 2 200 | 201 | --- 202 | (document 203 | (local_bind 204 | (local) 205 | (bind (id) 206 | (conditional 207 | condition: 208 | (binary 209 | left: (id) 210 | operator: (comparison) 211 | right: (number)) 212 | consequence: 213 | (binary 214 | left: (id) 215 | operator: (additive) 216 | right: (number)) 217 | alternative: 218 | (binary 219 | left: (id) 220 | operator: (additive) 221 | right: (number)) 222 | )) 223 | (binary 224 | left: (id) 225 | operator: (additive) 226 | right: (number)))) 227 | 228 | ================================= 229 | operator precedence 230 | ================================= 231 | 3 + 4 * true 232 | 233 | --- 234 | 235 | (document 236 | (binary 237 | left: (number) 238 | operator: (additive) 239 | right: 240 | (binary 241 | left: (number) 242 | operator: (multiplicative) 243 | right: (true)))) 244 | 245 | ====================== 246 | Application priority 247 | ====================== 248 | 249 | !foo(2, 3) 250 | 251 | --- 252 | (document 253 | (unary 254 | operator: (unaryop) 255 | argument: (functioncall 256 | (id) 257 | (args (number) (number))))) 258 | 259 | ====================== 260 | Implicit plus with empty object 261 | ====================== 262 | 263 | ({}) { } 264 | 265 | --- 266 | 267 | (document 268 | (implicit_plus 269 | (parenthesis (object)) 270 | (object))) 271 | -------------------------------------------------------------------------------- /test/corpus/fieldname.txt: -------------------------------------------------------------------------------- 1 | =============================== 2 | Resolve expr in fieldname key 1 3 | =============================== 4 | 5 | local a = 'a'; 6 | { [a]: 'a' } 7 | 8 | --- 9 | 10 | (document 11 | (local_bind 12 | (local) 13 | (bind 14 | (id) 15 | (string 16 | (string_start) 17 | (string_content) 18 | (string_end))) 19 | (object 20 | (member 21 | (field 22 | (fieldname (id)) 23 | (string 24 | (string_start) 25 | (string_content) 26 | (string_end))))))) 27 | 28 | =============================== 29 | Resolve expr in fieldname key 2 30 | =============================== 31 | 32 | local prefix = 'Happy Hour '; 33 | { 34 | [prefix + 'Mimosa']: 'Champagne', 35 | } 36 | 37 | --- 38 | 39 | (document 40 | (local_bind 41 | (local) 42 | (bind 43 | (id) 44 | (string 45 | (string_start) 46 | (string_content) 47 | (string_end))) 48 | (object 49 | (member 50 | (field 51 | (fieldname 52 | (binary 53 | (id) 54 | (additive) 55 | (string 56 | (string_start) 57 | (string_content) 58 | (string_end)))) 59 | (string 60 | (string_start) 61 | (string_content) 62 | (string_end))))))) 63 | 64 | =============================== 65 | Resolve expr in fieldname key 3 66 | =============================== 67 | 68 | local Margarita(salted) = { 69 | [if salted then 'garnish']: 'Salt', 70 | ingredients: [ 71 | { kind: 'Tequila Blanco', qty: 2 }, 72 | ], 73 | }; 74 | { 75 | Margarita: Margarita(true), 76 | 'Margarita Unsalted': Margarita(false), 77 | } 78 | 79 | --- 80 | 81 | (document 82 | (local_bind 83 | (local) 84 | (bind 85 | function: (id) 86 | params: 87 | (params 88 | (param 89 | identifier: (id))) 90 | body: (object 91 | (member 92 | (field 93 | (fieldname 94 | (conditional 95 | condition: (id) 96 | consequence: 97 | (string 98 | (string_start) 99 | (string_content) 100 | (string_end)))) 101 | (string 102 | (string_start) 103 | (string_content) 104 | (string_end)))) 105 | (member 106 | (field 107 | (fieldname (id)) 108 | (array 109 | (object 110 | (member 111 | (field 112 | (fieldname (id)) 113 | (string 114 | (string_start) 115 | (string_content) 116 | (string_end)))) 117 | (member 118 | (field 119 | (fieldname (id)) 120 | (number))))))))) 121 | (object 122 | (member 123 | (field 124 | (fieldname (id)) 125 | (functioncall 126 | (id) 127 | (args (true))))) 128 | (member 129 | (field 130 | (fieldname 131 | (string 132 | (string_start) 133 | (string_content) 134 | (string_end))) 135 | (functioncall 136 | (id) 137 | (args (false)))))))) 138 | -------------------------------------------------------------------------------- /test/corpus/forloop.txt: -------------------------------------------------------------------------------- 1 | ====================== 2 | For loop in array 3 | ====================== 4 | 5 | [ 6 | i 7 | for i in std.range(0,10) 8 | ] 9 | 10 | --- 11 | 12 | (document 13 | (forloop 14 | (id) 15 | (forspec 16 | (id) 17 | (functioncall 18 | (fieldaccess (id) last: (id)) 19 | (args (number) (number)))))) 20 | 21 | ====================== 22 | For loop in object 23 | ====================== 24 | 25 | { 26 | ['item' + i]: i 27 | for i in std.range(0,10) 28 | } 29 | 30 | --- 31 | 32 | (document 33 | (object 34 | (objforloop 35 | (field 36 | (fieldname 37 | (binary 38 | left: 39 | (string 40 | (string_start) 41 | (string_content) 42 | (string_end)) 43 | operator: (additive) 44 | right: (id))) 45 | (id)) 46 | (forspec 47 | (id) 48 | (functioncall 49 | (fieldaccess (id) last: (id)) 50 | (args (number) (number))))))) 51 | 52 | ================================ 53 | For loop in object with function 54 | ================================ 55 | 56 | { 57 | ['item' + i](v): i + v 58 | for i in std.range(0,10) 59 | } 60 | 61 | --- 62 | 63 | (document 64 | (object 65 | (objforloop 66 | (field 67 | function: (fieldname 68 | (binary 69 | left: (string 70 | (string_start) 71 | (string_content) 72 | (string_end)) 73 | operator: (additive) 74 | right: (id))) 75 | (params 76 | (param 77 | identifier: (id))) 78 | (binary 79 | left: (id) 80 | operator: (additive) 81 | right: (id))) 82 | (forspec 83 | (id) 84 | (functioncall 85 | (fieldaccess (id) last: (id)) 86 | (args (number) (number))))))) 87 | -------------------------------------------------------------------------------- /test/corpus/inoperator.txt: -------------------------------------------------------------------------------- 1 | ====================== 2 | In operator on object 3 | ====================== 4 | 5 | local obj = { a: null }; 6 | 'a' in obj 7 | 8 | --- 9 | 10 | (document 11 | (local_bind 12 | (local) 13 | (bind 14 | (id) 15 | (object 16 | (member 17 | (field 18 | (fieldname (id)) 19 | (null))))) 20 | (binary 21 | (string 22 | (string_start) 23 | (string_content) 24 | (string_end)) 25 | (comparison) 26 | (id)))) 27 | 28 | ====================== 29 | In operator on super 30 | ====================== 31 | 32 | local obj = { a: null }; 33 | obj + { b: 'a' in super } 34 | 35 | --- 36 | 37 | (document 38 | (local_bind 39 | (local) 40 | (bind 41 | (id) 42 | (object 43 | (member 44 | (field 45 | (fieldname (id)) 46 | (null))))) 47 | (binary 48 | (id) 49 | (additive) 50 | (object 51 | (member 52 | (field 53 | (fieldname (id)) 54 | (in_super 55 | (string 56 | (string_start) 57 | (string_content) 58 | (string_end)) 59 | (super)))))))) 60 | -------------------------------------------------------------------------------- /test/corpus/number.txt: -------------------------------------------------------------------------------- 1 | ====================== 2 | should parse literal 0 3 | ====================== 4 | 5 | 0 6 | 7 | --- 8 | 9 | (document 10 | (number)) 11 | 12 | ====================== 13 | should parse literal 1 14 | ====================== 15 | 16 | 1 17 | 18 | --- 19 | 20 | (document 21 | (number)) 22 | 23 | ========================= 24 | should parse literal 3.14 25 | ========================= 26 | 27 | 3.14 28 | 29 | --- 30 | 31 | (document 32 | (number)) 33 | 34 | ============================ 35 | should parse literal 1.23e10 36 | ============================ 37 | 38 | 1.23e10 39 | 40 | --- 41 | 42 | (document 43 | (number)) 44 | -------------------------------------------------------------------------------- /test/corpus/objlocal.txt: -------------------------------------------------------------------------------- 1 | ====================== 2 | Parses example 1 3 | ====================== 4 | 5 | 6 | local Mojito(virgin=false, large=false) = { 7 | // A local next to fields ends with ','. 8 | local factor = if large then 2 else 1, 9 | // The ingredients are split into 3 arrays, 10 | // the middle one is either length 1 or 0. 11 | ingredients: [], 12 | }; 13 | 14 | { 15 | Mojito: Mojito(), 16 | } 17 | 18 | --- 19 | 20 | 21 | (document 22 | (local_bind 23 | (local) 24 | (bind 25 | function: (id) 26 | params: (params 27 | (param 28 | identifier: (id) 29 | value: (false)) 30 | (param 31 | identifier: (id) 32 | value: (false))) 33 | body: (object 34 | (comment) 35 | (member 36 | (objlocal 37 | (local) 38 | (bind 39 | (id) 40 | (conditional 41 | condition: (id) 42 | consequence: (number) 43 | alternative: (number))))) 44 | (comment) 45 | (comment) 46 | (member 47 | (field 48 | (fieldname (id)) 49 | (array))))) 50 | (object 51 | (member 52 | (field 53 | (fieldname (id)) 54 | (functioncall 55 | (id))))))) 56 | --------------------------------------------------------------------------------