├── .eslintrc.js ├── .gitattributes ├── .github └── workflows │ ├── ci.yml │ ├── fuzz.yml │ ├── lint.yml │ ├── publish.yml │ └── release.yml ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── Package.swift ├── README.md ├── binding.gyp ├── bindings ├── node │ ├── binding.cc │ └── index.js ├── rust │ ├── README.md │ ├── build.rs │ └── lib.rs └── swift │ └── kdl.h ├── examples ├── 01-basic.kdl ├── 02-multiple-values.kdl ├── 03-properties.kdl ├── 04-child-nodes.kdl ├── 05-node-terminators.kdl ├── 06-string-formats.kdl ├── 07-multiline-string.kdl ├── 08-raw-string.kdl ├── 09-number.kdl ├── 10-number-forms.kdl ├── 11-number-with-underscores.kdl ├── 12-comments.kdl ├── 13-slashdash-comments.kdl ├── 14-type-annotations.kdl ├── 15-rich-example.kdl └── spec │ ├── Cargo.kdl │ ├── ci.kdl │ ├── kdl-schema.kdl │ ├── nuget.kdl │ └── website.kdl ├── grammar.js ├── package.json ├── queries ├── folds.scm ├── highlights.scm ├── indents.scm ├── injections.scm └── locals.scm ├── script ├── known_failures.txt └── parse-examples ├── src ├── grammar.json ├── node-types.json ├── parser.c ├── scanner.c └── tree_sitter │ ├── alloc.h │ ├── array.h │ └── parser.h └── test └── corpus └── node.txt /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'env': { 3 | 'commonjs': true, 4 | 'es2021': true, 5 | }, 6 | 'extends': 'google', 7 | 'overrides': [ 8 | ], 9 | 'parserOptions': { 10 | 'ecmaVersion': 'latest', 11 | 'sourceType': 'module', 12 | }, 13 | 'rules': { 14 | 'indent': ['error', 2, {'SwitchCase': 1}], 15 | 'max-len': [ 16 | 'error', 17 | {'code': 120, 'ignoreComments': true, 'ignoreUrls': true, 'ignoreStrings': true}, 18 | ], 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | /src/parser.c linguist-vendored 2 | /src/*.json linguist-vendored 3 | /examples/* linguist-vendored 4 | 5 | src/grammar.json -diff 6 | src/node-types.json -diff 7 | src/parser.c -diff 8 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 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: 18 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: 18 33 | - run: npm install 34 | - run: npm run-script test-windows 35 | -------------------------------------------------------------------------------- /.github/workflows/fuzz.yml: -------------------------------------------------------------------------------- 1 | name: Fuzz Parser 2 | 3 | on: 4 | push: 5 | paths: 6 | - src/scanner.c 7 | pull_request: 8 | paths: 9 | - src/scanner.c 10 | 11 | jobs: 12 | test: 13 | name: Parser fuzzing 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | - uses: vigoux/tree-sitter-fuzz-action@v1 18 | with: 19 | language: kdl 20 | external-scanner: src/scanner.c 21 | time: 60 22 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 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 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | pull_request: 5 | types: [closed] 6 | 7 | permissions: 8 | contents: write 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: actions/setup-node@v3 16 | with: 17 | node-version: 18 18 | - run: npm install 19 | - run: npm test 20 | 21 | publish: 22 | if: github.event.pull_request.merged && startsWith(github.event.pull_request.title, 'chore(master):') 23 | needs: build 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: actions/checkout@v3 27 | with: 28 | ref: ${{ github.event.pull_request.merge_commit_sha }} 29 | token: ${{ secrets.GITHUB_TOKEN }} 30 | - name: Extract version 31 | id: extract_version 32 | run: | 33 | PR_TITLE="${{ github.event.pull_request.title }}" 34 | VERSION=$(echo "$PR_TITLE" | grep -oP '(?<=release ).*$') 35 | echo "::set-output name=version::$VERSION" 36 | - name: Update versions 37 | run: | 38 | version="${{ steps.extract_version.outputs.version }}" 39 | repo_name="${{ github.repository }}" 40 | repo_name="${repo_name##*/}" 41 | 42 | git config user.name github-actions[bot] 43 | git config user.email github-actions[bot]@users.noreply.github.com 44 | git fetch origin master 45 | git checkout master 46 | 47 | sed -i "s/\"version\": \"[^\"]*\"/\"version\": \"$version\"/g" package.json 48 | sed -i "s/version = \"[^\"]*\"/version = \"$version\"/g" Cargo.toml 49 | sed -i "s/$repo_name = \"[^\"]*\"/$repo_name = \"$version\"/g" bindings/rust/README.md 50 | 51 | git add package.json Cargo.toml bindings/rust/README.md 52 | git commit -m "chore(manifests): bump version to $version" 53 | git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git HEAD:master 54 | - name: Setup Node.js 55 | uses: actions/setup-node@v3 56 | with: 57 | node-version: 18 58 | registry-url: https://registry.npmjs.org/ 59 | - run: npm publish 60 | env: 61 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 62 | - name: Setup Rust 63 | uses: actions-rs/toolchain@v1 64 | with: 65 | profile: minimal 66 | toolchain: stable 67 | override: true 68 | - name: Publish to Crates.io 69 | uses: katyo/publish-crates@v2 70 | with: 71 | registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} 72 | - uses: actions/checkout@v3 73 | - name: Tag stable versions 74 | run: | 75 | git config user.name github-actions[bot] 76 | git config user.email github-actions[bot]@users.noreply.github.com 77 | git remote add gh-token "https://${{ secrets.GITHUB_TOKEN }}@github.com/google-github-actions/release-please-action.git" 78 | git tag -d stable || true 79 | git push origin :stable || true 80 | git tag -a stable -m "Last Stable Release" 81 | git push origin stable 82 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | workflow_dispatch: 8 | 9 | permissions: 10 | contents: write 11 | pull-requests: write 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v3 18 | - uses: actions/setup-node@v3 19 | with: 20 | node-version: 18 21 | - run: npm install 22 | - run: npm test 23 | 24 | release: 25 | name: release 26 | if: ${{ github.ref == 'refs/heads/master' }} 27 | needs: 28 | - build 29 | runs-on: ubuntu-latest 30 | steps: 31 | - uses: google-github-actions/release-please-action@v3 32 | id: release 33 | with: 34 | release-type: simple 35 | package-name: tree-sitter-kdl 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | package-lock.json 3 | /build 4 | /node_modules 5 | /examples/*/ 6 | /target 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | build 2 | examples 3 | script 4 | target 5 | test 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [1.1.0](https://github.com/amaanq/tree-sitter-kdl/compare/v1.0.3...v1.1.0) (2023-05-13) 4 | 5 | 6 | ### Features 7 | 8 | * add release action ([245f6e0](https://github.com/amaanq/tree-sitter-kdl/commit/245f6e0ba4f7a5c81ca0e1075dfc875ff9f4edd0)) 9 | 10 | 11 | ### Bug Fixes 12 | 13 | * add lint script to package.json ([e36f054](https://github.com/amaanq/tree-sitter-kdl/commit/e36f054a60c4d9e5ae29567d439fdb8790b53b30)) 14 | * rename EOF to _EOF to avoid conflicts with stdio.h ([d118f93](https://github.com/amaanq/tree-sitter-kdl/commit/d118f9376ef4f0461975289302fe74a28f073876)) 15 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tree-sitter-kdl" 3 | description = "KDL grammar for tree-sitter" 4 | version = "1.1.0" 5 | authors = [ 6 | "Amaan Qureshi ", 7 | "Andrew Hlynskyi ", 8 | ] 9 | license = "MIT" 10 | readme = "bindings/rust/README.md" 11 | keywords = ["incremental", "parsing", "kdl"] 12 | categories = ["parsing", "text-editors"] 13 | repository = "https://github.com/amaanq/tree-sitter-kdl" 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.10" 25 | 26 | [build-dependencies] 27 | cc = "1.0" 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Amaan Qureshi , Andrew Hlynskyi 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 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "TreeSitterKDL", 6 | platforms: [.macOS(.v10_13), .iOS(.v11)], 7 | products: [ 8 | .library(name: "TreeSitterKDL", targets: ["TreeSitterKDL"]), 9 | ], 10 | dependencies: [], 11 | targets: [ 12 | .target(name: "TreeSitterKDL", 13 | path: ".", 14 | exclude: [ 15 | "binding.gyp", 16 | "bindings", 17 | "Cargo.toml", 18 | "test", 19 | "examples", 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-kdl 2 | 3 | [![Build Status](https://github.com/amaanq/tree-sitter-kdl/actions/workflows/ci.yml/badge.svg)](https://github.com/amaanq/tree-sitter-kdl/actions/workflows/ci.yml) 4 | [![Discord](https://img.shields.io/discord/1063097320771698699?logo=discord)](https://discord.gg/w7nTvsVJhm) 5 | 6 | KDL grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter) 7 | 8 | Adapted from the [official spec](https://github.com/kdl-org/kdl/blob/main/SPEC.md) 9 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_kdl_binding", 5 | "include_dirs": [ 6 | " 4 | 5 | using namespace v8; 6 | 7 | extern "C" TSLanguage *tree_sitter_kdl(); 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_kdl()); 22 | 23 | Nan::Set(instance, Nan::New("name").ToLocalChecked(), 24 | Nan::New("kdl").ToLocalChecked()); 25 | Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance); 26 | } 27 | 28 | NODE_MODULE(tree_sitter_kdl_binding, Init) 29 | 30 | } // namespace 31 | -------------------------------------------------------------------------------- /bindings/node/index.js: -------------------------------------------------------------------------------- 1 | try { 2 | module.exports = require('../../build/Release/tree_sitter_kdl_binding'); 3 | } catch (error1) { 4 | if (error1.code !== 'MODULE_NOT_FOUND') { 5 | throw error1; 6 | } 7 | try { 8 | module.exports = require('../../build/Debug/tree_sitter_kdl_binding'); 9 | } catch (error2) { 10 | if (error2.code !== 'MODULE_NOT_FOUND') { 11 | throw error2; 12 | } 13 | throw error1; 14 | } 15 | } 16 | 17 | try { 18 | module.exports.nodeTypeInfo = require('../../src/node-types.json'); 19 | } catch (_) {} 20 | -------------------------------------------------------------------------------- /bindings/rust/README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-kdl 2 | 3 | This crate provides a KDL 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.10" 12 | tree-sitter-kdl = "1.1.0" 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 | contents { 21 | section "First section" { 22 | paragraph "This is the first paragraph" 23 | paragraph "This is the second paragraph" 24 | } 25 | } 26 | "#; 27 | let mut parser = Parser::new(); 28 | parser.set_language(tree_sitter_kdl::language()).expect("Error loading KDL grammar"); 29 | let parsed = parser.parse(code, None); 30 | ``` 31 | 32 | If you have any questions, please reach out to us in the [tree-sitter 33 | discussions] page. 34 | 35 | [language func]: https://docs.rs/tree-sitter-kdl/*/tree_sitter_kdl/fn.language.html 36 | [parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html 37 | [tree-sitter]: https://tree-sitter.github.io/ 38 | [tree-sitter crate]: https://crates.io/crates/tree-sitter 39 | [tree-sitter discussions]: https://github.com/tree-sitter/tree-sitter/discussions 40 | -------------------------------------------------------------------------------- /bindings/rust/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let src_dir = std::path::Path::new("src"); 3 | 4 | let mut c_config = cc::Build::new(); 5 | c_config.include(src_dir); 6 | c_config 7 | .flag_if_supported("-Wno-unused-parameter") 8 | .flag_if_supported("-Wno-unused-but-set-variable") 9 | .flag_if_supported("-Wno-trigraphs"); 10 | let parser_path = src_dir.join("parser.c"); 11 | c_config.file(&parser_path); 12 | 13 | let scanner_path = src_dir.join("scanner.c"); 14 | c_config.file(&scanner_path); 15 | println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); 16 | 17 | c_config.compile("parser"); 18 | println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); 19 | } 20 | -------------------------------------------------------------------------------- /bindings/rust/lib.rs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------------ 2 | // Copyright © 2023, Amaan Qureshi , Andrew Hlynskyi 3 | // See the LICENSE file in this repo for license details. 4 | // ------------------------------------------------------------------------------------------------ 5 | 6 | //! This crate provides KDL 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_kdl::language()).expect("Error loading KDL 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_kdl() -> 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_kdl() } 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 KDL grammar"); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /bindings/swift/kdl.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_KDL_H_ 2 | #define TREE_SITTER_KDL_H_ 3 | 4 | typedef struct TSLanguage TSLanguage; 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | extern TSLanguage *tree_sitter_kdl(); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif // TREE_SITTER_KDL_H_ 17 | -------------------------------------------------------------------------------- /examples/01-basic.kdl: -------------------------------------------------------------------------------- 1 | title "Hello, World" 2 | -------------------------------------------------------------------------------- /examples/02-multiple-values.kdl: -------------------------------------------------------------------------------- 1 | bookmarks 12 15 188 1234 2 | -------------------------------------------------------------------------------- /examples/03-properties.kdl: -------------------------------------------------------------------------------- 1 | author "Alex Monad" email="alex@example.com" active=true 2 | -------------------------------------------------------------------------------- /examples/04-child-nodes.kdl: -------------------------------------------------------------------------------- 1 | contents { 2 | section "First section" { 3 | paragraph "This is the first paragraph" 4 | paragraph "This is the second paragraph" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/05-node-terminators.kdl: -------------------------------------------------------------------------------- 1 | node1; node2; node3; 2 | -------------------------------------------------------------------------------- /examples/06-string-formats.kdl: -------------------------------------------------------------------------------- 1 | node "this\nhas\tescapes" 2 | other r"C:\Users\zkat\" 3 | -------------------------------------------------------------------------------- /examples/07-multiline-string.kdl: -------------------------------------------------------------------------------- 1 | string "my 2 | multiline 3 | value" 4 | -------------------------------------------------------------------------------- /examples/08-raw-string.kdl: -------------------------------------------------------------------------------- 1 | other-raw r#"hello"world"# 2 | -------------------------------------------------------------------------------- /examples/09-number.kdl: -------------------------------------------------------------------------------- 1 | num 1.234e-42 2 | -------------------------------------------------------------------------------- /examples/10-number-forms.kdl: -------------------------------------------------------------------------------- 1 | my-hex 0xdeadbeef 2 | my-octal 0o755 3 | my-binary 0b10101101 4 | -------------------------------------------------------------------------------- /examples/11-number-with-underscores.kdl: -------------------------------------------------------------------------------- 1 | bignum 1_000_000 2 | -------------------------------------------------------------------------------- /examples/12-comments.kdl: -------------------------------------------------------------------------------- 1 | // C style 2 | 3 | /* 4 | C style multiline 5 | */ 6 | 7 | tag /*foo=true*/ bar=false 8 | 9 | /*/* 10 | hello 11 | */*/ 12 | -------------------------------------------------------------------------------- /examples/13-slashdash-comments.kdl: -------------------------------------------------------------------------------- 1 | // This entire node and its children are all commented out. 2 | /-mynode "foo" key=1 { 3 | a 4 | b 5 | c 6 | } 7 | 8 | mynode /-"commented" "not commented" /-key="value" /-{ 9 | a 10 | b 11 | } 12 | -------------------------------------------------------------------------------- /examples/14-type-annotations.kdl: -------------------------------------------------------------------------------- 1 | numbers (u8)10 (i32)20 myfloat=(f32)1.5 { 2 | strings (uuid)"123e4567-e89b-12d3-a456-426614174000" (date)"2021-02-03" filter=(regex)r"$\d+" 3 | (author)person name="Alex" 4 | } 5 | -------------------------------------------------------------------------------- /examples/15-rich-example.kdl: -------------------------------------------------------------------------------- 1 | // Nodes can be separated into multiple lines 2 | title \ 3 | "Some title" 4 | 5 | 6 | // Files must be utf8 encoded! 7 | smile "😁" 8 | 9 | // Instead of anonymous nodes, nodes and properties can be wrapped 10 | // in "" for arbitrary node names. 11 | "!@#$@$%Q#$%~@!40" "1.2.3" "!!!!!"=true 12 | 13 | // The following is a legal bare identifier: 14 | foo123~!@#$%^&*.:'|?+ "weeee" 15 | 16 | // And you can also use unicode! 17 | ノード お名前="☜(゚ヮ゚☜)" 18 | 19 | // kdl specifically allows properties and values to be 20 | // interspersed with each other, much like CLI commands. 21 | foo bar=true "baz" quux=false 1 2 3 22 | -------------------------------------------------------------------------------- /examples/spec/Cargo.kdl: -------------------------------------------------------------------------------- 1 | package { 2 | name "kdl" 3 | version "0.0.0" 4 | description "kat's document language" 5 | authors "Kat Marchán " 6 | license-file "LICENSE.md" 7 | edition "2018" 8 | } 9 | 10 | dependencies { 11 | nom "6.0.1" 12 | thiserror "1.0.22" 13 | } 14 | -------------------------------------------------------------------------------- /examples/spec/ci.kdl: -------------------------------------------------------------------------------- 1 | // This example is a GitHub Action if it used KDL syntax. 2 | // See .github/workflows/ci.yml for the file this was based on. 3 | name "CI" 4 | 5 | on "push" "pull_request" 6 | 7 | env { 8 | RUSTFLAGS "-Dwarnings" 9 | } 10 | 11 | jobs { 12 | fmt_and_docs "Check fmt & build docs" { 13 | runs-on "ubuntu-latest" 14 | steps { 15 | step uses="actions/checkout@v1" 16 | step "Install Rust" uses="actions-rs/toolchain@v1" { 17 | profile "minimal" 18 | toolchain "stable" 19 | components "rustfmt" 20 | override true 21 | } 22 | step "rustfmt" run="cargo fmt --all -- --check" 23 | step "docs" run="cargo doc --no-deps" 24 | } 25 | } 26 | build_and_test "Build & Test" { 27 | runs-on "${{ matrix.os }}" 28 | strategy { 29 | matrix { 30 | rust "1.46.0" "stable" 31 | os "ubuntu-latest" "macOS-latest" "windows-latest" 32 | } 33 | } 34 | 35 | steps { 36 | step uses="actions/checkout@v1" 37 | step "Install Rust" uses="actions-rs/toolchain@v1" { 38 | profile "minimal" 39 | toolchain "${{ matrix.rust }}" 40 | components "clippy" 41 | override true 42 | } 43 | step "Clippy" run="cargo clippy --all -- -D warnings" 44 | step "Run tests" run="cargo test --all --verbose" 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/spec/kdl-schema.kdl: -------------------------------------------------------------------------------- 1 | document { 2 | info { 3 | title "KDL Schema" lang="en" 4 | description "KDL Schema KDL schema in KDL" lang="en" 5 | author "Kat Marchán" { 6 | link "https://github.com/zkat" rel="self" 7 | } 8 | contributor "Lars Willighagen" { 9 | link "https://github.com/larsgw" rel="self" 10 | } 11 | link "https://github.com/zkat/kdl" rel="documentation" 12 | license "Creative Commons Attribution-ShareAlike 4.0 International License" spdx="CC-BY-SA-4.0" { 13 | link "https://creativecommons.org/licenses/by-sa/4.0/" lang="en" 14 | } 15 | published "2021-08-31" 16 | modified "2021-09-01" 17 | } 18 | node "document" { 19 | min 1 20 | max 1 21 | children id="node-children" { 22 | node "node-names" id="node-names-node" description="Validations to apply specifically to arbitrary node names" { 23 | children ref=r#"[id="validations"]"# 24 | } 25 | node "other-nodes-allowed" id="other-nodes-allowed-node" description="Whether to allow child nodes other than the ones explicitly listed. Defaults to 'false'." { 26 | max 1 27 | value { 28 | min 1 29 | max 1 30 | type "boolean" 31 | } 32 | } 33 | node "tag-names" description="Validations to apply specifically to arbitrary type tag names" { 34 | children ref=r#"[id="validations"]"# 35 | } 36 | node "other-tags-allowed" description="Whether to allow child node tags other than the ones explicitly listed. Defaults to 'false'." { 37 | max 1 38 | value { 39 | min 1 40 | max 1 41 | type "boolean" 42 | } 43 | } 44 | node "info" description="A child node that describes the schema itself." { 45 | children { 46 | node "title" description="The title of the schema or the format it describes" { 47 | value description="The title text" { 48 | type "string" 49 | min 1 50 | max 1 51 | } 52 | prop "lang" id="info-lang" description="The language of the text" { 53 | type "string" 54 | } 55 | } 56 | node "description" description="A description of the schema or the format it describes" { 57 | value description="The description text" { 58 | type "string" 59 | min 1 60 | max 1 61 | } 62 | prop ref=r#"[id="info-lang"]"# 63 | } 64 | node "author" description="Author of the schema" { 65 | value id="info-person-name" description="Person name" { 66 | type "string" 67 | min 1 68 | max 1 69 | } 70 | prop "orcid" id="info-orcid" description="The ORCID of the person" { 71 | type "string" 72 | pattern r"\d{4}-\d{4}-\d{4}-\d{4}" 73 | } 74 | children { 75 | node ref=r#"[id="info-link"]"# 76 | } 77 | } 78 | node "contributor" description="Contributor to the schema" { 79 | value ref=r#"[id="info-person-name"]"# 80 | prop ref=r#"[id="info-orcid"]"# 81 | children { 82 | node ref=r#"[id="info-link"]"# 83 | } 84 | } 85 | node "link" id="info-link" description="Links to itself, and to sources describing it" { 86 | value description="A URL that the link points to" { 87 | type "string" 88 | format "url" "irl" 89 | min 1 90 | max 1 91 | } 92 | prop "rel" description="The relation between the current entity and the URL" { 93 | type "string" 94 | enum "self" "documentation" 95 | } 96 | prop ref=r#"[id="info-lang"]"# 97 | } 98 | node "license" description="The license(s) that the schema is licensed under" { 99 | value description="Name of the used license" { 100 | type "string" 101 | min 1 102 | max 1 103 | } 104 | prop "spdx" description="An SPDX license identifier" { 105 | type "string" 106 | } 107 | children { 108 | node ref=r#"[id="info-link"]"# 109 | } 110 | } 111 | node "published" description="When the schema was published" { 112 | value description="Publication date" { 113 | type "string" 114 | format "date" 115 | min 1 116 | max 1 117 | } 118 | prop "time" id="info-time" description="A time to accompany the date" { 119 | type "string" 120 | format "time" 121 | } 122 | } 123 | node "modified" description="When the schema was last modified" { 124 | value description="Modification date" { 125 | type "string" 126 | format "date" 127 | min 1 128 | max 1 129 | } 130 | prop ref=r#"[id="info-time"]"# 131 | } 132 | node "version" description="The version number of this version of the schema" { 133 | value description="Semver version number" { 134 | type "string" 135 | pattern r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$" 136 | min 1 137 | max 1 138 | } 139 | } 140 | } 141 | } 142 | node "tag" id="tag-node" description="A tag belonging to a child node of `document` or another node." { 143 | value description="The name of the tag. If a tag name is not supplied, the node rules apply to _all_ nodes belonging to the parent." { 144 | type "string" 145 | max 1 146 | } 147 | prop "description" description="A description of this node's purpose." { 148 | type "string" 149 | } 150 | prop "id" description="A globally-unique ID for this node." { 151 | type "string" 152 | } 153 | prop "ref" description="A globally unique reference to another node." { 154 | type "string" 155 | format "kdl-query" 156 | } 157 | children { 158 | node ref=r#"[id="node-names-node"]"# 159 | node ref=r#"[id="other-nodes-allowed-node"]"# 160 | node ref=r#"[id="node-node"]"# 161 | } 162 | } 163 | node "node" id="node-node" description="A child node belonging either to `document` or to another `node`. Nodes may be anonymous." { 164 | value description="The name of the node. If a node name is not supplied, the node rules apply to _all_ nodes belonging to the parent." { 165 | type "string" 166 | max 1 167 | } 168 | prop "description" description="A description of this node's purpose." { 169 | type "string" 170 | } 171 | prop "id" description="A globally-unique ID for this node." { 172 | type "string" 173 | } 174 | prop "ref" description="A globally unique reference to another node." { 175 | type "string" 176 | format "kdl-query" 177 | } 178 | children { 179 | node "prop-names" description="Validations to apply specifically to arbitrary property names" { 180 | children ref=r#"[id="validations"]"# 181 | } 182 | node "other-props-allowed" description="Whether to allow properties other than the ones explicitly listed. Defaults to 'false'." { 183 | max 1 184 | value { 185 | min 1 186 | max 1 187 | type "boolean" 188 | } 189 | } 190 | node "min" description="minimum number of instances of this node in its parent's children." { 191 | max 1 192 | value { 193 | min 1 194 | max 1 195 | type "number" 196 | } 197 | } 198 | node "max" description="maximum number of instances of this node in its parent's children." { 199 | max 1 200 | value { 201 | min 1 202 | max 1 203 | type "number" 204 | } 205 | } 206 | node ref=r#"[id="value-tag-node"]"# 207 | node "prop" id="prop-node" description="A node property key/value pair." { 208 | value description="The property key." { 209 | type "string" 210 | } 211 | prop "id" description="A globally-unique ID of this property." { 212 | type "string" 213 | } 214 | prop "ref" description="A globally unique reference to another property node." { 215 | type "string" 216 | format "kdl-query" 217 | } 218 | prop "description" description="A description of this property's purpose." { 219 | type "string" 220 | } 221 | children description="Property-specific validations." { 222 | node "required" description="Whether this property is required if its parent is present." { 223 | max 1 224 | value { 225 | min 1 226 | max 1 227 | type "boolean" 228 | } 229 | } 230 | } 231 | children id="validations" description="General value validations." { 232 | node "tag" id="value-tag-node" description="The tags associated with this value" { 233 | max 1 234 | children ref=r#"[id="validations"]"# 235 | } 236 | node "type" description="The type for this prop's value." { 237 | max 1 238 | value { 239 | min 1 240 | type "string" 241 | } 242 | } 243 | node "enum" description="An enumeration of possible values" { 244 | max 1 245 | value description="Enumeration choices" { 246 | min 1 247 | } 248 | } 249 | node "pattern" description="PCRE (Regex) pattern or patterns to test prop values against." { 250 | value { 251 | min 1 252 | type "string" 253 | } 254 | } 255 | node "min-length" description="Minimum length of prop value, if it's a string." { 256 | max 1 257 | value { 258 | min 1 259 | type "number" 260 | } 261 | } 262 | node "max-length" description="Maximum length of prop value, if it's a string." { 263 | max 1 264 | value { 265 | min 1 266 | type "number" 267 | } 268 | } 269 | node "format" description="Intended data format." { 270 | max 1 271 | value { 272 | min 1 273 | type "string" 274 | // https://json-schema.org/understanding-json-schema/reference/string.html#format 275 | enum "date-time" "date" "time" "duration" "decimal" "currency" "country-2" "country-3" "country-subdivision" "email" "idn-email" "hostname" "idn-hostname" "ipv4" "ipv6" "url" "url-reference" "irl" "irl-reference" "url-template" "regex" "uuid" "kdl-query" "i8" "i16" "i32" "i64" "u8" "u16" "u32" "u64" "isize" "usize" "f32" "f64" "decimal64" "decimal128" 276 | } 277 | } 278 | node "%" description="Only used for numeric values. Constrains them to be multiples of the given number(s)" { 279 | max 1 280 | value { 281 | min 1 282 | type "number" 283 | } 284 | } 285 | node ">" description="Only used for numeric values. Constrains them to be greater than the given number(s)" { 286 | max 1 287 | value { 288 | min 1 289 | max 1 290 | type "number" 291 | } 292 | } 293 | node ">=" description="Only used for numeric values. Constrains them to be greater than or equal to the given number(s)" { 294 | max 1 295 | value { 296 | min 1 297 | max 1 298 | type "number" 299 | } 300 | } 301 | node "<" description="Only used for numeric values. Constrains them to be less than the given number(s)" { 302 | max 1 303 | value { 304 | min 1 305 | max 1 306 | type "number" 307 | } 308 | } 309 | node "<=" description="Only used for numeric values. Constrains them to be less than or equal to the given number(s)" { 310 | max 1 311 | value { 312 | min 1 313 | max 1 314 | type "number" 315 | } 316 | } 317 | } 318 | } 319 | node "value" id="value-node" description="one or more direct node values" { 320 | prop "id" description="A globally-unique ID of this value." { 321 | type "string" 322 | } 323 | prop "ref" description="A globally unique reference to another value node." { 324 | type "string" 325 | format "kdl-query" 326 | } 327 | prop "description" description="A description of this property's purpose." { 328 | type "string" 329 | } 330 | children ref=r#"[id="validations"]"# 331 | children description="Node value-specific validations" { 332 | node "min" description="minimum number of values for this node." { 333 | max 1 334 | value { 335 | min 1 336 | max 1 337 | type "number" 338 | } 339 | } 340 | node "max" description="maximum number of values for this node." { 341 | max 1 342 | value { 343 | min 1 344 | max 1 345 | type "number" 346 | } 347 | } 348 | } 349 | } 350 | node "children" id="children-node" { 351 | prop "id" description="A globally-unique ID of this children node." { 352 | type "string" 353 | } 354 | prop "ref" description="A globally unique reference to another children node." { 355 | type "string" 356 | format "kdl-query" 357 | } 358 | prop "description" description="A description of this these children's purpose." { 359 | type "string" 360 | } 361 | children ref=r#"[id="node-children"]"# 362 | } 363 | } 364 | } 365 | node "definitions" description="Definitions to reference in parts of the top-level nodes" { 366 | children { 367 | node ref=r#"[id="node-node"]"# 368 | node ref=r#"[id="value-node"]"# 369 | node ref=r#"[id="prop-node"]"# 370 | node ref=r#"[id="children-node"]"# 371 | node ref=r#"[id="tag-node"]"# 372 | } 373 | } 374 | } 375 | } 376 | } 377 | -------------------------------------------------------------------------------- /examples/spec/nuget.kdl: -------------------------------------------------------------------------------- 1 | // Based on https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Clients/NuGet.CommandLine/NuGet.CommandLine.csproj 2 | Project { 3 | PropertyGroup { 4 | IsCommandLinePackage true 5 | } 6 | 7 | Import Project=r"$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'README.md'))\build\common.props" 8 | Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" 9 | Import Project="ilmerge.props" 10 | 11 | PropertyGroup { 12 | RootNamespace "NuGet.CommandLine" 13 | AssemblyName "NuGet" 14 | AssemblyTitle "NuGet Command Line" 15 | PackageId "NuGet.CommandLine" 16 | TargetFramework "$(NETFXTargetFramework)" 17 | GenerateDocumentationFile false 18 | Description "NuGet Command Line Interface." 19 | ApplicationManifest "app.manifest" 20 | Shipping true 21 | OutputType "Exe" 22 | ComVisible false 23 | // Pack properties 24 | PackProject true 25 | IncludeBuildOutput false 26 | TargetsForTfmSpecificContentInPackage "$(TargetsForTfmSpecificContentInPackage)" "CreateCommandlineNupkg" 27 | SuppressDependenciesWhenPacking true 28 | DevelopmentDependency true 29 | PackageRequireLicenseAcceptance false 30 | UsePublicApiAnalyzer false 31 | } 32 | 33 | Target Name="CreateCommandlineNupkg" { 34 | ItemGroup { 35 | TfmSpecificPackageFile Include=r"$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe" { 36 | PackagePath "tools/" 37 | } 38 | TfmSpecificPackageFile Include=r"$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.pdb" { 39 | PackagePath "tools/" 40 | } 41 | } 42 | } 43 | 44 | ItemGroup Condition="$(DefineConstants.Contains(SIGNED_BUILD))" { 45 | AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" { 46 | _Parameter1 "NuGet.CommandLine.FuncTest, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293" 47 | } 48 | AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" { 49 | _Parameter1 "NuGet.CommandLine.Test, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293" 50 | } 51 | } 52 | 53 | ItemGroup Condition="!$(DefineConstants.Contains(SIGNED_BUILD))" { 54 | AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" { 55 | _Parameter1 "NuGet.CommandLine.FuncTest" 56 | } 57 | AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" { 58 | _Parameter1 "NuGet.CommandLine.Test" 59 | } 60 | } 61 | 62 | ItemGroup Condition="$(DefineConstants.Contains(SIGNED_BUILD))" { 63 | AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" { 64 | _Parameter1 "NuGet.CommandLine.Test, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293" 65 | } 66 | } 67 | 68 | ItemGroup Condition="!$(DefineConstants.Contains(SIGNED_BUILD))" { 69 | AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" { 70 | _Parameter1 "NuGet.CommandLine.Test" 71 | } 72 | } 73 | 74 | ItemGroup { 75 | Reference Include="Microsoft.Build.Utilities.v4.0" 76 | Reference Include="Microsoft.CSharp" 77 | Reference Include="System" 78 | Reference Include="System.ComponentModel.Composition" 79 | Reference Include="System.ComponentModel.Composition.Registration" 80 | Reference Include="System.ComponentModel.DataAnnotations" 81 | Reference Include="System.IO.Compression" 82 | Reference Include="System.Net.Http" 83 | Reference Include="System.Xml" 84 | Reference Include="System.Xml.Linq" 85 | Reference Include="NuGet.Core" { 86 | HintPath r"$(SolutionPackagesFolder)nuget.core\2.14.0-rtm-832\lib\net40-Client\NuGet.Core.dll" 87 | Aliases "CoreV2" 88 | } 89 | } 90 | ItemGroup { 91 | PackageReference Include="Microsoft.VisualStudio.Setup.Configuration.Interop" 92 | ProjectReference Include=r"$(NuGetCoreSrcDirectory)NuGet.PackageManagement\NuGet.PackageManagement.csproj" 93 | ProjectReference Include=r"$(NuGetCoreSrcDirectory)NuGet.Build.Tasks\NuGet.Build.Tasks.csproj" 94 | } 95 | 96 | ItemGroup { 97 | EmbeddedResource Update="NuGetCommand.resx" { 98 | Generator "ResXFileCodeGenerator" 99 | LastGenOutput "NuGetCommand.Designer.cs" 100 | } 101 | Compile Update="NuGetCommand.Designer.cs" { 102 | DesignTime true 103 | AutoGen true 104 | DependentUpon "NuGetCommand.resx" 105 | } 106 | EmbeddedResource Update="NuGetResources.resx" { 107 | // Strings are shared by other projects, use public strings. 108 | Generator "PublicResXFileCodeGenerator" 109 | LastGenOutput "NuGetResources.Designer.cs" 110 | } 111 | Compile Update="NuGetResources.Designer.cs" { 112 | DesignTime true 113 | AutoGen true 114 | DependentUpon "NuGetResources.resx" 115 | } 116 | } 117 | 118 | ItemGroup { 119 | EmbeddedResource Include=r"$(NuGetCoreSrcDirectory)NuGet.Build.Tasks\NuGet.targets" { 120 | Link "NuGet.targets" 121 | SubType "Designer" 122 | } 123 | } 124 | 125 | // Since we are moving some code and strings from NuGet.CommandLine to NuGet.Commands, we opted to go through normal localization process (build .resources.dll) and then add them to the ILMerged nuget.exe 126 | // This will also be called from CI build, after assemblies are localized, since our test infra takes nuget.exe before Localization 127 | Target Name="ILMergeNuGetExe" \ 128 | AfterTargets="Build" \ 129 | Condition="'$(BuildingInsideVisualStudio)' != 'true' and '$(SkipILMergeOfNuGetExe)' != 'true'" \ 130 | { 131 | PropertyGroup { 132 | // when done after build, no localizedartifacts are built yet, so expected localized artifact count is 0. 133 | ExpectedLocalizedArtifactCount 0 Condition="'$(ExpectedLocalizedArtifactCount)' == ''" 134 | } 135 | ItemGroup { 136 | BuildArtifacts Include=r"$(OutputPath)\*.dll" Exclude="@(MergeExclude)" 137 | // NuGet.exe needs all NuGet.Commands.resources.dll merged in 138 | LocalizedArtifacts Include=r"$(ArtifactsDirectory)\NuGet.Commands\**\$(NETFXTargetFramework)\**\*.resources.dll" 139 | } 140 | Error Text="Build dependencies are inconsistent with mergeinclude specified in ilmerge.props" \ 141 | Condition="'@(BuildArtifacts->Count())' != '@(MergeInclude->Count())'" 142 | Error Text="Satellite assemblies count ILMerged into NuGet.exe should be $(ExpectedLocalizedArtifactCount), but was: @(LocalizedArtifacts->Count())" \ 143 | Condition="'@(LocalizedArtifacts->Count())' != '$(ExpectedLocalizedArtifactCount)'" 144 | PropertyGroup { 145 | PathToBuiltNuGetExe "$(OutputPath)NuGet.exe" 146 | IlmergeCommand r"$(ILMergeExePath) /lib:$(OutputPath) /out:$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe @(MergeAllowDup -> '/allowdup:%(Identity)', ' ') /log:$(OutputPath)IlMergeLog.txt" 147 | IlmergeCommand Condition="Exists($(MS_PFX_PATH))" "$(IlmergeCommand) /delaysign /keyfile:$(MS_PFX_PATH)" 148 | // LocalizedArtifacts need fullpath, since there will be duplicate file names 149 | IlmergeCommand "$(IlmergeCommand) $(PathToBuiltNuGetExe) @(BuildArtifacts->'%(filename)%(extension)', ' ') @(LocalizedArtifacts->'%(fullpath)', ' ')" 150 | } 151 | MakeDir Directories="$(ArtifactsDirectory)$(VsixOutputDirName)" 152 | Exec Command="$(IlmergeCommand)" ContinueOnError="false" 153 | } 154 | 155 | Import Project="$(BuildCommonDirectory)common.targets" 156 | Import Project="$(BuildCommonDirectory)embedinterop.targets" 157 | 158 | // Do nothing. This basically strips away the framework assemblies from the resulting nuspec. 159 | Target Name="_GetFrameworkAssemblyReferences" DependsOnTargets="ResolveReferences" 160 | 161 | Target Name="GetSigningInputs" Returns="@(DllsToSign)" { 162 | ItemGroup { 163 | DllsToSign Include=r"$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe" { 164 | StrongName "MsSharedLib72" 165 | Authenticode "Microsoft400" 166 | } 167 | } 168 | } 169 | 170 | Target Name="GetSymbolsToIndex" Returns="@(SymbolsToIndex)" { 171 | ItemGroup { 172 | SymbolsToIndex Include=r"$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe" 173 | SymbolsToIndex Include=r"$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.pdb" 174 | } 175 | } 176 | 177 | Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" 178 | } 179 | -------------------------------------------------------------------------------- /examples/spec/website.kdl: -------------------------------------------------------------------------------- 1 | !doctype "html" 2 | html lang="en" { 3 | head { 4 | meta charset="utf-8" 5 | meta name="viewport" content="width=device-width, initial-scale=1.0" 6 | meta \ 7 | name="description" \ 8 | content="kdl is a document language, mostly based on SDLang, with xml-like semantics that looks like you're invoking a bunch of CLI commands!" 9 | title "kdl - Kat's Document Language" 10 | link rel="stylesheet" href="/styles/global.css" 11 | } 12 | body { 13 | main { 14 | header class="py-10 bg-gray-300" { 15 | h1 class="text-4xl text-center" "kdl - Kat's Document Language" 16 | } 17 | section class="kdl-section" id="description" { 18 | p { 19 | - "kdl is a document language, mostly based on " 20 | a href="https://sdlang.org" "SDLang" 21 | - " with xml-like semantics that looks like you're invoking a bunch of CLI commands" 22 | } 23 | p "It's meant to be used both as a serialization format and a configuration language, and is relatively light on syntax compared to XML." 24 | } 25 | section class="kdl-section" id="design-and-discussion" { 26 | h2 "Design and Discussion" 27 | p { 28 | - "kdl is still extremely new, and discussion about the format should happen over on the " 29 | a href="https://github.com/kdoclang/kdl/discussions" { 30 | - "discussions" 31 | } 32 | - " page in the Github repo. Feel free to jump in and give us your 2 cents!" 33 | } 34 | } 35 | section class="kdl-section" id="design-principles" { 36 | h2 "Design Principles" 37 | ol { 38 | li "Maintainability" 39 | li "Flexibility" 40 | li "Cognitive simplicity and Learnability" 41 | li "Ease of de/serialization" 42 | li "Ease of implementation" 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /grammar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file KDL grammar for tree-sitter 3 | * @author Amaan Qureshi 4 | * @license MIT 5 | * @see {@link https://kdl.dev|official website} 6 | * @see {@link https://github.com/kdl-org/kdl/blob/main/SPEC.md|official syntax spec} 7 | */ 8 | 9 | // deno-lint-ignore-file no-control-regex 10 | /* eslint-disable arrow-parens */ 11 | /* eslint-disable camelcase */ 12 | /* eslint-disable-next-line spaced-comment */ 13 | /// 14 | // @ts-check 15 | 16 | const ANNOTATION_BUILTINS = [ 17 | 'i8', 18 | 'i16', 19 | 'i32', 20 | 'i64', 21 | 'u8', 22 | 'u16', 23 | 'u32', 24 | 'u64', 25 | 'isize', 26 | 'usize', 27 | 'f32', 28 | 'f64', 29 | 'decimal64', 30 | 'decimal128', 31 | 'date-time', 32 | 'time', 33 | 'date', 34 | 'duration', 35 | 'decimal', 36 | 'currency', 37 | 'country-2', 38 | 'country-3', 39 | 'country-subdivision', 40 | 'email', 41 | 'idn-email', 42 | 'hostname', 43 | 'idn-hostname', 44 | 'ipv4', 45 | 'ipv6', 46 | 'url', 47 | 'url-reference', 48 | 'irl', 49 | 'iri-reference', 50 | 'url-template', 51 | 'uuid', 52 | 'regex', 53 | 'base64', 54 | ]; 55 | 56 | module.exports = grammar({ 57 | name: 'kdl', 58 | 59 | conflicts: $ => [ 60 | [$.document], 61 | [$._node_space], 62 | [$.node_children], 63 | ], 64 | 65 | externals: $ => [ 66 | $._eof, 67 | $.multi_line_comment, 68 | $._raw_string, 69 | ], 70 | 71 | extras: $ => [$.multi_line_comment], 72 | 73 | word: $ => $._normal_bare_identifier, 74 | 75 | rules: { 76 | // nodes := linespace* (node nodes?)? linespace* 77 | document: $ => 78 | seq( 79 | repeat($._linespace), 80 | optional(seq( 81 | $.node, 82 | repeat(seq( 83 | repeat($._linespace), 84 | $.node, 85 | )), 86 | )), 87 | repeat($._linespace), 88 | ), 89 | 90 | // node := ('/-' node-space*)? type? identifier (node-space+ node-prop-or-arg)* (node-space* node-children ws*)? node-space* node-terminator 91 | node: $ => prec(1, 92 | seq( 93 | alias(optional(seq('/-', repeat($._node_space))), $.node_comment), 94 | optional($.type), 95 | $.identifier, 96 | repeat(seq(repeat1($._node_space), $.node_field)), 97 | optional(seq(repeat($._node_space), field('children', $.node_children), repeat($._ws))), 98 | repeat($._node_space), 99 | $._node_terminator, 100 | ), 101 | ), 102 | 103 | // node-prop-or-arg (field) := ('/-' node-space*)? (prop | value) 104 | // _node_prop_or_arg: $ => 105 | // seq( 106 | // alias(optional(seq('/-', repeat($._node_space))), $.node_prop_or_arg_slash_dash), 107 | // field('node_prop_or_arg', choice($.prop, $.value)), 108 | // ), 109 | node_field: $ => choice($._node_field_comment, $._node_field), 110 | _node_field_comment: $ => alias(seq('/-', repeat($._node_space), $._node_field), $.node_field_comment), 111 | _node_field: $ => choice($.prop, $.value), 112 | // node-children := ('/-' node-space*)? '{' nodes '}' 113 | node_children: $ => 114 | seq( 115 | optional(seq(alias('/-', $.node_children_comment), repeat($._node_space))), 116 | '{', 117 | seq( 118 | repeat($._linespace), 119 | optional(seq($.node, repeat(seq(repeat($._linespace), $.node)))), 120 | repeat($._linespace), 121 | ), 122 | '}', 123 | ), 124 | // node-space := ws* escline ws* | ws+ 125 | _node_space: $ => 126 | choice( 127 | seq(repeat($._ws), $._escline, repeat($._ws)), 128 | repeat1($._ws), 129 | ), 130 | // node-terminator := single-line-comment | newline | ';' | eof 131 | _node_terminator: $ => 132 | choice($.single_line_comment, $._newline, ';', $._eof), 133 | 134 | // identifier := string | bare-identifier 135 | identifier: $ => choice($.string, $._bare_identifier), 136 | // bare-identifier := ((identifier-char - digit - sign) identifier-char* | sign ((identifier-char - digit) identifier-char*)?) - keyword 137 | _bare_identifier: $ => 138 | choice( 139 | $._normal_bare_identifier, 140 | seq($._sign, optional(seq($.__identifier_char_no_digit, repeat($._identifier_char)))), 141 | ), 142 | 143 | // _normal_bare_identifier: $ => $.__identifier_char_no_digit_sign, 144 | _normal_bare_identifier: _ => token( 145 | seq( 146 | /[\u4E00-\u9FFF\p{L}\p{M}\p{N}\p{Emoji}_~!@#\$%\^&\*.:'\|\?&&[^\s\d\/(){}<>;\[\]=,"]]/, 147 | /[\u4E00-\u9FFF\p{L}\p{M}\p{N}\p{Emoji}\-_~!@#\$%\^&\*.:'\|\?+&&[^\s\/(){}<>;\[\]=,"]]*/, 148 | ), 149 | ), 150 | // identifier-char := unicode - linespace - [\/(){}<>;[]=,"] 151 | _identifier_char: _ => token( 152 | /[\u4E00-\u9FFF\p{L}\p{M}\p{N}\-_~!@#\$%\^&\*.:'\|\?+&&[^\s\/(){}<>;\[\]=,"]]/, 153 | ), 154 | 155 | // can't start with a digit 156 | __identifier_char_no_digit: _ => token( 157 | /[\u4E00-\u9FFF\p{L}\p{M}\p{N}\-_~!@#\$%\^&\*.:'\|\?+&&[^\s\d\/(){}<>;\[\]=,"]]/, 158 | ), 159 | 160 | // can't start with a digit or sign 161 | __identifier_char_no_digit_sign: _ => token( 162 | /[\u4E00-\u9FFF\p{L}\p{M}\p{N}\-_~!@#\$%\^&\*.:'\|\?&&[^\s\d\+\-\/(){}<>;\[\]=,"]]/, 163 | ), 164 | 165 | // keyword := boolean | 'null' 166 | keyword: $ => choice($.boolean, 'null'), 167 | // type annotations 168 | annotation_type: _ => choice(...ANNOTATION_BUILTINS), 169 | // prop := identifier '=' value 170 | prop: $ => seq($.identifier, '=', $.value), 171 | // value := type? (string | number | keyword) 172 | value: $ => seq(optional($.type), choice($.string, $.number, $.keyword)), 173 | // type := '(' identifier ')' 174 | type: $ => seq('(', choice($.identifier, $.annotation_type), ')'), 175 | 176 | // String 177 | // string := raw-string | escaped-string 178 | string: $ => choice($._raw_string, $._escaped_string), 179 | // escaped-string := '"' character* '"' 180 | _escaped_string: $ => seq('"', alias(repeat(choice($.escape, /[^"]/)), $.string_fragment), '"'), 181 | // character := '\' escape | [^\"] 182 | _character: $ => choice($.escape, /[^"]/), 183 | // escape := ["\\/bfnrt] | 'u{' hex-digit{1, 6} '}' 184 | escape: _ => 185 | token.immediate(/\\\\|\\"|\\\/|\\b|\\f|\\n|\\r|\\t|\\u\{[0-9a-fA-F]{1,6}\}/), 186 | // hex-digit := [0-9a-fA-F] 187 | _hex_digit: _ => /[0-9a-fA-F]/, 188 | 189 | // number := decimal | hex | octal | binary 190 | number: $ => choice($._decimal, $._hex, $._octal, $._binary), 191 | 192 | // decimal := sign? integer ('.' integer)? exponent? 193 | _decimal: $ => 194 | seq( 195 | optional($._sign), 196 | $._integer, 197 | optional(seq('.', alias($._integer, $.decimal))), 198 | optional(alias($._exponent, $.exponent)), 199 | ), 200 | 201 | // exponent := ('e' | 'E') sign? integer 202 | _exponent: $ => seq(choice('e', 'E'), optional($._sign), $._integer), 203 | // integer := digit (digit | '_')* 204 | _integer: $ => seq($._digit, repeat(choice($._digit, '_'))), 205 | // digit := [0-9] 206 | _digit: _ => /[0-9]/, 207 | // sign := '+' | '-' 208 | _sign: _ => choice('+', '-'), 209 | 210 | // hex := sign? '0x' hex-digit (hex-digit | '_')* 211 | _hex: $ => seq(optional($._sign), '0x', $._hex_digit, repeat(choice($._hex_digit, '_'))), 212 | // octal := sign? '0o' [0-7] [0-7_]* 213 | _octal: $ => seq(optional($._sign), '0o', /[0-7]/, repeat(choice(/[0-7]/, '_'))), 214 | // binary := sign? '0b' ('0' | '1') ('0' | '1' | '_')* 215 | _binary: $ => seq(optional($._sign), '0b', choice('0', '1'), repeat(choice('0', '1', '_'))), 216 | 217 | // boolean := 'true' | 'false' 218 | boolean: _ => choice('true', 'false'), 219 | 220 | // escline := '\\' ws* (single-line-comment | newline) 221 | _escline: $ => seq('\\', repeat($._ws), choice($.single_line_comment, $._newline)), 222 | 223 | // linespace := newline | ws | single-line-comment 224 | _linespace: $ => choice($._newline, $._ws, $.single_line_comment), 225 | 226 | // newline := See Table (All line-break white_space) 227 | // Newline 228 | // The following characters should be treated as new lines: 229 | // 230 | // ╭──────────────────────────────────────────────────────────╮ 231 | // │ Acronym Name Code Pt │ 232 | // │ CR Carriage Return U+000D │ 233 | // │ LF Line Feed U+000A │ 234 | // │ CRLF Carriage Return and Line Feed U+000D + U+000A │ 235 | // │ NEL Next Line U+0085 │ 236 | // │ FF Form Feed U+000C │ 237 | // │ LS Line Separator U+2028 │ 238 | // │ PS Paragraph Separator U+2029 │ 239 | // ╰──────────────────────────────────────────────────────────╯ 240 | // Note that for the purpose of new lines, CRLF is considered a single newline. 241 | _newline: _ => choice(/\r'/, /\n/, /\r\n/, /\u0085/, /\u000C/, /\u2028/, /\u2029/), 242 | 243 | // ws := bom | unicode-space | multi-line-comment 244 | _ws: $ => choice($._bom, $._unicode_space, $.multi_line_comment), 245 | 246 | // bom := '\u{FEFF}' 247 | _bom: _ => /\u{FEFF}/, 248 | 249 | // unicode-space := See Table (All White_Space unicode characters which are not `newline`) 250 | // Whitespace 251 | // The following characters should be treated as non-Newline white space: 252 | // 253 | // ╭────────────────────────────────────╮ 254 | // │ Name Code Pt │ 255 | // │ Character Tabulation U+0009 │ 256 | // │ Space U+0020 │ 257 | // │ No-Break Space U+00A0 │ 258 | // │ Ogham Space Mark U+1680 │ 259 | // │ En Quad U+2000 │ 260 | // │ Em Quad U+2001 │ 261 | // │ En Space U+2002 │ 262 | // │ Em Space U+2003 │ 263 | // │ Three-Per-Em Space U+2004 │ 264 | // │ Four-Per-Em Space U+2005 │ 265 | // │ Six-Per-Em Space U+2006 │ 266 | // │ Figure Space U+2007 │ 267 | // │ Punctuation Space U+2008 │ 268 | // │ Thin Space U+2009 │ 269 | // │ Hair Space U+200A │ 270 | // │ Narrow No-Break Space U+202F │ 271 | // │ Medium Mathematical Space U+205F │ 272 | // │ Ideographic Space U+3000 │ 273 | // ╰────────────────────────────────────╯ 274 | _unicode_space: _ => 275 | /[\u0009\u0020\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000]/, 276 | 277 | // single-line-comment := '//' ^newline+ (newline | eof) 278 | single_line_comment: $ => 279 | seq( 280 | '//', 281 | repeat(/[^\r\n\u0085\u000C\u2028\u2029]/), 282 | choice($._newline, $._eof), 283 | ), 284 | }, 285 | }); 286 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-kdl", 3 | "version": "1.1.0", 4 | "description": "KDL grammar for tree-sitter", 5 | "main": "bindings/node", 6 | "keywords": [ 7 | "parser", 8 | "lexer", 9 | "kdl" 10 | ], 11 | "author": "Amaan Qureshi ", 12 | "contributors": [ 13 | "Andrew Hlynskyi " 14 | ], 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/amaanq/tree-sitter-kdl/issues" 18 | }, 19 | "homepage": "https://github.com/amaanq/tree-sitter-kdl#readme", 20 | "dependencies": { 21 | "nan": "^2.18.0" 22 | }, 23 | "devDependencies": { 24 | "eslint": "^8.56.0", 25 | "eslint-config-google": "^0.14.0", 26 | "tree-sitter-cli": "^0.20.8", 27 | "node-gyp": "^10.0.1" 28 | }, 29 | "repository": "https://github.com/amaanq/tree-sitter-kdl", 30 | "scripts": { 31 | "build": "tree-sitter generate && node-gyp build", 32 | "lint": "eslint grammar.js", 33 | "parse": "tree-sitter parse", 34 | "test": "tree-sitter test && script/parse-examples", 35 | "test-windows": "tree-sitter test" 36 | }, 37 | "tree-sitter": [ 38 | { 39 | "scope": "source.kdl", 40 | "injection-regex": "kdl", 41 | "file-types": [ 42 | "kdl" 43 | ], 44 | "highlights": [ 45 | "queries/highlights.scm" 46 | ] 47 | } 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /queries/folds.scm: -------------------------------------------------------------------------------- 1 | ; Folds 2 | 3 | [ 4 | (node) 5 | (node_children) 6 | (string) 7 | (multi_line_comment) 8 | ] @fold 9 | -------------------------------------------------------------------------------- /queries/highlights.scm: -------------------------------------------------------------------------------- 1 | ; Types 2 | 3 | (node (identifier) @type) 4 | 5 | (type) @type 6 | 7 | (annotation_type) @type.builtin 8 | 9 | ; Properties 10 | 11 | (prop (identifier) @property) 12 | 13 | ; Variables 14 | 15 | (identifier) @variable 16 | 17 | ; Operators 18 | [ 19 | "=" 20 | "+" 21 | "-" 22 | ] @operator 23 | 24 | ; Literals 25 | 26 | (string) @string 27 | 28 | (escape) @string.escape 29 | 30 | (number) @number 31 | 32 | (number (decimal) @float) 33 | (number (exponent) @float) 34 | 35 | (boolean) @boolean 36 | 37 | "null" @constant.builtin 38 | 39 | ; Punctuation 40 | 41 | ["{" "}"] @punctuation.bracket 42 | 43 | ["(" ")"] @punctuation.bracket 44 | 45 | [ 46 | ";" 47 | ] @punctuation.delimiter 48 | 49 | ; Comments 50 | 51 | [ 52 | (single_line_comment) 53 | (multi_line_comment) 54 | ] @comment @spell 55 | 56 | (node (node_comment) (#set! "priority" 105)) @comment 57 | (node (node_field (node_field_comment) (#set! "priority" 105)) @comment) 58 | (node_children (node_children_comment) (#set! "priority" 105)) @comment 59 | -------------------------------------------------------------------------------- /queries/indents.scm: -------------------------------------------------------------------------------- 1 | (node (node_children) @indent) 2 | 3 | "}" @indent_end 4 | 5 | [ "{" "}" ] @branch 6 | 7 | [ "(" ")" ] @branch 8 | -------------------------------------------------------------------------------- /queries/injections.scm: -------------------------------------------------------------------------------- 1 | [ 2 | (single_line_comment) 3 | (multi_line_comment) 4 | ] @comment 5 | -------------------------------------------------------------------------------- /queries/locals.scm: -------------------------------------------------------------------------------- 1 | (document) @scope 2 | (node (node_children) @scope) 3 | (node_children (node) @scope) 4 | 5 | (identifier) @reference 6 | 7 | (node_field) @definition.field 8 | 9 | (node (identifier) @definition.type) 10 | (type) @definition.type 11 | -------------------------------------------------------------------------------- /script/known_failures.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tree-sitter-grammars/tree-sitter-kdl/b37e3d58e5c5cf8d739b315d6114e02d42e66664/script/known_failures.txt -------------------------------------------------------------------------------- /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 kdl-org kdl 6feeccc491808fe0b5425a18aa7ab4a8ac435e55 29 | clone_repo kdl-org kdl-rs 8c028e5ea189470f07c5c848ab778f3d63ba89ab 30 | clone_repo kdl-org kdljs bb874a595e6f712950795ecaad62f24fd945f03d 31 | clone_repo kdl-org kdl-php 390fdc5ab8e2749feb01a113e8feb028de0861b3 32 | 33 | known_failures="$(cat script/known_failures.txt)" 34 | 35 | # Remove input directories 36 | find examples -type d -name input -exec rm -rf {} + 37 | 38 | # shellcheck disable=2046 39 | tree-sitter parse -q \ 40 | 'examples/**/*.kdl' \ 41 | $(for file in $known_failures; do echo "!${file}"; done) 42 | 43 | example_count=$(find examples -name "*.kdl" | wc -l) 44 | failure_count=$(wc -w <<<"$known_failures") 45 | success_count=$((example_count - failure_count)) 46 | success_percent=$(bc -l <<<"100*${success_count}/${example_count}") 47 | 48 | printf \ 49 | "Successfully parsed %d of %d example files (%.1f%%)\n" \ 50 | "$success_count" "$example_count" "$success_percent" 51 | -------------------------------------------------------------------------------- /src/grammar.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kdl", 3 | "word": "_normal_bare_identifier", 4 | "rules": { 5 | "document": { 6 | "type": "SEQ", 7 | "members": [ 8 | { 9 | "type": "REPEAT", 10 | "content": { 11 | "type": "SYMBOL", 12 | "name": "_linespace" 13 | } 14 | }, 15 | { 16 | "type": "CHOICE", 17 | "members": [ 18 | { 19 | "type": "SEQ", 20 | "members": [ 21 | { 22 | "type": "SYMBOL", 23 | "name": "node" 24 | }, 25 | { 26 | "type": "REPEAT", 27 | "content": { 28 | "type": "SEQ", 29 | "members": [ 30 | { 31 | "type": "REPEAT", 32 | "content": { 33 | "type": "SYMBOL", 34 | "name": "_linespace" 35 | } 36 | }, 37 | { 38 | "type": "SYMBOL", 39 | "name": "node" 40 | } 41 | ] 42 | } 43 | } 44 | ] 45 | }, 46 | { 47 | "type": "BLANK" 48 | } 49 | ] 50 | }, 51 | { 52 | "type": "REPEAT", 53 | "content": { 54 | "type": "SYMBOL", 55 | "name": "_linespace" 56 | } 57 | } 58 | ] 59 | }, 60 | "node": { 61 | "type": "PREC", 62 | "value": 1, 63 | "content": { 64 | "type": "SEQ", 65 | "members": [ 66 | { 67 | "type": "ALIAS", 68 | "content": { 69 | "type": "CHOICE", 70 | "members": [ 71 | { 72 | "type": "SEQ", 73 | "members": [ 74 | { 75 | "type": "STRING", 76 | "value": "/-" 77 | }, 78 | { 79 | "type": "REPEAT", 80 | "content": { 81 | "type": "SYMBOL", 82 | "name": "_node_space" 83 | } 84 | } 85 | ] 86 | }, 87 | { 88 | "type": "BLANK" 89 | } 90 | ] 91 | }, 92 | "named": true, 93 | "value": "node_comment" 94 | }, 95 | { 96 | "type": "CHOICE", 97 | "members": [ 98 | { 99 | "type": "SYMBOL", 100 | "name": "type" 101 | }, 102 | { 103 | "type": "BLANK" 104 | } 105 | ] 106 | }, 107 | { 108 | "type": "SYMBOL", 109 | "name": "identifier" 110 | }, 111 | { 112 | "type": "REPEAT", 113 | "content": { 114 | "type": "SEQ", 115 | "members": [ 116 | { 117 | "type": "REPEAT1", 118 | "content": { 119 | "type": "SYMBOL", 120 | "name": "_node_space" 121 | } 122 | }, 123 | { 124 | "type": "SYMBOL", 125 | "name": "node_field" 126 | } 127 | ] 128 | } 129 | }, 130 | { 131 | "type": "CHOICE", 132 | "members": [ 133 | { 134 | "type": "SEQ", 135 | "members": [ 136 | { 137 | "type": "REPEAT", 138 | "content": { 139 | "type": "SYMBOL", 140 | "name": "_node_space" 141 | } 142 | }, 143 | { 144 | "type": "FIELD", 145 | "name": "children", 146 | "content": { 147 | "type": "SYMBOL", 148 | "name": "node_children" 149 | } 150 | }, 151 | { 152 | "type": "REPEAT", 153 | "content": { 154 | "type": "SYMBOL", 155 | "name": "_ws" 156 | } 157 | } 158 | ] 159 | }, 160 | { 161 | "type": "BLANK" 162 | } 163 | ] 164 | }, 165 | { 166 | "type": "REPEAT", 167 | "content": { 168 | "type": "SYMBOL", 169 | "name": "_node_space" 170 | } 171 | }, 172 | { 173 | "type": "SYMBOL", 174 | "name": "_node_terminator" 175 | } 176 | ] 177 | } 178 | }, 179 | "node_field": { 180 | "type": "CHOICE", 181 | "members": [ 182 | { 183 | "type": "SYMBOL", 184 | "name": "_node_field_comment" 185 | }, 186 | { 187 | "type": "SYMBOL", 188 | "name": "_node_field" 189 | } 190 | ] 191 | }, 192 | "_node_field_comment": { 193 | "type": "ALIAS", 194 | "content": { 195 | "type": "SEQ", 196 | "members": [ 197 | { 198 | "type": "STRING", 199 | "value": "/-" 200 | }, 201 | { 202 | "type": "REPEAT", 203 | "content": { 204 | "type": "SYMBOL", 205 | "name": "_node_space" 206 | } 207 | }, 208 | { 209 | "type": "SYMBOL", 210 | "name": "_node_field" 211 | } 212 | ] 213 | }, 214 | "named": true, 215 | "value": "node_field_comment" 216 | }, 217 | "_node_field": { 218 | "type": "CHOICE", 219 | "members": [ 220 | { 221 | "type": "SYMBOL", 222 | "name": "prop" 223 | }, 224 | { 225 | "type": "SYMBOL", 226 | "name": "value" 227 | } 228 | ] 229 | }, 230 | "node_children": { 231 | "type": "SEQ", 232 | "members": [ 233 | { 234 | "type": "CHOICE", 235 | "members": [ 236 | { 237 | "type": "SEQ", 238 | "members": [ 239 | { 240 | "type": "ALIAS", 241 | "content": { 242 | "type": "STRING", 243 | "value": "/-" 244 | }, 245 | "named": true, 246 | "value": "node_children_comment" 247 | }, 248 | { 249 | "type": "REPEAT", 250 | "content": { 251 | "type": "SYMBOL", 252 | "name": "_node_space" 253 | } 254 | } 255 | ] 256 | }, 257 | { 258 | "type": "BLANK" 259 | } 260 | ] 261 | }, 262 | { 263 | "type": "STRING", 264 | "value": "{" 265 | }, 266 | { 267 | "type": "SEQ", 268 | "members": [ 269 | { 270 | "type": "REPEAT", 271 | "content": { 272 | "type": "SYMBOL", 273 | "name": "_linespace" 274 | } 275 | }, 276 | { 277 | "type": "CHOICE", 278 | "members": [ 279 | { 280 | "type": "SEQ", 281 | "members": [ 282 | { 283 | "type": "SYMBOL", 284 | "name": "node" 285 | }, 286 | { 287 | "type": "REPEAT", 288 | "content": { 289 | "type": "SEQ", 290 | "members": [ 291 | { 292 | "type": "REPEAT", 293 | "content": { 294 | "type": "SYMBOL", 295 | "name": "_linespace" 296 | } 297 | }, 298 | { 299 | "type": "SYMBOL", 300 | "name": "node" 301 | } 302 | ] 303 | } 304 | } 305 | ] 306 | }, 307 | { 308 | "type": "BLANK" 309 | } 310 | ] 311 | }, 312 | { 313 | "type": "REPEAT", 314 | "content": { 315 | "type": "SYMBOL", 316 | "name": "_linespace" 317 | } 318 | } 319 | ] 320 | }, 321 | { 322 | "type": "STRING", 323 | "value": "}" 324 | } 325 | ] 326 | }, 327 | "_node_space": { 328 | "type": "CHOICE", 329 | "members": [ 330 | { 331 | "type": "SEQ", 332 | "members": [ 333 | { 334 | "type": "REPEAT", 335 | "content": { 336 | "type": "SYMBOL", 337 | "name": "_ws" 338 | } 339 | }, 340 | { 341 | "type": "SYMBOL", 342 | "name": "_escline" 343 | }, 344 | { 345 | "type": "REPEAT", 346 | "content": { 347 | "type": "SYMBOL", 348 | "name": "_ws" 349 | } 350 | } 351 | ] 352 | }, 353 | { 354 | "type": "REPEAT1", 355 | "content": { 356 | "type": "SYMBOL", 357 | "name": "_ws" 358 | } 359 | } 360 | ] 361 | }, 362 | "_node_terminator": { 363 | "type": "CHOICE", 364 | "members": [ 365 | { 366 | "type": "SYMBOL", 367 | "name": "single_line_comment" 368 | }, 369 | { 370 | "type": "SYMBOL", 371 | "name": "_newline" 372 | }, 373 | { 374 | "type": "STRING", 375 | "value": ";" 376 | }, 377 | { 378 | "type": "SYMBOL", 379 | "name": "_eof" 380 | } 381 | ] 382 | }, 383 | "identifier": { 384 | "type": "CHOICE", 385 | "members": [ 386 | { 387 | "type": "SYMBOL", 388 | "name": "string" 389 | }, 390 | { 391 | "type": "SYMBOL", 392 | "name": "_bare_identifier" 393 | } 394 | ] 395 | }, 396 | "_bare_identifier": { 397 | "type": "CHOICE", 398 | "members": [ 399 | { 400 | "type": "SYMBOL", 401 | "name": "_normal_bare_identifier" 402 | }, 403 | { 404 | "type": "SEQ", 405 | "members": [ 406 | { 407 | "type": "SYMBOL", 408 | "name": "_sign" 409 | }, 410 | { 411 | "type": "CHOICE", 412 | "members": [ 413 | { 414 | "type": "SEQ", 415 | "members": [ 416 | { 417 | "type": "SYMBOL", 418 | "name": "__identifier_char_no_digit" 419 | }, 420 | { 421 | "type": "REPEAT", 422 | "content": { 423 | "type": "SYMBOL", 424 | "name": "_identifier_char" 425 | } 426 | } 427 | ] 428 | }, 429 | { 430 | "type": "BLANK" 431 | } 432 | ] 433 | } 434 | ] 435 | } 436 | ] 437 | }, 438 | "_normal_bare_identifier": { 439 | "type": "TOKEN", 440 | "content": { 441 | "type": "SEQ", 442 | "members": [ 443 | { 444 | "type": "PATTERN", 445 | "value": "[\\u4E00-\\u9FFF\\p{L}\\p{M}\\p{N}\\p{Emoji}_~!@#\\$%\\^&\\*.:'\\|\\?&&[^\\s\\d\\/(){}<>;\\[\\]=,\"]]" 446 | }, 447 | { 448 | "type": "PATTERN", 449 | "value": "[\\u4E00-\\u9FFF\\p{L}\\p{M}\\p{N}\\p{Emoji}\\-_~!@#\\$%\\^&\\*.:'\\|\\?+&&[^\\s\\/(){}<>;\\[\\]=,\"]]*" 450 | } 451 | ] 452 | } 453 | }, 454 | "_identifier_char": { 455 | "type": "TOKEN", 456 | "content": { 457 | "type": "PATTERN", 458 | "value": "[\\u4E00-\\u9FFF\\p{L}\\p{M}\\p{N}\\-_~!@#\\$%\\^&\\*.:'\\|\\?+&&[^\\s\\/(){}<>;\\[\\]=,\"]]" 459 | } 460 | }, 461 | "__identifier_char_no_digit": { 462 | "type": "TOKEN", 463 | "content": { 464 | "type": "PATTERN", 465 | "value": "[\\u4E00-\\u9FFF\\p{L}\\p{M}\\p{N}\\-_~!@#\\$%\\^&\\*.:'\\|\\?+&&[^\\s\\d\\/(){}<>;\\[\\]=,\"]]" 466 | } 467 | }, 468 | "__identifier_char_no_digit_sign": { 469 | "type": "TOKEN", 470 | "content": { 471 | "type": "PATTERN", 472 | "value": "[\\u4E00-\\u9FFF\\p{L}\\p{M}\\p{N}\\-_~!@#\\$%\\^&\\*.:'\\|\\?&&[^\\s\\d\\+\\-\\/(){}<>;\\[\\]=,\"]]" 473 | } 474 | }, 475 | "keyword": { 476 | "type": "CHOICE", 477 | "members": [ 478 | { 479 | "type": "SYMBOL", 480 | "name": "boolean" 481 | }, 482 | { 483 | "type": "STRING", 484 | "value": "null" 485 | } 486 | ] 487 | }, 488 | "annotation_type": { 489 | "type": "CHOICE", 490 | "members": [ 491 | { 492 | "type": "STRING", 493 | "value": "i8" 494 | }, 495 | { 496 | "type": "STRING", 497 | "value": "i16" 498 | }, 499 | { 500 | "type": "STRING", 501 | "value": "i32" 502 | }, 503 | { 504 | "type": "STRING", 505 | "value": "i64" 506 | }, 507 | { 508 | "type": "STRING", 509 | "value": "u8" 510 | }, 511 | { 512 | "type": "STRING", 513 | "value": "u16" 514 | }, 515 | { 516 | "type": "STRING", 517 | "value": "u32" 518 | }, 519 | { 520 | "type": "STRING", 521 | "value": "u64" 522 | }, 523 | { 524 | "type": "STRING", 525 | "value": "isize" 526 | }, 527 | { 528 | "type": "STRING", 529 | "value": "usize" 530 | }, 531 | { 532 | "type": "STRING", 533 | "value": "f32" 534 | }, 535 | { 536 | "type": "STRING", 537 | "value": "f64" 538 | }, 539 | { 540 | "type": "STRING", 541 | "value": "decimal64" 542 | }, 543 | { 544 | "type": "STRING", 545 | "value": "decimal128" 546 | }, 547 | { 548 | "type": "STRING", 549 | "value": "date-time" 550 | }, 551 | { 552 | "type": "STRING", 553 | "value": "time" 554 | }, 555 | { 556 | "type": "STRING", 557 | "value": "date" 558 | }, 559 | { 560 | "type": "STRING", 561 | "value": "duration" 562 | }, 563 | { 564 | "type": "STRING", 565 | "value": "decimal" 566 | }, 567 | { 568 | "type": "STRING", 569 | "value": "currency" 570 | }, 571 | { 572 | "type": "STRING", 573 | "value": "country-2" 574 | }, 575 | { 576 | "type": "STRING", 577 | "value": "country-3" 578 | }, 579 | { 580 | "type": "STRING", 581 | "value": "country-subdivision" 582 | }, 583 | { 584 | "type": "STRING", 585 | "value": "email" 586 | }, 587 | { 588 | "type": "STRING", 589 | "value": "idn-email" 590 | }, 591 | { 592 | "type": "STRING", 593 | "value": "hostname" 594 | }, 595 | { 596 | "type": "STRING", 597 | "value": "idn-hostname" 598 | }, 599 | { 600 | "type": "STRING", 601 | "value": "ipv4" 602 | }, 603 | { 604 | "type": "STRING", 605 | "value": "ipv6" 606 | }, 607 | { 608 | "type": "STRING", 609 | "value": "url" 610 | }, 611 | { 612 | "type": "STRING", 613 | "value": "url-reference" 614 | }, 615 | { 616 | "type": "STRING", 617 | "value": "irl" 618 | }, 619 | { 620 | "type": "STRING", 621 | "value": "iri-reference" 622 | }, 623 | { 624 | "type": "STRING", 625 | "value": "url-template" 626 | }, 627 | { 628 | "type": "STRING", 629 | "value": "uuid" 630 | }, 631 | { 632 | "type": "STRING", 633 | "value": "regex" 634 | }, 635 | { 636 | "type": "STRING", 637 | "value": "base64" 638 | } 639 | ] 640 | }, 641 | "prop": { 642 | "type": "SEQ", 643 | "members": [ 644 | { 645 | "type": "SYMBOL", 646 | "name": "identifier" 647 | }, 648 | { 649 | "type": "STRING", 650 | "value": "=" 651 | }, 652 | { 653 | "type": "SYMBOL", 654 | "name": "value" 655 | } 656 | ] 657 | }, 658 | "value": { 659 | "type": "SEQ", 660 | "members": [ 661 | { 662 | "type": "CHOICE", 663 | "members": [ 664 | { 665 | "type": "SYMBOL", 666 | "name": "type" 667 | }, 668 | { 669 | "type": "BLANK" 670 | } 671 | ] 672 | }, 673 | { 674 | "type": "CHOICE", 675 | "members": [ 676 | { 677 | "type": "SYMBOL", 678 | "name": "string" 679 | }, 680 | { 681 | "type": "SYMBOL", 682 | "name": "number" 683 | }, 684 | { 685 | "type": "SYMBOL", 686 | "name": "keyword" 687 | } 688 | ] 689 | } 690 | ] 691 | }, 692 | "type": { 693 | "type": "SEQ", 694 | "members": [ 695 | { 696 | "type": "STRING", 697 | "value": "(" 698 | }, 699 | { 700 | "type": "CHOICE", 701 | "members": [ 702 | { 703 | "type": "SYMBOL", 704 | "name": "identifier" 705 | }, 706 | { 707 | "type": "SYMBOL", 708 | "name": "annotation_type" 709 | } 710 | ] 711 | }, 712 | { 713 | "type": "STRING", 714 | "value": ")" 715 | } 716 | ] 717 | }, 718 | "string": { 719 | "type": "CHOICE", 720 | "members": [ 721 | { 722 | "type": "SYMBOL", 723 | "name": "_raw_string" 724 | }, 725 | { 726 | "type": "SYMBOL", 727 | "name": "_escaped_string" 728 | } 729 | ] 730 | }, 731 | "_escaped_string": { 732 | "type": "SEQ", 733 | "members": [ 734 | { 735 | "type": "STRING", 736 | "value": "\"" 737 | }, 738 | { 739 | "type": "ALIAS", 740 | "content": { 741 | "type": "REPEAT", 742 | "content": { 743 | "type": "CHOICE", 744 | "members": [ 745 | { 746 | "type": "SYMBOL", 747 | "name": "escape" 748 | }, 749 | { 750 | "type": "PATTERN", 751 | "value": "[^\"]" 752 | } 753 | ] 754 | } 755 | }, 756 | "named": true, 757 | "value": "string_fragment" 758 | }, 759 | { 760 | "type": "STRING", 761 | "value": "\"" 762 | } 763 | ] 764 | }, 765 | "_character": { 766 | "type": "CHOICE", 767 | "members": [ 768 | { 769 | "type": "SYMBOL", 770 | "name": "escape" 771 | }, 772 | { 773 | "type": "PATTERN", 774 | "value": "[^\"]" 775 | } 776 | ] 777 | }, 778 | "escape": { 779 | "type": "IMMEDIATE_TOKEN", 780 | "content": { 781 | "type": "PATTERN", 782 | "value": "\\\\\\\\|\\\\\"|\\\\\\/|\\\\b|\\\\f|\\\\n|\\\\r|\\\\t|\\\\u\\{[0-9a-fA-F]{1,6}\\}" 783 | } 784 | }, 785 | "_hex_digit": { 786 | "type": "PATTERN", 787 | "value": "[0-9a-fA-F]" 788 | }, 789 | "number": { 790 | "type": "CHOICE", 791 | "members": [ 792 | { 793 | "type": "SYMBOL", 794 | "name": "_decimal" 795 | }, 796 | { 797 | "type": "SYMBOL", 798 | "name": "_hex" 799 | }, 800 | { 801 | "type": "SYMBOL", 802 | "name": "_octal" 803 | }, 804 | { 805 | "type": "SYMBOL", 806 | "name": "_binary" 807 | } 808 | ] 809 | }, 810 | "_decimal": { 811 | "type": "SEQ", 812 | "members": [ 813 | { 814 | "type": "CHOICE", 815 | "members": [ 816 | { 817 | "type": "SYMBOL", 818 | "name": "_sign" 819 | }, 820 | { 821 | "type": "BLANK" 822 | } 823 | ] 824 | }, 825 | { 826 | "type": "SYMBOL", 827 | "name": "_integer" 828 | }, 829 | { 830 | "type": "CHOICE", 831 | "members": [ 832 | { 833 | "type": "SEQ", 834 | "members": [ 835 | { 836 | "type": "STRING", 837 | "value": "." 838 | }, 839 | { 840 | "type": "ALIAS", 841 | "content": { 842 | "type": "SYMBOL", 843 | "name": "_integer" 844 | }, 845 | "named": true, 846 | "value": "decimal" 847 | } 848 | ] 849 | }, 850 | { 851 | "type": "BLANK" 852 | } 853 | ] 854 | }, 855 | { 856 | "type": "CHOICE", 857 | "members": [ 858 | { 859 | "type": "ALIAS", 860 | "content": { 861 | "type": "SYMBOL", 862 | "name": "_exponent" 863 | }, 864 | "named": true, 865 | "value": "exponent" 866 | }, 867 | { 868 | "type": "BLANK" 869 | } 870 | ] 871 | } 872 | ] 873 | }, 874 | "_exponent": { 875 | "type": "SEQ", 876 | "members": [ 877 | { 878 | "type": "CHOICE", 879 | "members": [ 880 | { 881 | "type": "STRING", 882 | "value": "e" 883 | }, 884 | { 885 | "type": "STRING", 886 | "value": "E" 887 | } 888 | ] 889 | }, 890 | { 891 | "type": "CHOICE", 892 | "members": [ 893 | { 894 | "type": "SYMBOL", 895 | "name": "_sign" 896 | }, 897 | { 898 | "type": "BLANK" 899 | } 900 | ] 901 | }, 902 | { 903 | "type": "SYMBOL", 904 | "name": "_integer" 905 | } 906 | ] 907 | }, 908 | "_integer": { 909 | "type": "SEQ", 910 | "members": [ 911 | { 912 | "type": "SYMBOL", 913 | "name": "_digit" 914 | }, 915 | { 916 | "type": "REPEAT", 917 | "content": { 918 | "type": "CHOICE", 919 | "members": [ 920 | { 921 | "type": "SYMBOL", 922 | "name": "_digit" 923 | }, 924 | { 925 | "type": "STRING", 926 | "value": "_" 927 | } 928 | ] 929 | } 930 | } 931 | ] 932 | }, 933 | "_digit": { 934 | "type": "PATTERN", 935 | "value": "[0-9]" 936 | }, 937 | "_sign": { 938 | "type": "CHOICE", 939 | "members": [ 940 | { 941 | "type": "STRING", 942 | "value": "+" 943 | }, 944 | { 945 | "type": "STRING", 946 | "value": "-" 947 | } 948 | ] 949 | }, 950 | "_hex": { 951 | "type": "SEQ", 952 | "members": [ 953 | { 954 | "type": "CHOICE", 955 | "members": [ 956 | { 957 | "type": "SYMBOL", 958 | "name": "_sign" 959 | }, 960 | { 961 | "type": "BLANK" 962 | } 963 | ] 964 | }, 965 | { 966 | "type": "STRING", 967 | "value": "0x" 968 | }, 969 | { 970 | "type": "SYMBOL", 971 | "name": "_hex_digit" 972 | }, 973 | { 974 | "type": "REPEAT", 975 | "content": { 976 | "type": "CHOICE", 977 | "members": [ 978 | { 979 | "type": "SYMBOL", 980 | "name": "_hex_digit" 981 | }, 982 | { 983 | "type": "STRING", 984 | "value": "_" 985 | } 986 | ] 987 | } 988 | } 989 | ] 990 | }, 991 | "_octal": { 992 | "type": "SEQ", 993 | "members": [ 994 | { 995 | "type": "CHOICE", 996 | "members": [ 997 | { 998 | "type": "SYMBOL", 999 | "name": "_sign" 1000 | }, 1001 | { 1002 | "type": "BLANK" 1003 | } 1004 | ] 1005 | }, 1006 | { 1007 | "type": "STRING", 1008 | "value": "0o" 1009 | }, 1010 | { 1011 | "type": "PATTERN", 1012 | "value": "[0-7]" 1013 | }, 1014 | { 1015 | "type": "REPEAT", 1016 | "content": { 1017 | "type": "CHOICE", 1018 | "members": [ 1019 | { 1020 | "type": "PATTERN", 1021 | "value": "[0-7]" 1022 | }, 1023 | { 1024 | "type": "STRING", 1025 | "value": "_" 1026 | } 1027 | ] 1028 | } 1029 | } 1030 | ] 1031 | }, 1032 | "_binary": { 1033 | "type": "SEQ", 1034 | "members": [ 1035 | { 1036 | "type": "CHOICE", 1037 | "members": [ 1038 | { 1039 | "type": "SYMBOL", 1040 | "name": "_sign" 1041 | }, 1042 | { 1043 | "type": "BLANK" 1044 | } 1045 | ] 1046 | }, 1047 | { 1048 | "type": "STRING", 1049 | "value": "0b" 1050 | }, 1051 | { 1052 | "type": "CHOICE", 1053 | "members": [ 1054 | { 1055 | "type": "STRING", 1056 | "value": "0" 1057 | }, 1058 | { 1059 | "type": "STRING", 1060 | "value": "1" 1061 | } 1062 | ] 1063 | }, 1064 | { 1065 | "type": "REPEAT", 1066 | "content": { 1067 | "type": "CHOICE", 1068 | "members": [ 1069 | { 1070 | "type": "STRING", 1071 | "value": "0" 1072 | }, 1073 | { 1074 | "type": "STRING", 1075 | "value": "1" 1076 | }, 1077 | { 1078 | "type": "STRING", 1079 | "value": "_" 1080 | } 1081 | ] 1082 | } 1083 | } 1084 | ] 1085 | }, 1086 | "boolean": { 1087 | "type": "CHOICE", 1088 | "members": [ 1089 | { 1090 | "type": "STRING", 1091 | "value": "true" 1092 | }, 1093 | { 1094 | "type": "STRING", 1095 | "value": "false" 1096 | } 1097 | ] 1098 | }, 1099 | "_escline": { 1100 | "type": "SEQ", 1101 | "members": [ 1102 | { 1103 | "type": "STRING", 1104 | "value": "\\" 1105 | }, 1106 | { 1107 | "type": "REPEAT", 1108 | "content": { 1109 | "type": "SYMBOL", 1110 | "name": "_ws" 1111 | } 1112 | }, 1113 | { 1114 | "type": "CHOICE", 1115 | "members": [ 1116 | { 1117 | "type": "SYMBOL", 1118 | "name": "single_line_comment" 1119 | }, 1120 | { 1121 | "type": "SYMBOL", 1122 | "name": "_newline" 1123 | } 1124 | ] 1125 | } 1126 | ] 1127 | }, 1128 | "_linespace": { 1129 | "type": "CHOICE", 1130 | "members": [ 1131 | { 1132 | "type": "SYMBOL", 1133 | "name": "_newline" 1134 | }, 1135 | { 1136 | "type": "SYMBOL", 1137 | "name": "_ws" 1138 | }, 1139 | { 1140 | "type": "SYMBOL", 1141 | "name": "single_line_comment" 1142 | } 1143 | ] 1144 | }, 1145 | "_newline": { 1146 | "type": "CHOICE", 1147 | "members": [ 1148 | { 1149 | "type": "PATTERN", 1150 | "value": "\\r'" 1151 | }, 1152 | { 1153 | "type": "PATTERN", 1154 | "value": "\\n" 1155 | }, 1156 | { 1157 | "type": "PATTERN", 1158 | "value": "\\r\\n" 1159 | }, 1160 | { 1161 | "type": "PATTERN", 1162 | "value": "\\u0085" 1163 | }, 1164 | { 1165 | "type": "PATTERN", 1166 | "value": "\\u000C" 1167 | }, 1168 | { 1169 | "type": "PATTERN", 1170 | "value": "\\u2028" 1171 | }, 1172 | { 1173 | "type": "PATTERN", 1174 | "value": "\\u2029" 1175 | } 1176 | ] 1177 | }, 1178 | "_ws": { 1179 | "type": "CHOICE", 1180 | "members": [ 1181 | { 1182 | "type": "SYMBOL", 1183 | "name": "_bom" 1184 | }, 1185 | { 1186 | "type": "SYMBOL", 1187 | "name": "_unicode_space" 1188 | }, 1189 | { 1190 | "type": "SYMBOL", 1191 | "name": "multi_line_comment" 1192 | } 1193 | ] 1194 | }, 1195 | "_bom": { 1196 | "type": "PATTERN", 1197 | "value": "\\u{FEFF}" 1198 | }, 1199 | "_unicode_space": { 1200 | "type": "PATTERN", 1201 | "value": "[\\u0009\\u0020\\u00A0\\u1680\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000]" 1202 | }, 1203 | "single_line_comment": { 1204 | "type": "SEQ", 1205 | "members": [ 1206 | { 1207 | "type": "STRING", 1208 | "value": "//" 1209 | }, 1210 | { 1211 | "type": "REPEAT", 1212 | "content": { 1213 | "type": "PATTERN", 1214 | "value": "[^\\r\\n\\u0085\\u000C\\u2028\\u2029]" 1215 | } 1216 | }, 1217 | { 1218 | "type": "CHOICE", 1219 | "members": [ 1220 | { 1221 | "type": "SYMBOL", 1222 | "name": "_newline" 1223 | }, 1224 | { 1225 | "type": "SYMBOL", 1226 | "name": "_eof" 1227 | } 1228 | ] 1229 | } 1230 | ] 1231 | } 1232 | }, 1233 | "extras": [ 1234 | { 1235 | "type": "SYMBOL", 1236 | "name": "multi_line_comment" 1237 | } 1238 | ], 1239 | "conflicts": [ 1240 | [ 1241 | "document" 1242 | ], 1243 | [ 1244 | "_node_space" 1245 | ], 1246 | [ 1247 | "node_children" 1248 | ] 1249 | ], 1250 | "precedences": [], 1251 | "externals": [ 1252 | { 1253 | "type": "SYMBOL", 1254 | "name": "_eof" 1255 | }, 1256 | { 1257 | "type": "SYMBOL", 1258 | "name": "multi_line_comment" 1259 | }, 1260 | { 1261 | "type": "SYMBOL", 1262 | "name": "_raw_string" 1263 | } 1264 | ], 1265 | "inline": [], 1266 | "supertypes": [] 1267 | } 1268 | -------------------------------------------------------------------------------- /src/node-types.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "annotation_type", 4 | "named": true, 5 | "fields": {} 6 | }, 7 | { 8 | "type": "boolean", 9 | "named": true, 10 | "fields": {} 11 | }, 12 | { 13 | "type": "decimal", 14 | "named": true, 15 | "fields": {} 16 | }, 17 | { 18 | "type": "document", 19 | "named": true, 20 | "fields": {}, 21 | "children": { 22 | "multiple": true, 23 | "required": false, 24 | "types": [ 25 | { 26 | "type": "multi_line_comment", 27 | "named": true 28 | }, 29 | { 30 | "type": "node", 31 | "named": true 32 | }, 33 | { 34 | "type": "single_line_comment", 35 | "named": true 36 | } 37 | ] 38 | } 39 | }, 40 | { 41 | "type": "exponent", 42 | "named": true, 43 | "fields": {} 44 | }, 45 | { 46 | "type": "identifier", 47 | "named": true, 48 | "fields": {}, 49 | "children": { 50 | "multiple": false, 51 | "required": false, 52 | "types": [ 53 | { 54 | "type": "string", 55 | "named": true 56 | } 57 | ] 58 | } 59 | }, 60 | { 61 | "type": "keyword", 62 | "named": true, 63 | "fields": {}, 64 | "children": { 65 | "multiple": false, 66 | "required": false, 67 | "types": [ 68 | { 69 | "type": "boolean", 70 | "named": true 71 | } 72 | ] 73 | } 74 | }, 75 | { 76 | "type": "node", 77 | "named": true, 78 | "fields": { 79 | "children": { 80 | "multiple": false, 81 | "required": false, 82 | "types": [ 83 | { 84 | "type": "node_children", 85 | "named": true 86 | } 87 | ] 88 | } 89 | }, 90 | "children": { 91 | "multiple": true, 92 | "required": true, 93 | "types": [ 94 | { 95 | "type": "identifier", 96 | "named": true 97 | }, 98 | { 99 | "type": "multi_line_comment", 100 | "named": true 101 | }, 102 | { 103 | "type": "node_comment", 104 | "named": true 105 | }, 106 | { 107 | "type": "node_field", 108 | "named": true 109 | }, 110 | { 111 | "type": "single_line_comment", 112 | "named": true 113 | }, 114 | { 115 | "type": "type", 116 | "named": true 117 | } 118 | ] 119 | } 120 | }, 121 | { 122 | "type": "node_children", 123 | "named": true, 124 | "fields": {}, 125 | "children": { 126 | "multiple": true, 127 | "required": false, 128 | "types": [ 129 | { 130 | "type": "multi_line_comment", 131 | "named": true 132 | }, 133 | { 134 | "type": "node", 135 | "named": true 136 | }, 137 | { 138 | "type": "node_children_comment", 139 | "named": true 140 | }, 141 | { 142 | "type": "single_line_comment", 143 | "named": true 144 | } 145 | ] 146 | } 147 | }, 148 | { 149 | "type": "node_comment", 150 | "named": true, 151 | "fields": {}, 152 | "children": { 153 | "multiple": true, 154 | "required": false, 155 | "types": [ 156 | { 157 | "type": "multi_line_comment", 158 | "named": true 159 | }, 160 | { 161 | "type": "single_line_comment", 162 | "named": true 163 | } 164 | ] 165 | } 166 | }, 167 | { 168 | "type": "node_field", 169 | "named": true, 170 | "fields": {}, 171 | "children": { 172 | "multiple": true, 173 | "required": true, 174 | "types": [ 175 | { 176 | "type": "node_field_comment", 177 | "named": true 178 | }, 179 | { 180 | "type": "prop", 181 | "named": true 182 | }, 183 | { 184 | "type": "value", 185 | "named": true 186 | } 187 | ] 188 | } 189 | }, 190 | { 191 | "type": "node_field_comment", 192 | "named": true, 193 | "fields": {}, 194 | "children": { 195 | "multiple": true, 196 | "required": false, 197 | "types": [ 198 | { 199 | "type": "multi_line_comment", 200 | "named": true 201 | }, 202 | { 203 | "type": "prop", 204 | "named": true 205 | }, 206 | { 207 | "type": "single_line_comment", 208 | "named": true 209 | }, 210 | { 211 | "type": "value", 212 | "named": true 213 | } 214 | ] 215 | } 216 | }, 217 | { 218 | "type": "number", 219 | "named": true, 220 | "fields": {}, 221 | "children": { 222 | "multiple": true, 223 | "required": false, 224 | "types": [ 225 | { 226 | "type": "decimal", 227 | "named": true 228 | }, 229 | { 230 | "type": "exponent", 231 | "named": true 232 | } 233 | ] 234 | } 235 | }, 236 | { 237 | "type": "prop", 238 | "named": true, 239 | "fields": {}, 240 | "children": { 241 | "multiple": true, 242 | "required": true, 243 | "types": [ 244 | { 245 | "type": "identifier", 246 | "named": true 247 | }, 248 | { 249 | "type": "value", 250 | "named": true 251 | } 252 | ] 253 | } 254 | }, 255 | { 256 | "type": "single_line_comment", 257 | "named": true, 258 | "fields": {} 259 | }, 260 | { 261 | "type": "string", 262 | "named": true, 263 | "fields": {}, 264 | "children": { 265 | "multiple": false, 266 | "required": false, 267 | "types": [ 268 | { 269 | "type": "string_fragment", 270 | "named": true 271 | } 272 | ] 273 | } 274 | }, 275 | { 276 | "type": "string_fragment", 277 | "named": true, 278 | "fields": {}, 279 | "children": { 280 | "multiple": true, 281 | "required": false, 282 | "types": [ 283 | { 284 | "type": "escape", 285 | "named": true 286 | } 287 | ] 288 | } 289 | }, 290 | { 291 | "type": "type", 292 | "named": true, 293 | "fields": {}, 294 | "children": { 295 | "multiple": false, 296 | "required": true, 297 | "types": [ 298 | { 299 | "type": "annotation_type", 300 | "named": true 301 | }, 302 | { 303 | "type": "identifier", 304 | "named": true 305 | } 306 | ] 307 | } 308 | }, 309 | { 310 | "type": "value", 311 | "named": true, 312 | "fields": {}, 313 | "children": { 314 | "multiple": true, 315 | "required": true, 316 | "types": [ 317 | { 318 | "type": "keyword", 319 | "named": true 320 | }, 321 | { 322 | "type": "number", 323 | "named": true 324 | }, 325 | { 326 | "type": "string", 327 | "named": true 328 | }, 329 | { 330 | "type": "type", 331 | "named": true 332 | } 333 | ] 334 | } 335 | }, 336 | { 337 | "type": "\"", 338 | "named": false 339 | }, 340 | { 341 | "type": "(", 342 | "named": false 343 | }, 344 | { 345 | "type": ")", 346 | "named": false 347 | }, 348 | { 349 | "type": "+", 350 | "named": false 351 | }, 352 | { 353 | "type": "-", 354 | "named": false 355 | }, 356 | { 357 | "type": ".", 358 | "named": false 359 | }, 360 | { 361 | "type": "//", 362 | "named": false 363 | }, 364 | { 365 | "type": "0", 366 | "named": false 367 | }, 368 | { 369 | "type": "0b", 370 | "named": false 371 | }, 372 | { 373 | "type": "0o", 374 | "named": false 375 | }, 376 | { 377 | "type": "0x", 378 | "named": false 379 | }, 380 | { 381 | "type": "1", 382 | "named": false 383 | }, 384 | { 385 | "type": ";", 386 | "named": false 387 | }, 388 | { 389 | "type": "=", 390 | "named": false 391 | }, 392 | { 393 | "type": "E", 394 | "named": false 395 | }, 396 | { 397 | "type": "\\", 398 | "named": false 399 | }, 400 | { 401 | "type": "_", 402 | "named": false 403 | }, 404 | { 405 | "type": "base64", 406 | "named": false 407 | }, 408 | { 409 | "type": "country-2", 410 | "named": false 411 | }, 412 | { 413 | "type": "country-3", 414 | "named": false 415 | }, 416 | { 417 | "type": "country-subdivision", 418 | "named": false 419 | }, 420 | { 421 | "type": "currency", 422 | "named": false 423 | }, 424 | { 425 | "type": "date", 426 | "named": false 427 | }, 428 | { 429 | "type": "date-time", 430 | "named": false 431 | }, 432 | { 433 | "type": "decimal", 434 | "named": false 435 | }, 436 | { 437 | "type": "decimal128", 438 | "named": false 439 | }, 440 | { 441 | "type": "decimal64", 442 | "named": false 443 | }, 444 | { 445 | "type": "duration", 446 | "named": false 447 | }, 448 | { 449 | "type": "e", 450 | "named": false 451 | }, 452 | { 453 | "type": "email", 454 | "named": false 455 | }, 456 | { 457 | "type": "escape", 458 | "named": true 459 | }, 460 | { 461 | "type": "f32", 462 | "named": false 463 | }, 464 | { 465 | "type": "f64", 466 | "named": false 467 | }, 468 | { 469 | "type": "false", 470 | "named": false 471 | }, 472 | { 473 | "type": "hostname", 474 | "named": false 475 | }, 476 | { 477 | "type": "i16", 478 | "named": false 479 | }, 480 | { 481 | "type": "i32", 482 | "named": false 483 | }, 484 | { 485 | "type": "i64", 486 | "named": false 487 | }, 488 | { 489 | "type": "i8", 490 | "named": false 491 | }, 492 | { 493 | "type": "idn-email", 494 | "named": false 495 | }, 496 | { 497 | "type": "idn-hostname", 498 | "named": false 499 | }, 500 | { 501 | "type": "ipv4", 502 | "named": false 503 | }, 504 | { 505 | "type": "ipv6", 506 | "named": false 507 | }, 508 | { 509 | "type": "iri-reference", 510 | "named": false 511 | }, 512 | { 513 | "type": "irl", 514 | "named": false 515 | }, 516 | { 517 | "type": "isize", 518 | "named": false 519 | }, 520 | { 521 | "type": "multi_line_comment", 522 | "named": true 523 | }, 524 | { 525 | "type": "node_children_comment", 526 | "named": true 527 | }, 528 | { 529 | "type": "null", 530 | "named": false 531 | }, 532 | { 533 | "type": "regex", 534 | "named": false 535 | }, 536 | { 537 | "type": "time", 538 | "named": false 539 | }, 540 | { 541 | "type": "true", 542 | "named": false 543 | }, 544 | { 545 | "type": "u16", 546 | "named": false 547 | }, 548 | { 549 | "type": "u32", 550 | "named": false 551 | }, 552 | { 553 | "type": "u64", 554 | "named": false 555 | }, 556 | { 557 | "type": "u8", 558 | "named": false 559 | }, 560 | { 561 | "type": "url", 562 | "named": false 563 | }, 564 | { 565 | "type": "url-reference", 566 | "named": false 567 | }, 568 | { 569 | "type": "url-template", 570 | "named": false 571 | }, 572 | { 573 | "type": "usize", 574 | "named": false 575 | }, 576 | { 577 | "type": "uuid", 578 | "named": false 579 | }, 580 | { 581 | "type": "{", 582 | "named": false 583 | }, 584 | { 585 | "type": "}", 586 | "named": false 587 | } 588 | ] -------------------------------------------------------------------------------- /src/scanner.c: -------------------------------------------------------------------------------- 1 | #include "tree_sitter/parser.h" 2 | #include "wctype.h" 3 | #include 4 | 5 | enum { _EOF, MULTI_LINE_COMMENT, _RAW_STRING }; 6 | 7 | void *tree_sitter_kdl_external_scanner_create() { return NULL; } 8 | 9 | void tree_sitter_kdl_external_scanner_destroy(void *payload) {} 10 | 11 | unsigned tree_sitter_kdl_external_scanner_serialize(void *payload, char *buffer) { return 0; } 12 | 13 | void tree_sitter_kdl_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {} 14 | 15 | static void advance(TSLexer *lexer) { lexer->advance(lexer, false); } 16 | 17 | bool tree_sitter_kdl_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) { 18 | // check for End-of-file 19 | if (valid_symbols[_EOF] && lexer->lookahead == 0) { 20 | lexer->result_symbol = _EOF; 21 | advance(lexer); 22 | return true; 23 | } 24 | 25 | if (valid_symbols[_RAW_STRING] && lexer->lookahead == 'r') { 26 | advance(lexer); 27 | 28 | unsigned num_hashes = 0; 29 | while (lexer->lookahead == '#') { 30 | num_hashes += 1; 31 | advance(lexer); 32 | } 33 | 34 | if (lexer->lookahead != '"') { 35 | return false; 36 | } 37 | 38 | advance(lexer); 39 | 40 | for (;;) { 41 | if (lexer->eof(lexer)) { 42 | // Unclosed raw string caused by EOF. 43 | return false; 44 | } 45 | 46 | int32_t c = lexer->lookahead; 47 | advance(lexer); 48 | 49 | if (c != '"') { 50 | continue; 51 | } 52 | 53 | // Try to match `num_hashes` closing hashes. 54 | unsigned closing_hashes = 0; 55 | for (;;) { 56 | if (closing_hashes == num_hashes) { 57 | goto success; 58 | } 59 | 60 | if (lexer->lookahead != '#') { 61 | break; 62 | } 63 | 64 | advance(lexer); 65 | 66 | closing_hashes += 1; 67 | } 68 | } 69 | 70 | success: 71 | lexer->result_symbol = _RAW_STRING; 72 | return true; 73 | } 74 | 75 | // multi-line-comment := '/*' commented-block 76 | if (lexer->lookahead == '/') { 77 | advance(lexer); 78 | if (lexer->lookahead != '*') 79 | return false; 80 | advance(lexer); 81 | 82 | bool after_star = false; 83 | unsigned nesting_depth = 1; 84 | // commented-block := '*/' | (multi-line-comment | '*' | '/' | [^*/]+) 85 | // commented-block 86 | for (;;) { 87 | switch (lexer->lookahead) { 88 | case '\0': 89 | return false; 90 | case '*': 91 | advance(lexer); 92 | after_star = true; 93 | break; 94 | case '/': 95 | if (after_star) { 96 | advance(lexer); 97 | after_star = false; 98 | nesting_depth--; 99 | if (nesting_depth == 0) { 100 | lexer->result_symbol = MULTI_LINE_COMMENT; 101 | return true; 102 | } 103 | } else { 104 | advance(lexer); 105 | after_star = false; 106 | if (lexer->lookahead == '*') { 107 | nesting_depth++; 108 | advance(lexer); 109 | } 110 | } 111 | break; 112 | default: 113 | advance(lexer); 114 | after_star = false; 115 | break; 116 | } 117 | } 118 | } 119 | 120 | return false; 121 | } 122 | -------------------------------------------------------------------------------- /src/tree_sitter/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ALLOC_H_ 2 | #define TREE_SITTER_ALLOC_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | // Allow clients to override allocation functions 13 | #ifdef TREE_SITTER_REUSE_ALLOCATOR 14 | 15 | extern void *(*ts_current_malloc)(size_t); 16 | extern void *(*ts_current_calloc)(size_t, size_t); 17 | extern void *(*ts_current_realloc)(void *, size_t); 18 | extern void (*ts_current_free)(void *); 19 | 20 | #ifndef ts_malloc 21 | #define ts_malloc ts_current_malloc 22 | #endif 23 | #ifndef ts_calloc 24 | #define ts_calloc ts_current_calloc 25 | #endif 26 | #ifndef ts_realloc 27 | #define ts_realloc ts_current_realloc 28 | #endif 29 | #ifndef ts_free 30 | #define ts_free ts_current_free 31 | #endif 32 | 33 | #else 34 | 35 | #ifndef ts_malloc 36 | #define ts_malloc malloc 37 | #endif 38 | #ifndef ts_calloc 39 | #define ts_calloc calloc 40 | #endif 41 | #ifndef ts_realloc 42 | #define ts_realloc realloc 43 | #endif 44 | #ifndef ts_free 45 | #define ts_free free 46 | #endif 47 | 48 | #endif 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif // TREE_SITTER_ALLOC_H_ 55 | -------------------------------------------------------------------------------- /src/tree_sitter/array.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ARRAY_H_ 2 | #define TREE_SITTER_ARRAY_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "./alloc.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifdef _MSC_VER 17 | #pragma warning(disable : 4101) 18 | #elif defined(__GNUC__) || defined(__clang__) 19 | #pragma GCC diagnostic push 20 | #pragma GCC diagnostic ignored "-Wunused-variable" 21 | #endif 22 | 23 | #define Array(T) \ 24 | struct { \ 25 | T *contents; \ 26 | uint32_t size; \ 27 | uint32_t capacity; \ 28 | } 29 | 30 | /// Initialize an array. 31 | #define array_init(self) \ 32 | ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) 33 | 34 | /// Create an empty array. 35 | #define array_new() \ 36 | { NULL, 0, 0 } 37 | 38 | /// Get a pointer to the element at a given `index` in the array. 39 | #define array_get(self, _index) \ 40 | (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) 41 | 42 | /// Get a pointer to the first element in the array. 43 | #define array_front(self) array_get(self, 0) 44 | 45 | /// Get a pointer to the last element in the array. 46 | #define array_back(self) array_get(self, (self)->size - 1) 47 | 48 | /// Clear the array, setting its size to zero. Note that this does not free any 49 | /// memory allocated for the array's contents. 50 | #define array_clear(self) ((self)->size = 0) 51 | 52 | /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is 53 | /// less than the array's current capacity, this function has no effect. 54 | #define array_reserve(self, new_capacity) \ 55 | _array__reserve((Array *)(self), array_elem_size(self), new_capacity) 56 | 57 | /// Free any memory allocated for this array. Note that this does not free any 58 | /// memory allocated for the array's contents. 59 | #define array_delete(self) _array__delete((Array *)(self)) 60 | 61 | /// Push a new `element` onto the end of the array. 62 | #define array_push(self, element) \ 63 | (_array__grow((Array *)(self), 1, array_elem_size(self)), \ 64 | (self)->contents[(self)->size++] = (element)) 65 | 66 | /// Increase the array's size by `count` elements. 67 | /// New elements are zero-initialized. 68 | #define array_grow_by(self, count) \ 69 | do { \ 70 | if ((count) == 0) break; \ 71 | _array__grow((Array *)(self), count, array_elem_size(self)); \ 72 | memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ 73 | (self)->size += (count); \ 74 | } while (0) 75 | 76 | /// Append all elements from one array to the end of another. 77 | #define array_push_all(self, other) \ 78 | array_extend((self), (other)->size, (other)->contents) 79 | 80 | /// Append `count` elements to the end of the array, reading their values from the 81 | /// `contents` pointer. 82 | #define array_extend(self, count, contents) \ 83 | _array__splice( \ 84 | (Array *)(self), array_elem_size(self), (self)->size, \ 85 | 0, count, contents \ 86 | ) 87 | 88 | /// Remove `old_count` elements from the array starting at the given `index`. At 89 | /// the same index, insert `new_count` new elements, reading their values from the 90 | /// `new_contents` pointer. 91 | #define array_splice(self, _index, old_count, new_count, new_contents) \ 92 | _array__splice( \ 93 | (Array *)(self), array_elem_size(self), _index, \ 94 | old_count, new_count, new_contents \ 95 | ) 96 | 97 | /// Insert one `element` into the array at the given `index`. 98 | #define array_insert(self, _index, element) \ 99 | _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element)) 100 | 101 | /// Remove one element from the array at the given `index`. 102 | #define array_erase(self, _index) \ 103 | _array__erase((Array *)(self), array_elem_size(self), _index) 104 | 105 | /// Pop the last element off the array, returning the element by value. 106 | #define array_pop(self) ((self)->contents[--(self)->size]) 107 | 108 | /// Assign the contents of one array to another, reallocating if necessary. 109 | #define array_assign(self, other) \ 110 | _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self)) 111 | 112 | /// Swap one array with another 113 | #define array_swap(self, other) \ 114 | _array__swap((Array *)(self), (Array *)(other)) 115 | 116 | /// Get the size of the array contents 117 | #define array_elem_size(self) (sizeof *(self)->contents) 118 | 119 | /// Search a sorted array for a given `needle` value, using the given `compare` 120 | /// callback to determine the order. 121 | /// 122 | /// If an existing element is found to be equal to `needle`, then the `index` 123 | /// out-parameter is set to the existing value's index, and the `exists` 124 | /// out-parameter is set to true. Otherwise, `index` is set to an index where 125 | /// `needle` should be inserted in order to preserve the sorting, and `exists` 126 | /// is set to false. 127 | #define array_search_sorted_with(self, compare, needle, _index, _exists) \ 128 | _array__search_sorted(self, 0, compare, , needle, _index, _exists) 129 | 130 | /// Search a sorted array for a given `needle` value, using integer comparisons 131 | /// of a given struct field (specified with a leading dot) to determine the order. 132 | /// 133 | /// See also `array_search_sorted_with`. 134 | #define array_search_sorted_by(self, field, needle, _index, _exists) \ 135 | _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) 136 | 137 | /// Insert a given `value` into a sorted array, using the given `compare` 138 | /// callback to determine the order. 139 | #define array_insert_sorted_with(self, compare, value) \ 140 | do { \ 141 | unsigned _index, _exists; \ 142 | array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ 143 | if (!_exists) array_insert(self, _index, value); \ 144 | } while (0) 145 | 146 | /// Insert a given `value` into a sorted array, using integer comparisons of 147 | /// a given struct field (specified with a leading dot) to determine the order. 148 | /// 149 | /// See also `array_search_sorted_by`. 150 | #define array_insert_sorted_by(self, field, value) \ 151 | do { \ 152 | unsigned _index, _exists; \ 153 | array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ 154 | if (!_exists) array_insert(self, _index, value); \ 155 | } while (0) 156 | 157 | // Private 158 | 159 | typedef Array(void) Array; 160 | 161 | /// This is not what you're looking for, see `array_delete`. 162 | static inline void _array__delete(Array *self) { 163 | if (self->contents) { 164 | ts_free(self->contents); 165 | self->contents = NULL; 166 | self->size = 0; 167 | self->capacity = 0; 168 | } 169 | } 170 | 171 | /// This is not what you're looking for, see `array_erase`. 172 | static inline void _array__erase(Array *self, size_t element_size, 173 | uint32_t index) { 174 | assert(index < self->size); 175 | char *contents = (char *)self->contents; 176 | memmove(contents + index * element_size, contents + (index + 1) * element_size, 177 | (self->size - index - 1) * element_size); 178 | self->size--; 179 | } 180 | 181 | /// This is not what you're looking for, see `array_reserve`. 182 | static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) { 183 | if (new_capacity > self->capacity) { 184 | if (self->contents) { 185 | self->contents = ts_realloc(self->contents, new_capacity * element_size); 186 | } else { 187 | self->contents = ts_malloc(new_capacity * element_size); 188 | } 189 | self->capacity = new_capacity; 190 | } 191 | } 192 | 193 | /// This is not what you're looking for, see `array_assign`. 194 | static inline void _array__assign(Array *self, const Array *other, size_t element_size) { 195 | _array__reserve(self, element_size, other->size); 196 | self->size = other->size; 197 | memcpy(self->contents, other->contents, self->size * element_size); 198 | } 199 | 200 | /// This is not what you're looking for, see `array_swap`. 201 | static inline void _array__swap(Array *self, Array *other) { 202 | Array swap = *other; 203 | *other = *self; 204 | *self = swap; 205 | } 206 | 207 | /// This is not what you're looking for, see `array_push` or `array_grow_by`. 208 | static inline void _array__grow(Array *self, uint32_t count, size_t element_size) { 209 | uint32_t new_size = self->size + count; 210 | if (new_size > self->capacity) { 211 | uint32_t new_capacity = self->capacity * 2; 212 | if (new_capacity < 8) new_capacity = 8; 213 | if (new_capacity < new_size) new_capacity = new_size; 214 | _array__reserve(self, element_size, new_capacity); 215 | } 216 | } 217 | 218 | /// This is not what you're looking for, see `array_splice`. 219 | static inline void _array__splice(Array *self, size_t element_size, 220 | uint32_t index, uint32_t old_count, 221 | uint32_t new_count, const void *elements) { 222 | uint32_t new_size = self->size + new_count - old_count; 223 | uint32_t old_end = index + old_count; 224 | uint32_t new_end = index + new_count; 225 | assert(old_end <= self->size); 226 | 227 | _array__reserve(self, element_size, new_size); 228 | 229 | char *contents = (char *)self->contents; 230 | if (self->size > old_end) { 231 | memmove( 232 | contents + new_end * element_size, 233 | contents + old_end * element_size, 234 | (self->size - old_end) * element_size 235 | ); 236 | } 237 | if (new_count > 0) { 238 | if (elements) { 239 | memcpy( 240 | (contents + index * element_size), 241 | elements, 242 | new_count * element_size 243 | ); 244 | } else { 245 | memset( 246 | (contents + index * element_size), 247 | 0, 248 | new_count * element_size 249 | ); 250 | } 251 | } 252 | self->size += new_count - old_count; 253 | } 254 | 255 | /// A binary search routine, based on Rust's `std::slice::binary_search_by`. 256 | /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. 257 | #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ 258 | do { \ 259 | *(_index) = start; \ 260 | *(_exists) = false; \ 261 | uint32_t size = (self)->size - *(_index); \ 262 | if (size == 0) break; \ 263 | int comparison; \ 264 | while (size > 1) { \ 265 | uint32_t half_size = size / 2; \ 266 | uint32_t mid_index = *(_index) + half_size; \ 267 | comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ 268 | if (comparison <= 0) *(_index) = mid_index; \ 269 | size -= half_size; \ 270 | } \ 271 | comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ 272 | if (comparison == 0) *(_exists) = true; \ 273 | else if (comparison < 0) *(_index) += 1; \ 274 | } while (0) 275 | 276 | /// Helper macro for the `_sorted_by` routines below. This takes the left (existing) 277 | /// parameter by reference in order to work with the generic sorting function above. 278 | #define _compare_int(a, b) ((int)*(a) - (int)(b)) 279 | 280 | #ifdef _MSC_VER 281 | #pragma warning(default : 4101) 282 | #elif defined(__GNUC__) || defined(__clang__) 283 | #pragma GCC diagnostic pop 284 | #endif 285 | 286 | #ifdef __cplusplus 287 | } 288 | #endif 289 | 290 | #endif // TREE_SITTER_ARRAY_H_ 291 | -------------------------------------------------------------------------------- /src/tree_sitter/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_PARSER_H_ 2 | #define TREE_SITTER_PARSER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define ts_builtin_sym_error ((TSSymbol)-1) 13 | #define ts_builtin_sym_end 0 14 | #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 15 | 16 | #ifndef TREE_SITTER_API_H_ 17 | typedef uint16_t TSStateId; 18 | typedef uint16_t TSSymbol; 19 | typedef uint16_t TSFieldId; 20 | typedef struct TSLanguage TSLanguage; 21 | #endif 22 | 23 | typedef struct { 24 | TSFieldId field_id; 25 | uint8_t child_index; 26 | bool inherited; 27 | } TSFieldMapEntry; 28 | 29 | typedef struct { 30 | uint16_t index; 31 | uint16_t length; 32 | } TSFieldMapSlice; 33 | 34 | typedef struct { 35 | bool visible; 36 | bool named; 37 | bool supertype; 38 | } TSSymbolMetadata; 39 | 40 | typedef struct TSLexer TSLexer; 41 | 42 | struct TSLexer { 43 | int32_t lookahead; 44 | TSSymbol result_symbol; 45 | void (*advance)(TSLexer *, bool); 46 | void (*mark_end)(TSLexer *); 47 | uint32_t (*get_column)(TSLexer *); 48 | bool (*is_at_included_range_start)(const TSLexer *); 49 | bool (*eof)(const TSLexer *); 50 | }; 51 | 52 | typedef enum { 53 | TSParseActionTypeShift, 54 | TSParseActionTypeReduce, 55 | TSParseActionTypeAccept, 56 | TSParseActionTypeRecover, 57 | } TSParseActionType; 58 | 59 | typedef union { 60 | struct { 61 | uint8_t type; 62 | TSStateId state; 63 | bool extra; 64 | bool repetition; 65 | } shift; 66 | struct { 67 | uint8_t type; 68 | uint8_t child_count; 69 | TSSymbol symbol; 70 | int16_t dynamic_precedence; 71 | uint16_t production_id; 72 | } reduce; 73 | uint8_t type; 74 | } TSParseAction; 75 | 76 | typedef struct { 77 | uint16_t lex_state; 78 | uint16_t external_lex_state; 79 | } TSLexMode; 80 | 81 | typedef union { 82 | TSParseAction action; 83 | struct { 84 | uint8_t count; 85 | bool reusable; 86 | } entry; 87 | } TSParseActionEntry; 88 | 89 | typedef struct { 90 | int32_t start; 91 | int32_t end; 92 | } TSCharacterRange; 93 | 94 | struct TSLanguage { 95 | uint32_t version; 96 | uint32_t symbol_count; 97 | uint32_t alias_count; 98 | uint32_t token_count; 99 | uint32_t external_token_count; 100 | uint32_t state_count; 101 | uint32_t large_state_count; 102 | uint32_t production_id_count; 103 | uint32_t field_count; 104 | uint16_t max_alias_sequence_length; 105 | const uint16_t *parse_table; 106 | const uint16_t *small_parse_table; 107 | const uint32_t *small_parse_table_map; 108 | const TSParseActionEntry *parse_actions; 109 | const char * const *symbol_names; 110 | const char * const *field_names; 111 | const TSFieldMapSlice *field_map_slices; 112 | const TSFieldMapEntry *field_map_entries; 113 | const TSSymbolMetadata *symbol_metadata; 114 | const TSSymbol *public_symbol_map; 115 | const uint16_t *alias_map; 116 | const TSSymbol *alias_sequences; 117 | const TSLexMode *lex_modes; 118 | bool (*lex_fn)(TSLexer *, TSStateId); 119 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 120 | TSSymbol keyword_capture_token; 121 | struct { 122 | const bool *states; 123 | const TSSymbol *symbol_map; 124 | void *(*create)(void); 125 | void (*destroy)(void *); 126 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 127 | unsigned (*serialize)(void *, char *); 128 | void (*deserialize)(void *, const char *, unsigned); 129 | } external_scanner; 130 | const TSStateId *primary_state_ids; 131 | }; 132 | 133 | static inline bool set_contains(TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { 134 | uint32_t index = 0; 135 | uint32_t size = len - index; 136 | while (size > 1) { 137 | uint32_t half_size = size / 2; 138 | uint32_t mid_index = index + half_size; 139 | TSCharacterRange *range = &ranges[mid_index]; 140 | if (lookahead >= range->start && lookahead <= range->end) { 141 | return true; 142 | } else if (lookahead > range->end) { 143 | index = mid_index; 144 | } 145 | size -= half_size; 146 | } 147 | TSCharacterRange *range = &ranges[index]; 148 | return (lookahead >= range->start && lookahead <= range->end); 149 | } 150 | 151 | /* 152 | * Lexer Macros 153 | */ 154 | 155 | #ifdef _MSC_VER 156 | #define UNUSED __pragma(warning(suppress : 4101)) 157 | #else 158 | #define UNUSED __attribute__((unused)) 159 | #endif 160 | 161 | #define START_LEXER() \ 162 | bool result = false; \ 163 | bool skip = false; \ 164 | UNUSED \ 165 | bool eof = false; \ 166 | int32_t lookahead; \ 167 | goto start; \ 168 | next_state: \ 169 | lexer->advance(lexer, skip); \ 170 | start: \ 171 | skip = false; \ 172 | lookahead = lexer->lookahead; 173 | 174 | #define ADVANCE(state_value) \ 175 | { \ 176 | state = state_value; \ 177 | goto next_state; \ 178 | } 179 | 180 | #define ADVANCE_MAP(...) \ 181 | { \ 182 | static const uint16_t map[] = { __VA_ARGS__ }; \ 183 | for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ 184 | if (map[i] == lookahead) { \ 185 | state = map[i + 1]; \ 186 | goto next_state; \ 187 | } \ 188 | } \ 189 | } 190 | 191 | #define SKIP(state_value) \ 192 | { \ 193 | skip = true; \ 194 | state = state_value; \ 195 | goto next_state; \ 196 | } 197 | 198 | #define ACCEPT_TOKEN(symbol_value) \ 199 | result = true; \ 200 | lexer->result_symbol = symbol_value; \ 201 | lexer->mark_end(lexer); 202 | 203 | #define END_STATE() return result; 204 | 205 | /* 206 | * Parse Table Macros 207 | */ 208 | 209 | #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) 210 | 211 | #define STATE(id) id 212 | 213 | #define ACTIONS(id) id 214 | 215 | #define SHIFT(state_value) \ 216 | {{ \ 217 | .shift = { \ 218 | .type = TSParseActionTypeShift, \ 219 | .state = (state_value) \ 220 | } \ 221 | }} 222 | 223 | #define SHIFT_REPEAT(state_value) \ 224 | {{ \ 225 | .shift = { \ 226 | .type = TSParseActionTypeShift, \ 227 | .state = (state_value), \ 228 | .repetition = true \ 229 | } \ 230 | }} 231 | 232 | #define SHIFT_EXTRA() \ 233 | {{ \ 234 | .shift = { \ 235 | .type = TSParseActionTypeShift, \ 236 | .extra = true \ 237 | } \ 238 | }} 239 | 240 | #define REDUCE(symbol_name, children, precedence, prod_id) \ 241 | {{ \ 242 | .reduce = { \ 243 | .type = TSParseActionTypeReduce, \ 244 | .symbol = symbol_name, \ 245 | .child_count = children, \ 246 | .dynamic_precedence = precedence, \ 247 | .production_id = prod_id \ 248 | }, \ 249 | }} 250 | 251 | #define RECOVER() \ 252 | {{ \ 253 | .type = TSParseActionTypeRecover \ 254 | }} 255 | 256 | #define ACCEPT_INPUT() \ 257 | {{ \ 258 | .type = TSParseActionTypeAccept \ 259 | }} 260 | 261 | #ifdef __cplusplus 262 | } 263 | #endif 264 | 265 | #endif // TREE_SITTER_PARSER_H_ 266 | -------------------------------------------------------------------------------- /test/corpus/node.txt: -------------------------------------------------------------------------------- 1 | ===================== 2 | Test Empty String Arg 3 | ===================== 4 | 5 | node "" 6 | 7 | --- 8 | 9 | (document 10 | (node 11 | (identifier) 12 | (node_field 13 | (value 14 | (string))))) 15 | 16 | ================ 17 | Test Single Prop 18 | ================ 19 | 20 | node prop="val" 21 | 22 | --- 23 | 24 | (document 25 | (node 26 | (identifier) 27 | (node_field 28 | (prop 29 | (identifier) 30 | (value 31 | (string 32 | (string_fragment))))))) 33 | 34 | ============== 35 | Test Node Type 36 | ============== 37 | 38 | (type)node 39 | 40 | --- 41 | 42 | (document 43 | (node 44 | (type 45 | (identifier)) 46 | (identifier))) 47 | 48 | ================== 49 | Test Block Comment 50 | ================== 51 | 52 | node "arg" 53 | 54 | --- 55 | 56 | (document 57 | (node 58 | (identifier) 59 | (node_field 60 | (value 61 | (string 62 | (string_fragment)))))) 63 | 64 | ========================= 65 | Test Escaped String Quote 66 | ========================= 67 | 68 | node "a\"b" 69 | 70 | --- 71 | 72 | (document 73 | (node 74 | (identifier) 75 | (node_field 76 | (value 77 | (string 78 | (string_fragment 79 | (escape))))))) 80 | 81 | ================== 82 | Test Arg Null Type 83 | ================== 84 | 85 | node (type)null 86 | 87 | --- 88 | 89 | (document 90 | (node 91 | (identifier) 92 | (node_field 93 | (value 94 | (type 95 | (identifier)) 96 | (keyword))))) 97 | 98 | ========================= 99 | Test Semicolon Terminated 100 | ========================= 101 | 102 | node1 103 | 104 | --- 105 | 106 | (document 107 | (node 108 | (identifier))) 109 | 110 | ===================================== 111 | Test Slashdash Arg Before Newline Esc 112 | ===================================== 113 | 114 | node 115 | 116 | --- 117 | 118 | (document 119 | (node 120 | (identifier))) 121 | 122 | ================= 123 | Test Repeated Arg 124 | ================= 125 | 126 | node "arg" "arg" 127 | 128 | --- 129 | 130 | (document 131 | (node 132 | (identifier) 133 | (node_field 134 | (value 135 | (string 136 | (string_fragment)))) 137 | (node_field 138 | (value 139 | (string 140 | (string_fragment)))))) 141 | 142 | =================== 143 | Test Arg False Type 144 | =================== 145 | 146 | node (type)false 147 | 148 | --- 149 | 150 | (document 151 | (node 152 | (identifier) 153 | (node_field 154 | (value 155 | (type 156 | (identifier)) 157 | (keyword 158 | (boolean)))))) 159 | 160 | ================== 161 | Test Arg True Type 162 | ================== 163 | 164 | node (type)true 165 | 166 | --- 167 | 168 | (document 169 | (node 170 | (identifier) 171 | (node_field 172 | (value 173 | (type 174 | (identifier)) 175 | (keyword 176 | (boolean)))))) 177 | 178 | =================== 179 | Test Commented Node 180 | =================== 181 | 182 | node_2 183 | 184 | --- 185 | 186 | (document 187 | (node 188 | (identifier))) 189 | 190 | ============ 191 | Test Escline 192 | ============ 193 | 194 | node "arg" 195 | 196 | --- 197 | 198 | (document 199 | (node 200 | (identifier) 201 | (node_field 202 | (value 203 | (string 204 | (string_fragment)))))) 205 | 206 | ============================= 207 | Test Escaped String Backslash 208 | ============================= 209 | 210 | node "\\n" 211 | 212 | --- 213 | 214 | (document 215 | (node 216 | (identifier) 217 | (node_field 218 | (value 219 | (string 220 | (string_fragment 221 | (escape))))))) 222 | 223 | ======================== 224 | Test Preserve Node Order 225 | ======================== 226 | 227 | node2 228 | node5 229 | node1 230 | 231 | --- 232 | 233 | (document 234 | (node 235 | (identifier)) 236 | (node 237 | (identifier)) 238 | (node 239 | (identifier))) 240 | 241 | ======================== 242 | Test Slashdash Only Node 243 | ======================== 244 | 245 | 246 | 247 | --- 248 | 249 | (document) 250 | 251 | ========================= 252 | Test Empty Quoted Node Id 253 | ========================= 254 | 255 | "" "arg" 256 | 257 | --- 258 | 259 | (document 260 | (node 261 | (identifier 262 | (string)) 263 | (node_field 264 | (value 265 | (string 266 | (string_fragment)))))) 267 | 268 | ================= 269 | Test Boolean Prop 270 | ================= 271 | 272 | node prop1=true prop2=false 273 | 274 | --- 275 | 276 | (document 277 | (node 278 | (identifier) 279 | (node_field 280 | (prop 281 | (identifier) 282 | (value 283 | (keyword 284 | (boolean))))) 285 | (node_field 286 | (prop 287 | (identifier) 288 | (value 289 | (keyword 290 | (boolean))))))) 291 | 292 | =========================== 293 | Test Slashdash In Slashdash 294 | =========================== 295 | 296 | node2 297 | 298 | --- 299 | 300 | (document 301 | (node 302 | (identifier))) 303 | 304 | ============================== 305 | Test Newlines In Block Comment 306 | ============================== 307 | 308 | node "arg" 309 | 310 | --- 311 | 312 | (document 313 | (node 314 | (identifier) 315 | (node_field 316 | (value 317 | (string 318 | (string_fragment)))))) 319 | 320 | =================================== 321 | Test Slashdash Only Node With Space 322 | =================================== 323 | 324 | 325 | 326 | --- 327 | 328 | (document) 329 | 330 | =================== 331 | Test Prop Zero Type 332 | =================== 333 | 334 | node key=(type)0 335 | 336 | --- 337 | 338 | (document 339 | (node 340 | (identifier) 341 | (node_field 342 | (prop 343 | (identifier) 344 | (value 345 | (type 346 | (identifier)) 347 | (number)))))) 348 | 349 | ============================= 350 | Test Preserve Duplicate Nodes 351 | ============================= 352 | 353 | node 354 | node 355 | 356 | --- 357 | 358 | (document 359 | (node 360 | (identifier)) 361 | (node 362 | (identifier))) 363 | 364 | ===================== 365 | Test Prop String Type 366 | ===================== 367 | 368 | node key=(type)"str" 369 | 370 | --- 371 | 372 | (document 373 | (node 374 | (identifier) 375 | (node_field 376 | (prop 377 | (identifier) 378 | (value 379 | (type 380 | (identifier)) 381 | (string 382 | (string_fragment))))))) 383 | 384 | ============================= 385 | Test Unusual Chars In Bare Id 386 | ============================= 387 | 388 | foo123~!@#$%^&*.:'|?+ "weeee" 389 | 390 | --- 391 | 392 | (document 393 | (node 394 | (identifier) 395 | (node_field 396 | (value 397 | (string 398 | (string_fragment)))))) 399 | 400 | ================= 401 | Test Just Newline 402 | ================= 403 | 404 | 405 | 406 | --- 407 | 408 | (document) 409 | 410 | ===================== 411 | Test Quoted Node Name 412 | ===================== 413 | 414 | "0node" 415 | 416 | --- 417 | 418 | (document 419 | (node 420 | (identifier 421 | (string 422 | (string_fragment))))) 423 | 424 | ================= 425 | Test Numeric Prop 426 | ================= 427 | 428 | node prop=10.0 429 | 430 | --- 431 | 432 | (document 433 | (node 434 | (identifier) 435 | (node_field 436 | (prop 437 | (identifier) 438 | (value 439 | (number 440 | (decimal))))))) 441 | 442 | ======================================= 443 | Test Unusual Bare Id Chars In Quoted Id 444 | ======================================= 445 | 446 | foo123~!@#$%^&*.:'|?+ "weeee" 447 | 448 | --- 449 | 450 | (document 451 | (node 452 | (identifier) 453 | (node_field 454 | (value 455 | (string 456 | (string_fragment)))))) 457 | 458 | ====================== 459 | Test Only Line Comment 460 | ====================== 461 | 462 | 463 | 464 | --- 465 | 466 | (document) 467 | 468 | ============== 469 | Test Null Prop 470 | ============== 471 | 472 | node prop=null 473 | 474 | --- 475 | 476 | (document 477 | (node 478 | (identifier) 479 | (node_field 480 | (prop 481 | (identifier) 482 | (value 483 | (keyword)))))) 484 | 485 | ========================= 486 | Test Escline Line Comment 487 | ========================= 488 | 489 | node "arg" "arg2\n" 490 | 491 | --- 492 | 493 | (document 494 | (node 495 | (identifier) 496 | (node_field 497 | (value 498 | (string 499 | (string_fragment)))) 500 | (node_field 501 | (value 502 | (string 503 | (string_fragment 504 | (escape))))))) 505 | 506 | =========================== 507 | Test Only Line Comment Crlf 508 | =========================== 509 | 510 | 511 | 512 | --- 513 | 514 | (document) 515 | 516 | ============== 517 | Test Tab Space 518 | ============== 519 | 520 | node 521 | 522 | --- 523 | 524 | (document 525 | (node 526 | (identifier))) 527 | 528 | ================ 529 | Test Numeric Arg 530 | ================ 531 | 532 | node 15.7 533 | 534 | --- 535 | 536 | (document 537 | (node 538 | (identifier) 539 | (node_field 540 | (value 541 | (number 542 | (decimal)))))) 543 | 544 | ========================== 545 | Test Esc Newline In String 546 | ========================== 547 | 548 | node "hello\nworld" 549 | 550 | --- 551 | 552 | (document 553 | (node 554 | (identifier) 555 | (node_field 556 | (value 557 | (string 558 | (string_fragment 559 | (escape))))))) 560 | 561 | ==================== 562 | Test All Node Fields 563 | ==================== 564 | 565 | node { 566 | inner_node 567 | } 568 | 569 | --- 570 | 571 | (document 572 | (node 573 | (identifier) 574 | (node_children 575 | (node 576 | (identifier))))) 577 | 578 | ============================ 579 | Test Slashdash Node In Child 580 | ============================ 581 | 582 | node1 583 | 584 | --- 585 | 586 | (document 587 | (node 588 | (identifier))) 589 | 590 | ========== 591 | Test Empty 592 | ========== 593 | 594 | 595 | 596 | --- 597 | 598 | (document) 599 | 600 | ===================== 601 | Test Hex Leading Zero 602 | ===================== 603 | 604 | node 1 605 | 606 | --- 607 | 608 | (document 609 | (node 610 | (identifier) 611 | (node_field 612 | (value 613 | (number))))) 614 | 615 | ====================== 616 | Test Positive Exponent 617 | ====================== 618 | 619 | node 1.0E+10 620 | 621 | --- 622 | 623 | (document 624 | (node 625 | (identifier) 626 | (node_field 627 | (value 628 | (number 629 | (decimal) 630 | (exponent)))))) 631 | 632 | ============================ 633 | Test Null Prefix In Prop Key 634 | ============================ 635 | 636 | node null_id=1 637 | 638 | --- 639 | 640 | (document 641 | (node 642 | (identifier) 643 | (node_field 644 | (prop 645 | (identifier) 646 | (value 647 | (number)))))) 648 | 649 | ============================ 650 | Test Int Multiple Underscore 651 | ============================ 652 | 653 | node 1234 654 | 655 | --- 656 | 657 | (document 658 | (node 659 | (identifier) 660 | (node_field 661 | (value 662 | (number))))) 663 | 664 | ============================== 665 | Test Block Comment Before Node 666 | ============================== 667 | 668 | node 669 | 670 | --- 671 | 672 | (document 673 | (node 674 | (identifier))) 675 | 676 | ================= 677 | Test Escline Node 678 | ================= 679 | 680 | node1 681 | node2 682 | 683 | --- 684 | 685 | (document 686 | (node 687 | (identifier)) 688 | (node 689 | (identifier))) 690 | 691 | ===================== 692 | Test Quoted Prop Name 693 | ===================== 694 | 695 | node "0prop"="val" 696 | 697 | --- 698 | 699 | (document 700 | (node 701 | (identifier) 702 | (node_field 703 | (prop 704 | (identifier 705 | (string 706 | (string_fragment))) 707 | (value 708 | (string 709 | (string_fragment))))))) 710 | 711 | ============================== 712 | Test Escaped String Just Quote 713 | ============================== 714 | 715 | node "\"" 716 | 717 | --- 718 | 719 | (document 720 | (node 721 | (identifier) 722 | (node_field 723 | (value 724 | (string 725 | (string_fragment 726 | (escape))))))) 727 | 728 | ============== 729 | Test Prop Type 730 | ============== 731 | 732 | node key=(type)true 733 | 734 | --- 735 | 736 | (document 737 | (node 738 | (identifier) 739 | (node_field 740 | (prop 741 | (identifier) 742 | (value 743 | (type 744 | (identifier)) 745 | (keyword 746 | (boolean))))))) 747 | 748 | ==================== 749 | Test Blank Node Type 750 | ==================== 751 | 752 | ("")node 753 | 754 | --- 755 | 756 | (document 757 | (node 758 | (type 759 | (identifier 760 | (string))) 761 | (identifier))) 762 | 763 | ========== 764 | Test Octal 765 | ========== 766 | 767 | node 16434824 768 | 769 | --- 770 | 771 | (document 772 | (node 773 | (identifier) 774 | (node_field 775 | (value 776 | (number))))) 777 | 778 | =================== 779 | Test Slashdash Prop 780 | =================== 781 | 782 | node "arg" 783 | 784 | --- 785 | 786 | (document 787 | (node 788 | (identifier) 789 | (node_field 790 | (value 791 | (string 792 | (string_fragment)))))) 793 | 794 | ==================== 795 | Test Leading Newline 796 | ==================== 797 | 798 | node 799 | 800 | --- 801 | 802 | (document 803 | (node 804 | (identifier))) 805 | 806 | =========================== 807 | Test Slashdash Raw Prop Key 808 | =========================== 809 | 810 | node 811 | 812 | --- 813 | 814 | (document 815 | (node 816 | (identifier))) 817 | 818 | ================== 819 | Test Repeated Prop 820 | ================== 821 | 822 | node prop=11 823 | 824 | --- 825 | 826 | (document 827 | (node 828 | (identifier) 829 | (node_field 830 | (prop 831 | (identifier) 832 | (value 833 | (number)))))) 834 | 835 | ================== 836 | Test Raw Prop Type 837 | ================== 838 | 839 | node key=(type)true 840 | 841 | --- 842 | 843 | (document 844 | (node 845 | (identifier) 846 | (node_field 847 | (prop 848 | (identifier) 849 | (value 850 | (type 851 | (identifier)) 852 | (keyword 853 | (boolean))))))) 854 | 855 | ===================== 856 | Test Leading Zero Int 857 | ===================== 858 | 859 | node 11 860 | 861 | --- 862 | 863 | (document 864 | (node 865 | (identifier) 866 | (node_field 867 | (value 868 | (number))))) 869 | 870 | =================== 871 | Test Commented Line 872 | =================== 873 | 874 | node_2 875 | 876 | --- 877 | 878 | (document 879 | (node 880 | (identifier))) 881 | 882 | ============================ 883 | Test Slashdash Repeated Prop 884 | ============================ 885 | 886 | node arg="correct" 887 | 888 | --- 889 | 890 | (document 891 | (node 892 | (identifier) 893 | (node_field 894 | (prop 895 | (identifier) 896 | (value 897 | (string 898 | (string_fragment))))))) 899 | 900 | ======================== 901 | Test Underscore In Octal 902 | ======================== 903 | 904 | node 342391 905 | 906 | --- 907 | 908 | (document 909 | (node 910 | (identifier) 911 | (node_field 912 | (value 913 | (number))))) 914 | 915 | ============= 916 | Test Zero Int 917 | ============= 918 | 919 | node 0 920 | 921 | --- 922 | 923 | (document 924 | (node 925 | (identifier) 926 | (node_field 927 | (value 928 | (number))))) 929 | 930 | ================ 931 | Test Empty Child 932 | ================ 933 | 934 | node 935 | 936 | --- 937 | 938 | (document 939 | (node 940 | (identifier))) 941 | 942 | =========================== 943 | Test Null Prefix In Bare Id 944 | =========================== 945 | 946 | null_id 947 | 948 | --- 949 | 950 | (document 951 | (node 952 | (identifier))) 953 | 954 | =============================== 955 | Test Binary Trailing Underscore 956 | =============================== 957 | 958 | node 2 959 | 960 | --- 961 | 962 | (document 963 | (node 964 | (identifier) 965 | (node_field 966 | (value 967 | (number))))) 968 | 969 | ==================== 970 | Test Commented Child 971 | ==================== 972 | 973 | node "arg" 974 | 975 | --- 976 | 977 | (document 978 | (node 979 | (identifier) 980 | (node_field 981 | (value 982 | (string 983 | (string_fragment)))))) 984 | 985 | ============================= 986 | Test Block Comment After Node 987 | ============================= 988 | 989 | node "arg" 990 | 991 | --- 992 | 993 | (document 994 | (node 995 | (identifier) 996 | (node_field 997 | (value 998 | (string 999 | (string_fragment)))))) 1000 | 1001 | ======================== 1002 | Test Escaped String Prop 1003 | ======================== 1004 | 1005 | node_1 prop="arg\\n" 1006 | node_2 prop="\"arg\"\\n" 1007 | node_3 prop="#\"arg\"#\\n" 1008 | 1009 | --- 1010 | 1011 | (document 1012 | (node 1013 | (identifier) 1014 | (node_field 1015 | (prop 1016 | (identifier) 1017 | (value 1018 | (string 1019 | (string_fragment 1020 | (escape))))))) 1021 | (node 1022 | (identifier) 1023 | (node_field 1024 | (prop 1025 | (identifier) 1026 | (value 1027 | (string 1028 | (string_fragment 1029 | (escape) 1030 | (escape) 1031 | (escape))))))) 1032 | (node 1033 | (identifier) 1034 | (node_field 1035 | (prop 1036 | (identifier) 1037 | (value 1038 | (string 1039 | (string_fragment 1040 | (escape) 1041 | (escape) 1042 | (escape)))))))) 1043 | 1044 | ============ 1045 | Test Only Cr 1046 | ============ 1047 | 1048 | 1049 | 1050 | --- 1051 | 1052 | (document) 1053 | 1054 | ===================== 1055 | Test Quoted Node Type 1056 | ===================== 1057 | 1058 | ("type/")node 1059 | 1060 | --- 1061 | 1062 | (document 1063 | (node 1064 | (type 1065 | (identifier 1066 | (string 1067 | (string_fragment)))) 1068 | (identifier))) 1069 | 1070 | =============== 1071 | Test Node False 1072 | =============== 1073 | 1074 | node false 1075 | 1076 | --- 1077 | 1078 | (document 1079 | (node 1080 | (identifier) 1081 | (node_field 1082 | (value 1083 | (keyword 1084 | (boolean)))))) 1085 | 1086 | ======================= 1087 | Test Sci Notation Large 1088 | ======================= 1089 | 1090 | node prop=1.23E+1000 1091 | 1092 | --- 1093 | 1094 | (document 1095 | (node 1096 | (identifier) 1097 | (node_field 1098 | (prop 1099 | (identifier) 1100 | (value 1101 | (number 1102 | (decimal) 1103 | (exponent))))))) 1104 | 1105 | ================== 1106 | Test Arg Zero Type 1107 | ================== 1108 | 1109 | node (type)0 1110 | 1111 | --- 1112 | 1113 | (document 1114 | (node 1115 | (identifier) 1116 | (node_field 1117 | (value 1118 | (type 1119 | (identifier)) 1120 | (number))))) 1121 | 1122 | =========================== 1123 | Test Empty Child Whitespace 1124 | =========================== 1125 | 1126 | node 1127 | 1128 | --- 1129 | 1130 | (document 1131 | (node 1132 | (identifier))) 1133 | 1134 | ============================== 1135 | Test Semicolon Separated Nodes 1136 | ============================== 1137 | 1138 | node1 1139 | node2 1140 | 1141 | --- 1142 | 1143 | (document 1144 | (node 1145 | (identifier)) 1146 | (node 1147 | (identifier))) 1148 | 1149 | ======================= 1150 | Test Semicolon In Child 1151 | ======================= 1152 | 1153 | node1 { 1154 | node2 1155 | } 1156 | 1157 | --- 1158 | 1159 | (document 1160 | (node 1161 | (identifier) 1162 | (node_children 1163 | (node 1164 | (identifier))))) 1165 | 1166 | ============================= 1167 | Test Prop Escaped String Type 1168 | ============================= 1169 | 1170 | node key=(type)"str" 1171 | 1172 | --- 1173 | 1174 | (document 1175 | (node 1176 | (identifier) 1177 | (node_field 1178 | (prop 1179 | (identifier) 1180 | (value 1181 | (type 1182 | (identifier)) 1183 | (string 1184 | (string_fragment))))))) 1185 | 1186 | ========================== 1187 | Test Block Comment Newline 1188 | ========================== 1189 | 1190 | 1191 | 1192 | --- 1193 | 1194 | (document) 1195 | 1196 | ==================== 1197 | Test Blank Prop Type 1198 | ==================== 1199 | 1200 | node key=("")true 1201 | 1202 | --- 1203 | 1204 | (document 1205 | (node 1206 | (identifier) 1207 | (node_field 1208 | (prop 1209 | (identifier) 1210 | (value 1211 | (type 1212 | (identifier 1213 | (string))) 1214 | (keyword 1215 | (boolean))))))) 1216 | 1217 | ======================== 1218 | Test Slashdash Full Node 1219 | ======================== 1220 | 1221 | 1222 | 1223 | --- 1224 | 1225 | (document) 1226 | 1227 | ============================= 1228 | Test False Prefix In Prop Key 1229 | ============================= 1230 | 1231 | node false_id=1 1232 | 1233 | --- 1234 | 1235 | (document 1236 | (node 1237 | (identifier) 1238 | (node_field 1239 | (prop 1240 | (identifier) 1241 | (value 1242 | (number)))))) 1243 | 1244 | ====================== 1245 | Test Negative Exponent 1246 | ====================== 1247 | 1248 | node 1.0E-10 1249 | 1250 | --- 1251 | 1252 | (document 1253 | (node 1254 | (identifier) 1255 | (node_field 1256 | (value 1257 | (number 1258 | (decimal) 1259 | (exponent)))))) 1260 | 1261 | =============== 1262 | Test Single Arg 1263 | =============== 1264 | 1265 | node "arg" 1266 | 1267 | --- 1268 | 1269 | (document 1270 | (node 1271 | (identifier) 1272 | (node_field 1273 | (value 1274 | (string 1275 | (string_fragment)))))) 1276 | 1277 | ================================= 1278 | Test Escaped String Multiple Hash 1279 | ================================= 1280 | 1281 | node "\"#\"##" 1282 | 1283 | --- 1284 | 1285 | (document 1286 | (node 1287 | (identifier) 1288 | (node_field 1289 | (value 1290 | (string 1291 | (string_fragment 1292 | (escape) 1293 | (escape))))))) 1294 | 1295 | ================ 1296 | Test Boolean Arg 1297 | ================ 1298 | 1299 | node false true 1300 | 1301 | --- 1302 | 1303 | (document 1304 | (node 1305 | (identifier) 1306 | (node_field 1307 | (value 1308 | (keyword 1309 | (boolean)))) 1310 | (node_field 1311 | (value 1312 | (keyword 1313 | (boolean)))))) 1314 | 1315 | ============================ 1316 | Test Arg Escaped String Type 1317 | ============================ 1318 | 1319 | node (type)"str" 1320 | 1321 | --- 1322 | 1323 | (document 1324 | (node 1325 | (identifier) 1326 | (node_field 1327 | (value 1328 | (type 1329 | (identifier)) 1330 | (string 1331 | (string_fragment)))))) 1332 | 1333 | =================================== 1334 | Test Nested Multiline Block Comment 1335 | =================================== 1336 | 1337 | node "arg" 1338 | 1339 | --- 1340 | 1341 | (document 1342 | (node 1343 | (identifier) 1344 | (node_field 1345 | (value 1346 | (string 1347 | (string_fragment)))))) 1348 | 1349 | ================= 1350 | Test Positive Int 1351 | ================= 1352 | 1353 | node 10 1354 | 1355 | --- 1356 | 1357 | (document 1358 | (node 1359 | (identifier) 1360 | (node_field 1361 | (value 1362 | (number))))) 1363 | 1364 | ==================== 1365 | Test Prop Float Type 1366 | ==================== 1367 | 1368 | node key=(type)2.5E+10 1369 | 1370 | --- 1371 | 1372 | (document 1373 | (node 1374 | (identifier) 1375 | (node_field 1376 | (prop 1377 | (identifier) 1378 | (value 1379 | (type 1380 | (identifier)) 1381 | (number 1382 | (decimal) 1383 | (exponent))))))) 1384 | 1385 | ============= 1386 | Test Arg Type 1387 | ============= 1388 | 1389 | node (type)"arg" 1390 | 1391 | --- 1392 | 1393 | (document 1394 | (node 1395 | (identifier) 1396 | (node_field 1397 | (value 1398 | (type 1399 | (identifier)) 1400 | (string 1401 | (string_fragment)))))) 1402 | 1403 | ============================ 1404 | Test Trailing Underscore Hex 1405 | ============================ 1406 | 1407 | node 1194684 1408 | 1409 | --- 1410 | 1411 | (document 1412 | (node 1413 | (identifier) 1414 | (node_field 1415 | (value 1416 | (number))))) 1417 | 1418 | ========================= 1419 | Test Nested Block Comment 1420 | ========================= 1421 | 1422 | node "arg" 1423 | 1424 | --- 1425 | 1426 | (document 1427 | (node 1428 | (identifier) 1429 | (node_field 1430 | (value 1431 | (string 1432 | (string_fragment)))))) 1433 | 1434 | ==================== 1435 | Test Quoted Arg Type 1436 | ==================== 1437 | 1438 | node ("type/")10 1439 | 1440 | --- 1441 | 1442 | (document 1443 | (node 1444 | (identifier) 1445 | (node_field 1446 | (value 1447 | (type 1448 | (identifier 1449 | (string 1450 | (string_fragment)))) 1451 | (number))))) 1452 | 1453 | ==================== 1454 | Test Nested Comments 1455 | ==================== 1456 | 1457 | node "arg" 1458 | 1459 | --- 1460 | 1461 | (document 1462 | (node 1463 | (identifier) 1464 | (node_field 1465 | (value 1466 | (string 1467 | (string_fragment)))))) 1468 | 1469 | ================================== 1470 | Test Escaped String Just Backslash 1471 | ================================== 1472 | 1473 | "\\" 1474 | 1475 | --- 1476 | 1477 | (document 1478 | (node 1479 | (identifier 1480 | (string 1481 | (string_fragment 1482 | (escape)))))) 1483 | 1484 | =================== 1485 | Test Commented Prop 1486 | =================== 1487 | 1488 | node "arg" 1489 | 1490 | --- 1491 | 1492 | (document 1493 | (node 1494 | (identifier) 1495 | (node_field 1496 | (value 1497 | (string 1498 | (string_fragment)))))) 1499 | 1500 | ======================= 1501 | Test Crlf Between Nodes 1502 | ======================= 1503 | 1504 | node1 1505 | node2 1506 | 1507 | --- 1508 | 1509 | (document 1510 | (node 1511 | (identifier)) 1512 | (node 1513 | (identifier))) 1514 | 1515 | ============= 1516 | Test Null Arg 1517 | ============= 1518 | 1519 | node null 1520 | 1521 | --- 1522 | 1523 | (document 1524 | (node 1525 | (identifier) 1526 | (node_field 1527 | (value 1528 | (keyword))))) 1529 | 1530 | ===================== 1531 | Test Leading Zero Oct 1532 | ===================== 1533 | 1534 | node 1 1535 | 1536 | --- 1537 | 1538 | (document 1539 | (node 1540 | (identifier) 1541 | (node_field 1542 | (value 1543 | (number))))) 1544 | 1545 | =========================== 1546 | Test Escaped String Newline 1547 | =========================== 1548 | 1549 | node "\nhello\nworld\n" 1550 | 1551 | --- 1552 | 1553 | (document 1554 | (node 1555 | (identifier) 1556 | (node_field 1557 | (value 1558 | (string 1559 | (string_fragment 1560 | (escape) 1561 | (escape) 1562 | (escape))))))) 1563 | 1564 | ========================== 1565 | Test Empty Child Same Line 1566 | ========================== 1567 | 1568 | node 1569 | 1570 | --- 1571 | 1572 | (document 1573 | (node 1574 | (identifier))) 1575 | 1576 | ================= 1577 | Test Just Node Id 1578 | ================= 1579 | 1580 | node 1581 | 1582 | --- 1583 | 1584 | (document 1585 | (node 1586 | (identifier))) 1587 | 1588 | ============== 1589 | Test Same Args 1590 | ============== 1591 | 1592 | node "whee" "whee" 1593 | 1594 | --- 1595 | 1596 | (document 1597 | (node 1598 | (identifier) 1599 | (node_field 1600 | (value 1601 | (string 1602 | (string_fragment)))) 1603 | (node_field 1604 | (value 1605 | (string 1606 | (string_fragment)))))) 1607 | 1608 | ========================== 1609 | Test Empty Quoted Prop Key 1610 | ========================== 1611 | 1612 | node ""="empty" 1613 | 1614 | --- 1615 | 1616 | (document 1617 | (node 1618 | (identifier) 1619 | (node_field 1620 | (prop 1621 | (identifier 1622 | (string)) 1623 | (value 1624 | (string 1625 | (string_fragment))))))) 1626 | 1627 | ========================== 1628 | Test Esc Unicode In String 1629 | ========================== 1630 | 1631 | node "hello\nworld" 1632 | 1633 | --- 1634 | 1635 | (document 1636 | (node 1637 | (identifier) 1638 | (node_field 1639 | (value 1640 | (string 1641 | (string_fragment 1642 | (escape))))))) 1643 | 1644 | =========== 1645 | Test Binary 1646 | =========== 1647 | 1648 | node 2 1649 | 1650 | --- 1651 | 1652 | (document 1653 | (node 1654 | (identifier) 1655 | (node_field 1656 | (value 1657 | (number))))) 1658 | 1659 | ================ 1660 | Test All Escapes 1661 | ================ 1662 | 1663 | node "\"\\/\b\f\n\r\t" 1664 | 1665 | --- 1666 | 1667 | (document 1668 | (node 1669 | (identifier) 1670 | (node_field 1671 | (value 1672 | (string 1673 | (string_fragment 1674 | (escape) 1675 | (escape) 1676 | (escape) 1677 | (escape) 1678 | (escape) 1679 | (escape) 1680 | (escape))))))) 1681 | 1682 | ==================== 1683 | Test Arg String Type 1684 | ==================== 1685 | 1686 | node (type)"str" 1687 | 1688 | --- 1689 | 1690 | (document 1691 | (node 1692 | (identifier) 1693 | (node_field 1694 | (value 1695 | (type 1696 | (identifier)) 1697 | (string 1698 | (string_fragment)))))) 1699 | 1700 | =================== 1701 | Test Quoted Numeric 1702 | =================== 1703 | 1704 | node prop="10.0" 1705 | 1706 | --- 1707 | 1708 | (document 1709 | (node 1710 | (identifier) 1711 | (node_field 1712 | (prop 1713 | (identifier) 1714 | (value 1715 | (string 1716 | (string_fragment))))))) 1717 | 1718 | =========================== 1719 | Test Underscore In Exponent 1720 | =========================== 1721 | 1722 | node 1.0E-100 1723 | 1724 | --- 1725 | 1726 | (document 1727 | (node 1728 | (identifier) 1729 | (node_field 1730 | (value 1731 | (number 1732 | (decimal) 1733 | (exponent)))))) 1734 | 1735 | ============================== 1736 | Test Trailing Underscore Octal 1737 | ============================== 1738 | 1739 | node 83 1740 | 1741 | --- 1742 | 1743 | (document 1744 | (node 1745 | (identifier) 1746 | (node_field 1747 | (value 1748 | (number))))) 1749 | 1750 | ==================== 1751 | Test Prop False Type 1752 | ==================== 1753 | 1754 | node key=(type)false 1755 | 1756 | --- 1757 | 1758 | (document 1759 | (node 1760 | (identifier) 1761 | (node_field 1762 | (prop 1763 | (identifier) 1764 | (value 1765 | (type 1766 | (identifier)) 1767 | (keyword 1768 | (boolean))))))) 1769 | 1770 | ======================== 1771 | Test Leading Zero Binary 1772 | ======================== 1773 | 1774 | node 1 1775 | 1776 | --- 1777 | 1778 | (document 1779 | (node 1780 | (identifier) 1781 | (node_field 1782 | (value 1783 | (number))))) 1784 | 1785 | ======================= 1786 | Test Escaped String Arg 1787 | ======================= 1788 | 1789 | node_1 "arg\\n" 1790 | node_2 "\"arg\\n\"and stuff" 1791 | node_3 "#\"arg\\n\"#and stuff" 1792 | 1793 | --- 1794 | 1795 | (document 1796 | (node 1797 | (identifier) 1798 | (node_field 1799 | (value 1800 | (string 1801 | (string_fragment 1802 | (escape)))))) 1803 | (node 1804 | (identifier) 1805 | (node_field 1806 | (value 1807 | (string 1808 | (string_fragment 1809 | (escape) 1810 | (escape) 1811 | (escape)))))) 1812 | (node 1813 | (identifier) 1814 | (node_field 1815 | (value 1816 | (string 1817 | (string_fragment 1818 | (escape) 1819 | (escape) 1820 | (escape))))))) 1821 | 1822 | ================================ 1823 | Test Empty Child Different Lines 1824 | ================================ 1825 | 1826 | node 1827 | 1828 | --- 1829 | 1830 | (document 1831 | (node 1832 | (identifier))) 1833 | 1834 | ====================== 1835 | Test Binary Underscore 1836 | ====================== 1837 | 1838 | node 2 1839 | 1840 | --- 1841 | 1842 | (document 1843 | (node 1844 | (identifier) 1845 | (node_field 1846 | (value 1847 | (number))))) 1848 | 1849 | =================== 1850 | Test Blank Arg Type 1851 | =================== 1852 | 1853 | node ("")10 1854 | 1855 | --- 1856 | 1857 | (document 1858 | (node 1859 | (identifier) 1860 | (node_field 1861 | (value 1862 | (type 1863 | (identifier 1864 | (string))) 1865 | (number))))) 1866 | 1867 | ======================== 1868 | Test Parse All Arg Types 1869 | ======================== 1870 | 1871 | node 1 1.0 1.0E+10 1.0E-10 1 7 2 "arg" "arg\\\\" true false null 1872 | 1873 | --- 1874 | 1875 | (document 1876 | (node 1877 | (identifier) 1878 | (node_field 1879 | (value 1880 | (number))) 1881 | (node_field 1882 | (value 1883 | (number 1884 | (decimal)))) 1885 | (node_field 1886 | (value 1887 | (number 1888 | (decimal) 1889 | (exponent)))) 1890 | (node_field 1891 | (value 1892 | (number 1893 | (decimal) 1894 | (exponent)))) 1895 | (node_field 1896 | (value 1897 | (number))) 1898 | (node_field 1899 | (value 1900 | (number))) 1901 | (node_field 1902 | (value 1903 | (number))) 1904 | (node_field 1905 | (value 1906 | (string 1907 | (string_fragment)))) 1908 | (node_field 1909 | (value 1910 | (string 1911 | (string_fragment 1912 | (escape) 1913 | (escape))))) 1914 | (node_field 1915 | (value 1916 | (keyword 1917 | (boolean)))) 1918 | (node_field 1919 | (value 1920 | (keyword 1921 | (boolean)))) 1922 | (node_field 1923 | (value 1924 | (keyword))))) 1925 | 1926 | ============================ 1927 | Test True Prefix In Prop Key 1928 | ============================ 1929 | 1930 | node true_id=1 1931 | 1932 | --- 1933 | 1934 | (document 1935 | (node 1936 | (identifier) 1937 | (node_field 1938 | (prop 1939 | (identifier) 1940 | (value 1941 | (number)))))) 1942 | 1943 | ========================== 1944 | Test Semicolon After Child 1945 | ========================== 1946 | 1947 | node { 1948 | childnode 1949 | } 1950 | 1951 | --- 1952 | 1953 | (document 1954 | (node 1955 | (identifier) 1956 | (node_children 1957 | (node 1958 | (identifier))))) 1959 | 1960 | ========================== 1961 | Test Slashdash Empty Child 1962 | ========================== 1963 | 1964 | node 1965 | 1966 | --- 1967 | 1968 | (document 1969 | (node 1970 | (identifier))) 1971 | 1972 | ======================== 1973 | Test Underscore In Float 1974 | ======================== 1975 | 1976 | node 11.0 1977 | 1978 | --- 1979 | 1980 | (document 1981 | (node 1982 | (identifier) 1983 | (node_field 1984 | (value 1985 | (number 1986 | (decimal)))))) 1987 | 1988 | ====================== 1989 | Test Underscore In Int 1990 | ====================== 1991 | 1992 | node 10 1993 | 1994 | --- 1995 | 1996 | (document 1997 | (node 1998 | (identifier) 1999 | (node_field 2000 | (value 2001 | (number))))) 2002 | 2003 | ===================== 2004 | Test Quoted Prop Type 2005 | ===================== 2006 | 2007 | node key=("type/")true 2008 | 2009 | --- 2010 | 2011 | (document 2012 | (node 2013 | (identifier) 2014 | (node_field 2015 | (prop 2016 | (identifier) 2017 | (value 2018 | (type 2019 | (identifier 2020 | (string 2021 | (string_fragment)))) 2022 | (keyword 2023 | (boolean))))))) 2024 | 2025 | ================== 2026 | Test Commented Arg 2027 | ================== 2028 | 2029 | node "arg2" 2030 | 2031 | --- 2032 | 2033 | (document 2034 | (node 2035 | (identifier) 2036 | (node_field 2037 | (value 2038 | (string 2039 | (string_fragment)))))) 2040 | 2041 | ==================== 2042 | Test Nested Children 2043 | ==================== 2044 | 2045 | node1 { 2046 | node2 { 2047 | node 2048 | } 2049 | } 2050 | 2051 | --- 2052 | 2053 | (document 2054 | (node 2055 | (identifier) 2056 | (node_children 2057 | (node 2058 | (identifier) 2059 | (node_children 2060 | (node 2061 | (identifier))))))) 2062 | 2063 | ============== 2064 | Test Node True 2065 | ============== 2066 | 2067 | node true 2068 | 2069 | --- 2070 | 2071 | (document 2072 | (node 2073 | (identifier) 2074 | (node_field 2075 | (value 2076 | (keyword 2077 | (boolean)))))) 2078 | 2079 | ============================== 2080 | Test Slashdash Negative Number 2081 | ============================== 2082 | 2083 | node 2.0 2084 | 2085 | --- 2086 | 2087 | (document 2088 | (node 2089 | (identifier) 2090 | (node_field 2091 | (value 2092 | (number 2093 | (decimal)))))) 2094 | 2095 | =============== 2096 | Test Just Space 2097 | =============== 2098 | 2099 | 2100 | 2101 | --- 2102 | 2103 | (document) 2104 | 2105 | ============================== 2106 | Test Asterisk In Block Comment 2107 | ============================== 2108 | 2109 | node 2110 | 2111 | --- 2112 | 2113 | (document 2114 | (node 2115 | (identifier))) 2116 | 2117 | ============ 2118 | Test Hex Int 2119 | ============ 2120 | 2121 | node 207698809136909011942886895 2122 | 2123 | --- 2124 | 2125 | (document 2126 | (node 2127 | (identifier) 2128 | (node_field 2129 | (value 2130 | (number))))) 2131 | 2132 | ========================== 2133 | Test Newline Between Nodes 2134 | ========================== 2135 | 2136 | node1 2137 | node2 2138 | 2139 | --- 2140 | 2141 | (document 2142 | (node 2143 | (identifier)) 2144 | (node 2145 | (identifier))) 2146 | 2147 | ========== 2148 | Test Emoji 2149 | ========== 2150 | 2151 | node "😀" 2152 | 2153 | --- 2154 | 2155 | (document 2156 | (node 2157 | (identifier) 2158 | (node_field 2159 | (value 2160 | (string 2161 | (string_fragment)))))) 2162 | 2163 | ==================================== 2164 | Test Slashdash Arg After Newline Esc 2165 | ==================================== 2166 | 2167 | node "arg2" 2168 | 2169 | --- 2170 | 2171 | (document 2172 | (node 2173 | (identifier) 2174 | (node_field 2175 | (value 2176 | (string 2177 | (string_fragment)))))) 2178 | 2179 | ============================== 2180 | Test Only Line Comment Newline 2181 | ============================== 2182 | 2183 | 2184 | 2185 | --- 2186 | 2187 | (document) 2188 | 2189 | =============== 2190 | Test String Arg 2191 | =============== 2192 | 2193 | node "arg" 2194 | 2195 | --- 2196 | 2197 | (document 2198 | (node 2199 | (identifier) 2200 | (node_field 2201 | (value 2202 | (string 2203 | (string_fragment)))))) 2204 | 2205 | =========================== 2206 | Test Arg And Prop Same Name 2207 | =========================== 2208 | 2209 | node "arg" arg="val" 2210 | 2211 | --- 2212 | 2213 | (document 2214 | (node 2215 | (identifier) 2216 | (node_field 2217 | (value 2218 | (string 2219 | (string_fragment)))) 2220 | (node_field 2221 | (prop 2222 | (identifier) 2223 | (value 2224 | (string 2225 | (string_fragment))))))) 2226 | 2227 | ===================== 2228 | Test Multiline String 2229 | ===================== 2230 | 2231 | node " hey\neveryone\nhow goes?\n" 2232 | 2233 | --- 2234 | 2235 | (document 2236 | (node 2237 | (identifier) 2238 | (node_field 2239 | (value 2240 | (string 2241 | (string_fragment 2242 | (escape) 2243 | (escape) 2244 | (escape))))))) 2245 | 2246 | ================= 2247 | Test Negative Int 2248 | ================= 2249 | 2250 | node -10 prop=-15 2251 | 2252 | --- 2253 | 2254 | (document 2255 | (node 2256 | (identifier) 2257 | (node_field 2258 | (value 2259 | (number))) 2260 | (node_field 2261 | (prop 2262 | (identifier) 2263 | (value 2264 | (number)))))) 2265 | 2266 | ====================== 2267 | Test Multiline Comment 2268 | ====================== 2269 | 2270 | node "arg" 2271 | 2272 | --- 2273 | 2274 | (document 2275 | (node 2276 | (identifier) 2277 | (node_field 2278 | (value 2279 | (string 2280 | (string_fragment)))))) 2281 | 2282 | ================== 2283 | Test Prop Hex Type 2284 | ================== 2285 | 2286 | node key=(type)16 2287 | 2288 | --- 2289 | 2290 | (document 2291 | (node 2292 | (identifier) 2293 | (node_field 2294 | (prop 2295 | (identifier) 2296 | (value 2297 | (type 2298 | (identifier)) 2299 | (number)))))) 2300 | 2301 | =============== 2302 | Test Zero Float 2303 | =============== 2304 | 2305 | node 0.0 2306 | 2307 | --- 2308 | 2309 | (document 2310 | (node 2311 | (identifier) 2312 | (node_field 2313 | (value 2314 | (number 2315 | (decimal)))))) 2316 | 2317 | ======== 2318 | Test Hex 2319 | ======== 2320 | 2321 | node 12379813812177893520 2322 | 2323 | --- 2324 | 2325 | (document 2326 | (node 2327 | (identifier) 2328 | (node_field 2329 | (value 2330 | (number))))) 2331 | 2332 | =========== 2333 | Test R Node 2334 | =========== 2335 | 2336 | r "arg" 2337 | 2338 | --- 2339 | 2340 | (document 2341 | (node 2342 | (identifier) 2343 | (node_field 2344 | (value 2345 | (string 2346 | (string_fragment)))))) 2347 | 2348 | ============= 2349 | Test Zero Arg 2350 | ============= 2351 | 2352 | node 0 2353 | 2354 | --- 2355 | 2356 | (document 2357 | (node 2358 | (identifier) 2359 | (node_field 2360 | (value 2361 | (number))))) 2362 | 2363 | ======================== 2364 | Test Semicolon Separated 2365 | ======================== 2366 | 2367 | node1 2368 | node2 2369 | 2370 | --- 2371 | 2372 | (document 2373 | (node 2374 | (identifier)) 2375 | (node 2376 | (identifier))) 2377 | 2378 | =============== 2379 | Test Bare Emoji 2380 | =============== 2381 | 2382 | 😁 "happy!" 2383 | 2384 | --- 2385 | 2386 | (document 2387 | (node 2388 | (identifier) 2389 | (node_field 2390 | (value 2391 | (string 2392 | (string_fragment)))))) 2393 | 2394 | =========================== 2395 | Test Underscore In Fraction 2396 | =========================== 2397 | 2398 | node 1.02 2399 | 2400 | --- 2401 | 2402 | (document 2403 | (node 2404 | (identifier) 2405 | (node_field 2406 | (value 2407 | (number 2408 | (decimal)))))) 2409 | 2410 | ==================== 2411 | Test Multiline Nodes 2412 | ==================== 2413 | 2414 | node "arg1" "arg2" 2415 | 2416 | --- 2417 | 2418 | (document 2419 | (node 2420 | (identifier) 2421 | (node_field 2422 | (value 2423 | (string 2424 | (string_fragment)))) 2425 | (node_field 2426 | (value 2427 | (string 2428 | (string_fragment)))))) 2429 | 2430 | ============================== 2431 | Test Slashdash Node With Child 2432 | ============================== 2433 | 2434 | 2435 | 2436 | --- 2437 | 2438 | (document) 2439 | 2440 | ================= 2441 | Test Arg Hex Type 2442 | ================= 2443 | 2444 | node (type)16 2445 | 2446 | --- 2447 | 2448 | (document 2449 | (node 2450 | (identifier) 2451 | (node_field 2452 | (value 2453 | (type 2454 | (identifier)) 2455 | (number))))) 2456 | 2457 | ================== 2458 | Test Trailing Crlf 2459 | ================== 2460 | 2461 | node 2462 | 2463 | --- 2464 | 2465 | (document 2466 | (node 2467 | (identifier))) 2468 | 2469 | =================== 2470 | Test Prop Null Type 2471 | =================== 2472 | 2473 | node key=(type)null 2474 | 2475 | --- 2476 | 2477 | (document 2478 | (node 2479 | (identifier) 2480 | (node_field 2481 | (prop 2482 | (identifier) 2483 | (value 2484 | (type 2485 | (identifier)) 2486 | (keyword)))))) 2487 | 2488 | ================ 2489 | Test String Prop 2490 | ================ 2491 | 2492 | node prop="val" 2493 | 2494 | --- 2495 | 2496 | (document 2497 | (node 2498 | (identifier) 2499 | (node_field 2500 | (prop 2501 | (identifier) 2502 | (value 2503 | (string 2504 | (string_fragment))))))) 2505 | 2506 | ======================= 2507 | Test Sci Notation Small 2508 | ======================= 2509 | 2510 | node prop=1.23E-1000 2511 | 2512 | --- 2513 | 2514 | (document 2515 | (node 2516 | (identifier) 2517 | (node_field 2518 | (prop 2519 | (identifier) 2520 | (value 2521 | (number 2522 | (decimal) 2523 | (exponent))))))) 2524 | 2525 | ======================== 2526 | Test No Decimal Exponent 2527 | ======================== 2528 | 2529 | node 1E+10 2530 | 2531 | --- 2532 | 2533 | (document 2534 | (node 2535 | (identifier) 2536 | (node_field 2537 | (value 2538 | (number 2539 | (exponent)))))) 2540 | 2541 | ================= 2542 | Test Raw Arg Type 2543 | ================= 2544 | 2545 | node (type)true 2546 | 2547 | --- 2548 | 2549 | (document 2550 | (node 2551 | (identifier) 2552 | (node_field 2553 | (value 2554 | (type 2555 | (identifier)) 2556 | (keyword 2557 | (boolean)))))) 2558 | 2559 | ============== 2560 | Test Two Nodes 2561 | ============== 2562 | 2563 | node1 2564 | node2 2565 | 2566 | --- 2567 | 2568 | (document 2569 | (node 2570 | (identifier)) 2571 | (node 2572 | (identifier))) 2573 | 2574 | =========================== 2575 | Test True Prefix In Bare Id 2576 | =========================== 2577 | 2578 | true_id 2579 | 2580 | --- 2581 | 2582 | (document 2583 | (node 2584 | (identifier))) 2585 | 2586 | ============================ 2587 | Test False Prefix In Bare Id 2588 | ============================ 2589 | 2590 | false_id 2591 | 2592 | --- 2593 | 2594 | (document 2595 | (node 2596 | (identifier))) 2597 | 2598 | =============================== 2599 | Test Escaped String Hash No Esc 2600 | =============================== 2601 | 2602 | node "#" 2603 | 2604 | --- 2605 | 2606 | (document 2607 | (node 2608 | (identifier) 2609 | (node_field 2610 | (value 2611 | (string 2612 | (string_fragment)))))) 2613 | 2614 | ================== 2615 | Test Raw Node Type 2616 | ================== 2617 | 2618 | (type)node 2619 | 2620 | --- 2621 | 2622 | (document 2623 | (node 2624 | (type 2625 | (identifier)) 2626 | (identifier))) 2627 | 2628 | ================== 2629 | Test Raw Node Name 2630 | ================== 2631 | 2632 | "\\node" 2633 | 2634 | --- 2635 | 2636 | (document 2637 | (node 2638 | (identifier 2639 | (string 2640 | (string_fragment 2641 | (escape)))))) 2642 | 2643 | ======================== 2644 | Test Hex Int Underscores 2645 | ======================== 2646 | 2647 | node 737894400291 2648 | 2649 | --- 2650 | 2651 | (document 2652 | (node 2653 | (identifier) 2654 | (node_field 2655 | (value 2656 | (number))))) 2657 | 2658 | ======================= 2659 | Test Just Block Comment 2660 | ======================= 2661 | 2662 | 2663 | 2664 | --- 2665 | 2666 | (document) 2667 | 2668 | =================== 2669 | Test Arg Float Type 2670 | =================== 2671 | 2672 | node (type)2.5 2673 | 2674 | --- 2675 | 2676 | (document 2677 | (node 2678 | (identifier) 2679 | (node_field 2680 | (value 2681 | (type 2682 | (identifier)) 2683 | (number 2684 | (decimal)))))) 2685 | 2686 | ======================================= 2687 | Test Block Comment Before Node No Space 2688 | ======================================= 2689 | 2690 | node 2691 | 2692 | --- 2693 | 2694 | (document 2695 | (node 2696 | (identifier))) 2697 | 2698 | ==================== 2699 | Test Same Name Nodes 2700 | ==================== 2701 | 2702 | node 2703 | node 2704 | 2705 | --- 2706 | 2707 | (document 2708 | (node 2709 | (identifier)) 2710 | (node 2711 | (identifier))) 2712 | 2713 | =================== 2714 | Test Negative Float 2715 | =================== 2716 | 2717 | node -1.0 key=-10.0 2718 | 2719 | --- 2720 | 2721 | (document 2722 | (node 2723 | (identifier) 2724 | (node_field 2725 | (value 2726 | (number 2727 | (decimal)))) 2728 | (node_field 2729 | (prop 2730 | (identifier) 2731 | (value 2732 | (number 2733 | (decimal))))))) 2734 | 2735 | ==================== 2736 | Test Slashdash Child 2737 | ==================== 2738 | 2739 | node 2740 | 2741 | --- 2742 | 2743 | (document 2744 | (node 2745 | (identifier))) 2746 | 2747 | =================== 2748 | Test Prop True Type 2749 | =================== 2750 | 2751 | node key=(type)true 2752 | 2753 | --- 2754 | 2755 | (document 2756 | (node 2757 | (identifier) 2758 | (node_field 2759 | (prop 2760 | (identifier) 2761 | (value 2762 | (type 2763 | (identifier)) 2764 | (keyword 2765 | (boolean))))))) 2766 | 2767 | =============== 2768 | Test Just Child 2769 | =============== 2770 | 2771 | node { 2772 | inner_node 2773 | } 2774 | 2775 | --- 2776 | 2777 | (document 2778 | (node 2779 | (identifier) 2780 | (node_children 2781 | (node 2782 | (identifier))))) 2783 | 2784 | ===================================== 2785 | Test Empty Raw String Arg Single Hash 2786 | ===================================== 2787 | 2788 | node r#""# 2789 | 2790 | --- 2791 | 2792 | (document 2793 | (node 2794 | (identifier) 2795 | (node_field 2796 | (value 2797 | (string))))) 2798 | 2799 | ===================================== 2800 | Test Empty Raw String Arg Many Hashes 2801 | ===================================== 2802 | 2803 | node r####""#### 2804 | 2805 | --- 2806 | 2807 | (document 2808 | (node 2809 | (identifier) 2810 | (node_field 2811 | (value 2812 | (string))))) 2813 | 2814 | ================================================= 2815 | Test Empty Raw String Arg With Partial Terminator 2816 | ================================================= 2817 | 2818 | node r####""###"#### 2819 | 2820 | --- 2821 | 2822 | (document 2823 | (node 2824 | (identifier) 2825 | (node_field 2826 | (value 2827 | (string))))) 2828 | 2829 | ==================================================== 2830 | Test Incomplete Raw String Opener As Node Identifier 2831 | ==================================================== 2832 | 2833 | r#### 2834 | 2835 | --- 2836 | 2837 | (document 2838 | (node 2839 | (identifier))) 2840 | --------------------------------------------------------------------------------