├── queries ├── injections.scm ├── folds.scm ├── indents.scm ├── locals.scm └── highlights.scm ├── .npmignore ├── envrc.EXAMPLE ├── neovim-ts.png ├── .gitignore ├── .gitattributes ├── test └── corpus │ ├── toplevel.txt │ ├── package.txt │ ├── literals.txt │ ├── identifier.txt │ ├── bytes.txt │ ├── attributes.txt │ ├── comprehensions.txt │ ├── lists.txt │ ├── aliases.txt │ ├── strings.txt │ ├── numbers.txt │ ├── structs.txt │ └── expressions.txt ├── bindings ├── swift │ └── cue.h ├── node │ ├── index.js │ └── binding.cc └── rust │ ├── build.rs │ ├── README.md │ └── lib.rs ├── .github └── workflows │ ├── lint.yml │ ├── fuzz.yml │ └── ci.yml ├── script ├── known_failures.txt └── parse-examples ├── binding.gyp ├── .eslintrc.js ├── Cargo.toml ├── flake.nix ├── tree-sitter.json ├── README.md ├── package.json ├── LICENSE ├── src ├── tree_sitter │ ├── alloc.h │ ├── parser.h │ └── array.h ├── scanner.c └── node-types.json ├── Package.swift ├── flake.lock └── grammar.js /queries/injections.scm: -------------------------------------------------------------------------------- 1 | (comment) @comment 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | build 2 | examples 3 | script 4 | target 5 | test 6 | -------------------------------------------------------------------------------- /envrc.EXAMPLE: -------------------------------------------------------------------------------- 1 | use flake 2 | export PATH=$PATH:./node_modules/.bin 3 | -------------------------------------------------------------------------------- /neovim-ts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eonpatapon/tree-sitter-cue/HEAD/neovim-ts.png -------------------------------------------------------------------------------- /queries/folds.scm: -------------------------------------------------------------------------------- 1 | [ 2 | (import_spec_list) 3 | (field) 4 | (string) 5 | ] @fold 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | package-lock.json 3 | /build 4 | /node_modules 5 | /examples/*/ 6 | /target 7 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | /src/** linguist-vendored 2 | /examples/* linguist-vendored 3 | 4 | src/grammar.json -diff 5 | src/node-types.json -diff 6 | src/parser.c -diff 7 | -------------------------------------------------------------------------------- /test/corpus/toplevel.txt: -------------------------------------------------------------------------------- 1 | === 2 | literal 3 | === 4 | 5 | package foo 6 | 7 | "Hello world!" 8 | 9 | --- 10 | 11 | (source_file 12 | (package_clause 13 | (package_identifier)) 14 | (string)) 15 | -------------------------------------------------------------------------------- /bindings/swift/cue.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_CUE_H_ 2 | #define TREE_SITTER_CUE_H_ 3 | 4 | typedef struct TSLanguage TSLanguage; 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | extern TSLanguage *tree_sitter_cue(); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif // TREE_SITTER_CUE_H_ 17 | -------------------------------------------------------------------------------- /queries/indents.scm: -------------------------------------------------------------------------------- 1 | [ 2 | (import_spec_list) 3 | (field) 4 | ] @indent.begin 5 | 6 | [ 7 | "}" 8 | "]" 9 | ")" 10 | ] @indent.end 11 | 12 | [ "{" "}" ] @indent.branch 13 | 14 | [ "[" "]" ] @indent.branch 15 | 16 | [ "(" ")" ] @indent.branch 17 | 18 | [ 19 | (ERROR) 20 | (comment) 21 | ] @indent.auto 22 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - "**" 10 | 11 | jobs: 12 | lint: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: Install modules 17 | run: npm install 18 | - name: Run ESLint 19 | run: npm run lint 20 | -------------------------------------------------------------------------------- /script/known_failures.txt: -------------------------------------------------------------------------------- 1 | examples/cue/cue/load/testdata/testmod/tagsbad/prod.cue 2 | examples/cue/cue/load/testdata/testmod/tagsbad/stage.cue 3 | examples/cue/cue/parser/testdata/corpus/+commas.cue 4 | examples/cue/cue/parser/testdata/corpus/+comp.cue 5 | examples/cue/cue/scanner/testdata/corpus/+basic.cue 6 | examples/cue/cue/scanner/testdata/corpus/+comments.cue 7 | examples/cue/cue/scanner/testdata/corpus/+tokens.cue 8 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_cue_binding", 5 | "include_dirs": [ 6 | "", 7 | "Amaan Qureshi ", 8 | ] 9 | license = "MIT" 10 | readme = "bindings/rust/README.md" 11 | keywords = ["incremental", "parsing", "cue"] 12 | categories = ["parsing", "text-editors"] 13 | repository = "https://github.com/eonpatapon/tree-sitter-cue" 14 | edition = "2021" 15 | autoexamples = false 16 | 17 | build = "bindings/rust/build.rs" 18 | include = ["bindings/rust/*", "grammar.js", "queries/*", "src/*"] 19 | 20 | [lib] 21 | path = "bindings/rust/lib.rs" 22 | 23 | [dependencies] 24 | tree-sitter = "~0.20.3" 25 | 26 | [build-dependencies] 27 | cc = "1.0" 28 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - "**" 10 | 11 | jobs: 12 | test: 13 | runs-on: ${{ matrix.os }} 14 | strategy: 15 | fail-fast: true 16 | matrix: 17 | os: [macos-latest, ubuntu-latest] 18 | steps: 19 | - uses: actions/checkout@v3 20 | - uses: actions/setup-node@v2 21 | with: 22 | node-version: 22 23 | - run: npm install 24 | - run: npm test 25 | 26 | test_windows: 27 | runs-on: windows-2019 28 | steps: 29 | - uses: actions/checkout@v3 30 | - uses: actions/setup-node@v2 31 | with: 32 | node-version: 22 33 | - run: npm install 34 | - run: npm run-script test-windows 35 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:nixos/nixpkgs?ref=nixpkgs-unstable"; 4 | utils.url = "github:numtide/flake-utils"; 5 | }; 6 | 7 | outputs = { utils, nixpkgs, ... }: 8 | let 9 | pkgs = nixpkgs.legacyPackages.x86_64-linux; 10 | mkGrammar = pkgs.callPackage 11 | (pkgs.path + "/pkgs/development/tools/parsing/tree-sitter/grammar.nix") 12 | { }; 13 | in utils.lib.eachDefaultSystem (system: { 14 | 15 | packages.default = mkGrammar { 16 | language = "tree-sitter-cue"; 17 | version = "0.0.1"; 18 | src = ./.; 19 | }; 20 | 21 | devShell = pkgs.mkShell { 22 | buildInputs = [ 23 | pkgs.nodejs 24 | pkgs.bc 25 | pkgs.tree-sitter 26 | pkgs.python3 27 | ]; 28 | }; 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /test/corpus/attributes.txt: -------------------------------------------------------------------------------- 1 | === 2 | build 3 | === 4 | 5 | @if(foo) 6 | 7 | package foo 8 | 9 | --- 10 | 11 | (source_file 12 | (attribute (identifier) (identifier)) 13 | (package_clause (package_identifier))) 14 | 15 | 16 | === 17 | data 18 | === 19 | 20 | a: string @tag(type=bool,short=foo|bar) 21 | b: { 22 | @foo(bar) 23 | c: 1 24 | } 25 | 26 | --- 27 | 28 | (source_file 29 | (field 30 | (label 31 | (identifier)) 32 | (value 33 | (primitive_type)) 34 | (attribute 35 | (identifier) 36 | (identifier) 37 | (primitive_type) 38 | (identifier) 39 | (identifier) 40 | (identifier))) 41 | (field 42 | (label 43 | (identifier)) 44 | (value 45 | (struct_lit 46 | (attribute 47 | (identifier) 48 | (identifier)) 49 | (field 50 | (label 51 | (identifier)) 52 | (value 53 | (number))))))) 54 | -------------------------------------------------------------------------------- /tree-sitter.json: -------------------------------------------------------------------------------- 1 | { 2 | "grammars": [ 3 | { 4 | "name": "cue", 5 | "camelcase": "cue", 6 | "scope": "source.cue", 7 | "path": ".", 8 | "file-types": [ 9 | "cue" 10 | ], 11 | "highlights": [ 12 | "queries/highlights.scm" 13 | ], 14 | "injection-regex": "^(cue)$" 15 | } 16 | ], 17 | "metadata": { 18 | "version": "0.0.1", 19 | "license": "MIT", 20 | "description": "Cue grammar for tree-sitter", 21 | "authors": [ 22 | { 23 | "name": "Jean-Philippe Braun", 24 | "email": "eon@patapon.info" 25 | } 26 | ], 27 | "links": { 28 | "repository": "https://github.com/eonpatapon/tree-sitter-cue" 29 | } 30 | }, 31 | "bindings": { 32 | "c": true, 33 | "go": true, 34 | "node": true, 35 | "python": true, 36 | "rust": true, 37 | "swift": true 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/corpus/comprehensions.txt: -------------------------------------------------------------------------------- 1 | === 2 | struct 3 | === 4 | 5 | c: { 6 | for x in a 7 | if x < 4 8 | let y = 1 { 9 | "\(x)": x + y 10 | } 11 | } 12 | 13 | --- 14 | 15 | (source_file 16 | (field (label (identifier)) 17 | (value (struct_lit 18 | (comprehension 19 | (for_clause (identifier) (identifier)) 20 | (guard_clause (binary_expression (identifier) (number))) 21 | (let_clause (identifier) (number)) 22 | (struct_lit 23 | (field 24 | (label (string (interpolation (identifier)))) 25 | (value (binary_expression (identifier) (identifier)))))))))) 26 | 27 | === 28 | list 29 | === 30 | 31 | b: [ for x in a if x > 1 { x+1 } ] 32 | 33 | -- 34 | 35 | (source_file 36 | (field (label (identifier)) 37 | (value (list_lit 38 | (comprehension 39 | (for_clause (identifier) (identifier)) 40 | (guard_clause (binary_expression (identifier) (number))) 41 | (struct_lit (binary_expression (identifier) (number)))))))) 42 | -------------------------------------------------------------------------------- /bindings/node/binding.cc: -------------------------------------------------------------------------------- 1 | #include "nan.h" 2 | #include "tree_sitter/parser.h" 3 | #include 4 | 5 | using namespace v8; 6 | 7 | extern "C" TSLanguage *tree_sitter_cue(); 8 | 9 | namespace { 10 | 11 | NAN_METHOD(New) {} 12 | 13 | void Init(Local exports, Local module) { 14 | Local tpl = Nan::New(New); 15 | tpl->SetClassName(Nan::New("Language").ToLocalChecked()); 16 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 17 | 18 | Local constructor = Nan::GetFunction(tpl).ToLocalChecked(); 19 | Local instance = 20 | constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked(); 21 | Nan::SetInternalFieldPointer(instance, 0, tree_sitter_cue()); 22 | 23 | Nan::Set(instance, Nan::New("name").ToLocalChecked(), 24 | Nan::New("cue").ToLocalChecked()); 25 | Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance); 26 | } 27 | 28 | NODE_MODULE(tree_sitter_cue_binding, Init) 29 | 30 | } // namespace 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-cue 2 | 3 | [![Build Status](https://github.com/eonpatapon/tree-sitter-cue/actions/workflows/ci.yml/badge.svg)](https://github.com/eonpatapon/tree-sitter-cue/actions/workflows/ci.yml) 4 | [![Discord](https://img.shields.io/discord/1063097320771698699?logo=discord)](https://discord.gg/w7nTvsVJhm) 5 | 6 | [Cue][] grammar for [tree-sitter][]. 7 | 8 | ![AST and highlights in Neovim](./neovim-ts.png) 9 | 10 | ## Setup in Neovim 11 | 12 | Using [lazy.nvim](https://github.com/folke/lazy.nvim) 13 | 14 | ```lua 15 | 16 | return { 17 | "nvim-treesitter/nvim-treesitter", 18 | build = ":TSUpdate", 19 | event = { "BufReadPost", "BufNewFile" }, 20 | --- @type TSConfig 21 | opts = { 22 | ensure_installed = { 23 | "cue", 24 | }, 25 | }, 26 | ---@param opts TSConfig 27 | config = function(_, opts) 28 | require("nvim-treesitter.configs").setup(opts) 29 | end, 30 | } 31 | ``` 32 | 33 | [tree-sitter]: https://github.com/tree-sitter/tree-sitter 34 | [cue]: https://github.com/cue-lang/cue 35 | -------------------------------------------------------------------------------- /test/corpus/lists.txt: -------------------------------------------------------------------------------- 1 | === 2 | simple 3 | === 4 | 5 | l: [1] 6 | l: [ 7 | 1, 8 | ] 9 | l: [1,2,3] 10 | l: [ 11 | 1, 12 | 2, 13 | ] 14 | 15 | --- 16 | 17 | (source_file 18 | (field (label (identifier)) (value (list_lit (number)))) 19 | (field (label (identifier)) (value (list_lit (number)))) 20 | (field (label (identifier)) (value (list_lit (number) (number) (number)))) 21 | (field (label (identifier)) (value (list_lit (number) (number))))) 22 | 23 | === 24 | ellipsis 25 | === 26 | 27 | l: [ 28 | {a: "foo", b: 10}, 29 | ...{ 30 | a: string, 31 | b: int 32 | } 33 | ] 34 | 35 | --- 36 | 37 | (source_file 38 | (field (label (identifier)) (value (list_lit 39 | (struct_lit 40 | (field (label (identifier)) (value (string))) 41 | (field (label (identifier)) (value (number)))) 42 | (ellipsis) (struct_lit 43 | (field (label (identifier)) (value (primitive_type))) 44 | (field (label (identifier)) (value (primitive_type)))))))) 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-cue", 3 | "version": "0.1.0", 4 | "description": "Cue grammar for tree-sitter", 5 | "main": "bindings/node", 6 | "keywords": [ 7 | "parser", 8 | "lexer", 9 | "cue", 10 | "cuelang" 11 | ], 12 | "author": "Jean-Philippe Braun ", 13 | "contributors": [ 14 | "Amaan Qureshi " 15 | ], 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/eonpatapon/tree-sitter-cue/issues" 19 | }, 20 | "homepage": "https://github.com/eonpatapon/tree-sitter-cue#readme", 21 | "dependencies": { 22 | "nan": "^2.22.0" 23 | }, 24 | "devDependencies": { 25 | "eslint": "^8.33.0", 26 | "eslint-config-google": "^0.14.0", 27 | "tree-sitter-cli": "^0.24.6" 28 | }, 29 | "repository": "https://github.com/eonpatapon/tree-sitter-cue", 30 | "scripts": { 31 | "build": "tree-sitter generate && node-gyp build", 32 | "test": "tree-sitter test && script/parse-examples", 33 | "parse": "tree-sitter parse", 34 | "test-windows": "tree-sitter test", 35 | "lint": "eslint grammar.js" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-2021 Jean-Philippe Braun , Amaan Qureshi 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 | -------------------------------------------------------------------------------- /script/parse-examples: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu 4 | 5 | cd "$(dirname "$0")/.." 6 | 7 | function clone_repo { 8 | owner=$1 9 | name=$2 10 | sha=$3 11 | 12 | path=examples/$name 13 | if [ ! -d "$path" ]; then 14 | echo "Cloning $owner/$name" 15 | git clone "https://github.com/$owner/$name" "$path" 16 | fi 17 | 18 | pushd "$path" >/dev/null 19 | actual_sha=$(git rev-parse HEAD) 20 | if [ "$actual_sha" != "$sha" ]; then 21 | echo "Updating $owner/$name to $sha" 22 | git fetch 23 | git reset --hard "$sha" 24 | fi 25 | popd >/dev/null 26 | } 27 | 28 | clone_repo cue-lang cue 7d4d90de3798a00807f50373466322771bd0a10a 29 | 30 | known_failures="$(cat script/known_failures.txt)" 31 | 32 | # shellcheck disable=2046 33 | tree-sitter parse -q \ 34 | "examples/**/*.cue" \ 35 | $(for file in $known_failures; do echo "!${file}"; done) 36 | 37 | example_count=$(find examples -name "*.cue" | wc -l) 38 | failure_count=$(wc -w <<<"$known_failures") 39 | success_count=$((example_count - failure_count)) 40 | success_percent=$(bc -l <<<"100*${success_count}/${example_count}") 41 | 42 | printf \ 43 | "Successfully parsed %d of %d example files (%.1f%%)\n" \ 44 | "$success_count" "$example_count" "$success_percent" 45 | -------------------------------------------------------------------------------- /src/tree_sitter/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ALLOC_H_ 2 | #define TREE_SITTER_ALLOC_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | // Allow clients to override allocation functions 13 | #ifdef TREE_SITTER_REUSE_ALLOCATOR 14 | 15 | extern void *(*ts_current_malloc)(size_t size); 16 | extern void *(*ts_current_calloc)(size_t count, size_t size); 17 | extern void *(*ts_current_realloc)(void *ptr, size_t size); 18 | extern void (*ts_current_free)(void *ptr); 19 | 20 | #ifndef ts_malloc 21 | #define ts_malloc ts_current_malloc 22 | #endif 23 | #ifndef ts_calloc 24 | #define ts_calloc ts_current_calloc 25 | #endif 26 | #ifndef ts_realloc 27 | #define ts_realloc ts_current_realloc 28 | #endif 29 | #ifndef ts_free 30 | #define ts_free ts_current_free 31 | #endif 32 | 33 | #else 34 | 35 | #ifndef ts_malloc 36 | #define ts_malloc malloc 37 | #endif 38 | #ifndef ts_calloc 39 | #define ts_calloc calloc 40 | #endif 41 | #ifndef ts_realloc 42 | #define ts_realloc realloc 43 | #endif 44 | #ifndef ts_free 45 | #define ts_free free 46 | #endif 47 | 48 | #endif 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif // TREE_SITTER_ALLOC_H_ 55 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "TreeSitterCue", 6 | platforms: [.macOS(.v10_13), .iOS(.v11)], 7 | products: [ 8 | .library(name: "TreeSitterCue", targets: ["TreeSitterCue"]), 9 | ], 10 | dependencies: [], 11 | targets: [ 12 | .target(name: "TreeSitterCue", 13 | path: ".", 14 | exclude: [ 15 | "binding.gyp", 16 | "bindings", 17 | "Cargo.toml", 18 | "examples", 19 | "test", 20 | "grammar.js", 21 | "LICENSE", 22 | "package.json", 23 | "README.md", 24 | "script", 25 | "src/grammar.json", 26 | "src/node-types.json", 27 | ], 28 | sources: [ 29 | "src/parser.c", 30 | "src/scanner.c", 31 | ], 32 | resources: [ 33 | .copy("queries") 34 | ], 35 | publicHeadersPath: "bindings/swift", 36 | cSettings: [.headerSearchPath("src")]) 37 | ] 38 | ) 39 | -------------------------------------------------------------------------------- /bindings/rust/README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-cue 2 | 3 | This crate provides a Cue grammar for the [tree-sitter][] parsing library. To 4 | use this crate, add it to the `[dependencies]` section of your `Cargo.toml` 5 | file. (Note that you will probably also need to depend on the 6 | [`tree-sitter`][tree-sitter crate] crate to use the parsed result in any useful 7 | way.) 8 | 9 | ```toml 10 | [dependencies] 11 | tree-sitter = "~0.20.3" 12 | tree-sitter-cue = "0.0.1" 13 | ``` 14 | 15 | Typically, you will use the [language][language func] function to add this 16 | grammar to a tree-sitter [Parser][], and then use the parser to parse some code: 17 | 18 | ```rust 19 | let code = r#" 20 | fn double(x: i32) -> i32 { 21 | x * 2 22 | } 23 | "#; 24 | let mut parser = Parser::new(); 25 | parser.set_language(tree_sitter_cue::language()).expect("Error loading Cue grammar"); 26 | let parsed = parser.parse(code, None); 27 | ``` 28 | 29 | If you have any questions, please reach out to us in the [tree-sitter 30 | discussions] page. 31 | 32 | [language func]: https://docs.rs/tree-sitter-cue/*/tree_sitter_cue/fn.language.html 33 | [parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html 34 | [tree-sitter]: https://tree-sitter.github.io/ 35 | [tree-sitter crate]: https://crates.io/crates/tree-sitter 36 | [tree-sitter discussions]: https://github.com/tree-sitter/tree-sitter/discussions 37 | -------------------------------------------------------------------------------- /test/corpus/aliases.txt: -------------------------------------------------------------------------------- 1 | === 2 | field label 3 | === 4 | 5 | a: { 6 | F=f: string 7 | X="my-identifier": bool 8 | } 9 | 10 | --- 11 | 12 | (source_file 13 | (field (label (identifier)) (value (struct_lit 14 | (field (label (identifier) (identifier)) (value (primitive_type))) 15 | (field (label (identifier) (string)) (value (primitive_type))))))) 16 | 17 | 18 | === 19 | field value 20 | === 21 | 22 | a: X={ 23 | s: string 24 | X.b 25 | } 26 | 27 | --- 28 | 29 | (source_file 30 | (field (label (identifier)) (value (identifier) (struct_lit 31 | (field (label (identifier)) (value (primitive_type))) 32 | (selector_expression (identifier) (identifier)))))) 33 | 34 | === 35 | list elem 36 | === 37 | 38 | l: [X="a", "b"] 39 | 40 | --- 41 | 42 | (source_file 43 | (field (label (identifier)) (value 44 | (list_lit 45 | (identifier) (string) 46 | (string))))) 47 | 48 | === 49 | bracketed label 50 | === 51 | 52 | a: [X=string]: int 53 | 54 | --- 55 | 56 | (source_file (field (label (identifier)) (label (optional (identifier) (primitive_type))) (value (primitive_type)))) 57 | 58 | === 59 | let expression 60 | === 61 | 62 | let X = a * 2 63 | 64 | --- 65 | 66 | (source_file (let_clause (identifier) (binary_expression (identifier) (number)))) 67 | -------------------------------------------------------------------------------- /test/corpus/strings.txt: -------------------------------------------------------------------------------- 1 | ==== 2 | simple string 3 | ==== 4 | 5 | s1: "\n \" foo" 6 | s3: "日本語" 7 | s4: "\u65e5本\U00008a9e" 8 | s5: #"raw " '''string ""# 9 | s6: string 10 | 11 | --- 12 | 13 | (source_file 14 | (field (label (identifier)) (value (string (escape_char) (escape_char)))) 15 | (field (label (identifier)) (value (string))) 16 | (field (label (identifier)) (value (string (escape_unicode) (escape_unicode)))) 17 | (field (label (identifier)) (value (string))) 18 | (field (label (identifier)) (value (primitive_type)))) 19 | 20 | === 21 | multiline string 22 | === 23 | 24 | s1: """ 25 | Hello world! \/\/""" 26 | s2: """ 27 | Hello world 28 | \U00008a9e ! 29 | " 30 | """ 31 | s3: #""" 32 | Hello world \a foo 33 | """# 34 | 35 | --- 36 | 37 | (source_file 38 | (field (label (identifier)) (value (string))) 39 | (field (label (identifier)) (value (string))) 40 | (field (label (identifier)) (value (string)))) 41 | 42 | === 43 | string interpolation 44 | === 45 | 46 | s1: "Hello, \( name )!" 47 | s2: """ 48 | Hello "\( name )" ! 49 | """ 50 | s3: #""" 51 | Hello "\#( name )" ! 52 | \(.) 53 | """# 54 | 55 | --- 56 | 57 | (source_file 58 | (field (label (identifier)) (value (string (interpolation (identifier))))) 59 | (field (label (identifier)) (value (string (interpolation (identifier))))) 60 | (field (label (identifier)) (value (string (raw_interpolation (identifier)))))) 61 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1738422722, 6 | "narHash": "sha256-Q4vhtbLYWBUnjWD4iQb003Lt+N5PuURDad1BngGKdUs=", 7 | "owner": "nixos", 8 | "repo": "nixpkgs", 9 | "rev": "102a39bfee444533e6b4e8611d7e92aa39b7bec1", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "nixos", 14 | "ref": "nixpkgs-unstable", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs", 22 | "utils": "utils" 23 | } 24 | }, 25 | "systems": { 26 | "locked": { 27 | "lastModified": 1681028828, 28 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 29 | "owner": "nix-systems", 30 | "repo": "default", 31 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 32 | "type": "github" 33 | }, 34 | "original": { 35 | "owner": "nix-systems", 36 | "repo": "default", 37 | "type": "github" 38 | } 39 | }, 40 | "utils": { 41 | "inputs": { 42 | "systems": "systems" 43 | }, 44 | "locked": { 45 | "lastModified": 1731533236, 46 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 47 | "owner": "numtide", 48 | "repo": "flake-utils", 49 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 50 | "type": "github" 51 | }, 52 | "original": { 53 | "owner": "numtide", 54 | "repo": "flake-utils", 55 | "type": "github" 56 | } 57 | } 58 | }, 59 | "root": "root", 60 | "version": 7 61 | } 62 | -------------------------------------------------------------------------------- /test/corpus/numbers.txt: -------------------------------------------------------------------------------- 1 | === 2 | int type 3 | === 4 | 5 | i1: int 6 | i2: int16 7 | i3: float32 8 | i4: number 9 | i5: uint 10 | i6: uint16 11 | 12 | --- 13 | 14 | (source_file 15 | (field (label (identifier)) (value (primitive_type))) 16 | (field (label (identifier)) (value (primitive_type))) 17 | (field (label (identifier)) (value (primitive_type))) 18 | (field (label (identifier)) (value (primitive_type))) 19 | (field (label (identifier)) (value (primitive_type))) 20 | (field (label (identifier)) (value (primitive_type)))) 21 | 22 | === 23 | int literals 24 | === 25 | 26 | i1: 42 27 | i2: 1.5G 28 | i3: 1.3Ki 29 | i4: 170_141_183_460_469_231_731_687_303_715_884_105_727 30 | i5: 0xBad_Face 31 | i6: 0o755 32 | i7: 0b0101_0001 33 | 34 | --- 35 | 36 | (source_file 37 | (field (label (identifier)) (value (number))) 38 | (field (label (identifier)) (value (si_unit (float)))) 39 | (field (label (identifier)) (value (si_unit (float)))) 40 | (field (label (identifier)) (value (number))) 41 | (field (label (identifier)) (value (number))) 42 | (field (label (identifier)) (value (number))) 43 | (field (label (identifier)) (value (number)))) 44 | 45 | === 46 | float literals 47 | === 48 | 49 | f1: 0. 50 | f2: 72.40 51 | f3: 072.40 52 | f4: 2.71828 53 | f5: 1.e+0 54 | f6: 6.67428e-11 55 | f7: 1E6 56 | f8: .25 57 | f9: .12345E+5 58 | f10: -2.5 59 | f11: -.25 60 | 61 | --- 62 | 63 | (source_file 64 | (field (label (identifier)) (value (float))) 65 | (field (label (identifier)) (value (float))) 66 | (field (label (identifier)) (value (float))) 67 | (field (label (identifier)) (value (float))) 68 | (field (label (identifier)) (value (float))) 69 | (field (label (identifier)) (value (float))) 70 | (field (label (identifier)) (value (float))) 71 | (field (label (identifier)) (value (float))) 72 | (field (label (identifier)) (value (float))) 73 | (field (label (identifier)) (value (float))) 74 | (field (label (identifier)) (value (float)))) 75 | -------------------------------------------------------------------------------- /queries/highlights.scm: -------------------------------------------------------------------------------- 1 | ; Includes 2 | 3 | [ 4 | "package" 5 | "import" 6 | ] @include 7 | 8 | ; Namespaces 9 | 10 | (package_identifier) @namespace 11 | 12 | (import_spec ["." "_"] @punctuation.special) 13 | 14 | [ 15 | (attr_path) 16 | (package_path) 17 | ] @text.uri ;; In attributes 18 | 19 | ; Attributes 20 | 21 | (attribute) @attribute 22 | 23 | ; Conditionals 24 | 25 | "if" @conditional 26 | 27 | ; Repeats 28 | 29 | [ 30 | "for" 31 | ] @repeat 32 | 33 | (for_clause "_" @punctuation.special) 34 | 35 | ; Keywords 36 | 37 | [ 38 | "let" 39 | ] @keyword 40 | 41 | [ 42 | "in" 43 | ] @keyword.operator 44 | 45 | ; Operators 46 | 47 | [ 48 | "+" 49 | "-" 50 | "*" 51 | "/" 52 | "|" 53 | "&" 54 | "||" 55 | "&&" 56 | "==" 57 | "!=" 58 | "<" 59 | "<=" 60 | ">" 61 | ">=" 62 | "=~" 63 | "!~" 64 | "!" 65 | "=" 66 | ] @operator 67 | 68 | ; Fields & Properties 69 | 70 | (field 71 | (label 72 | (identifier) @field)) 73 | 74 | (selector_expression 75 | (_) 76 | (identifier) @property) 77 | 78 | ; Functions 79 | 80 | (call_expression 81 | function: (identifier) @function.call) 82 | (call_expression 83 | function: (selector_expression 84 | (_) 85 | (identifier) @function.call)) 86 | (call_expression 87 | function: (builtin_function) @function.call) 88 | 89 | (builtin_function) @function.builtin 90 | 91 | ; Variables 92 | 93 | (identifier) @variable 94 | 95 | ; Types 96 | 97 | (primitive_type) @type.builtin 98 | 99 | ((identifier) @type 100 | (#match? @type "^(#|_#)")) 101 | 102 | [ 103 | (slice_type) 104 | (pointer_type) 105 | ] @type ;; In attributes 106 | 107 | ; Punctuation 108 | 109 | [ 110 | "," 111 | ":" 112 | ] @punctuation.delimiter 113 | 114 | [ "{" "}" ] @punctuation.bracket 115 | 116 | [ "[" "]" ] @punctuation.bracket 117 | 118 | [ "(" ")" ] @punctuation.bracket 119 | 120 | [ "<" ">" ] @punctuation.bracket 121 | 122 | [ 123 | (ellipsis) 124 | "?" 125 | "!" 126 | ] @punctuation.special 127 | 128 | ; Literals 129 | 130 | (string) @string 131 | 132 | [ 133 | (escape_char) 134 | (escape_unicode) 135 | ] @string.escape 136 | 137 | (number) @number 138 | 139 | (float) @float 140 | 141 | (si_unit 142 | (float) 143 | (_) @symbol) 144 | 145 | (boolean) @boolean 146 | 147 | [ 148 | (null) 149 | (top) 150 | (bottom) 151 | ] @constant.builtin 152 | 153 | ; Interpolations 154 | 155 | (interpolation "\\(" @punctuation.special (_) ")" @punctuation.special) @none 156 | 157 | (interpolation "\\(" (identifier) @variable ")") 158 | 159 | ; Comments 160 | 161 | (comment) @comment @spell 162 | 163 | ; Errors 164 | 165 | (ERROR) @error 166 | -------------------------------------------------------------------------------- /bindings/rust/lib.rs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------------ 2 | // Copyright © 2023, Jean-Philippe Braun , Amaan Qureshi 3 | // See the LICENSE file in this repo for license details. 4 | // ------------------------------------------------------------------------------------------------ 5 | 6 | //! This crate provides Cue language support for the [tree-sitter][] parsing library. 7 | //! 8 | //! Typically, you will use the [language][language func] function to add this language to a 9 | //! tree-sitter [Parser][], and then use the parser to parse some code: 10 | //! 11 | //! ``` 12 | //! let code = ""; 13 | //! let mut parser = tree_sitter::Parser::new(); 14 | //! parser.set_language(tree_sitter_cue::language()).expect("Error loading Cue grammar"); 15 | //! let tree = parser.parse(code, None).unwrap(); 16 | //! ``` 17 | //! 18 | //! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html 19 | //! [language func]: fn.language.html 20 | //! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html 21 | //! [tree-sitter]: https://tree-sitter.github.io/ 22 | 23 | use tree_sitter::Language; 24 | 25 | extern "C" { 26 | fn tree_sitter_cue() -> Language; 27 | } 28 | 29 | /// Get the tree-sitter [Language][] for this grammar. 30 | /// 31 | /// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html 32 | pub fn language() -> Language { 33 | unsafe { tree_sitter_cue() } 34 | } 35 | 36 | /// The source of the Rust tree-sitter grammar description. 37 | pub const GRAMMAR: &str = include_str!("../../grammar.js"); 38 | 39 | /// The folds query for this language. 40 | pub const FOLDS_QUERY: &str = include_str!("../../queries/folds.scm"); 41 | 42 | /// The syntax highlighting query for this language. 43 | pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm"); 44 | 45 | /// The indents query for this language. 46 | pub const INDENTS_QUERY: &str = include_str!("../../queries/indents.scm"); 47 | 48 | /// The injection query for this language. 49 | pub const INJECTIONS_QUERY: &str = include_str!("../../queries/injections.scm"); 50 | 51 | /// The symbol tagging query for this language. 52 | pub const LOCALS_QUERY: &str = include_str!("../../queries/locals.scm"); 53 | 54 | /// The content of the [`node-types.json`][] file for this grammar. 55 | /// 56 | /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types 57 | pub const NODE_TYPES: &str = include_str!("../../src/node-types.json"); 58 | 59 | #[cfg(test)] 60 | mod tests { 61 | #[test] 62 | fn test_can_load_grammar() { 63 | let mut parser = tree_sitter::Parser::new(); 64 | parser 65 | .set_language(super::language()) 66 | .expect("Error loading Cue grammar"); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /test/corpus/structs.txt: -------------------------------------------------------------------------------- 1 | === 2 | simple 3 | === 4 | 5 | a: { 6 | foo?: int 7 | bar?: string 8 | required!: int 9 | _hidden: string 10 | a: b: c: string 11 | } 12 | 13 | --- 14 | 15 | (source_file 16 | (field 17 | (label 18 | (identifier)) 19 | (value 20 | (struct_lit 21 | (field 22 | (label 23 | (optional 24 | (identifier))) 25 | (value 26 | (primitive_type))) 27 | (field 28 | (label 29 | (optional 30 | (identifier))) 31 | (value 32 | (primitive_type))) 33 | (field 34 | (label 35 | (required 36 | (identifier))) 37 | (value 38 | (primitive_type))) 39 | (field 40 | (label 41 | (identifier)) 42 | (value 43 | (primitive_type))) 44 | (field 45 | (label 46 | (identifier)) 47 | (label 48 | (identifier)) 49 | (label 50 | (identifier)) 51 | (value 52 | (primitive_type))))))) 53 | 54 | === 55 | closed 56 | === 57 | 58 | a: close({ 59 | field: int 60 | }) 61 | 62 | 63 | b: a & { 64 | field: 3 65 | } 66 | 67 | --- 68 | 69 | (source_file 70 | (field 71 | (label 72 | (identifier)) 73 | (value 74 | (call_expression 75 | (builtin_function) 76 | (arguments 77 | (struct_lit 78 | (field 79 | (label 80 | (identifier)) 81 | (value 82 | (primitive_type)))))))) 83 | (field 84 | (label 85 | (identifier)) 86 | (value 87 | (binary_expression 88 | (identifier) 89 | (struct_lit 90 | (field 91 | (label 92 | (identifier)) 93 | (value 94 | (number)))))))) 95 | 96 | === 97 | bulk 98 | === 99 | 100 | a: { 101 | foo: string 102 | ["^i"]: bool 103 | ...string 104 | } 105 | 106 | --- 107 | 108 | (source_file 109 | (field 110 | (label 111 | (identifier)) 112 | (value 113 | (struct_lit 114 | (field 115 | (label 116 | (identifier)) 117 | (value 118 | (primitive_type))) 119 | (field 120 | (label 121 | (optional 122 | (string))) 123 | (value 124 | (primitive_type))) 125 | (ellipsis) 126 | (primitive_type))))) 127 | 128 | === 129 | definition 130 | === 131 | 132 | #A: { 133 | field: int 134 | } 135 | 136 | _#B: { 137 | field: string 138 | } 139 | 140 | --- 141 | 142 | (source_file 143 | (field (label (identifier)) (value (struct_lit (field (label (identifier)) (value (primitive_type)))))) 144 | (field (label (identifier)) (value (struct_lit (field (label (identifier)) (value (primitive_type))))))) 145 | 146 | 147 | === 148 | embedding 149 | === 150 | 151 | s1: { 152 | a: 1 153 | b: 2 154 | { 155 | c: 3 156 | } 157 | } 158 | 159 | s2: { 160 | "Hello world!" 161 | } 162 | 163 | --- 164 | 165 | (source_file 166 | (field 167 | (label 168 | (identifier)) 169 | (value 170 | (struct_lit 171 | (field 172 | (label 173 | (identifier)) 174 | (value 175 | (number))) 176 | (field 177 | (label 178 | (identifier)) 179 | (value 180 | (number))) 181 | (struct_lit 182 | (field 183 | (label 184 | (identifier)) 185 | (value 186 | (number))))))) 187 | (field 188 | (label 189 | (identifier)) 190 | (value 191 | (struct_lit 192 | (string))))) 193 | -------------------------------------------------------------------------------- /test/corpus/expressions.txt: -------------------------------------------------------------------------------- 1 | === 2 | binary 3 | === 4 | 5 | e: a & b 6 | e: (a & b) | (c) 7 | e: len(a) >= 2 8 | e: ({a:1}|*{b:1}) & ({a:1}|*{b:1}) 9 | 10 | --- 11 | 12 | (source_file 13 | (field 14 | (label 15 | (identifier)) 16 | (value 17 | (binary_expression 18 | (identifier) 19 | (identifier)))) 20 | (field 21 | (label 22 | (identifier)) 23 | (value 24 | (binary_expression 25 | (parenthesized_expression 26 | (binary_expression 27 | (identifier) 28 | (identifier))) 29 | (parenthesized_expression 30 | (identifier))))) 31 | (field 32 | (label 33 | (identifier)) 34 | (value 35 | (binary_expression 36 | (call_expression 37 | (builtin_function) 38 | (arguments 39 | (identifier))) 40 | (number)))) 41 | (field 42 | (label 43 | (identifier)) 44 | (value 45 | (binary_expression 46 | (parenthesized_expression 47 | (binary_expression 48 | (struct_lit 49 | (field 50 | (label 51 | (identifier)) 52 | (value 53 | (number)))) 54 | (unary_expression 55 | (struct_lit 56 | (field 57 | (label 58 | (identifier)) 59 | (value 60 | (number))))))) 61 | (parenthesized_expression 62 | (binary_expression 63 | (struct_lit 64 | (field 65 | (label 66 | (identifier)) 67 | (value 68 | (number)))) 69 | (unary_expression 70 | (struct_lit 71 | (field 72 | (label 73 | (identifier)) 74 | (value 75 | (number))))))))))) 76 | 77 | === 78 | unary 79 | === 80 | 81 | i: *1 | number 82 | r: =~ "foo" 83 | c: * >=5 | int 84 | 85 | --- 86 | 87 | (source_file 88 | (field 89 | (label 90 | (identifier)) 91 | (value 92 | (binary_expression 93 | (unary_expression 94 | (number)) 95 | (primitive_type)))) 96 | (field 97 | (label 98 | (identifier)) 99 | (value 100 | (unary_expression 101 | (string)))) 102 | (field 103 | (label 104 | (identifier)) 105 | (value 106 | (binary_expression 107 | (unary_expression 108 | (unary_expression 109 | (number))) 110 | (primitive_type))))) 111 | 112 | === 113 | call 114 | === 115 | 116 | b: base64.Encode(null, "foo") 117 | s: close({ 118 | let X = len(["a", "b", "c"]) 119 | }) 120 | 121 | --- 122 | 123 | (source_file 124 | (field 125 | (label 126 | (identifier)) 127 | (value 128 | (call_expression 129 | (selector_expression 130 | (identifier) 131 | (identifier)) 132 | (arguments 133 | (null) 134 | (string))))) 135 | (field 136 | (label 137 | (identifier)) 138 | (value 139 | (call_expression 140 | (builtin_function) 141 | (arguments 142 | (struct_lit 143 | (let_clause 144 | (identifier) 145 | (call_expression 146 | (builtin_function) 147 | (arguments 148 | (list_lit 149 | (string) 150 | (string) 151 | (string))))))))))) 152 | 153 | === 154 | selector 155 | === 156 | 157 | a: a.b."foo" 158 | 159 | --- 160 | 161 | (source_file 162 | (field 163 | (label 164 | (identifier)) 165 | (value 166 | (selector_expression 167 | (selector_expression 168 | (identifier) 169 | (identifier)) 170 | (string))))) 171 | 172 | === 173 | index 174 | === 175 | 176 | b: a["f"][x] 177 | l: [1, 2][0] 178 | 179 | --- 180 | 181 | (source_file 182 | (field 183 | (label 184 | (identifier)) 185 | (value 186 | (identifier))) 187 | (list_lit 188 | (string)) 189 | (list_lit 190 | (identifier)) 191 | (field 192 | (label 193 | (identifier)) 194 | (value 195 | (list_lit 196 | (number) 197 | (number)))) 198 | (list_lit 199 | (number))) 200 | 201 | === 202 | dynamic 203 | === 204 | 205 | (b)?: "bar" 206 | (list.Slice(a.b, 0, 1)[0])!: string 207 | (x): (a.c[0]): "y" 208 | 209 | --- 210 | 211 | (source_file 212 | (field 213 | (label 214 | (optional 215 | (dynamic 216 | (identifier)))) 217 | (value 218 | (string))) 219 | (field 220 | (label 221 | (required 222 | (dynamic 223 | (index_expression 224 | (call_expression 225 | (selector_expression 226 | (identifier) 227 | (identifier)) 228 | (arguments 229 | (selector_expression 230 | (identifier) 231 | (identifier)) 232 | (number) 233 | (number))) 234 | (number))))) 235 | (value 236 | (primitive_type))) 237 | (field 238 | (label 239 | (dynamic 240 | (identifier))) 241 | (label 242 | (dynamic 243 | (index_expression 244 | (selector_expression 245 | (identifier) 246 | (identifier)) 247 | (number)))) 248 | (value 249 | (string)))) 250 | 251 | -------------------------------------------------------------------------------- /src/scanner.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | enum TokenType { 4 | MULTI_STR_CONTENT, 5 | MULTI_BYTES_CONTENT, 6 | RAW_STR_CONTENT, 7 | RAW_BYTES_CONTENT, 8 | MULTI_RAW_STR_CONTENT, 9 | MULTI_RAW_BYTES_CONTENT, 10 | }; 11 | 12 | static void advance(TSLexer *lexer) { lexer->advance(lexer, false); } 13 | 14 | static void skip(TSLexer *lexer) { lexer->advance(lexer, true); } 15 | 16 | static bool scan_multiline(TSLexer *lexer, int c) { 17 | bool has_content = false; 18 | if (c == '"') { 19 | lexer->result_symbol = MULTI_STR_CONTENT; 20 | } else if (c == '\'') { 21 | lexer->result_symbol = MULTI_BYTES_CONTENT; 22 | } 23 | 24 | while (true) { 25 | switch (lexer->lookahead) { 26 | case '\'': 27 | case '"': 28 | lexer->mark_end(lexer); 29 | advance(lexer); 30 | if (lexer->lookahead == c) { 31 | advance(lexer); 32 | if (lexer->lookahead == c) { 33 | if (has_content) { 34 | return true; 35 | } else { 36 | return false; 37 | } 38 | } 39 | } 40 | break; 41 | case '\\': 42 | lexer->mark_end(lexer); 43 | advance(lexer); 44 | if (lexer->lookahead == '(') { 45 | if (has_content) { 46 | return true; 47 | } else { 48 | return false; 49 | } 50 | } else { 51 | // FIXME: Accept anything after '\' 52 | advance(lexer); 53 | } 54 | has_content = true; 55 | break; 56 | case '\0': 57 | if (lexer->eof(lexer)) { 58 | return false; 59 | } 60 | advance(lexer); 61 | has_content = true; 62 | break; 63 | default: 64 | advance(lexer); 65 | has_content = true; 66 | break; 67 | } 68 | } 69 | } 70 | 71 | static bool scan_raw_multiline(TSLexer *lexer, int c) { 72 | bool has_content = false; 73 | if (c == '"') { 74 | lexer->result_symbol = MULTI_RAW_STR_CONTENT; 75 | } else if (c == '\'') { 76 | lexer->result_symbol = MULTI_RAW_BYTES_CONTENT; 77 | } 78 | 79 | while (true) { 80 | switch (lexer->lookahead) { 81 | case '\'': 82 | case '"': 83 | lexer->mark_end(lexer); 84 | advance(lexer); 85 | if (lexer->lookahead == c) { 86 | advance(lexer); 87 | if (lexer->lookahead == c) { 88 | advance(lexer); 89 | if (lexer->lookahead == '#') { 90 | if (has_content) { 91 | return true; 92 | } else { 93 | return false; 94 | } 95 | } 96 | } 97 | } 98 | break; 99 | case '\\': 100 | lexer->mark_end(lexer); 101 | advance(lexer); 102 | if (lexer->lookahead == '#') { 103 | advance(lexer); 104 | if (lexer->lookahead == '(') { 105 | if (has_content) { 106 | return true; 107 | } else { 108 | return false; 109 | } 110 | } 111 | } 112 | has_content = true; 113 | break; 114 | case '\0': 115 | if (lexer->eof(lexer)) { 116 | return false; 117 | } 118 | advance(lexer); 119 | has_content = true; 120 | break; 121 | default: 122 | advance(lexer); 123 | has_content = true; 124 | break; 125 | } 126 | } 127 | } 128 | 129 | static bool scan_raw(TSLexer *lexer, int c) { 130 | bool has_content = false; 131 | if (c == '"') { 132 | lexer->result_symbol = RAW_STR_CONTENT; 133 | } else if (c == '\'') { 134 | lexer->result_symbol = RAW_BYTES_CONTENT; 135 | } 136 | 137 | while (true) { 138 | switch (lexer->lookahead) { 139 | case '\'': 140 | case '"': 141 | lexer->mark_end(lexer); 142 | advance(lexer); 143 | if (lexer->lookahead == '#') { 144 | if (has_content) { 145 | return true; 146 | } else { 147 | return false; 148 | } 149 | } 150 | break; 151 | case '\\': 152 | lexer->mark_end(lexer); 153 | advance(lexer); 154 | if (lexer->lookahead == '#') { 155 | advance(lexer); 156 | if (lexer->lookahead == '(') { 157 | if (has_content) { 158 | return true; 159 | } else { 160 | return false; 161 | } 162 | } 163 | } else { 164 | advance(lexer); 165 | } 166 | has_content = true; 167 | break; 168 | case '\0': 169 | if (lexer->eof(lexer)) { 170 | return false; 171 | } 172 | advance(lexer); 173 | has_content = true; 174 | break; 175 | default: 176 | advance(lexer); 177 | has_content = true; 178 | break; 179 | } 180 | } 181 | } 182 | 183 | static bool scan(TSLexer *lexer, const bool *valid_symbols) { 184 | if (valid_symbols[MULTI_STR_CONTENT]) { 185 | return scan_multiline(lexer, '"'); 186 | } else if (valid_symbols[MULTI_BYTES_CONTENT]) { 187 | return scan_multiline(lexer, '\''); 188 | } else if (valid_symbols[MULTI_RAW_STR_CONTENT]) { 189 | return scan_raw_multiline(lexer, '"'); 190 | } else if (valid_symbols[MULTI_RAW_BYTES_CONTENT]) { 191 | return scan_raw_multiline(lexer, '\''); 192 | } else if (valid_symbols[RAW_STR_CONTENT]) { 193 | return scan_raw(lexer, '"'); 194 | } else if (valid_symbols[RAW_BYTES_CONTENT]) { 195 | return scan_raw(lexer, '\''); 196 | } 197 | 198 | return false; 199 | } 200 | 201 | #ifdef __cplusplus 202 | extern "C" { 203 | #endif 204 | 205 | void *tree_sitter_cue_external_scanner_create() { return NULL; } 206 | 207 | bool tree_sitter_cue_external_scanner_scan(void *payload, TSLexer *lexer, 208 | const bool *valid_symbols) { 209 | return scan(lexer, valid_symbols); 210 | } 211 | 212 | unsigned tree_sitter_cue_external_scanner_serialize(void *payload, 213 | char *buffer) { 214 | return 0; 215 | } 216 | 217 | void tree_sitter_cue_external_scanner_deserialize(void *payload, 218 | const char *buffer, 219 | unsigned length) {} 220 | 221 | void tree_sitter_cue_external_scanner_destroy(void *payload) {} 222 | 223 | #ifdef __cplusplus 224 | } 225 | #endif 226 | -------------------------------------------------------------------------------- /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 | void (*log)(const TSLexer *, const char *, ...); 51 | }; 52 | 53 | typedef enum { 54 | TSParseActionTypeShift, 55 | TSParseActionTypeReduce, 56 | TSParseActionTypeAccept, 57 | TSParseActionTypeRecover, 58 | } TSParseActionType; 59 | 60 | typedef union { 61 | struct { 62 | uint8_t type; 63 | TSStateId state; 64 | bool extra; 65 | bool repetition; 66 | } shift; 67 | struct { 68 | uint8_t type; 69 | uint8_t child_count; 70 | TSSymbol symbol; 71 | int16_t dynamic_precedence; 72 | uint16_t production_id; 73 | } reduce; 74 | uint8_t type; 75 | } TSParseAction; 76 | 77 | typedef struct { 78 | uint16_t lex_state; 79 | uint16_t external_lex_state; 80 | } TSLexMode; 81 | 82 | typedef union { 83 | TSParseAction action; 84 | struct { 85 | uint8_t count; 86 | bool reusable; 87 | } entry; 88 | } TSParseActionEntry; 89 | 90 | typedef struct { 91 | int32_t start; 92 | int32_t end; 93 | } TSCharacterRange; 94 | 95 | struct TSLanguage { 96 | uint32_t version; 97 | uint32_t symbol_count; 98 | uint32_t alias_count; 99 | uint32_t token_count; 100 | uint32_t external_token_count; 101 | uint32_t state_count; 102 | uint32_t large_state_count; 103 | uint32_t production_id_count; 104 | uint32_t field_count; 105 | uint16_t max_alias_sequence_length; 106 | const uint16_t *parse_table; 107 | const uint16_t *small_parse_table; 108 | const uint32_t *small_parse_table_map; 109 | const TSParseActionEntry *parse_actions; 110 | const char * const *symbol_names; 111 | const char * const *field_names; 112 | const TSFieldMapSlice *field_map_slices; 113 | const TSFieldMapEntry *field_map_entries; 114 | const TSSymbolMetadata *symbol_metadata; 115 | const TSSymbol *public_symbol_map; 116 | const uint16_t *alias_map; 117 | const TSSymbol *alias_sequences; 118 | const TSLexMode *lex_modes; 119 | bool (*lex_fn)(TSLexer *, TSStateId); 120 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 121 | TSSymbol keyword_capture_token; 122 | struct { 123 | const bool *states; 124 | const TSSymbol *symbol_map; 125 | void *(*create)(void); 126 | void (*destroy)(void *); 127 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 128 | unsigned (*serialize)(void *, char *); 129 | void (*deserialize)(void *, const char *, unsigned); 130 | } external_scanner; 131 | const TSStateId *primary_state_ids; 132 | }; 133 | 134 | static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { 135 | uint32_t index = 0; 136 | uint32_t size = len - index; 137 | while (size > 1) { 138 | uint32_t half_size = size / 2; 139 | uint32_t mid_index = index + half_size; 140 | TSCharacterRange *range = &ranges[mid_index]; 141 | if (lookahead >= range->start && lookahead <= range->end) { 142 | return true; 143 | } else if (lookahead > range->end) { 144 | index = mid_index; 145 | } 146 | size -= half_size; 147 | } 148 | TSCharacterRange *range = &ranges[index]; 149 | return (lookahead >= range->start && lookahead <= range->end); 150 | } 151 | 152 | /* 153 | * Lexer Macros 154 | */ 155 | 156 | #ifdef _MSC_VER 157 | #define UNUSED __pragma(warning(suppress : 4101)) 158 | #else 159 | #define UNUSED __attribute__((unused)) 160 | #endif 161 | 162 | #define START_LEXER() \ 163 | bool result = false; \ 164 | bool skip = false; \ 165 | UNUSED \ 166 | bool eof = false; \ 167 | int32_t lookahead; \ 168 | goto start; \ 169 | next_state: \ 170 | lexer->advance(lexer, skip); \ 171 | start: \ 172 | skip = false; \ 173 | lookahead = lexer->lookahead; 174 | 175 | #define ADVANCE(state_value) \ 176 | { \ 177 | state = state_value; \ 178 | goto next_state; \ 179 | } 180 | 181 | #define ADVANCE_MAP(...) \ 182 | { \ 183 | static const uint16_t map[] = { __VA_ARGS__ }; \ 184 | for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ 185 | if (map[i] == lookahead) { \ 186 | state = map[i + 1]; \ 187 | goto next_state; \ 188 | } \ 189 | } \ 190 | } 191 | 192 | #define SKIP(state_value) \ 193 | { \ 194 | skip = true; \ 195 | state = state_value; \ 196 | goto next_state; \ 197 | } 198 | 199 | #define ACCEPT_TOKEN(symbol_value) \ 200 | result = true; \ 201 | lexer->result_symbol = symbol_value; \ 202 | lexer->mark_end(lexer); 203 | 204 | #define END_STATE() return result; 205 | 206 | /* 207 | * Parse Table Macros 208 | */ 209 | 210 | #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) 211 | 212 | #define STATE(id) id 213 | 214 | #define ACTIONS(id) id 215 | 216 | #define SHIFT(state_value) \ 217 | {{ \ 218 | .shift = { \ 219 | .type = TSParseActionTypeShift, \ 220 | .state = (state_value) \ 221 | } \ 222 | }} 223 | 224 | #define SHIFT_REPEAT(state_value) \ 225 | {{ \ 226 | .shift = { \ 227 | .type = TSParseActionTypeShift, \ 228 | .state = (state_value), \ 229 | .repetition = true \ 230 | } \ 231 | }} 232 | 233 | #define SHIFT_EXTRA() \ 234 | {{ \ 235 | .shift = { \ 236 | .type = TSParseActionTypeShift, \ 237 | .extra = true \ 238 | } \ 239 | }} 240 | 241 | #define REDUCE(symbol_name, children, precedence, prod_id) \ 242 | {{ \ 243 | .reduce = { \ 244 | .type = TSParseActionTypeReduce, \ 245 | .symbol = symbol_name, \ 246 | .child_count = children, \ 247 | .dynamic_precedence = precedence, \ 248 | .production_id = prod_id \ 249 | }, \ 250 | }} 251 | 252 | #define RECOVER() \ 253 | {{ \ 254 | .type = TSParseActionTypeRecover \ 255 | }} 256 | 257 | #define ACCEPT_INPUT() \ 258 | {{ \ 259 | .type = TSParseActionTypeAccept \ 260 | }} 261 | 262 | #ifdef __cplusplus 263 | } 264 | #endif 265 | 266 | #endif // TREE_SITTER_PARSER_H_ 267 | -------------------------------------------------------------------------------- /src/tree_sitter/array.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ARRAY_H_ 2 | #define TREE_SITTER_ARRAY_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "./alloc.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef _MSC_VER 17 | #pragma warning(push) 18 | #pragma warning(disable : 4101) 19 | #elif defined(__GNUC__) || defined(__clang__) 20 | #pragma GCC diagnostic push 21 | #pragma GCC diagnostic ignored "-Wunused-variable" 22 | #endif 23 | 24 | #define Array(T) \ 25 | struct { \ 26 | T *contents; \ 27 | uint32_t size; \ 28 | uint32_t capacity; \ 29 | } 30 | 31 | /// Initialize an array. 32 | #define array_init(self) \ 33 | ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) 34 | 35 | /// Create an empty array. 36 | #define array_new() \ 37 | { NULL, 0, 0 } 38 | 39 | /// Get a pointer to the element at a given `index` in the array. 40 | #define array_get(self, _index) \ 41 | (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) 42 | 43 | /// Get a pointer to the first element in the array. 44 | #define array_front(self) array_get(self, 0) 45 | 46 | /// Get a pointer to the last element in the array. 47 | #define array_back(self) array_get(self, (self)->size - 1) 48 | 49 | /// Clear the array, setting its size to zero. Note that this does not free any 50 | /// memory allocated for the array's contents. 51 | #define array_clear(self) ((self)->size = 0) 52 | 53 | /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is 54 | /// less than the array's current capacity, this function has no effect. 55 | #define array_reserve(self, new_capacity) \ 56 | _array__reserve((Array *)(self), array_elem_size(self), new_capacity) 57 | 58 | /// Free any memory allocated for this array. Note that this does not free any 59 | /// memory allocated for the array's contents. 60 | #define array_delete(self) _array__delete((Array *)(self)) 61 | 62 | /// Push a new `element` onto the end of the array. 63 | #define array_push(self, element) \ 64 | (_array__grow((Array *)(self), 1, array_elem_size(self)), \ 65 | (self)->contents[(self)->size++] = (element)) 66 | 67 | /// Increase the array's size by `count` elements. 68 | /// New elements are zero-initialized. 69 | #define array_grow_by(self, count) \ 70 | do { \ 71 | if ((count) == 0) break; \ 72 | _array__grow((Array *)(self), count, array_elem_size(self)); \ 73 | memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ 74 | (self)->size += (count); \ 75 | } while (0) 76 | 77 | /// Append all elements from one array to the end of another. 78 | #define array_push_all(self, other) \ 79 | array_extend((self), (other)->size, (other)->contents) 80 | 81 | /// Append `count` elements to the end of the array, reading their values from the 82 | /// `contents` pointer. 83 | #define array_extend(self, count, contents) \ 84 | _array__splice( \ 85 | (Array *)(self), array_elem_size(self), (self)->size, \ 86 | 0, count, contents \ 87 | ) 88 | 89 | /// Remove `old_count` elements from the array starting at the given `index`. At 90 | /// the same index, insert `new_count` new elements, reading their values from the 91 | /// `new_contents` pointer. 92 | #define array_splice(self, _index, old_count, new_count, new_contents) \ 93 | _array__splice( \ 94 | (Array *)(self), array_elem_size(self), _index, \ 95 | old_count, new_count, new_contents \ 96 | ) 97 | 98 | /// Insert one `element` into the array at the given `index`. 99 | #define array_insert(self, _index, element) \ 100 | _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element)) 101 | 102 | /// Remove one element from the array at the given `index`. 103 | #define array_erase(self, _index) \ 104 | _array__erase((Array *)(self), array_elem_size(self), _index) 105 | 106 | /// Pop the last element off the array, returning the element by value. 107 | #define array_pop(self) ((self)->contents[--(self)->size]) 108 | 109 | /// Assign the contents of one array to another, reallocating if necessary. 110 | #define array_assign(self, other) \ 111 | _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self)) 112 | 113 | /// Swap one array with another 114 | #define array_swap(self, other) \ 115 | _array__swap((Array *)(self), (Array *)(other)) 116 | 117 | /// Get the size of the array contents 118 | #define array_elem_size(self) (sizeof *(self)->contents) 119 | 120 | /// Search a sorted array for a given `needle` value, using the given `compare` 121 | /// callback to determine the order. 122 | /// 123 | /// If an existing element is found to be equal to `needle`, then the `index` 124 | /// out-parameter is set to the existing value's index, and the `exists` 125 | /// out-parameter is set to true. Otherwise, `index` is set to an index where 126 | /// `needle` should be inserted in order to preserve the sorting, and `exists` 127 | /// is set to false. 128 | #define array_search_sorted_with(self, compare, needle, _index, _exists) \ 129 | _array__search_sorted(self, 0, compare, , needle, _index, _exists) 130 | 131 | /// Search a sorted array for a given `needle` value, using integer comparisons 132 | /// of a given struct field (specified with a leading dot) to determine the order. 133 | /// 134 | /// See also `array_search_sorted_with`. 135 | #define array_search_sorted_by(self, field, needle, _index, _exists) \ 136 | _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) 137 | 138 | /// Insert a given `value` into a sorted array, using the given `compare` 139 | /// callback to determine the order. 140 | #define array_insert_sorted_with(self, compare, value) \ 141 | do { \ 142 | unsigned _index, _exists; \ 143 | array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ 144 | if (!_exists) array_insert(self, _index, value); \ 145 | } while (0) 146 | 147 | /// Insert a given `value` into a sorted array, using integer comparisons of 148 | /// a given struct field (specified with a leading dot) to determine the order. 149 | /// 150 | /// See also `array_search_sorted_by`. 151 | #define array_insert_sorted_by(self, field, value) \ 152 | do { \ 153 | unsigned _index, _exists; \ 154 | array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ 155 | if (!_exists) array_insert(self, _index, value); \ 156 | } while (0) 157 | 158 | // Private 159 | 160 | typedef Array(void) Array; 161 | 162 | /// This is not what you're looking for, see `array_delete`. 163 | static inline void _array__delete(Array *self) { 164 | if (self->contents) { 165 | ts_free(self->contents); 166 | self->contents = NULL; 167 | self->size = 0; 168 | self->capacity = 0; 169 | } 170 | } 171 | 172 | /// This is not what you're looking for, see `array_erase`. 173 | static inline void _array__erase(Array *self, size_t element_size, 174 | uint32_t index) { 175 | assert(index < self->size); 176 | char *contents = (char *)self->contents; 177 | memmove(contents + index * element_size, contents + (index + 1) * element_size, 178 | (self->size - index - 1) * element_size); 179 | self->size--; 180 | } 181 | 182 | /// This is not what you're looking for, see `array_reserve`. 183 | static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) { 184 | if (new_capacity > self->capacity) { 185 | if (self->contents) { 186 | self->contents = ts_realloc(self->contents, new_capacity * element_size); 187 | } else { 188 | self->contents = ts_malloc(new_capacity * element_size); 189 | } 190 | self->capacity = new_capacity; 191 | } 192 | } 193 | 194 | /// This is not what you're looking for, see `array_assign`. 195 | static inline void _array__assign(Array *self, const Array *other, size_t element_size) { 196 | _array__reserve(self, element_size, other->size); 197 | self->size = other->size; 198 | memcpy(self->contents, other->contents, self->size * element_size); 199 | } 200 | 201 | /// This is not what you're looking for, see `array_swap`. 202 | static inline void _array__swap(Array *self, Array *other) { 203 | Array swap = *other; 204 | *other = *self; 205 | *self = swap; 206 | } 207 | 208 | /// This is not what you're looking for, see `array_push` or `array_grow_by`. 209 | static inline void _array__grow(Array *self, uint32_t count, size_t element_size) { 210 | uint32_t new_size = self->size + count; 211 | if (new_size > self->capacity) { 212 | uint32_t new_capacity = self->capacity * 2; 213 | if (new_capacity < 8) new_capacity = 8; 214 | if (new_capacity < new_size) new_capacity = new_size; 215 | _array__reserve(self, element_size, new_capacity); 216 | } 217 | } 218 | 219 | /// This is not what you're looking for, see `array_splice`. 220 | static inline void _array__splice(Array *self, size_t element_size, 221 | uint32_t index, uint32_t old_count, 222 | uint32_t new_count, const void *elements) { 223 | uint32_t new_size = self->size + new_count - old_count; 224 | uint32_t old_end = index + old_count; 225 | uint32_t new_end = index + new_count; 226 | assert(old_end <= self->size); 227 | 228 | _array__reserve(self, element_size, new_size); 229 | 230 | char *contents = (char *)self->contents; 231 | if (self->size > old_end) { 232 | memmove( 233 | contents + new_end * element_size, 234 | contents + old_end * element_size, 235 | (self->size - old_end) * element_size 236 | ); 237 | } 238 | if (new_count > 0) { 239 | if (elements) { 240 | memcpy( 241 | (contents + index * element_size), 242 | elements, 243 | new_count * element_size 244 | ); 245 | } else { 246 | memset( 247 | (contents + index * element_size), 248 | 0, 249 | new_count * element_size 250 | ); 251 | } 252 | } 253 | self->size += new_count - old_count; 254 | } 255 | 256 | /// A binary search routine, based on Rust's `std::slice::binary_search_by`. 257 | /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. 258 | #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ 259 | do { \ 260 | *(_index) = start; \ 261 | *(_exists) = false; \ 262 | uint32_t size = (self)->size - *(_index); \ 263 | if (size == 0) break; \ 264 | int comparison; \ 265 | while (size > 1) { \ 266 | uint32_t half_size = size / 2; \ 267 | uint32_t mid_index = *(_index) + half_size; \ 268 | comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ 269 | if (comparison <= 0) *(_index) = mid_index; \ 270 | size -= half_size; \ 271 | } \ 272 | comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ 273 | if (comparison == 0) *(_exists) = true; \ 274 | else if (comparison < 0) *(_index) += 1; \ 275 | } while (0) 276 | 277 | /// Helper macro for the `_sorted_by` routines below. This takes the left (existing) 278 | /// parameter by reference in order to work with the generic sorting function above. 279 | #define _compare_int(a, b) ((int)*(a) - (int)(b)) 280 | 281 | #ifdef _MSC_VER 282 | #pragma warning(pop) 283 | #elif defined(__GNUC__) || defined(__clang__) 284 | #pragma GCC diagnostic pop 285 | #endif 286 | 287 | #ifdef __cplusplus 288 | } 289 | #endif 290 | 291 | #endif // TREE_SITTER_ARRAY_H_ 292 | -------------------------------------------------------------------------------- /grammar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Cue grammar for tree-sitter 3 | * @author Jean-Philippe Braun 4 | * @author Amaan Qureshi 5 | * @license MIT 6 | * @see {@link https://cuelang.org|official website} 7 | * @see {@link https://github.com/cue-lang/cue/blob/master/doc/ref/spec.md|official syntax spec} 8 | */ 9 | 10 | // deno-lint-ignore-file ban-ts-comment 11 | /* eslint-disable arrow-parens */ 12 | /* eslint-disable camelcase */ 13 | /* eslint-disable-next-line spaced-comment */ 14 | /// 15 | // @ts-check 16 | 17 | /** 18 | * Creates a rule to match one or more of the rules separated by the separator 19 | * and optionally adds a trailing separator (default is false). 20 | * 21 | * @param {Rule} rule 22 | * @param {string} separator - The separator to use. 23 | * @param {boolean?} trailing_separator - Whether to allow a trailing separator or not. 24 | * 25 | * @return {SeqRule} 26 | * 27 | */ 28 | function listSeq(rule, separator, trailing_separator = false) { 29 | return trailing_separator ? 30 | seq(rule, repeat(seq(separator, rule)), optional(separator)) : 31 | seq(rule, repeat(seq(separator, rule))); 32 | } 33 | 34 | /** 35 | * Creates a rule to match one or more of the rules separated by a comma 36 | * 37 | * @param {Rule} rule 38 | * @param {boolean?} trailing_separator - Whether to allow a trailing separator or not. 39 | * 40 | * @return {SeqRule} 41 | */ 42 | function commaSep1(rule, trailing_separator = false) { 43 | return listSeq(rule, ',', trailing_separator); 44 | } 45 | 46 | /** 47 | * Creates a rule to optionally match one or more of the rules separated by a comma 48 | * 49 | * @param {Rule} rule 50 | * @param {boolean?} trailing_separator - Whether to allow a trailing separator or not. 51 | * 52 | * @return {ChoiceRule} 53 | * 54 | */ 55 | function commaSep(rule, trailing_separator = false) { 56 | return optional(commaSep1(rule, trailing_separator)); 57 | } 58 | 59 | /** 60 | * Creates a rule to match one or more of the rules optionally separated by a comma 61 | * 62 | * @param {Rule} rule 63 | * 64 | * @return {SeqRule} 65 | * 66 | */ 67 | function optionalCommaSep1(rule) { 68 | return seq(rule, repeat(seq(optional(','), rule)), optional(',')); 69 | } 70 | 71 | /** 72 | * Creates a rule to optionally match one or more of the rules optionally separated by a comma 73 | * 74 | * @param {Rule} rule 75 | * 76 | * @return {ChoiceRule} 77 | * 78 | */ 79 | function optionalCommaSep(rule) { 80 | return optional(optionalCommaSep1(rule)); 81 | } 82 | 83 | const PREC = { 84 | bitwise_or: 1, 85 | bitwise_and: 2, 86 | or: 3, 87 | and: 4, 88 | compare: 5, 89 | add: 6, 90 | multiply: 7, 91 | unary: 8, 92 | call: 9, 93 | }; 94 | 95 | const primitive_types = [ 96 | 'number', 97 | 'float', 98 | 'float32', 99 | 'float64', 100 | 'uint', 101 | 'uint8', 102 | 'uint16', 103 | 'uint32', 104 | 'uint64', 105 | 'uint128', 106 | 'int', 107 | 'int8', 108 | 'int16', 109 | 'int32', 110 | 'int64', 111 | 'int128', 112 | 'string', 113 | 'bytes', 114 | 'bool', 115 | ]; 116 | 117 | module.exports = grammar({ 118 | name: 'cue', 119 | 120 | extras: $ => [ 121 | $.comment, 122 | /\s/, 123 | ], 124 | 125 | externals: $ => [ 126 | $._multi_str_content, 127 | $._multi_bytes_content, 128 | $._raw_str_content, 129 | $._raw_bytes_content, 130 | $._multi_raw_str_content, 131 | $._multi_raw_bytes_content, 132 | ], 133 | 134 | inline: $ => [ 135 | $.keyword_identifier, 136 | ], 137 | 138 | supertypes: $ => [ 139 | $.expression, 140 | $.primary_expression, 141 | ], 142 | 143 | conflicts: $ => [ 144 | [$._embedding, $._label_alias_expr], 145 | ], 146 | 147 | word: $ => $.identifier, 148 | 149 | rules: { 150 | source_file: $ => seq( 151 | optional($.attribute), 152 | optional($.package_clause), 153 | optional(repeat($.import_declaration)), 154 | optionalCommaSep($._declaration), 155 | ), 156 | 157 | _package_identifier: $ => alias($.identifier, $.package_identifier), 158 | 159 | package_clause: $ => seq( 160 | 'package', 161 | $._package_identifier, 162 | ), 163 | 164 | import_declaration: $ => seq( 165 | 'import', 166 | choice( 167 | $.import_spec, 168 | $.import_spec_list, 169 | ), 170 | ), 171 | 172 | import_spec: $ => seq( 173 | optional(field('name', choice( 174 | '.', 175 | '_', 176 | $._package_identifier, 177 | ))), 178 | field('path', $.string), 179 | ), 180 | 181 | import_spec_list: $ => seq( 182 | '(', 183 | optionalCommaSep($.import_spec), 184 | ')', 185 | ), 186 | 187 | identifier: _ => token(choice( 188 | seq( 189 | optional(choice('_#', '#', '_')), 190 | choice(/\p{L}/, '$', '_'), 191 | repeat(choice(/\p{L}/, '$', '_', /[0-9]/)), 192 | ), 193 | choice('_#', '#', '_'), 194 | )), 195 | keyword_identifier: $ => prec(-3, alias( 196 | choice( 197 | 'let', 198 | 'if', 199 | 'for', 200 | ...primitive_types, 201 | ), 202 | $.identifier, 203 | )), 204 | 205 | attribute: $ => seq( 206 | '@', 207 | $.identifier, 208 | '(', 209 | optional(choice(',', '-')), 210 | repeat( 211 | prec.right(choice( 212 | commaSep1($._attr_token), 213 | seq('(', commaSep($._attr_token), ')'), 214 | seq('[', commaSep($._attr_token), ']'), 215 | seq('{', commaSep($._attr_token), '}'), 216 | seq('<', commaSep($._attr_token), '>'), 217 | )), 218 | ), 219 | ')', 220 | ), 221 | _attr_token: $ => prec.right(choice( 222 | $._attr_item, 223 | seq($._attr_item, '=', choice($._attr_item, $.attr_path)), 224 | seq('(', $._attr_item, ')', '=', choice($._attr_item, $.attr_path)), 225 | )), 226 | 227 | _attr_item: $ => choice( 228 | $.string, 229 | $.number, 230 | $.float, 231 | $.si_unit, 232 | $.boolean, 233 | $.null, 234 | $.top, 235 | $.bottom, 236 | $.primitive_type, 237 | seq('[', ']', alias($._attr_item, $.slice_type)), 238 | seq('*', alias($._attr_item, $.pointer_type)), 239 | $.package_path, 240 | $.identifier, 241 | prec(-1, /[^0-9_]/), 242 | ), 243 | attr_path: _ => /(?:\/[\p{L}\d\.]+)*[\p{L}\d\.]+(?:\/[\p{L}\d\.]+)*(?:\/)?/, 244 | package_path: $ => seq($.identifier, repeat1(seq('.', $.identifier))), 245 | 246 | builtin_function: _ => choice( 247 | 'len', 248 | 'close', 249 | 'and', 250 | 'or', 251 | 'div', 252 | 'mod', 253 | 'quo', 254 | 'rem', 255 | ), 256 | 257 | _declaration: $ => choice( 258 | $.field, 259 | $.ellipsis, 260 | $._embedding, 261 | $.let_clause, 262 | ), 263 | 264 | _list_elem: $ => prec.right(choice( 265 | $.ellipsis, 266 | seq( 267 | $._embedding, 268 | optional(repeat(seq(',', $._embedding))), 269 | optional(seq(',', $.ellipsis)), 270 | optional(','), 271 | ), 272 | )), 273 | 274 | list_lit: $ => seq('[', repeat($._list_elem), ']'), 275 | 276 | struct_lit: $ => seq( 277 | '{', 278 | optionalCommaSep(choice($._declaration, $.attribute)), 279 | '}', 280 | ), 281 | 282 | ellipsis: $ => prec.left(seq( 283 | '...', 284 | optional($.expression), 285 | )), 286 | 287 | _embedding: $ => choice( 288 | $.comprehension, 289 | $._alias_expr, 290 | ), 291 | 292 | _label_name: $ => prec(1, choice( 293 | $.identifier, 294 | $.keyword_identifier, 295 | alias($._simple_string_lit, $.string), 296 | $.selector_expression, 297 | alias($.parenthesized_expression, $.dynamic), 298 | )), 299 | 300 | _label_alias_expr: $ => alias($._alias_expr, $.optional), 301 | 302 | required: $ => seq($._label_name, '!'), 303 | 304 | optional: $ => seq($._label_name, '?'), 305 | 306 | _label_expr: $ => choice( 307 | $._label_name, 308 | $.optional, 309 | $.required, 310 | seq('[', $._label_alias_expr, ']'), 311 | ), 312 | 313 | label: $ => seq( 314 | optional(seq( 315 | field('alias', choice($.identifier, $.keyword_identifier)), 316 | '=', 317 | )), 318 | $._label_expr, 319 | ), 320 | 321 | field: $ => prec.right(seq( 322 | repeat1(seq($.label, ':')), 323 | $._value, 324 | optional($.attribute), 325 | )), 326 | 327 | _value: $ => alias($._alias_expr, $.value), 328 | 329 | for_clause: $ => seq( 330 | 'for', 331 | choice($.identifier, '_'), 332 | optional(seq(',', choice($.identifier, '_'))), 333 | 'in', $.expression, 334 | ), 335 | 336 | guard_clause: $ => seq('if', field('condition', $.expression)), 337 | 338 | let_clause: $ => seq('let', field('left', $.identifier), '=', field('right', $.expression)), 339 | 340 | _clause: $ => choice($.for_clause, $.guard_clause, $.let_clause), 341 | 342 | comprehension: $ => seq( 343 | choice($.for_clause, $.guard_clause), 344 | repeat(seq(optional(','), $._clause)), 345 | $.struct_lit, 346 | ), 347 | 348 | _alias_expr: $ => seq( 349 | optional(seq(field('alias', $.identifier), '=')), 350 | $.expression, 351 | ), 352 | 353 | parenthesized_expression: $ => seq('(', $.expression, ')'), 354 | 355 | expression: $ => prec.left(choice( 356 | $.primary_expression, 357 | $.unary_expression, 358 | $.binary_expression, 359 | )), 360 | 361 | primary_expression: $ => choice( 362 | $.parenthesized_expression, 363 | $.selector_expression, 364 | $.index_expression, 365 | $.call_expression, 366 | $.identifier, 367 | $._literal, 368 | ), 369 | 370 | binary_expression: $ => { 371 | const table = [ 372 | ['+', PREC.add], 373 | ['-', PREC.add], 374 | ['*', PREC.multiply], 375 | ['/', PREC.multiply], 376 | ['|', PREC.bitwise_or], 377 | ['&', PREC.bitwise_and], 378 | ['||', PREC.or], 379 | ['&&', PREC.and], 380 | [choice('==', '=~', '!~', '!=', '<', '<=', '>', '>='), PREC.compare], 381 | ]; 382 | 383 | // @ts-ignore 384 | return choice(...table.map(([operator, precedence]) => prec.left(precedence, seq( 385 | field('left', $.expression), 386 | // @ts-ignore 387 | field('operator', operator), 388 | field('right', $.expression), 389 | )))); 390 | }, 391 | 392 | unary_expression: $ => { 393 | const unary_operators = ['+', '-', '!', '*', '!=', '<', '<=', '>', '>=', '=~', '!~']; 394 | 395 | return choice(...unary_operators.map((operator) => prec(PREC.unary, seq( 396 | field('operator', operator), 397 | field('argument', $.expression), 398 | )))); 399 | }, 400 | 401 | call_expression: $ => prec(PREC.call, seq( 402 | field('function', choice( 403 | $.builtin_function, 404 | $.selector_expression, 405 | $.identifier, 406 | )), 407 | $.arguments, 408 | )), 409 | 410 | index_expression: $ => seq( 411 | $.primary_expression, 412 | '[', 413 | $.expression, 414 | ']', 415 | ), 416 | 417 | selector_expression: $ => seq( 418 | $.primary_expression, 419 | '.', 420 | choice($.identifier, alias($._simple_string_lit, $.string)), 421 | ), 422 | 423 | arguments: $ => seq( 424 | '(', 425 | commaSep(optional($.expression)), 426 | ')', 427 | ), 428 | 429 | _literal: $ => 430 | choice( 431 | $.struct_lit, 432 | $.list_lit, 433 | $.string, 434 | $.number, 435 | $.float, 436 | $.si_unit, 437 | $.boolean, 438 | $.null, 439 | $.top, 440 | $.bottom, 441 | $.primitive_type, 442 | ), 443 | 444 | primitive_type: _ => choice(...primitive_types), 445 | 446 | top: _ => '_', 447 | 448 | bottom: _ => '_|_', 449 | 450 | boolean: _ => choice('true', 'false'), 451 | 452 | null: _ => 'null', 453 | 454 | number: _ => { 455 | const binary_literal = seq( 456 | /0[bB]/, 457 | /[01](_?[01])*/, 458 | ); 459 | 460 | const hex_literal = seq( 461 | /0[xX]/, 462 | /[\da-fA-F](_?[\da-fA-F])*/, 463 | ); 464 | 465 | const octal_literal = seq( 466 | optional(choice('-', '+')), 467 | /0[oO]/, 468 | /[0-7](_?[0-7])*/, 469 | ); 470 | 471 | const decimal_digits = /\d(_?\d)*/; 472 | const signed_integer = seq(optional(choice('-', '+')), decimal_digits); 473 | 474 | const decimal_integer_literal = choice( 475 | '0', 476 | seq(optional('0'), /[1-9]/, optional(seq(optional('_'), decimal_digits))), 477 | ); 478 | 479 | const decimal_literal = choice( 480 | seq(optional(choice('-', '+')), decimal_integer_literal), 481 | decimal_digits, 482 | signed_integer, 483 | ); 484 | 485 | 486 | return token(choice( 487 | hex_literal, 488 | binary_literal, 489 | decimal_literal, 490 | octal_literal, 491 | )); 492 | }, 493 | 494 | float: _ => { 495 | const hex_digit = /[0-9a-fA-F]/; 496 | const hex_digits = seq(hex_digit, repeat(seq(optional('_'), hex_digit))); 497 | 498 | const decimal_digits = /\d(_?\d)*/; 499 | 500 | const decimal_exponent = seq(choice('e', 'E'), optional(choice('+', '-')), decimal_digits); 501 | 502 | const decimal_float_literal = choice( 503 | seq(optional('-'), optional(decimal_digits), '.', optional(decimal_digits), optional(decimal_exponent)), 504 | seq(decimal_digits, decimal_exponent), 505 | ); 506 | 507 | const hex_exponent = seq(choice('p', 'P'), optional(choice('+', '-')), decimal_digits); 508 | const hex_mantissa = choice( 509 | seq(optional('_'), hex_digits, '.', optional(hex_digits)), 510 | seq(optional('_'), hex_digits), 511 | seq('.', hex_digits), 512 | ); 513 | const hex_float_literal = seq('0', choice('x', 'X'), hex_mantissa, hex_exponent); 514 | 515 | return token(choice(decimal_float_literal, hex_float_literal)); 516 | }, 517 | 518 | si_unit: $ => seq( 519 | $.float, 520 | field('unit', 521 | token.immediate(seq( 522 | choice('K', 'M', 'G', 'T', 'P'), 523 | optional('i'), 524 | )), 525 | ), 526 | ), 527 | 528 | escape_char: _ => token.immediate(seq( 529 | '\\', 530 | repeat('#'), 531 | seq(choice('a', 'b', 'f', 'n', 'r', 't', 'v', '/', '\\', '\'', '"')), 532 | )), 533 | 534 | escape_byte: _ => token.immediate(seq( 535 | '\\', 536 | repeat('#'), 537 | choice( 538 | /[0-7]{3}/, // octal byte value 539 | /x[0-9a-fA-F]{2}/, // hex byte value 540 | ), 541 | )), 542 | 543 | _escape_unicode: $ => choice( 544 | $.escape_char, 545 | alias(token.immediate(seq( 546 | '\\', 547 | repeat('#'), 548 | choice( 549 | /u[0-9a-fA-F]{4}/, 550 | /U[0-9a-fA-F]{8}/, 551 | ))), 552 | $.escape_unicode, 553 | ), 554 | ), 555 | 556 | string: $ => choice( 557 | $._simple_string_lit, 558 | $._simple_bytes_lit, 559 | $._multiline_string_lit, 560 | $._multiline_bytes_lit, 561 | $._simple_raw_string_lit, 562 | $._simple_raw_bytes_lit, 563 | $._multiline_raw_string_lit, 564 | $._multiline_raw_bytes_lit, 565 | ), 566 | 567 | _simple_string_lit: $ => seq( 568 | '"', 569 | repeat(choice( 570 | token.immediate(prec(1, /[^"\n\\]+/)), 571 | $.interpolation, 572 | $._escape_unicode, 573 | )), 574 | '"', 575 | ), 576 | 577 | _simple_bytes_lit: $ => seq( 578 | '\'', 579 | repeat(choice( 580 | token.immediate(prec(1, /[^'\n\\]+/)), 581 | $.interpolation, 582 | $.escape_byte, 583 | $._escape_unicode, 584 | )), 585 | '\'', 586 | ), 587 | 588 | _multiline_string_lit: $ => seq( 589 | token('"""'), 590 | repeat(choice( 591 | $._multi_str_content, 592 | $.interpolation, 593 | $._escape_unicode, 594 | )), 595 | token('"""'), 596 | ), 597 | 598 | _multiline_bytes_lit: $ => seq( 599 | token('\'\'\''), 600 | repeat(choice( 601 | $._multi_bytes_content, 602 | $.interpolation, 603 | $.escape_byte, 604 | $._escape_unicode, 605 | )), 606 | token('\'\'\''), 607 | ), 608 | 609 | _simple_raw_string_lit: $ => seq( 610 | '#"', 611 | repeat(choice( 612 | $._raw_str_content, 613 | $.raw_interpolation, 614 | $._escape_unicode, 615 | )), 616 | '"#', 617 | ), 618 | 619 | _simple_raw_bytes_lit: $ => seq( 620 | '#\'', 621 | repeat(choice( 622 | $._raw_bytes_content, 623 | $.raw_interpolation, 624 | $.escape_byte, 625 | $._escape_unicode, 626 | )), 627 | '\'#', 628 | ), 629 | 630 | _multiline_raw_string_lit: $ => seq( 631 | token('#"""'), 632 | repeat(choice( 633 | $._multi_raw_str_content, 634 | $.raw_interpolation, 635 | $._escape_unicode, 636 | )), 637 | token('"""#'), 638 | ), 639 | 640 | _multiline_raw_bytes_lit: $ => seq( 641 | token('#\'\'\''), 642 | repeat(choice( 643 | $._multi_raw_bytes_content, 644 | $.raw_interpolation, 645 | $.escape_byte, 646 | $._escape_unicode, 647 | )), 648 | token('\'\'\'#'), 649 | ), 650 | 651 | interpolation: $ => seq('\\(', $.expression, ')'), 652 | 653 | raw_interpolation: $ => seq('\\#(', $.expression, ')'), 654 | 655 | comment: _ => token(seq('//', /.*/)), 656 | }, 657 | }); 658 | 659 | module.exports.PREC = PREC; 660 | -------------------------------------------------------------------------------- /src/node-types.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "expression", 4 | "named": true, 5 | "subtypes": [ 6 | { 7 | "type": "binary_expression", 8 | "named": true 9 | }, 10 | { 11 | "type": "primary_expression", 12 | "named": true 13 | }, 14 | { 15 | "type": "unary_expression", 16 | "named": true 17 | } 18 | ] 19 | }, 20 | { 21 | "type": "primary_expression", 22 | "named": true, 23 | "subtypes": [ 24 | { 25 | "type": "boolean", 26 | "named": true 27 | }, 28 | { 29 | "type": "bottom", 30 | "named": true 31 | }, 32 | { 33 | "type": "call_expression", 34 | "named": true 35 | }, 36 | { 37 | "type": "float", 38 | "named": true 39 | }, 40 | { 41 | "type": "identifier", 42 | "named": true 43 | }, 44 | { 45 | "type": "index_expression", 46 | "named": true 47 | }, 48 | { 49 | "type": "list_lit", 50 | "named": true 51 | }, 52 | { 53 | "type": "null", 54 | "named": true 55 | }, 56 | { 57 | "type": "number", 58 | "named": true 59 | }, 60 | { 61 | "type": "parenthesized_expression", 62 | "named": true 63 | }, 64 | { 65 | "type": "primitive_type", 66 | "named": true 67 | }, 68 | { 69 | "type": "selector_expression", 70 | "named": true 71 | }, 72 | { 73 | "type": "si_unit", 74 | "named": true 75 | }, 76 | { 77 | "type": "string", 78 | "named": true 79 | }, 80 | { 81 | "type": "struct_lit", 82 | "named": true 83 | }, 84 | { 85 | "type": "top", 86 | "named": true 87 | } 88 | ] 89 | }, 90 | { 91 | "type": "arguments", 92 | "named": true, 93 | "fields": {}, 94 | "children": { 95 | "multiple": true, 96 | "required": false, 97 | "types": [ 98 | { 99 | "type": "expression", 100 | "named": true 101 | } 102 | ] 103 | } 104 | }, 105 | { 106 | "type": "attribute", 107 | "named": true, 108 | "fields": {}, 109 | "children": { 110 | "multiple": true, 111 | "required": true, 112 | "types": [ 113 | { 114 | "type": "attr_path", 115 | "named": true 116 | }, 117 | { 118 | "type": "boolean", 119 | "named": true 120 | }, 121 | { 122 | "type": "bottom", 123 | "named": true 124 | }, 125 | { 126 | "type": "float", 127 | "named": true 128 | }, 129 | { 130 | "type": "identifier", 131 | "named": true 132 | }, 133 | { 134 | "type": "null", 135 | "named": true 136 | }, 137 | { 138 | "type": "number", 139 | "named": true 140 | }, 141 | { 142 | "type": "package_path", 143 | "named": true 144 | }, 145 | { 146 | "type": "pointer_type", 147 | "named": true 148 | }, 149 | { 150 | "type": "primitive_type", 151 | "named": true 152 | }, 153 | { 154 | "type": "si_unit", 155 | "named": true 156 | }, 157 | { 158 | "type": "slice_type", 159 | "named": true 160 | }, 161 | { 162 | "type": "string", 163 | "named": true 164 | }, 165 | { 166 | "type": "top", 167 | "named": true 168 | } 169 | ] 170 | } 171 | }, 172 | { 173 | "type": "binary_expression", 174 | "named": true, 175 | "fields": { 176 | "left": { 177 | "multiple": false, 178 | "required": true, 179 | "types": [ 180 | { 181 | "type": "expression", 182 | "named": true 183 | } 184 | ] 185 | }, 186 | "operator": { 187 | "multiple": false, 188 | "required": true, 189 | "types": [ 190 | { 191 | "type": "!=", 192 | "named": false 193 | }, 194 | { 195 | "type": "!~", 196 | "named": false 197 | }, 198 | { 199 | "type": "&", 200 | "named": false 201 | }, 202 | { 203 | "type": "&&", 204 | "named": false 205 | }, 206 | { 207 | "type": "*", 208 | "named": false 209 | }, 210 | { 211 | "type": "+", 212 | "named": false 213 | }, 214 | { 215 | "type": "-", 216 | "named": false 217 | }, 218 | { 219 | "type": "/", 220 | "named": false 221 | }, 222 | { 223 | "type": "<", 224 | "named": false 225 | }, 226 | { 227 | "type": "<=", 228 | "named": false 229 | }, 230 | { 231 | "type": "==", 232 | "named": false 233 | }, 234 | { 235 | "type": "=~", 236 | "named": false 237 | }, 238 | { 239 | "type": ">", 240 | "named": false 241 | }, 242 | { 243 | "type": ">=", 244 | "named": false 245 | }, 246 | { 247 | "type": "|", 248 | "named": false 249 | }, 250 | { 251 | "type": "||", 252 | "named": false 253 | } 254 | ] 255 | }, 256 | "right": { 257 | "multiple": false, 258 | "required": true, 259 | "types": [ 260 | { 261 | "type": "expression", 262 | "named": true 263 | } 264 | ] 265 | } 266 | } 267 | }, 268 | { 269 | "type": "boolean", 270 | "named": true, 271 | "fields": {} 272 | }, 273 | { 274 | "type": "builtin_function", 275 | "named": true, 276 | "fields": {} 277 | }, 278 | { 279 | "type": "call_expression", 280 | "named": true, 281 | "fields": { 282 | "function": { 283 | "multiple": false, 284 | "required": true, 285 | "types": [ 286 | { 287 | "type": "builtin_function", 288 | "named": true 289 | }, 290 | { 291 | "type": "identifier", 292 | "named": true 293 | }, 294 | { 295 | "type": "selector_expression", 296 | "named": true 297 | } 298 | ] 299 | } 300 | }, 301 | "children": { 302 | "multiple": false, 303 | "required": true, 304 | "types": [ 305 | { 306 | "type": "arguments", 307 | "named": true 308 | } 309 | ] 310 | } 311 | }, 312 | { 313 | "type": "comprehension", 314 | "named": true, 315 | "fields": {}, 316 | "children": { 317 | "multiple": true, 318 | "required": true, 319 | "types": [ 320 | { 321 | "type": "for_clause", 322 | "named": true 323 | }, 324 | { 325 | "type": "guard_clause", 326 | "named": true 327 | }, 328 | { 329 | "type": "let_clause", 330 | "named": true 331 | }, 332 | { 333 | "type": "struct_lit", 334 | "named": true 335 | } 336 | ] 337 | } 338 | }, 339 | { 340 | "type": "dynamic", 341 | "named": true, 342 | "fields": {}, 343 | "children": { 344 | "multiple": false, 345 | "required": true, 346 | "types": [ 347 | { 348 | "type": "expression", 349 | "named": true 350 | } 351 | ] 352 | } 353 | }, 354 | { 355 | "type": "ellipsis", 356 | "named": true, 357 | "fields": {}, 358 | "children": { 359 | "multiple": false, 360 | "required": false, 361 | "types": [ 362 | { 363 | "type": "expression", 364 | "named": true 365 | } 366 | ] 367 | } 368 | }, 369 | { 370 | "type": "field", 371 | "named": true, 372 | "fields": {}, 373 | "children": { 374 | "multiple": true, 375 | "required": true, 376 | "types": [ 377 | { 378 | "type": "attribute", 379 | "named": true 380 | }, 381 | { 382 | "type": "label", 383 | "named": true 384 | }, 385 | { 386 | "type": "value", 387 | "named": true 388 | } 389 | ] 390 | } 391 | }, 392 | { 393 | "type": "for_clause", 394 | "named": true, 395 | "fields": {}, 396 | "children": { 397 | "multiple": true, 398 | "required": true, 399 | "types": [ 400 | { 401 | "type": "expression", 402 | "named": true 403 | }, 404 | { 405 | "type": "identifier", 406 | "named": true 407 | } 408 | ] 409 | } 410 | }, 411 | { 412 | "type": "guard_clause", 413 | "named": true, 414 | "fields": { 415 | "condition": { 416 | "multiple": false, 417 | "required": true, 418 | "types": [ 419 | { 420 | "type": "expression", 421 | "named": true 422 | } 423 | ] 424 | } 425 | } 426 | }, 427 | { 428 | "type": "import_declaration", 429 | "named": true, 430 | "fields": {}, 431 | "children": { 432 | "multiple": false, 433 | "required": true, 434 | "types": [ 435 | { 436 | "type": "import_spec", 437 | "named": true 438 | }, 439 | { 440 | "type": "import_spec_list", 441 | "named": true 442 | } 443 | ] 444 | } 445 | }, 446 | { 447 | "type": "import_spec", 448 | "named": true, 449 | "fields": { 450 | "name": { 451 | "multiple": false, 452 | "required": false, 453 | "types": [ 454 | { 455 | "type": ".", 456 | "named": false 457 | }, 458 | { 459 | "type": "_", 460 | "named": false 461 | }, 462 | { 463 | "type": "package_identifier", 464 | "named": true 465 | } 466 | ] 467 | }, 468 | "path": { 469 | "multiple": false, 470 | "required": true, 471 | "types": [ 472 | { 473 | "type": "string", 474 | "named": true 475 | } 476 | ] 477 | } 478 | } 479 | }, 480 | { 481 | "type": "import_spec_list", 482 | "named": true, 483 | "fields": {}, 484 | "children": { 485 | "multiple": true, 486 | "required": false, 487 | "types": [ 488 | { 489 | "type": "import_spec", 490 | "named": true 491 | } 492 | ] 493 | } 494 | }, 495 | { 496 | "type": "index_expression", 497 | "named": true, 498 | "fields": {}, 499 | "children": { 500 | "multiple": true, 501 | "required": true, 502 | "types": [ 503 | { 504 | "type": "expression", 505 | "named": true 506 | } 507 | ] 508 | } 509 | }, 510 | { 511 | "type": "interpolation", 512 | "named": true, 513 | "fields": {}, 514 | "children": { 515 | "multiple": false, 516 | "required": true, 517 | "types": [ 518 | { 519 | "type": "expression", 520 | "named": true 521 | } 522 | ] 523 | } 524 | }, 525 | { 526 | "type": "label", 527 | "named": true, 528 | "fields": { 529 | "alias": { 530 | "multiple": false, 531 | "required": false, 532 | "types": [ 533 | { 534 | "type": "identifier", 535 | "named": true 536 | } 537 | ] 538 | } 539 | }, 540 | "children": { 541 | "multiple": false, 542 | "required": true, 543 | "types": [ 544 | { 545 | "type": "dynamic", 546 | "named": true 547 | }, 548 | { 549 | "type": "identifier", 550 | "named": true 551 | }, 552 | { 553 | "type": "optional", 554 | "named": true 555 | }, 556 | { 557 | "type": "required", 558 | "named": true 559 | }, 560 | { 561 | "type": "selector_expression", 562 | "named": true 563 | }, 564 | { 565 | "type": "string", 566 | "named": true 567 | } 568 | ] 569 | } 570 | }, 571 | { 572 | "type": "let_clause", 573 | "named": true, 574 | "fields": { 575 | "left": { 576 | "multiple": false, 577 | "required": true, 578 | "types": [ 579 | { 580 | "type": "identifier", 581 | "named": true 582 | } 583 | ] 584 | }, 585 | "right": { 586 | "multiple": false, 587 | "required": true, 588 | "types": [ 589 | { 590 | "type": "expression", 591 | "named": true 592 | } 593 | ] 594 | } 595 | } 596 | }, 597 | { 598 | "type": "list_lit", 599 | "named": true, 600 | "fields": { 601 | "alias": { 602 | "multiple": true, 603 | "required": false, 604 | "types": [ 605 | { 606 | "type": "identifier", 607 | "named": true 608 | } 609 | ] 610 | } 611 | }, 612 | "children": { 613 | "multiple": true, 614 | "required": false, 615 | "types": [ 616 | { 617 | "type": "comprehension", 618 | "named": true 619 | }, 620 | { 621 | "type": "ellipsis", 622 | "named": true 623 | }, 624 | { 625 | "type": "expression", 626 | "named": true 627 | } 628 | ] 629 | } 630 | }, 631 | { 632 | "type": "optional", 633 | "named": true, 634 | "fields": { 635 | "alias": { 636 | "multiple": false, 637 | "required": false, 638 | "types": [ 639 | { 640 | "type": "identifier", 641 | "named": true 642 | } 643 | ] 644 | } 645 | }, 646 | "children": { 647 | "multiple": false, 648 | "required": true, 649 | "types": [ 650 | { 651 | "type": "dynamic", 652 | "named": true 653 | }, 654 | { 655 | "type": "expression", 656 | "named": true 657 | }, 658 | { 659 | "type": "identifier", 660 | "named": true 661 | }, 662 | { 663 | "type": "selector_expression", 664 | "named": true 665 | }, 666 | { 667 | "type": "string", 668 | "named": true 669 | } 670 | ] 671 | } 672 | }, 673 | { 674 | "type": "package_clause", 675 | "named": true, 676 | "fields": {}, 677 | "children": { 678 | "multiple": false, 679 | "required": true, 680 | "types": [ 681 | { 682 | "type": "package_identifier", 683 | "named": true 684 | } 685 | ] 686 | } 687 | }, 688 | { 689 | "type": "package_path", 690 | "named": true, 691 | "fields": {}, 692 | "children": { 693 | "multiple": true, 694 | "required": true, 695 | "types": [ 696 | { 697 | "type": "identifier", 698 | "named": true 699 | } 700 | ] 701 | } 702 | }, 703 | { 704 | "type": "parenthesized_expression", 705 | "named": true, 706 | "fields": {}, 707 | "children": { 708 | "multiple": false, 709 | "required": true, 710 | "types": [ 711 | { 712 | "type": "expression", 713 | "named": true 714 | } 715 | ] 716 | } 717 | }, 718 | { 719 | "type": "pointer_type", 720 | "named": true, 721 | "fields": {}, 722 | "children": { 723 | "multiple": false, 724 | "required": false, 725 | "types": [ 726 | { 727 | "type": "boolean", 728 | "named": true 729 | }, 730 | { 731 | "type": "bottom", 732 | "named": true 733 | }, 734 | { 735 | "type": "float", 736 | "named": true 737 | }, 738 | { 739 | "type": "identifier", 740 | "named": true 741 | }, 742 | { 743 | "type": "null", 744 | "named": true 745 | }, 746 | { 747 | "type": "number", 748 | "named": true 749 | }, 750 | { 751 | "type": "package_path", 752 | "named": true 753 | }, 754 | { 755 | "type": "pointer_type", 756 | "named": true 757 | }, 758 | { 759 | "type": "primitive_type", 760 | "named": true 761 | }, 762 | { 763 | "type": "si_unit", 764 | "named": true 765 | }, 766 | { 767 | "type": "slice_type", 768 | "named": true 769 | }, 770 | { 771 | "type": "string", 772 | "named": true 773 | }, 774 | { 775 | "type": "top", 776 | "named": true 777 | } 778 | ] 779 | } 780 | }, 781 | { 782 | "type": "primitive_type", 783 | "named": true, 784 | "fields": {} 785 | }, 786 | { 787 | "type": "raw_interpolation", 788 | "named": true, 789 | "fields": {}, 790 | "children": { 791 | "multiple": false, 792 | "required": true, 793 | "types": [ 794 | { 795 | "type": "expression", 796 | "named": true 797 | } 798 | ] 799 | } 800 | }, 801 | { 802 | "type": "required", 803 | "named": true, 804 | "fields": {}, 805 | "children": { 806 | "multiple": false, 807 | "required": true, 808 | "types": [ 809 | { 810 | "type": "dynamic", 811 | "named": true 812 | }, 813 | { 814 | "type": "identifier", 815 | "named": true 816 | }, 817 | { 818 | "type": "selector_expression", 819 | "named": true 820 | }, 821 | { 822 | "type": "string", 823 | "named": true 824 | } 825 | ] 826 | } 827 | }, 828 | { 829 | "type": "selector_expression", 830 | "named": true, 831 | "fields": {}, 832 | "children": { 833 | "multiple": true, 834 | "required": true, 835 | "types": [ 836 | { 837 | "type": "primary_expression", 838 | "named": true 839 | } 840 | ] 841 | } 842 | }, 843 | { 844 | "type": "si_unit", 845 | "named": true, 846 | "fields": {}, 847 | "children": { 848 | "multiple": false, 849 | "required": true, 850 | "types": [ 851 | { 852 | "type": "float", 853 | "named": true 854 | } 855 | ] 856 | } 857 | }, 858 | { 859 | "type": "slice_type", 860 | "named": true, 861 | "fields": {}, 862 | "children": { 863 | "multiple": false, 864 | "required": false, 865 | "types": [ 866 | { 867 | "type": "boolean", 868 | "named": true 869 | }, 870 | { 871 | "type": "bottom", 872 | "named": true 873 | }, 874 | { 875 | "type": "float", 876 | "named": true 877 | }, 878 | { 879 | "type": "identifier", 880 | "named": true 881 | }, 882 | { 883 | "type": "null", 884 | "named": true 885 | }, 886 | { 887 | "type": "number", 888 | "named": true 889 | }, 890 | { 891 | "type": "package_path", 892 | "named": true 893 | }, 894 | { 895 | "type": "pointer_type", 896 | "named": true 897 | }, 898 | { 899 | "type": "primitive_type", 900 | "named": true 901 | }, 902 | { 903 | "type": "si_unit", 904 | "named": true 905 | }, 906 | { 907 | "type": "slice_type", 908 | "named": true 909 | }, 910 | { 911 | "type": "string", 912 | "named": true 913 | }, 914 | { 915 | "type": "top", 916 | "named": true 917 | } 918 | ] 919 | } 920 | }, 921 | { 922 | "type": "source_file", 923 | "named": true, 924 | "root": true, 925 | "fields": { 926 | "alias": { 927 | "multiple": true, 928 | "required": false, 929 | "types": [ 930 | { 931 | "type": "identifier", 932 | "named": true 933 | } 934 | ] 935 | } 936 | }, 937 | "children": { 938 | "multiple": true, 939 | "required": false, 940 | "types": [ 941 | { 942 | "type": "attribute", 943 | "named": true 944 | }, 945 | { 946 | "type": "comprehension", 947 | "named": true 948 | }, 949 | { 950 | "type": "ellipsis", 951 | "named": true 952 | }, 953 | { 954 | "type": "expression", 955 | "named": true 956 | }, 957 | { 958 | "type": "field", 959 | "named": true 960 | }, 961 | { 962 | "type": "import_declaration", 963 | "named": true 964 | }, 965 | { 966 | "type": "let_clause", 967 | "named": true 968 | }, 969 | { 970 | "type": "package_clause", 971 | "named": true 972 | } 973 | ] 974 | } 975 | }, 976 | { 977 | "type": "string", 978 | "named": true, 979 | "fields": {}, 980 | "children": { 981 | "multiple": true, 982 | "required": false, 983 | "types": [ 984 | { 985 | "type": "escape_byte", 986 | "named": true 987 | }, 988 | { 989 | "type": "escape_char", 990 | "named": true 991 | }, 992 | { 993 | "type": "escape_unicode", 994 | "named": true 995 | }, 996 | { 997 | "type": "interpolation", 998 | "named": true 999 | }, 1000 | { 1001 | "type": "raw_interpolation", 1002 | "named": true 1003 | } 1004 | ] 1005 | } 1006 | }, 1007 | { 1008 | "type": "struct_lit", 1009 | "named": true, 1010 | "fields": { 1011 | "alias": { 1012 | "multiple": true, 1013 | "required": false, 1014 | "types": [ 1015 | { 1016 | "type": "identifier", 1017 | "named": true 1018 | } 1019 | ] 1020 | } 1021 | }, 1022 | "children": { 1023 | "multiple": true, 1024 | "required": false, 1025 | "types": [ 1026 | { 1027 | "type": "attribute", 1028 | "named": true 1029 | }, 1030 | { 1031 | "type": "comprehension", 1032 | "named": true 1033 | }, 1034 | { 1035 | "type": "ellipsis", 1036 | "named": true 1037 | }, 1038 | { 1039 | "type": "expression", 1040 | "named": true 1041 | }, 1042 | { 1043 | "type": "field", 1044 | "named": true 1045 | }, 1046 | { 1047 | "type": "let_clause", 1048 | "named": true 1049 | } 1050 | ] 1051 | } 1052 | }, 1053 | { 1054 | "type": "top", 1055 | "named": true, 1056 | "fields": {} 1057 | }, 1058 | { 1059 | "type": "unary_expression", 1060 | "named": true, 1061 | "fields": { 1062 | "argument": { 1063 | "multiple": false, 1064 | "required": true, 1065 | "types": [ 1066 | { 1067 | "type": "expression", 1068 | "named": true 1069 | } 1070 | ] 1071 | }, 1072 | "operator": { 1073 | "multiple": false, 1074 | "required": true, 1075 | "types": [ 1076 | { 1077 | "type": "!", 1078 | "named": false 1079 | }, 1080 | { 1081 | "type": "!=", 1082 | "named": false 1083 | }, 1084 | { 1085 | "type": "!~", 1086 | "named": false 1087 | }, 1088 | { 1089 | "type": "*", 1090 | "named": false 1091 | }, 1092 | { 1093 | "type": "+", 1094 | "named": false 1095 | }, 1096 | { 1097 | "type": "-", 1098 | "named": false 1099 | }, 1100 | { 1101 | "type": "<", 1102 | "named": false 1103 | }, 1104 | { 1105 | "type": "<=", 1106 | "named": false 1107 | }, 1108 | { 1109 | "type": "=~", 1110 | "named": false 1111 | }, 1112 | { 1113 | "type": ">", 1114 | "named": false 1115 | }, 1116 | { 1117 | "type": ">=", 1118 | "named": false 1119 | } 1120 | ] 1121 | } 1122 | } 1123 | }, 1124 | { 1125 | "type": "value", 1126 | "named": true, 1127 | "fields": { 1128 | "alias": { 1129 | "multiple": false, 1130 | "required": false, 1131 | "types": [ 1132 | { 1133 | "type": "identifier", 1134 | "named": true 1135 | } 1136 | ] 1137 | } 1138 | }, 1139 | "children": { 1140 | "multiple": false, 1141 | "required": true, 1142 | "types": [ 1143 | { 1144 | "type": "expression", 1145 | "named": true 1146 | } 1147 | ] 1148 | } 1149 | }, 1150 | { 1151 | "type": "!", 1152 | "named": false 1153 | }, 1154 | { 1155 | "type": "!=", 1156 | "named": false 1157 | }, 1158 | { 1159 | "type": "!~", 1160 | "named": false 1161 | }, 1162 | { 1163 | "type": "\"", 1164 | "named": false 1165 | }, 1166 | { 1167 | "type": "\"\"\"", 1168 | "named": false 1169 | }, 1170 | { 1171 | "type": "\"\"\"#", 1172 | "named": false 1173 | }, 1174 | { 1175 | "type": "\"#", 1176 | "named": false 1177 | }, 1178 | { 1179 | "type": "#\"", 1180 | "named": false 1181 | }, 1182 | { 1183 | "type": "#\"\"\"", 1184 | "named": false 1185 | }, 1186 | { 1187 | "type": "#'", 1188 | "named": false 1189 | }, 1190 | { 1191 | "type": "#'''", 1192 | "named": false 1193 | }, 1194 | { 1195 | "type": "&", 1196 | "named": false 1197 | }, 1198 | { 1199 | "type": "&&", 1200 | "named": false 1201 | }, 1202 | { 1203 | "type": "'", 1204 | "named": false 1205 | }, 1206 | { 1207 | "type": "'#", 1208 | "named": false 1209 | }, 1210 | { 1211 | "type": "'''", 1212 | "named": false 1213 | }, 1214 | { 1215 | "type": "'''#", 1216 | "named": false 1217 | }, 1218 | { 1219 | "type": "(", 1220 | "named": false 1221 | }, 1222 | { 1223 | "type": ")", 1224 | "named": false 1225 | }, 1226 | { 1227 | "type": "*", 1228 | "named": false 1229 | }, 1230 | { 1231 | "type": "+", 1232 | "named": false 1233 | }, 1234 | { 1235 | "type": ",", 1236 | "named": false 1237 | }, 1238 | { 1239 | "type": "-", 1240 | "named": false 1241 | }, 1242 | { 1243 | "type": ".", 1244 | "named": false 1245 | }, 1246 | { 1247 | "type": "...", 1248 | "named": false 1249 | }, 1250 | { 1251 | "type": "/", 1252 | "named": false 1253 | }, 1254 | { 1255 | "type": ":", 1256 | "named": false 1257 | }, 1258 | { 1259 | "type": "<", 1260 | "named": false 1261 | }, 1262 | { 1263 | "type": "<=", 1264 | "named": false 1265 | }, 1266 | { 1267 | "type": "=", 1268 | "named": false 1269 | }, 1270 | { 1271 | "type": "==", 1272 | "named": false 1273 | }, 1274 | { 1275 | "type": "=~", 1276 | "named": false 1277 | }, 1278 | { 1279 | "type": ">", 1280 | "named": false 1281 | }, 1282 | { 1283 | "type": ">=", 1284 | "named": false 1285 | }, 1286 | { 1287 | "type": "?", 1288 | "named": false 1289 | }, 1290 | { 1291 | "type": "@", 1292 | "named": false 1293 | }, 1294 | { 1295 | "type": "[", 1296 | "named": false 1297 | }, 1298 | { 1299 | "type": "\\#(", 1300 | "named": false 1301 | }, 1302 | { 1303 | "type": "\\(", 1304 | "named": false 1305 | }, 1306 | { 1307 | "type": "]", 1308 | "named": false 1309 | }, 1310 | { 1311 | "type": "_", 1312 | "named": false 1313 | }, 1314 | { 1315 | "type": "and", 1316 | "named": false 1317 | }, 1318 | { 1319 | "type": "attr_path", 1320 | "named": true 1321 | }, 1322 | { 1323 | "type": "bool", 1324 | "named": false 1325 | }, 1326 | { 1327 | "type": "bottom", 1328 | "named": true 1329 | }, 1330 | { 1331 | "type": "bytes", 1332 | "named": false 1333 | }, 1334 | { 1335 | "type": "close", 1336 | "named": false 1337 | }, 1338 | { 1339 | "type": "comment", 1340 | "named": true 1341 | }, 1342 | { 1343 | "type": "div", 1344 | "named": false 1345 | }, 1346 | { 1347 | "type": "escape_byte", 1348 | "named": true 1349 | }, 1350 | { 1351 | "type": "escape_char", 1352 | "named": true 1353 | }, 1354 | { 1355 | "type": "escape_unicode", 1356 | "named": true 1357 | }, 1358 | { 1359 | "type": "false", 1360 | "named": false 1361 | }, 1362 | { 1363 | "type": "float", 1364 | "named": true 1365 | }, 1366 | { 1367 | "type": "float", 1368 | "named": false 1369 | }, 1370 | { 1371 | "type": "float32", 1372 | "named": false 1373 | }, 1374 | { 1375 | "type": "float64", 1376 | "named": false 1377 | }, 1378 | { 1379 | "type": "for", 1380 | "named": false 1381 | }, 1382 | { 1383 | "type": "identifier", 1384 | "named": true 1385 | }, 1386 | { 1387 | "type": "if", 1388 | "named": false 1389 | }, 1390 | { 1391 | "type": "import", 1392 | "named": false 1393 | }, 1394 | { 1395 | "type": "in", 1396 | "named": false 1397 | }, 1398 | { 1399 | "type": "int", 1400 | "named": false 1401 | }, 1402 | { 1403 | "type": "int128", 1404 | "named": false 1405 | }, 1406 | { 1407 | "type": "int16", 1408 | "named": false 1409 | }, 1410 | { 1411 | "type": "int32", 1412 | "named": false 1413 | }, 1414 | { 1415 | "type": "int64", 1416 | "named": false 1417 | }, 1418 | { 1419 | "type": "int8", 1420 | "named": false 1421 | }, 1422 | { 1423 | "type": "len", 1424 | "named": false 1425 | }, 1426 | { 1427 | "type": "let", 1428 | "named": false 1429 | }, 1430 | { 1431 | "type": "mod", 1432 | "named": false 1433 | }, 1434 | { 1435 | "type": "null", 1436 | "named": true 1437 | }, 1438 | { 1439 | "type": "number", 1440 | "named": true 1441 | }, 1442 | { 1443 | "type": "number", 1444 | "named": false 1445 | }, 1446 | { 1447 | "type": "or", 1448 | "named": false 1449 | }, 1450 | { 1451 | "type": "package", 1452 | "named": false 1453 | }, 1454 | { 1455 | "type": "package_identifier", 1456 | "named": true 1457 | }, 1458 | { 1459 | "type": "quo", 1460 | "named": false 1461 | }, 1462 | { 1463 | "type": "rem", 1464 | "named": false 1465 | }, 1466 | { 1467 | "type": "string", 1468 | "named": false 1469 | }, 1470 | { 1471 | "type": "true", 1472 | "named": false 1473 | }, 1474 | { 1475 | "type": "uint", 1476 | "named": false 1477 | }, 1478 | { 1479 | "type": "uint128", 1480 | "named": false 1481 | }, 1482 | { 1483 | "type": "uint16", 1484 | "named": false 1485 | }, 1486 | { 1487 | "type": "uint32", 1488 | "named": false 1489 | }, 1490 | { 1491 | "type": "uint64", 1492 | "named": false 1493 | }, 1494 | { 1495 | "type": "uint8", 1496 | "named": false 1497 | }, 1498 | { 1499 | "type": "{", 1500 | "named": false 1501 | }, 1502 | { 1503 | "type": "|", 1504 | "named": false 1505 | }, 1506 | { 1507 | "type": "||", 1508 | "named": false 1509 | }, 1510 | { 1511 | "type": "}", 1512 | "named": false 1513 | } 1514 | ] --------------------------------------------------------------------------------