Compare commits

..

No commits in common. "0f2b1022f2cc973665115769c10bbf0a55237e00" and "3943c1401a631881abaddd3aeded72d55e4a8681" have entirely different histories.

58 changed files with 34177 additions and 147 deletions

@ -2,7 +2,7 @@
### Parsing
Added support for protocol buffer files. Updated Ada, Clojure, CMake, Dart,
Added support for protocol buffer files. Updated Ada, CMake, Dart,
Devicetree, Elm, Gleam, HCL, Newick, QML, R, Racket, SQL, Scheme, and
Solidity parsers.

11
Cargo.lock generated

@ -279,7 +279,6 @@ dependencies = [
"tree-sitter-bash",
"tree-sitter-c",
"tree-sitter-c-sharp",
"tree-sitter-clojure-orchard",
"tree-sitter-cmake",
"tree-sitter-cpp",
"tree-sitter-css",
@ -1063,16 +1062,6 @@ dependencies = [
"tree-sitter-language",
]
[[package]]
name = "tree-sitter-clojure-orchard"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62ff7bdebec1f2578787697e32b5539842b8ea9e35df784b537c22cf1ed1aa8f"
dependencies = [
"cc",
"tree-sitter-language",
]
[[package]]
name = "tree-sitter-cmake"
version = "0.7.1"

@ -80,7 +80,6 @@ tree-sitter-ada = "0.1.0"
tree-sitter-bash = "0.23.3"
tree-sitter-c = "0.23.4"
tree-sitter-c-sharp = "0.23.1"
tree-sitter-clojure-orchard = "0.2.0"
tree-sitter-cmake = "0.7.1"
tree-sitter-cpp = "0.23.4"
tree-sitter-css = "0.23.1"

@ -67,6 +67,11 @@ impl TreeSitterParser {
fn main() {
let parsers = vec![
TreeSitterParser {
name: "tree-sitter-clojure",
src_dir: "vendored_parsers/tree-sitter-clojure-src",
extra_files: vec![],
},
TreeSitterParser {
name: "tree-sitter-commonlisp",
src_dir: "vendored_parsers/tree-sitter-commonlisp-src",

@ -14,10 +14,10 @@ with `difft --list-languages`.
| C | [tree-sitter/tree-sitter-c](https://github.com/tree-sitter/tree-sitter-c) |
| C++ | [tree-sitter/tree-sitter-cpp](https://github.com/tree-sitter/tree-sitter-cpp) |
| C# | [tree-sitter/tree-sitter-c-sharp](https://github.com/tree-sitter/tree-sitter-c-sharp) |
| Clojure | [grammar-orchard/tree-sitter-clojure-orchard](https://codeberg.org/grammar-orchard/tree-sitter-clojure-orchard) |
| Clojure | [sogaiu/tree-sitter-clojure](https://github.com/sogaiu/tree-sitter-clojure) |
| CMake | [uyha/tree-sitter-cmake](https://github.com/uyha/tree-sitter-cmake) |
| Common Lisp | [theHamsta/tree-sitter-commonlisp](https://github.com/theHamsta/tree-sitter-commonlisp) |
| Dart | [grammar-orchard/tree-sitter-dart-orchard](https://codeberg.org/grammar-orchard/tree-sitter-dart-orchard) |
| Dart | [grammar-orchard/tree-sitter-dart](https://codeberg.org/grammar-orchard/tree-sitter-dart-orchard) |
| Device Tree | [joelspadin/tree-sitter-devicetree](https://github.com/joelspadin/tree-sitter-devicetree) |
| Elixir | [elixir-lang/tree-sitter-elixir](https://github.com/elixir-lang/tree-sitter-elixir) |
| Elm | [elm-tooling/tree-sitter-elm](https://github.com/elm-tooling/tree-sitter-elm) |
@ -48,12 +48,12 @@ with `difft --list-languages`.
| R | [r-lib/tree-sitter-r](https://github.com/r-lib/tree-sitter-r) |
| Racket | [6cdh/tree-sitter-racket](https://github.com/6cdh/tree-sitter-racket) |
| Ruby | [tree-sitter/tree-sitter-ruby](https://github.com/tree-sitter/tree-sitter-ruby) |
| Rust | [grammar-orchard/tree-sitter-rust-orchard](https://codeberg.org/grammar-orchard/tree-sitter-rust-orchard) |
| Rust | [tree-sitter/tree-sitter-rust](https://github.com/tree-sitter/tree-sitter-rust) |
| Scala | [tree-sitter/tree-sitter-scala](https://github.com/tree-sitter/tree-sitter-scala) |
| Scheme | [6cdh/tree-sitter-scheme](https://github.com/6cdh/tree-sitter-scheme) |
| Smali | [amaanq/tree-sitter-smali](https://github.com/amaanq/tree-sitter-smali) |
| Solidity | [JoranHonig/tree-sitter-solidity](https://github.com/JoranHonig/tree-sitter-solidity) |
| SQL | [derekstride/tree-sitter-sql](https://github.com/derekstride/tree-sitter-sql) |
| SQL | [derekstride/tree-sitter-sql](https://github.com/derekstride/tree-sitter-sql) |
| Swift | [alex-pinkus/tree-sitter-swift](https://github.com/alex-pinkus/tree-sitter-swift) |
| TypeScript, TSX | [tree-sitter/tree-sitter-typescript](https://github.com/tree-sitter/tree-sitter-typescript) |
| Verilog | [tree-sitter/tree-sitter-verilog](https://github.com/tree-sitter/tree-sitter-verilog) |

@ -1,14 +1,14 @@
sample_files/Session_1.kt sample_files/Session_2.kt
fec9f5421c5bdb3cb485c2cfd2f336a6 -
a5899a29b0ebb0800923ac368b95fa1e -
sample_files/ada_1.adb sample_files/ada_2.adb
7498a465384992689732536fcf6ec19b -
0f5fafa73393305ea0d6aba11149efd2 -
sample_files/added_line_1.txt sample_files/added_line_2.txt
8a1587e6b5fc53f2ec2ac665a5d00372 -
sample_files/align_footer_1.txt sample_files/align_footer_2.txt
a7ed15e00ccc8094621e2a9d3c29449c -
0c2a263268f6c1dd27aa5e6aed686b6c -
sample_files/all_changed_1.js sample_files/all_changed_2.js
6f6cbd4d2ed1045e3883143787dbd75b -
@ -17,97 +17,94 @@ sample_files/apex_1.cls sample_files/apex_2.cls
8e477350907734ac4d5201752523dff3 -
sample_files/b2_math_1.h sample_files/b2_math_2.h
ea7421bd7970a6edf2897f8785053ce4 -
1ab24165d072f91be11893b92bc0943f -
sample_files/bad_combine_1.rs sample_files/bad_combine_2.rs
a6d674bd88d54f085c22c70c2d5a4c80 -
dabc6d2f9df43eeaebdbbb44e23a73bb -
sample_files/big_text_hunk_1.txt sample_files/big_text_hunk_2.txt
fc26d41a5ff771670e04033b177973d2 -
sample_files/change_outer_1.el sample_files/change_outer_2.el
ae93896664a63c1f0d4a5f9c4d26dd70 -
13d4673474ea6c7ee980f8a955fff26b -
sample_files/chinese_1.po sample_files/chinese_2.po
582b2c28cca7a60b7c6b0410dfa436bc -
0c40e3f3093cdda64ac9c9674ded3bce -
sample_files/clojure_1.clj sample_files/clojure_2.clj
f1a045dfa78cac71d355951fe0b363a0 -
cdc99aad6117c0cfc2e6896fe629876e -
sample_files/comma_1.js sample_files/comma_2.js
dfd18ec953d29545380fa656e54ff70e -
0e29285c944ffe768790ffbbf9542470 -
sample_files/comma_and_comment_1.js sample_files/comma_and_comment_2.js
0a5ccbcd368607e62eaff0c4ae25049f -
sample_files/comments_1.rs sample_files/comments_2.rs
d8c3c256de454bc23944cf1a4300c66e -
a75827163654d6aed8f837bb586e733c -
sample_files/context_1.rs sample_files/context_2.rs
9b84c492d07d125912de77002bcaad9a -
1a1633bcf672a582867c815381ae1609 -
sample_files/contiguous_1.js sample_files/contiguous_2.js
7ac6081dee02e3529a88defca194bc00 -
22da862378dbee68e55ecba8b0fcec42 -
sample_files/css_1.css sample_files/css_2.css
43a2bbc8dc2f4b4733ecb5a888d10dfc -
3d911704ac4d76697c748e1dcd40eece -
sample_files/dart_1.dart sample_files/dart_2.dart
107d073c2922ff14e9ba66ee0f489592 -
sample_files/devicetree_1.dts sample_files/devicetree_2.dts
100d21f4d762db8991757b489c794db1 -
7ab2bd26334b6729a481665e5566cf97 -
sample_files/elisp_1.el sample_files/elisp_2.el
3e8c8abcb65a5141a2fb54bae4a9ca06 -
d7bdaf5f87e1c44475774c6e7ba70822 -
sample_files/elisp_contiguous_1.el sample_files/elisp_contiguous_2.el
4a5a33873a4f84ee055d95e1448fba35 -
sample_files/elixir_1.ex sample_files/elixir_2.ex
5ab1a845f7cb3ca6db1fdef7bc4a042f -
85494310196ac5065b3b4ce1d4b350fd -
sample_files/elm_1.elm sample_files/elm_2.elm
8a67269f2dd2e4913f885b3b6e6d6a07 -
ccc1f4bb568cd72781dbcd623b612c43 -
sample_files/elvish_1.elv sample_files/elvish_2.elv
93af1d46752d57db84011ca7482ae842 -
sample_files/erlang_1.erl sample_files/erlang_2.erl
268056b80b3311309a17a6c5485f68cd -
4c3e2bd1f0918ed339e87a5f8e0b05cb -
sample_files/f_sharp_1.fs sample_files/f_sharp_2.fs
f6c90edd5c4fb81b793f3b7c9b367845 -
25253b18ef64469c67cf9a7131c8c125 -
sample_files/hack_1.php sample_files/hack_2.php
c2bb0aa7d7b07d6ced79f6a5363e878b -
sample_files/hare_1.ha sample_files/hare_2.ha
b0d0b2c446b46285c585a8eca75e6dd3 -
ef6fd59edc55241311a97d21dd81e4c0 -
sample_files/haskell_1.hs sample_files/haskell_2.hs
e47ca7a69c6f90d9ed9e8b9d47eb2cd4 -
68fd7f9865c2b1defe05ffd509e08b93 -
sample_files/hcl_1.hcl sample_files/hcl_2.hcl
b4de7a8269018e05c0eba247d8097111 -
7c2aaa3a8b401bc007817f5dd608946d -
sample_files/hello_world_1.smali sample_files/hello_world_2.smali
bb8463618fcb7f263bd2dafeef7a8b06 -
c6a0a04710c1dbf30cec4ebed4a35ec9 -
sample_files/helpful_1.el sample_files/helpful_2.el
6eda1c77cb5dc13bc321e90e41a6b64d -
295640aa4cbc23640658a80ad2393ce4 -
sample_files/html_1.html sample_files/html_2.html
2b873fd1ea8f77d2463ceb08aa23967c -
3cc8b445a56b74f05e1d7bb84874edab -
sample_files/html_simple_1.html sample_files/html_simple_2.html
4122689b7d2e3d59d822d2a5d93ebdd0 -
bb129dce38cd26eac81ca52d2016bade -
sample_files/huge_cpp_1.cpp sample_files/huge_cpp_2.cpp
05d96cce94db8ebdfaf4f2d52239470c -
sample_files/hyphen_subwords_1.json sample_files/hyphen_subwords_2.json
d0728537a824a0404a910b5b8dc05b1b -
09e8a30ad7be5686e4d03a3e6b2588aa -
sample_files/identical_1.scala sample_files/identical_2.scala
15c5a789e644348cb7e0de051ff4b63e -
@ -119,61 +116,61 @@ sample_files/insert_blank_1.txt sample_files/insert_blank_2.txt
a5fd75afcc99aa7b2b285f1f9ced8607 -
sample_files/janet_1.janet sample_files/janet_2.janet
7dc0f1a3ce49f489fa4b64edefebb3c5 -
4dba18ec3a9eeee68da7dcccba0fe5a5 -
sample_files/java_1.java sample_files/java_2.java
f4b15ddf3283e6c14d200efd06c0e85a -
028c9176ac031eb3859f3d04bc43ed10 -
sample_files/javascript_1.js sample_files/javascript_2.js
7fc853454d1133da215c646732ac67f3 -
96bc1817594be11dfba02ad675aba076 -
sample_files/javascript_simple_1.js sample_files/javascript_simple_2.js
1a2fdfb7210a93c80a7ce7c0768920c3 -
449a5a824892da502f7211714214684e -
sample_files/json_1.json sample_files/json_2.json
2ac602e995cdcb4bbbc1be6f4622e296 -
133c9224b47a5ee9940536a6ad70fd2e -
sample_files/jsx_1.jsx sample_files/jsx_2.jsx
89832bde34f9c54c99a1bfb0f68291a9 -
712ef0cf61b469bbacc84b53b944e5ff -
sample_files/julia_1.jl sample_files/julia_2.jl
10ac32ea1bd1d48b20386f1deeca40a0 -
532405b3959d8864c06d2fb3548df119 -
sample_files/load_1.js sample_files/load_2.js
2e47b7908951ff8390058856edbaf715 -
289f061e6f36e009f646fb927335326a -
sample_files/long_line_1.txt sample_files/long_line_2.txt
7fc50bd547f0c20fda89a1931e5eb61e -
sample_files/lua_1.lua sample_files/lua_2.lua
11693bb34168541f2ac9f4154d246038 -
81ad9478e64494320e96284cb7632ced -
sample_files/makefile_1.mk sample_files/makefile_2.mk
1a132d165294d0325f9b0dae5569a4d0 -
4759883325ade33566f2c8afa09e2d82 -
sample_files/many_newlines_1.txt sample_files/many_newlines_2.txt
52ca05855e520876479e6f608c5e7831 -
sample_files/metadata_1.clj sample_files/metadata_2.clj
b788a546c4ccc5662e98ed30473dd776 -
fd0fee4a660e938c44182e6f77746d0e -
sample_files/modules_1.ml sample_files/modules_2.ml
d0a10fce6354902c0a1708571ab17ffc -
8584f755c99a93dd744a6722596a4418 -
sample_files/multibyte_1.py sample_files/multibyte_2.py
222fad0d771916afb86dfede9906895b -
f761255d521267ace4f4887a21664a12 -
sample_files/multiline_string_1.ml sample_files/multiline_string_2.ml
ed80815053ba156505d156277d0f4195 -
sample_files/multiline_string_eof_1.yml sample_files/multiline_string_eof_2.yml
79f24009a062f256054cf36e0317dc5d -
cd9cfd627c28b8ecd7c990adc683281a -
sample_files/nest_1.rs sample_files/nest_2.rs
bb3c526d9400776ffae5bf78631fa0c3 -
d3a799fe2cd9d81aa251c96af5cd9711 -
sample_files/nested_slider_1.el sample_files/nested_slider_2.el
7691443ec4ab9d35837f7caa5bfad2de -
0880b11fd8a2e1245622f1f2a908e0c4 -
sample_files/nested_slider_1.rs sample_files/nested_slider_2.rs
342df46db959e8c90925ff4400c0fa63 -
@ -182,31 +179,31 @@ sample_files/nesting_1.el sample_files/nesting_2.el
cf32f6b798a080a2bf14a430337ac4a6 -
sample_files/newick_1.nwk sample_files/newick_2.nwk
bbc830fc20d60c5fdca7a99edc3fde78 -
4244a6609827bae5dabb01b91c9cbd37 -
sample_files/nix_1.nix sample_files/nix_2.nix
5f591ced7633a07f13cdda9766110715 -
6f9bea063047d66e9f857123dfe95e10 -
sample_files/nullable_1.kt sample_files/nullable_2.kt
d0a51e7201cc16dc6bcb99cbad64f6be -
sample_files/objc_header_1.h sample_files/objc_header_2.h
37267814a3d241a8f1497ef3239b360c -
122f030f33e779fb60d0ee83d5a187f4 -
sample_files/objc_module_1.m sample_files/objc_module_2.m
63d3b15c53dfcb54c5cf6ff10c22a965 -
f6c69d2b8b283619f5e093b689e7eb23 -
sample_files/ocaml_1.ml sample_files/ocaml_2.ml
e99bb9f1f789bce0e9a1d4e5205b8139 -
20586eb6dedffb55c7a9e264ed3739c9 -
sample_files/outer_delimiter_1.el sample_files/outer_delimiter_2.el
971c3ddebfae222ded24f7a97ec7b5d7 -
sample_files/pascal_1.pascal sample_files/pascal_2.pascal
de04f7fdb7af7bd70ca62f1868504f11 -
4e8dbdc95cbaba358cbc5dfa4cb22a55 -
sample_files/perl_1.pl sample_files/perl_2.pl
2cd2638b2b6d07248911f1f2e5ad1b25 -
e90ef13054f1e541addcac5ee4bad880 -
sample_files/prefer_outer_1.el sample_files/prefer_outer_2.el
991038c9988cccc2c824652e33f772a2 -
@ -215,25 +212,25 @@ sample_files/preprocessor_1.h sample_files/preprocessor_2.h
d94f452bbf7cb3accc8d538fdd7ab5e4 -
sample_files/qml_1.qml sample_files/qml_2.qml
ec69003436e7780633b6224861c3cccf -
26fed88e46817e49c59fe466701ee574 -
sample_files/r_1.R sample_files/r_2.R
f86f4d5f494756079a4ccfdc17521ef3 -
f9ee6c271d614bfcd510633bddc9e49d -
sample_files/racket_1.rkt sample_files/racket_2.rkt
4debb7e7af49678aa19726acb5c55d7d -
ba1164af47f67d0865a4ba7706096bbc -
sample_files/repeated_line_no_eol_1.txt sample_files/repeated_line_no_eol_2.txt
b63c743f2133480de3ba42ecdec5eb93 -
sample_files/ruby_1.rb sample_files/ruby_2.rb
a0a7121421e3d57acadc08519275dcce -
af0b05e67f4338db6be0fd21454c6a08 -
sample_files/scala_1.scala sample_files/scala_2.scala
2304bea82a6dae573964afdaeb47f845 -
13181dc30f15675747ce5315cd8073e6 -
sample_files/scheme_1.scm sample_files/scheme_2.scm
2d18a48f788361085a05812c2446de91 -
09f8683219a8491c22d9a2fa1ce98c16 -
sample_files/simple_1.js sample_files/simple_2.js
1d49d0e440067284015eb5621f4a6adf -
@ -245,13 +242,13 @@ sample_files/simple_1.txt sample_files/simple_2.txt
7df04bd5dbc68a2392b2f0b375c4413e -
sample_files/slider_1.rs sample_files/slider_2.rs
ebdc9db32892d1d74f7e745f45fbaba6 -
346155adadb1340c026bbfa5cfd5669d -
sample_files/slider_at_end_1.json sample_files/slider_at_end_2.json
6c994cd99226f6584f74f531bb27d54f -
cb370f1c0ccc5e155743330629f899f0 -
sample_files/slow_1.rs sample_files/slow_2.rs
4eabdb287f5fa31f5765117f4874d218 -
74dcf4792d2dc7d7e03ee367aadc3b3c -
sample_files/small_1.js sample_files/small_2.js
86b1132b6c17fcc2cbec65b1c248baa9 -
@ -260,65 +257,65 @@ sample_files/sql_1.sql sample_files/sql_2.sql
ee54ee3f974aa54c8bdfc2b9075824f2 -
sample_files/string_subwords_1.el sample_files/string_subwords_2.el
5c72eae6a018e26189868bcc28747c72 -
b66e960672189960c2d35ef68b47a195 -
sample_files/strings_1.el sample_files/strings_2.el
ae3b58de9c115cac8a1044e6cdf77723 -
26ea57243abb16043088b17bfee482a4 -
sample_files/swift_1.swift sample_files/swift_2.swift
73830b14bd8aacac8d4590a3bed61c40 -
sample_files/syntax_error_1.js sample_files/syntax_error_2.js
c3b918adc3e37f06c65e76fdd4f967e3 -
5bbd81f688bdcfbdbdf69d870f0c1357 -
sample_files/tab_1.c sample_files/tab_2.c
3e19a5dfb37bcda0fbc20e0446c65692 -
a7f9bce0ca76ce356413fb218d82d686 -
sample_files/tab_1.txt sample_files/tab_2.txt
10e9a853917dc9d92d2867e3453269b2 -
a17e978720fe4c1b25614402910cc695 -
sample_files/tailwind_1.css sample_files/tailwind_2.css
132f217659bf9dac8b82feabf5643f47 -
sample_files/text_1.txt sample_files/text_2.txt
caa98983e0fc26ae2bc833ae90fb0a1c -
f8f81946284fc625ac8e9ae441f31e6d -
sample_files/todomvc_1.gleam sample_files/todomvc_2.gleam
6b3b8c9f1e813617819b97144cc5cc4a -
sample_files/toml_1.toml sample_files/toml_2.toml
e1002ceba14d973fcc8abc23619e65b0 -
c331bdb54c00b0a5b5a622dbd250042a -
sample_files/trailling_newline_1.yaml sample_files/trailling_newline_2.yaml
8e37febfec957288576f9c2020cfc4f2 -
sample_files/typescript_1.ts sample_files/typescript_2.ts
e15ceae53da7cfb308960f8c3f30b891 -
fee7ee33d2037ad1941ba6bb5532a1db -
sample_files/typing_1.ml sample_files/typing_2.ml
ae41c3f5aa1ba13c2a424d3afa7ece6c -
975a97f2a6798abd1e4c0ce219e183fd -
sample_files/utf16_1.py sample_files/utf16_2.py
58f2fd906a5ed1b7c5d933bb380c5a1c -
3bcee785d4cebc38a42eafe49a198b52 -
sample_files/verilog_1.sv sample_files/verilog_2.sv
0fbb9bd8ff99b8ee852741860d2c25d0 -
2f59632b5a4e5addfa7b4d5274da72cc -
sample_files/vhdl_1.vhd sample_files/vhdl_2.vhd
d23ea3d27a4cba037729adf485c84afa -
ca98b4d14fc21e0f04cf24aeb3d2526c -
sample_files/whitespace_1.tsx sample_files/whitespace_2.tsx
789689b170b80ef280a322b3a6c7363b -
6449f177ecbaadbbf97d2eedfbf26f16 -
sample_files/windows1251_1.txt sample_files/windows1251_2.txt
28cb8832f6b172c34a28082012512269 -
9ebe6bb440ac2e630f889827b98d4714 -
sample_files/xml_1.xml sample_files/xml_2.xml
d943cb3ae6ea5a5b933ceb1b9987c06b -
e629cbd2e721fd249c7ce1626f17e953 -
sample_files/yaml_1.yaml sample_files/yaml_2.yaml
a539973fd87b6f1fe1391ce73a9b9f90 -
521a2075e4f8b0ea9fb74436e0445b52 -
sample_files/zig_1.zig sample_files/zig_2.zig
f548aaa131854792fe3b72bc283f1280 -
2cb2ce5bcb62c02a29da7ce8a33c6265 -

@ -324,48 +324,6 @@ pub(crate) fn novel_style(style: Style, side: Side, background: BackgroundColor)
}
}
/// Merge spans where the end of one span matches the start of the
/// next span.
///
/// This reduces the number of ANSI character codes in the
/// output. This is negligible for performance, but makes regression
/// testing easier for difftastic.
///
/// The file compare.expected contains hashes of the output, so it
/// considers `<green>ab</green>` to be distinct from
/// `<green>a</green><green>b</green>`. Merging the spans normalises
/// the output to `<green>ab</green>`.
fn merge_adjacent(items: &[(SingleLineSpan, Style)]) -> Vec<(SingleLineSpan, Style)> {
let mut merged: Vec<(SingleLineSpan, Style)> = vec![];
let mut prev_item: Option<(SingleLineSpan, Style)> = None;
for (span, style) in items.iter().copied() {
match prev_item.take() {
Some((mut prev_span, prev_style)) => {
if prev_style == style
&& prev_span.line == span.line
&& prev_span.end_col == span.start_col
{
prev_span.end_col = span.end_col;
prev_item = Some((prev_span, style));
} else {
merged.push((prev_span, prev_style));
prev_item = Some((span, style));
}
}
None => {
prev_item = Some((span, style));
}
}
}
if let Some(last_item) = prev_item {
merged.push(last_item);
}
merged
}
pub(crate) fn color_positions(
side: Side,
background: BackgroundColor,
@ -444,8 +402,7 @@ pub(crate) fn color_positions(
};
styles.push((mp.pos, style));
}
merge_adjacent(&styles)
styles
}
pub(crate) fn apply_colors(

@ -4,9 +4,6 @@
//! manual](http://difftastic.wilfred.me.uk/).
//!
// I frequently develop difftastic on a newer rustc than the MSRV, so
// these two aren't relevant.
#![allow(renamed_and_removed_lints)]
// This tends to trigger on larger tuples of simple types, and naming
// them would probably be worse for readability.
#![allow(clippy::type_complexity)]
@ -40,6 +37,9 @@
// Debugging features shouldn't be in checked-in code.
#![warn(clippy::todo)]
#![warn(clippy::dbg_macro)]
// I frequently develop difftastic on a newer rustc than the MSRV, so
// this isn't relevant.
#![allow(renamed_and_removed_lints)]
mod conflicts;
mod constants;

@ -69,6 +69,7 @@ pub(crate) struct TreeSitterConfig {
}
extern "C" {
fn tree_sitter_clojure() -> ts::Language;
fn tree_sitter_commonlisp() -> ts::Language;
fn tree_sitter_elisp() -> ts::Language;
fn tree_sitter_elvish() -> ts::Language;
@ -183,9 +184,7 @@ pub(crate) fn from_language(language: guess::Language) -> TreeSitterConfig {
}
}
Clojure => {
let language_fn = tree_sitter_clojure_orchard::LANGUAGE;
let language = tree_sitter::Language::new(language_fn);
let language = unsafe { tree_sitter_clojure() };
TreeSitterConfig {
language: language.clone(),
atom_nodes: ["kwd_lit", "regex_lit"].into_iter().collect(),
@ -194,7 +193,7 @@ pub(crate) fn from_language(language: guess::Language) -> TreeSitterConfig {
.collect(),
highlight_query: ts::Query::new(
&language,
tree_sitter_clojure_orchard::HIGHLIGHTS_QUERY,
include_str!("../../vendored_parsers/highlights/clojure.scm"),
)
.unwrap(),
sub_languages: vec![],

@ -0,0 +1 @@
../tree-sitter-clojure/queries/highlights.scm

@ -0,0 +1 @@
tree-sitter-clojure/src

@ -0,0 +1,5 @@
node_modules
bin
build
*.log

@ -0,0 +1,175 @@
## Changelog
Bits may be missing and/or inaccurate :)
### Future?
* Handle zero bytes?
* Decide about inline use (e.g. add some \_bare\_\* constructs? stop using?)
([#41](https://github.com/sogaiu/tree-sitter-clojure/issues/41))
### v0.0.13 - 2024-05-15
* Features and Fixes
* Increase API number from 13 to 14
([#60](https://github.com/sogaiu/tree-sitter-clojure/issues/60))
* Remove Node and Rust Bindings
([#61](https://github.com/sogaiu/tree-sitter-clojure/issues/61))
* Update version info in package.json
* Docs
* What and why doc - update bindings info
### v0.0.12 - 2023-05-07
* Features and Fixes
* Loosen sym_val_lit definition
([#51](https://github.com/sogaiu/tree-sitter-clojure/issues/51))
* Handle metadata that is an evaling_lit
([#35](https://github.com/sogaiu/tree-sitter-clojure/issues/35),
[#46](https://github.com/sogaiu/tree-sitter-clojure/issues/46),
[#50](https://github.com/sogaiu/tree-sitter-clojure/issues/50))
* Handle construct used for ClojureDart's parameterized types
([#35](https://github.com/sogaiu/tree-sitter-clojure/issues/35),
[#44](https://github.com/sogaiu/tree-sitter-clojure/pull/44),
[#46](https://github.com/sogaiu/tree-sitter-clojure/issues/46))
* Generate parser.c and friends with tree-sitter 0.20.7 (ABI 13)
([#26](https://github.com/sogaiu/tree-sitter-clojure/pull/26),
[#34](https://github.com/sogaiu/tree-sitter-clojure/issues/34),
[#45](https://github.com/sogaiu/tree-sitter-clojure/issues/45))
* Docs
* README
* Add section on "what and why"
([#38](https://github.com/sogaiu/tree-sitter-clojure/issues/38))
* Add section pointing to other docs
([#47](https://github.com/sogaiu/tree-sitter-clojure/issues/47))
* Move resources list to own document
([#47](https://github.com/sogaiu/tree-sitter-clojure/issues/47))
* Remove npm-related descriptions
([#47](https://github.com/sogaiu/tree-sitter-clojure/issues/47))
* Use doc - mostly new users added
([#47](https://github.com/sogaiu/tree-sitter-clojure/issues/47))
* Scope doc - corrections and refinements
([#47](https://github.com/sogaiu/tree-sitter-clojure/issues/47))
* Testing doc - link and format updates
([#47](https://github.com/sogaiu/tree-sitter-clojure/issues/47))
* What and why doc - added
([#47](https://github.com/sogaiu/tree-sitter-clojure/issues/47))
* Limits doc - added
* notes.txt - removed
* Developer-related
* Improve maintainability of grammar.js
([#39](https://github.com/sogaiu/tree-sitter-clojure/issues/39),
[#40](https://github.com/sogaiu/tree-sitter-clojure/issues/40))
* Remove dependence on npm
([#36](https://github.com/sogaiu/tree-sitter-clojure/issues/36),
[#37](https://github.com/sogaiu/tree-sitter-clojure/issues/37),
[#38](https://github.com/sogaiu/tree-sitter-clojure/issues/38),
[#45](https://github.com/sogaiu/tree-sitter-clojure/issues/45))
* Cleanup package.json
([#34](https://github.com/sogaiu/tree-sitter-clojure/issues/34),
[#36](https://github.com/sogaiu/tree-sitter-clojure/issues/36),
[#37](https://github.com/sogaiu/tree-sitter-clojure/issues/37),
[#38](https://github.com/sogaiu/tree-sitter-clojure/issues/38),
[#45](https://github.com/sogaiu/tree-sitter-clojure/issues/45))
* Move corpus to test/corpus
* Most developer-bits moved to separate repository
([#35](https://github.com/sogaiu/tree-sitter-clojure/issues/35),
[#36](https://github.com/sogaiu/tree-sitter-clojure/issues/36),
[#39](https://github.com/sogaiu/tree-sitter-clojure/issues/39),
[#42](https://github.com/sogaiu/tree-sitter-clojure/issues/42),
[#43](https://github.com/sogaiu/tree-sitter-clojure/issues/43),
[#45](https://github.com/sogaiu/tree-sitter-clojure/issues/45),
[#46](https://github.com/sogaiu/tree-sitter-clojure/issues/46),
[#47](https://github.com/sogaiu/tree-sitter-clojure/issues/47))
* Credits
* borkdude
([#51](https://github.com/sogaiu/tree-sitter-clojure/issues/51))
* cgrand
([#44](https://github.com/sogaiu/tree-sitter-clojure/pull/44))
* dannyfreeman
([#26](https://github.com/sogaiu/tree-sitter-clojure/pull/26),
[#35](https://github.com/sogaiu/tree-sitter-clojure/issues/35),
[#37](https://github.com/sogaiu/tree-sitter-clojure/issues/37),
[#38](https://github.com/sogaiu/tree-sitter-clojure/issues/38),
[#39](https://github.com/sogaiu/tree-sitter-clojure/issues/39),
[#40](https://github.com/sogaiu/tree-sitter-clojure/issues/40),
[#41](https://github.com/sogaiu/tree-sitter-clojure/issues/41),
[#42](https://github.com/sogaiu/tree-sitter-clojure/issues/42),
[#43](https://github.com/sogaiu/tree-sitter-clojure/issues/43),
[#46](https://github.com/sogaiu/tree-sitter-clojure/issues/46),
[#48](https://github.com/sogaiu/tree-sitter-clojure/pull/48),
[#49](https://github.com/sogaiu/tree-sitter-clojure/issues/49),
[#51](https://github.com/sogaiu/tree-sitter-clojure/issues/51))
* dmiller
([#42](https://github.com/sogaiu/tree-sitter-clojure/issues/42))
* IGJoshua
([#35](https://github.com/sogaiu/tree-sitter-clojure/issues/35))
* NoahTheDuke
([#26](https://github.com/sogaiu/tree-sitter-clojure/pull/26),
[#35](https://github.com/sogaiu/tree-sitter-clojure/issues/35),
[#37](https://github.com/sogaiu/tree-sitter-clojure/issues/37),
[#38](https://github.com/sogaiu/tree-sitter-clojure/issues/38),
[#39](https://github.com/sogaiu/tree-sitter-clojure/issues/39),
[#40](https://github.com/sogaiu/tree-sitter-clojure/issues/40),
[#42](https://github.com/sogaiu/tree-sitter-clojure/issues/42))
* phronmophobic
([#35](https://github.com/sogaiu/tree-sitter-clojure/issues/35))
### v0.0.11 - 2023-01-22
* Update version info in package.json
### v0.0.10 - 2023-01-06
* Tokenize symbols and keywords further
([#31](https://github.com/sogaiu/tree-sitter-clojure/issues/31)) -
dannyfreeman
* Address symbols after metadata issue
([#21](https://github.com/sogaiu/tree-sitter-clojure/issues/21)) -
dannyfreeman
* Change formatting of grammar.js
### v0.0.9 - 2022-06-03
* Add corpus for light testing
* Add highlighting queries for difftastic
([#20](https://github.com/sogaiu/tree-sitter-clojure/issues/20))
* Remove web-tree-sitter dependency
([#19](https://github.com/sogaiu/tree-sitter-clojure/issues/19))
* Re-add binding.gyp
### v0.0.8 - 2021-03-17
* Upgrade tree-sitter to 0.19.3
* Add Cargo.toml
* Upgrade tree-sitter to 0.19.2
* Add generated bindings directory and content
### v0.0.7 - 2021-01-05
* CC0-1.0 ([#11](https://github.com/sogaiu/tree-sitter-clojure/issues/11))
* Tweak grammar.js
### v0.0.3 - 2020-10-30
* Add generated src directory and content
* Major renaming
* More fields
* Refine metadata bits
* Refine \_bare\_\* constructs usage
* Address discard / number parsing issue
([#7](https://github.com/sogaiu/tree-sitter-clojure/issues/7))
* Octal number tweak
* Restore visibility of comment nodes
* ?
### v0.0.2 - 2020-09-02
* Handle whitespace explicitly, no extras
* Start using some \_bare\_\* constructs
* ?
### v0.0.1 - 2020-07-05
* First tagging

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

@ -0,0 +1,46 @@
# tree-sitter-clojure
A tree-sitter grammar for Clojure and ClojureScript
## What the Repository Provides
This repository provides some files used to create various artifacts
(e.g. dynamic libraries) used for handling Clojure and ClojureScript
source code via tree-sitter.
Please see the [what and why document](doc/what-and-why.md) for
detailed information.
## Potential Changes Announcements
Changes may occur because:
1. There may be unanticipated important use cases we may want to
account for
2. The grammar depends on tree-sitter which remains in flux (and is
still pre 1.0)
3. It's possible we missed something or got something wrong about
Clojure and we might want to remedy that
To get a heads-up before such changes occur, please consider
subscribing to the [Potential Changes Announcements
issue](https://github.com/sogaiu/tree-sitter-clojure/issues/33) to be
notified beforehand.
Note that previously tagged versions may work fine depending on the
use case. See the [changelog](CHANGELOG.md) for details.
## Other Documents
There are some documents in the [`doc` directory](doc/) covering
topics such as:
* [Scope](doc/scope.md)
* [Limits](doc/limits.md)
* [Testing](doc/testing.md)
* [Uses](doc/use.md)
## Acknowledgments
Please see the [credits](doc/credits.md).

@ -0,0 +1,59 @@
## Credits
Many people were directly and indirectly involved in bringing about tree-sitter-clojure. I may have missed some people below, please let me know if I have. Thanks to all!
* Aerijo - Guide to your first Tree-sitter grammar
* ahlinc - tree-sitter work
* alehatsman - nvim-treesitter and related discussion
* alexmiller - clojure-related inquiries and docs
* andrewchambers - discussion
* bbatsov - discussions and clojure-ts-mode
* bfredl - neovim and tree-sitter work
* borkdude - analyze-reify, babashka, clj-kondo, edamame, and more
* carocad - parcera and discussions
* cgrand - ClojureDart and related reader explanation
* clojars - including everyone who has uploaded there
* CoenraadS - Bracket-Pair-Colorizer-2
* dannyfreeman - grammar.js enhancements and fixes, clojure-ts-mode and discussions
* dmiller - ClojureCLR consultation
* EvegeniyPeshkov - syntax-highlighter
* georgewfraser - vscode-tree-sitter
* gfredericks - test.check, generators, and discussions
* GrayJack - discussions and tree-sitter-janet
* hitode909 - vscode-perl-outline
* iarenaza - discussions
* IGJoshua - ClojureCLR investigations
* jafingerhut - clojure-related inquiries and haironfire research
* jeff-hykin - tree-sitter and VSCode related
* kolja - nrepl-alliance and tree-sitter question concerning Clojure on StackOverflow
* lread - rewrite-cljc and discussions
* mauricioszabo - clover and repl-tooling
* maxbrunsfeld - tree-sitter and related
* monnier - emacs-tree-sitter related
* NoahTheDuke - discussion and suggestions
* nwjsmith - tree-sitter upgrade
* oakmac - tree-sitter-clojure.oakmac, conj 2018 unsession, advice, etc.
* p00f - nvim-ts-rainbow
* pedrorgirardi - discussions, vscode and tree-sitter-clojure bits
* PEZ - calva, vscode tips, and general discussion
* phronmophobic - dewey, discussion, and repository data
* pyrmont - review, error-spotting, fix, and discussions
* rewinfrey - helpful bits from tree-sitter-haskell
* richhickey - clojure, etc.
* rrudakov - discussions and clojure-ts-mode
* Saikyun - discussions
* seancorfield - clojure-related inquiries
* SergeevPavel - tree-sitter-clojure.SergeevPavel (fork of tree-sitter-clojure.Tavistock with further work)
* SevereOverfl0w - tree-sitter and vim info
* shackra - tree-sitter-query.el
* SignSpice - discussion
* snoe - discussions
* Tavistock - tree-sitter-clojure.Tavistock
* th0rex - emacs-tree-sitter related
* theHamsta - neovim, nvim-treesitter, tree-sitter-commonlisp
* tobias - clojars work
* tonsky - sublime-clojure work with test data, clojure north talk, alabaster theme
* ubolonton - emacs-tree-sitter
* vigoux - nvim-treesitter and related
* Wilfred - difftastic, bug reporting, and discussion

@ -0,0 +1,28 @@
# Limits
The following items are known to not necessarily work:
* [Some template
files](https://github.com/sogaiu/tree-sitter-clojure/issues/42#issuecomment-1426727973) -
these are often not strictly speaking Clojure, though they look pretty close
* Other code that is not standard Clojure
[1](https://github.com/fjarri/clojure-scribble#basic-usage)
[2](https://github.com/dgrnbrg/piplin/blob/4c39386413d62ec9c2d679fa4c742313d97f75ef/src/piplin/mips.clj#L12)
because it uses functionality that modifies Clojure's reader behavior
in certain ways [1](https://github.com/jwymanm/chiara#the-syntax)
[2](https://github.com/dgrnbrg/piplin/blob/4c39386413d62ec9c2d679fa4c742313d97f75ef/src/piplin/types/bits.clj#L231-L251)
* Some older Clojure code - for example, `^` used to mean "wrap the
following thing in `(meta ...)`"
[1](https://github.com/clojure/clojure/blob/1.0.x/src/jvm/clojure/lang/LispReader.java#L71)
[2](https://github.com/clojure/clojure/blob/1.0.x/src/clj/clojure/zip.clj#L58)
* [ClojureCLR's pipe syntax for
symbols](https://github.com/sogaiu/tree-sitter-clojure/issues/35#issuecomment-1407320526)
([comment at #42](https://github.com/sogaiu/tree-sitter-clojure/issues/42#issuecomment-1450290140))
* [Files that contain one or more
zero-bytes](https://github.com/sogaiu/tree-sitter-clojure/issues/42#issuecomment-1430546851)
[1](https://github.com/santifa/clj-dbase/blob/a269ca62d529cf82cec7bffce2e38b71458c6087/src/clj_dbase/core.clj#L121)
[2](https://github.com/ont-app/vocabulary/blob/5929b9b1a16b07dc60f1012070da684e8f073326/resources/uri-escapes.edn) -
this might be a tree-sitter limitation
See [#42](https://github.com/sogaiu/tree-sitter-clojure/issues/42) for
more details.

@ -0,0 +1,17 @@
# Resources
Below is a list of resources related to tree-sitter and/or Clojure.
Some may be a bit dated at this point.
* [Guide to your first Tree-sitter
grammar](https://gist.github.com/Aerijo/df27228d70c633e088b0591b8857eeef)
* [sublime-clojure](https://github.com/tonsky/sublime-clojure)
* [syntax-highlighter](https://github.com/EvgeniyPeshkov/syntax-highlighter)
* [tree-sitter](http://tree-sitter.github.io/tree-sitter/)
* [tree-sitter-clojure.oakmac](https://github.com/oakmac/tree-sitter-clojure)
* [tree-sitter-clojure.SergeevPavel](https://github.com/SergeevPavel/tree-sitter-clojure)
* [tree-sitter-clojure.Tavistock](https://github.com/Tavistock/tree-sitter-clojure)
* [vscode-tree-sitter](https://github.com/georgewfraser/vscode-tree-sitter)
* [web-tree-sitter
API](https://github.com/tree-sitter/tree-sitter/blob/master/lib/binding_web/tree-sitter-web.d.ts)

@ -0,0 +1,103 @@
# Scope of tree-sitter-clojure
## TLDR
Only "primitives"
(e.g. [symbols](https://github.com/sogaiu/tree-sitter-clojure/blob/c00293fb0cd5ce3a7005c0601e9b546c1ea73094/grammar.js#L280-L282),
[lists](https://github.com/sogaiu/tree-sitter-clojure/blob/c00293fb0cd5ce3a7005c0601e9b546c1ea73094/grammar.js#L307-L309),
etc.) are supported, i.e. no higher level constructs like `defn`.
## The Details
### Why
For some background, Clojure (and other Lisps) have runtime extensible
"syntax" via macros, but AFAIU tree-sitter's current design assumes a
fixed syntax.
Keeping the above in mind, below are some of the factors that
influenced the current stance on scope:
* Clojure has no language specification. This means it's unclear what
to try to support in the grammar. For example, `defn` is defined in
the `clojure.core` namespace, but then so are a lot of other things
and `clojure.core` is not a small namespace.
* Each additional item added to the grammar tends to increase the
difficulty of getting the grammar to function correctly (or well
enough). In the event that an issue is discovered or a much desired
feature surfaces, the more items there already are in the grammar,
generally, the harder it may be to accomodate / adjust.
* Handling more things might lead to degraded performance. Apart from
possibly that being a negative for end-user use, that might also
lead to more waiting time while testing across large samples of code
(which has been essential because of the lack of a specification).
### Alternatives
It is possible to [use tree-sitter-clojure as a
base](https://github.com/tree-sitter/tree-sitter/issues/645) to add
additional constructs to a "derived" grammar. For example, such a
grammar might be specialized to look for "definitions". At least in
[emacs-tree-sitter](https://github.com/ubolonton/emacs-tree-sitter),
[it is technically possibly to have multiple grammars be used on
single
buffer](https://github.com/ubolonton/emacs-tree-sitter/discussions/129#discussioncomment-502836):
> If you want 2 parse trees in the same buffer instead, you would need
> to define an advice for tree-sitter--do-parse, as well as additional
> buffer-local variables for the secondary grammar.
Apparently it became possible in September of 2020 for [queries to
match on any of a node's
supertypes](https://github.com/tree-sitter/tree-sitter/pull/738). It
may be possible to make a list supertype that is "composed of" `defn`
and things that are not `defn`.
[tree-sitter-clojure-def](https://github.com/sogaiu/tree-sitter-clojure-def)
is an attempt at realizing this apoproach.
However, depending on one's goals, it might make more sense to
consider leveraging [clj-kondo's analysis
capabilities](https://github.com/clj-kondo/clj-kondo/tree/master/analysis)
as clj-kondo already understands Clojure pretty well. IIUC,
[clojure-lsp does
this](https://github.com/clojure-lsp/clojure-lsp/blob/14724457f0d553795dfe16317d3ee6c5fc97d4ba/deps.edn#L21).
### Miscellaneous Points
* Earlier attempts at adding `def` and friends resulted in
unacceptably high error rates [1]. The tests were conducted against
code from [Clojars](https://clojars.org/) (uncontrived code) [2].
* For use cases like structural editing, it seems important to be able
to distinguish between the following sorts of cases:
* `defn` used for defining a function, and
* [Using the symbol `defn` within a macro to construct code to
define a
function](https://github.com/Raynes/conch/blob/685f2c73138f376f2aa0623053dfdaba350a04f4/src/me/raynes/conch.clj#L251-L252)
AFAICT, the approach taken in tree-sitter-clojure-def does not
make telling these sorts of things apart possible.
* It doesn't seem possible to support all "defining" macros like
`defsomething`
(e.g. https://github.com/redplanetlabs/specter/blob/efaf35558a2c0068f5b6a8ef1dbbd0912702bdbd/src/clj/com/rpl/specter.cljc#L57-L60)
since a user's Clojure code can define these.
## Footnotes
* [1] Author's opinion :)
* [2] Two of the previous tree-sitter-clojure attempts (by
[oakmac](https://github.com/oakmac/tree-sitter-clojure) and
[Tavistock](https://github.com/Tavistock/tree-sitter-clojure)) also
had unacceptably high error rates. The former of those two grammars
tried to handle higher level constructs and it had a notably higher
error rate. After trying to modify that grammar to address the error
rate unsuccessfully, it seemed like the two points were related. Note
though that this is just a suspicion.
## References
* https://www.reddit.com/r/Clojure/comments/fkc6uv/is_anyone_working_on_a_treesitter_parser_for/fksmf67/
* https://github.com/sogaiu/tree-sitter-clojure/issues/15#issuecomment-880729889

@ -0,0 +1,226 @@
# Testing tree-sitter-clojure
## TLDR
[tree-sitter-clojure](https://github.com/sogaiu/tree-sitter-clojure)
has been tested using a variety of methods.
_Note_: Current serious testing is done via the code and instructions
in the [ts-clojure](https://github.com/sogaiu/ts-clojure) repository.
The description below is left for historical purposes.
## The Details
This document will touch on some of those methods and why they were
attempted:
1. Using corpus data from other tree-sitter-clojure attempts
2. Using Clojure source from [Clojars](https://clojars.org/)
3. Generative testing via
[Hypothesis](https://github.com/HypothesisWorks/hypothesis)
Other employed methods that won't be covered (in much, if any, detail)
here:
1. Sporadic manual invocations
2. Using [tonsky's
sublime-clojure](https://github.com/tonsky/sublime-clojure) test
data
3. Generative testing via
[test.check](https://github.com/clojure/test.check/)
4. [Manual inspection of the
grammar](https://github.com/sogaiu/tree-sitter-clojure/issues/3)
## Using corpus data from other tree-sitter-clojure attempts
There were at least two previous attempts at implementing
tree-sitter-clojure, [one by
oakmac](https://github.com/oakmac/tree-sitter-clojure) and [another by
Tavistock](https://github.com/Tavistock/tree-sitter-clojure).
Important things were learned by trying to make these attempts work,
but for reasons not covered here, a separate attempt was started.
Both earlier attempts had
[corpus](https://github.com/oakmac/tree-sitter-clojure/tree/master/corpus)
[data](https://github.com/Tavistock/tree-sitter-clojure/tree/master/corpus)
that could be adapted for testing. Consequently,
[tsclj-tests-parser](https://github.com/sogaiu/tsclj-tests-parser) was
created to extract [the relevant data as plain
files](https://github.com/sogaiu/tsclj-tests-parser/-/tree/master/test-files).
These were in turn fed to tree-sitter's `parse` command using the
tree-sitter-clojure grammar to check for parsing errors.
If changes are made to tree-sitter-clojure's grammar, this method can
be used to quickly check for some forms of undesirable breakage.
(This could be taken a bit further by adapting the content as corpus
data for tree-sitter-clojure.)
### But...
One issue with this approach is that it relies on manually identifying
and spelling out appropriate test cases, which in the case of Clojure,
is complicated by the lack of a language specification.
Apart from detailed research, this was partially addressed by testing
against a large sample of Clojure source code written by the
community.
## Using Clojure source from Clojars
The most fruitful method of testing was working with Clojure source
written by humans for purposes other than for testing
tree-sitter-clojure.
### Where to get samples of Clojure source
Initially, repositories were cloned from a variety of locations, but
before long a decision was made to switch to using "release" jars from
Clojars.
The latter decision was motivated by wanting source that was less
likely to be "broken" in various ways. Compared to "release" jar
content from Clojars, the default branch of a repository seemed to
have a higher probability of "not quite working". Although the
Clojars "release" idea was an improvement, weeding out inappropriate
Clojure source was still necessary.
A variety of approaches were used to come up with a specific list of
jars from Clojars, but the most recent attempt is
[gen-clru-list](https://github.com/sogaiu/gen-clru-list). This is
basically a [babashka](https://github.com/babashka/babashka) script
that fetches [Clojars'
feed.clj](https://github.com/clojars/clojars-web/wiki/Data#useful-extracts-from-the-poms),
does some processing, and writes out a list of urls. For reference,
this approach currently yields a number of urls in the neighborhood of
19,000.
### How to check retrieved Clojure samples
The retrieved content was initially checked using
[a-tsclj-checker](https://github.com/sogaiu/a-tsclj-checker) (an
adaptation of
[analyze-reify](https://github.com/borkdude/analyze-reify)) which uses
[Rust bindings for
tree-sitter](https://github.com/tree-sitter/tree-sitter/tree/master/lib/binding_rust)
and tree-sitter-clojure to parse Clojure source code. Notably, it can
traverse directories and also operate on `.jar` files.
Once an error is detected, it is easier to investigate if one has
direct access to the Clojure source file in question (as compared with
rummaging around `.jar` files). Thus, it was decided to create a
single directory tree containing extracted data from all retrieved
jars. On a side note, the single directory tree took less than 2 GB
of disk space.
A less fancy, but easier to maintain (i.e. not written in Rust) tool --
[ts-grammar-checker](https://github.com/sogaiu/ts-grammar-checker) -- was
developed as an alternative to `a-tsclj-checker`. Strictly speaking,
`ts-grammar-checker` may not be necessary as one can probably employ
tree-sitter's `parse` command in combination with `find`, `xargs` and the like
if on some kind of \*nix. An example of a comparable invocation is:
```
find ~/src/clojars-cljish -type f -regex '.*\.clj[cs]?$' -print0 | xargs -0 tree-sitter parse --quiet > my-results.txt
```
`a-tsclj-checker` is the fastest tool but it has not been updated to
the most recent version of tree-sitter-clojure. `ts-grammar-checker`
is not quite as fast, but it can be easily adapted to work with other
tree-sitter grammars (e.g. it's
[used](https://github.com/sogaiu/ts-grammar-checker/-/blob/master/janet-checker.janet)
for
[tree-sitter-janet-simple](https://github.com/sogaiu/tree-sitter-janet-simple)
as well). However, it does not support accessing content within
`.jar` files.
Across somewhat less than 150,000 files (.clj, .cljc, .cljs),
`a-tsclj-checker` typically takes a little less than 30 seconds, while
`ts-grammar-checker` typically takes a bit more than 100 seconds (at
least on the author's machine). In subjective terms, it hasn't felt
terribly different because knowing there is at least a 30 second wait,
[one typically doesn't sit waiting at a prompt for execution
completion](https://xkcd.com/303/).
For any files that parse with errors, it can be handy to apply
[clj-kondo](https://github.com/clj-kondo/clj-kondo). The specific
details that `clj-kondo` reported were often helpful when examining
individual files, but that diagnostic information also provided a way
to partition the files into groups. Subjectively it can feel more
manageable to deal with 5 groups of files compared with 100 separate
files (though it's true that the grouping does not always turn out to
be that meaningful).
An individual "suspect" file is typically viewed manually in an editor
(usually one that has `clj-kondo` support enabled) and examined for
"issues".
In practice, testing the grammar against appropriate Clojure source
from Clojars has been the most useful in finding issues with the
grammar. The lack of a specification for Clojure increased the
difficulty of creating an appropriate grammar, but having a large
sample of code to test against helped to mitigate this a bit. On more
than one occasion some version of the grammar failed to parse some
legitimate Clojure source and subsequent investigation revealed that
the grammar had not accounted for an uncommom and/or unanticipated
usage.
### But...
This method has a significant weakness as there could be cases where
tree-sitter would parse successfully but the result could be
inappropriate. For example, if the grammar definition was faulty,
something which should be parsed as a symbol might end up parsed as a
number with no error reported.
To partially address this issue, generative / property-based testing
was attempted.
## Generative testing via Hypothesis
Initially, [some effort was made to use
test.check](https://gist.github.com/sogaiu/c0d668d050b63e298ef63549e357f9d2).
However, [an outstanding issue with
test.check](https://github.com/clojure/test.check/blob/master/doc/growth-and-shrinking.md#unnecessary-bind)
(aka TCHECK-112) seemed very likely to be relevant for the types of
tests being considered. Also, the approach used
[libpython-clj](https://github.com/clj-python/libpython-clj) to call
tree-sitter via [Python bindings for
tree-sitter](https://github.com/tree-sitter/py-tree-sitter). Although
invoking tree-sitter via Python worked, it was awkward to connect this
with `test.check`. For the above reasons, the `test.check` +
`libpython-clj` approach (neat as it was) was abandoned.
Interestingly, Python's Hypothesis doesn't suffer from test.check's
["long-standing Hard
Problem"](https://clojure.atlassian.net/browse/TCHECK-112) so that was
given a try.
[prop-test-ts-clj](https://github.com/sogaiu/prop-test-ts-clj) and
[hypothesis-grammar-clojure](https://github.com/sogaiu/hypothesis-grammar-clojure)
are the resulting bits.
At least [one
issue](https://github.com/sogaiu/tree-sitter-clojure/issues/7) was
discovered and it also turned out that
[parcera](https://github.com/carocad/parcera) was
[affected](https://github.com/carocad/parcera/issues/86).
The code was also adapted a bit to test
[Calva](https://github.com/BetterThanTomorrow/calva). Some issues
were discovered and [reported
upstream](https://github.com/BetterThanTomorrow/calva/issues/802).
### But...
A drawback of this approach is that details of the tree-sitter-clojure
grammar became embedded in the tests. One consequence is that if
tree-sitter-clojure's grammar changes, then the tests may need to be
updated to reflect changes in the grammar (if there is an intent to
continue to use them).
## Summary
tree-sitter-clojure has been tested in a variety ways attempting to
address various real-world constraints (e.g. lack of a language
specification, limitations of tree-sitter's approach for a language
with extensible syntax, etc.). AFAICT, for what it sets out to do, it
seems to work pretty well so far.

@ -0,0 +1,25 @@
## Use Information
tree-sitter-clojure has been used in or by the following:
* [clojure-ts-mode](https://github.com/clojure-emacs/clojure-ts-mode)
* [Cursorless](https://github.com/cursorless-dev/cursorless)
* [difftastic](https://github.com/Wilfred/difftastic)
* [Helix Editor](https://github.com/helix-editor/helix)
* [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter)
* [Semgrep](https://github.com/returntocorp/semgrep)
* [tree-sitter-langs](https://github.com/emacs-tree-sitter/tree-sitter-langs)
* Exploring [alternative highlighting
ideas](https://github.com/ubolonton/emacs-tree-sitter/issues/68) and
[an early emacs user
foray](https://ag91.github.io/blog/2021/06/22/how-(simple-is)-to-install-a-clojure-tree-sitter-grammar-and-use-it-from-emacs/),
both via
[emacs-tree-sitter](https://github.com/ubolonton/emacs-tree-sitter).

@ -0,0 +1,101 @@
# What the Repository Provides and Why
This document describes what files and directories the repository
provides and associated reasoning. First it covers things which are
likely to remain in place for some time (except perhaps the `src`
directory). This is followed by a description of things that are more
likely to change or be removed.
One might be interested in this content out of academic curiosity but
more likely it might be because one is thinking of depending on the
repository in some way.
## What and Why
The order of the following files and directories is alphabetical and
not meant to reflect relative importance.
* `CHANGELOG.md` - this file contains a changelog.
* `COPYING.txt` - this file contains license information for the
repository.
* `grammar.js` - this file contains a grammar description and is used
in the process of generating parser source code that lives in `src`.
It's likely that this (or something comparable) will continue to be
provided assuming tree-sitter doesn't change the way it works.
* `package.json` - this file is needed by a
[component](https://github.com/cursorless-dev/vscode-parse-tree/) of
[Cursorless](https://www.cursorless.org/). It uses our grammar via
yarn and `package.json` seems to be essential.
* `queries` - this directory and the simple file it contains are
provided on request from
[`difftastic`](https://github.com/Wilfred/difftastic) folks. The
file it contains doesn't contain much and is not likely to be the
sort of thing one expects to be used in an editor.
* `README.md` - this file contains the repository's README content.
* `src` - this directory contains source files that are generated [1]
from `grammar.js`. The files are typically used to generate a
dynamic library / shared object that can be used by the tree-sitter
library to handle Clojure / ClojureScript source code. Although the
content of this directory is generated, the files are provided
because in practice, multiple parties have already become dependant
on them. There have been opinions voiced that this should not
remain so, but change in that direction has not been widespread. We
would prefer not to be hosting this directory and its content, but
are leaving it in place for the time being. See
[here](https://github.com/sogaiu/ts-questions/blob/master/questions/should-parser-source-be-committed/README.md)
for more on the topic if interested.
* `test/corpus` - this directory contains tree-sitter's corpus
test-related files.
## Other Content
The rest of the content of the repository is currently documentation
that lives in the `doc` directory.
## About Bindings
The repository does not host any bindings (e.g. for Rust, Node, or
other programming language).
They should be straight-forward to generate as long as one has a
suitable `tree-sitter` cli and the `grammar.js` file mentioned above.
Binding code used to be created by the `generate` subcommand, but this
appears to have [changed from version 0.24.0 of the `tree-sitter`
cli](https://github.com/tree-sitter/tree-sitter/releases/tag/v0.24.0):
> Move generation of grammar files to an init command ([#3694](https://github.com/tree-sitter/tree-sitter/pull/3694))
Note that "grammar files" here seems to refer to "bindings" files.
Further evidence in support of this change is [this
documentation](https://tree-sitter.github.io/tree-sitter/cli/init.html#binding-files):
> When you run tree-sitter init, the CLI will also generate a number
> of files in your repository that allow for your parser to be used
> from different language.
Which languages bindings files are generated for is affected by [the
`bindings` field in
`tree-sitter.json`](https://tree-sitter.github.io/tree-sitter/cli/init.html#the-bindings-field).
(It appears that omitting the field means "don't generate any
bindings".)
Probably it's better to consult the official documentation and/or ask
around about what the latest procedure is rather than rely on these
brief notes though.
## Footnotes
[1] If the grammar uses an external scanner, `src` may contain
non-generated files such as `scanner.c`, `scanner.cc`, etc. In the
current case, no external scanner is used and the `src` directory
content is entirely generated.

@ -0,0 +1,528 @@
// one aim is to try to parse what is correct (in the sense of
// officially supported), but also be looser in parsing additional
// things. this is more or less in line with advice from tree-sitter
// folks.
function regex(...patts) {
return RegExp(patts.join(""));
}
// java.lang.Character.isWhitespace AND comma
//
// Space Separator (Zs) but NOT including (U+00A0, U+2007, U+202F)
// U+0020, U+1680, U+2000, U+2001, U+2002, U+2003, U+2004, U+2005,
// U+2006, U+2008, U+2009, U+200A, U+205F, U+3000
// Line Separator (Zl)
// U+2028
// Paragraph Separator (Zp)
// U+2029
// Horizontal Tabulation
// \t
// Line Feed
// \n
// Vertical Tabulation
// U+000B
// Form Feed
// \f
// Carriage Return
// \r
// File Separator
// U+001C
// Group Separator
// U+001D
// Record Separator
// U+001E
// Unit Separator
// U+001F
const WHITESPACE_CHAR =
regex("[",
"\\f\\n\\r\\t, ",
"\\u000B\\u001C\\u001D\\u001E\\u001F",
"\\u2028\\u2029\\u1680",
"\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2008",
"\\u2009\\u200a\\u205f\\u3000",
"]");
const WHITESPACE =
token(repeat1(WHITESPACE_CHAR));
const COMMENT =
token(regex('(;|#!).*\n?'));
const DIGIT =
regex('[0-9]');
const ALPHANUMERIC =
regex('[0-9a-zA-Z]');
const HEX_DIGIT =
regex('[0-9a-fA-F]');
const OCTAL_DIGIT =
regex('[0-7]');
const HEX_NUMBER =
seq("0",
regex('[xX]'),
repeat1(HEX_DIGIT),
optional("N"));
const OCTAL_NUMBER =
seq("0",
repeat1(OCTAL_DIGIT),
optional("N"));
// XXX: not constraining number before r/R
// XXX: not constraining portion after r/R
const RADIX_NUMBER =
seq(repeat1(DIGIT),
regex('[rR]'),
repeat1(ALPHANUMERIC));
const RATIO =
seq(repeat1(DIGIT),
"/",
repeat1(DIGIT));
const DOUBLE =
seq(repeat1(DIGIT),
optional(seq(".",
repeat(DIGIT))),
optional(seq(regex('[eE]'),
optional(regex('[+-]')),
repeat1(DIGIT))),
optional("M"));
const INTEGER =
seq(repeat1(DIGIT),
optional(regex('[MN]')));
const NUMBER =
token(prec(10, seq(optional(regex('[+-]')),
choice(HEX_NUMBER,
OCTAL_NUMBER,
RADIX_NUMBER,
RATIO,
DOUBLE,
INTEGER))));
const NIL =
token('nil');
const BOOLEAN =
token(choice('false',
'true'));
const KEYWORD_HEAD =
regex("[^",
"\\f\\n\\r\\t ",
"()",
"\\[\\]",
"{}",
'"',
"@~^;`",
"\\\\",
",:/",
"\\u000B\\u001C\\u001D\\u001E\\u001F",
"\\u2028\\u2029\\u1680",
"\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2008",
"\\u2009\\u200a\\u205f\\u3000",
"]");
const KEYWORD_BODY =
choice(regex("[:']"), KEYWORD_HEAD);
const KEYWORD_NAMESPACED_BODY =
token(repeat1(choice(regex("[:'/]"), KEYWORD_HEAD)));
const KEYWORD_NO_SIGIL =
token(seq(KEYWORD_HEAD,
repeat(KEYWORD_BODY)));
const KEYWORD_MARK =
token(":");
const AUTO_RESOLVE_MARK =
token("::");
const STRING =
token(seq('"',
repeat(regex('[^"\\\\]')),
repeat(seq("\\",
regex("."),
repeat(regex('[^"\\\\]')))),
'"'));
// XXX: better to match \o378 as a single item
const OCTAL_CHAR =
seq("o",
choice(seq(DIGIT, DIGIT, DIGIT),
seq(DIGIT, DIGIT),
seq(DIGIT)));
const NAMED_CHAR =
choice("backspace",
"formfeed",
"newline",
"return",
"space",
"tab");
// XXX: outside of: (c >= '\uD800' && c <= '\uDFFF') - LispReader.java
// but not doing this
const UNICODE =
seq("u",
HEX_DIGIT,
HEX_DIGIT,
HEX_DIGIT,
HEX_DIGIT);
// XXX: not quite sure what this is supposed to be...
// return Character.valueOf(token.charAt(0)); -- LispReader.java
// java char is 16 bits...what can tree-sitter manage?
//
// XXX: null is supposed to be usable but putting \x00 below
// does not seem to work
const ANY_CHAR =
regex('.|\n');
const CHARACTER =
token(seq("\\",
choice(OCTAL_CHAR,
NAMED_CHAR,
UNICODE,
ANY_CHAR)));
const SYMBOL_HEAD =
regex("[^",
"\\f\\n\\r\\t ",
"/",
"()\\[\\]{}",
'"',
"@~^;`",
"\\\\",
",:#'0-9",
"\\u000B\\u001C\\u001D\\u001E\\u001F",
"\\u2028\\u2029\\u1680",
"\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2008",
"\\u2009\\u200a\\u205f\\u3000",
"]");
const NS_DELIMITER =
token("/");
const SYMBOL_BODY =
choice(SYMBOL_HEAD,
regex("[:#'0-9]"));
const SYMBOL_NAMESPACED_NAME =
token(repeat1(choice(SYMBOL_HEAD,
regex("[/:#'0-9]"))));
// XXX: no attempt is made to enforce certain complex things, e.g.
//
// Symbols beginning or ending with ':' are reserved by Clojure.
// A symbol can contain one or more non-repeating ':'s
const SYMBOL =
token(seq(SYMBOL_HEAD,
repeat(SYMBOL_BODY)));
module.exports = grammar({
name: 'clojure',
extras: $ =>
[],
conflicts: $ =>
[],
inline: $ =>
[$._kwd_leading_slash,
$._kwd_just_slash,
$._kwd_qualified,
$._kwd_unqualified,
$._kwd_marker,
$._sym_qualified,
$._sym_unqualified],
rules: {
// THIS MUST BE FIRST -- even though this doesn't look like it matters
source: $ =>
repeat(choice($._form,
$._gap)),
_gap: $ =>
choice($._ws,
$.comment,
$.dis_expr),
_ws: $ =>
WHITESPACE,
comment: $ =>
COMMENT,
dis_expr: $ =>
seq(field('marker', "#_"),
repeat($._gap),
field('value', $._form)),
_form: $ =>
choice($.num_lit, // atom-ish
$.kwd_lit,
$.str_lit,
$.char_lit,
$.nil_lit,
$.bool_lit,
$.sym_lit,
// basic collection-ish
$.list_lit,
$.map_lit,
$.vec_lit,
// dispatch reader macros
$.set_lit,
$.anon_fn_lit,
$.regex_lit,
$.read_cond_lit,
$.splicing_read_cond_lit,
$.ns_map_lit,
$.var_quoting_lit,
$.sym_val_lit,
$.evaling_lit,
$.tagged_or_ctor_lit,
// some other reader macros
$.derefing_lit,
$.quoting_lit,
$.syn_quoting_lit,
$.unquote_splicing_lit,
$.unquoting_lit),
num_lit: $ =>
NUMBER,
kwd_lit: $ =>
choice($._kwd_leading_slash,
$._kwd_just_slash,
$._kwd_qualified,
$._kwd_unqualified),
// (namespace :/usr/bin/env) ; => ""
// (name :/usr/bin/env) ; => "usr/bin/env"
_kwd_leading_slash: $ =>
seq(field('marker', $._kwd_marker),
field('delimiter', NS_DELIMITER),
field('name', alias(KEYWORD_NAMESPACED_BODY, $.kwd_name))),
// (namespace :/) ;=> nil
// (name :/) ;=> "/"
_kwd_just_slash: $ =>
seq(field('marker', $._kwd_marker),
field('name', alias(NS_DELIMITER, $.kwd_name))),
_kwd_qualified: $ =>
prec(2, seq(field('marker', $._kwd_marker),
field('namespace', alias(KEYWORD_NO_SIGIL, $.kwd_ns)),
field('delimiter', NS_DELIMITER),
field('name', alias(KEYWORD_NAMESPACED_BODY, $.kwd_name)))),
_kwd_unqualified: $ =>
prec(1, seq(field('marker', $._kwd_marker),
field('name', alias(KEYWORD_NO_SIGIL, $.kwd_name)))),
_kwd_marker: $ =>
choice(KEYWORD_MARK, AUTO_RESOLVE_MARK),
str_lit: $ =>
STRING,
char_lit: $ =>
CHARACTER,
nil_lit: $ =>
NIL,
bool_lit: $ =>
BOOLEAN,
sym_lit: $ =>
seq(repeat($._metadata_lit),
choice($._sym_qualified, $._sym_unqualified)),
_sym_qualified: $ =>
prec(1, seq(field("namespace", alias(SYMBOL, $.sym_ns)),
field("delimiter", NS_DELIMITER),
field("name", alias(SYMBOL_NAMESPACED_NAME, $.sym_name)))),
_sym_unqualified: $ =>
field('name', alias(choice(NS_DELIMITER, // division symbol
SYMBOL),
$.sym_name)),
_metadata_lit: $ =>
seq(choice(field("meta", $.meta_lit),
field("old_meta", $.old_meta_lit)),
optional(repeat($._gap))),
meta_lit: $ =>
seq(field('marker', "^"),
repeat($._gap),
field('value', $._form)),
old_meta_lit: $ =>
seq(field('marker', "#^"),
repeat($._gap),
field('value', $._form)),
list_lit: $ =>
seq(repeat($._metadata_lit),
$._bare_list_lit),
_bare_list_lit: $ =>
seq(field('open', "("),
repeat(choice(field('value', $._form),
$._gap)),
field('close', ")")),
map_lit: $ =>
seq(repeat($._metadata_lit),
$._bare_map_lit),
_bare_map_lit: $ =>
seq(field('open', "{"),
repeat(choice(field('value', $._form),
$._gap)),
field('close', "}")),
vec_lit: $ =>
seq(repeat($._metadata_lit),
$._bare_vec_lit),
_bare_vec_lit: $ =>
seq(field('open', "["),
repeat(choice(field('value', $._form),
$._gap)),
field('close', "]")),
set_lit: $ =>
seq(repeat($._metadata_lit),
$._bare_set_lit),
_bare_set_lit: $ =>
seq(field('marker', "#"),
field('open', "{"),
repeat(choice(field('value', $._form),
$._gap)),
field('close', "}")),
anon_fn_lit: $ =>
seq(repeat($._metadata_lit),
field('marker', "#"),
$._bare_list_lit),
regex_lit: $ =>
seq(field('marker', "#"),
STRING),
read_cond_lit: $ =>
seq(repeat($._metadata_lit),
field('marker', "#?"),
// whitespace possible, but neither comment nor discard
repeat($._ws),
$._bare_list_lit),
splicing_read_cond_lit: $ =>
// XXX: metadata here doesn't seem to make sense, but the repl
// will accept: [^:x #?@(:clj [[:a]] :cljr [[:b]])]
seq(repeat($._metadata_lit),
field('marker', "#?@"),
// whitespace possible, but neither comment nor discard
repeat($._ws),
$._bare_list_lit),
auto_res_mark: $ =>
AUTO_RESOLVE_MARK,
ns_map_lit: $ =>
seq(repeat($._metadata_lit),
field('marker', "#"),
field('prefix', choice($.auto_res_mark,
$.kwd_lit)),
repeat($._gap),
$._bare_map_lit),
var_quoting_lit: $ =>
seq(repeat($._metadata_lit),
field('marker', "#'"),
repeat($._gap),
// XXX: symbol, reader conditional, and tagged literal can work
// any other things?
field('value', $._form)),
sym_val_lit: $ =>
seq(field('marker', "##"),
repeat($._gap),
field('value', $._form)),
evaling_lit: $ =>
seq(repeat($._metadata_lit), // ^:x #=(vector 1)
field('marker', "#="),
repeat($._gap),
field('value', choice($.list_lit,
$.read_cond_lit,
// #= ^:a java.lang.String
$.sym_lit))),
// #uuid "00000000-0000-0000-0000-000000000000"
// #user.Fun[1 2]
// #user.Fun{:a 1 :b 2}
tagged_or_ctor_lit: $ =>
seq(repeat($._metadata_lit),
field('marker', "#"),
// # uuid "00000000-0000-0000-0000-000000000000"
// # #_ 1 uuid "00000000-0000-0000-0000-000000000000"
// etc.
repeat($._gap),
// # ^:a uuid "00000000-0000-0000-0000-000000000000"
field('tag', $.sym_lit),
repeat($._gap),
field('value', $._form)),
derefing_lit: $ =>
seq(repeat($._metadata_lit),
field('marker', "@"),
repeat($._gap),
field('value', $._form)),
quoting_lit: $ =>
seq(repeat($._metadata_lit),
field('marker', "'"),
repeat($._gap),
field('value', $._form)),
syn_quoting_lit: $ =>
seq(repeat($._metadata_lit),
field('marker', "`"),
repeat($._gap),
field('value', $._form)),
unquote_splicing_lit: $ =>
// XXX: metadata here doesn't seem to make sense, but the repl
// will accept: `(^:x ~@[:a :b :c])
seq(repeat($._metadata_lit),
field('marker', "~@"),
repeat($._gap),
field('value', $._form)),
unquoting_lit: $ =>
seq(repeat($._metadata_lit),
field('marker', "~"),
repeat($._gap),
field('value', $._form)),
}
});
// Local Variables:
// mode: js-mode
// js-indent-align-list-continuation: t
// js-indent-level: 2
// End:

@ -0,0 +1,16 @@
{
"name": "tree-sitter-clojure",
"version": "0.0.13",
"description": "Clojure grammar for tree-sitter",
"tree-sitter": [
{
"scope": "source.clojure",
"file-types": [
"bb",
"clj",
"cljc",
"cljs"
]
}
]
}

@ -0,0 +1,29 @@
;; Literals
(num_lit) @number
[
(char_lit)
(str_lit)
] @string
[
(bool_lit)
(nil_lit)
] @constant.builtin
(kwd_lit) @constant
;; Comments
(comment) @comment
;; Treat quasiquotation as operators for the purpose of highlighting.
[
"'"
"`"
"~"
"@"
"~@"
] @operator

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,230 @@
#ifndef TREE_SITTER_PARSER_H_
#define TREE_SITTER_PARSER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#define ts_builtin_sym_error ((TSSymbol)-1)
#define ts_builtin_sym_end 0
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
#ifndef TREE_SITTER_API_H_
typedef uint16_t TSStateId;
typedef uint16_t TSSymbol;
typedef uint16_t TSFieldId;
typedef struct TSLanguage TSLanguage;
#endif
typedef struct {
TSFieldId field_id;
uint8_t child_index;
bool inherited;
} TSFieldMapEntry;
typedef struct {
uint16_t index;
uint16_t length;
} TSFieldMapSlice;
typedef struct {
bool visible;
bool named;
bool supertype;
} TSSymbolMetadata;
typedef struct TSLexer TSLexer;
struct TSLexer {
int32_t lookahead;
TSSymbol result_symbol;
void (*advance)(TSLexer *, bool);
void (*mark_end)(TSLexer *);
uint32_t (*get_column)(TSLexer *);
bool (*is_at_included_range_start)(const TSLexer *);
bool (*eof)(const TSLexer *);
};
typedef enum {
TSParseActionTypeShift,
TSParseActionTypeReduce,
TSParseActionTypeAccept,
TSParseActionTypeRecover,
} TSParseActionType;
typedef union {
struct {
uint8_t type;
TSStateId state;
bool extra;
bool repetition;
} shift;
struct {
uint8_t type;
uint8_t child_count;
TSSymbol symbol;
int16_t dynamic_precedence;
uint16_t production_id;
} reduce;
uint8_t type;
} TSParseAction;
typedef struct {
uint16_t lex_state;
uint16_t external_lex_state;
} TSLexMode;
typedef union {
TSParseAction action;
struct {
uint8_t count;
bool reusable;
} entry;
} TSParseActionEntry;
struct TSLanguage {
uint32_t version;
uint32_t symbol_count;
uint32_t alias_count;
uint32_t token_count;
uint32_t external_token_count;
uint32_t state_count;
uint32_t large_state_count;
uint32_t production_id_count;
uint32_t field_count;
uint16_t max_alias_sequence_length;
const uint16_t *parse_table;
const uint16_t *small_parse_table;
const uint32_t *small_parse_table_map;
const TSParseActionEntry *parse_actions;
const char * const *symbol_names;
const char * const *field_names;
const TSFieldMapSlice *field_map_slices;
const TSFieldMapEntry *field_map_entries;
const TSSymbolMetadata *symbol_metadata;
const TSSymbol *public_symbol_map;
const uint16_t *alias_map;
const TSSymbol *alias_sequences;
const TSLexMode *lex_modes;
bool (*lex_fn)(TSLexer *, TSStateId);
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
TSSymbol keyword_capture_token;
struct {
const bool *states;
const TSSymbol *symbol_map;
void *(*create)(void);
void (*destroy)(void *);
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
unsigned (*serialize)(void *, char *);
void (*deserialize)(void *, const char *, unsigned);
} external_scanner;
const TSStateId *primary_state_ids;
};
/*
* Lexer Macros
*/
#ifdef _MSC_VER
#define UNUSED __pragma(warning(suppress : 4101))
#else
#define UNUSED __attribute__((unused))
#endif
#define START_LEXER() \
bool result = false; \
bool skip = false; \
UNUSED \
bool eof = false; \
int32_t lookahead; \
goto start; \
next_state: \
lexer->advance(lexer, skip); \
start: \
skip = false; \
lookahead = lexer->lookahead;
#define ADVANCE(state_value) \
{ \
state = state_value; \
goto next_state; \
}
#define SKIP(state_value) \
{ \
skip = true; \
state = state_value; \
goto next_state; \
}
#define ACCEPT_TOKEN(symbol_value) \
result = true; \
lexer->result_symbol = symbol_value; \
lexer->mark_end(lexer);
#define END_STATE() return result;
/*
* Parse Table Macros
*/
#define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT)
#define STATE(id) id
#define ACTIONS(id) id
#define SHIFT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = (state_value) \
} \
}}
#define SHIFT_REPEAT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = (state_value), \
.repetition = true \
} \
}}
#define SHIFT_EXTRA() \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.extra = true \
} \
}}
#define REDUCE(symbol_val, child_count_val, ...) \
{{ \
.reduce = { \
.type = TSParseActionTypeReduce, \
.symbol = symbol_val, \
.child_count = child_count_val, \
__VA_ARGS__ \
}, \
}}
#define RECOVER() \
{{ \
.type = TSParseActionTypeRecover \
}}
#define ACCEPT_INPUT() \
{{ \
.type = TSParseActionTypeAccept \
}}
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_PARSER_H_

@ -0,0 +1,24 @@
================================================================================
Empty Anonymous Function
================================================================================
#()
--------------------------------------------------------------------------------
(source
(anon_fn_lit))
================================================================================
Anonymous Function
================================================================================
#(+ % 8)
--------------------------------------------------------------------------------
(source
(anon_fn_lit
(sym_lit (sym_name))
(sym_lit (sym_name))
(num_lit)))

@ -0,0 +1,21 @@
================================================================================
True
================================================================================
true
--------------------------------------------------------------------------------
(source
(bool_lit))
================================================================================
False
================================================================================
false
--------------------------------------------------------------------------------
(source
(bool_lit))

@ -0,0 +1,43 @@
================================================================================
Simple Char
================================================================================
\a
--------------------------------------------------------------------------------
(source
(char_lit))
================================================================================
Octal Char
================================================================================
\o377
--------------------------------------------------------------------------------
(source
(char_lit))
================================================================================
Named Char
================================================================================
\backspace
--------------------------------------------------------------------------------
(source
(char_lit))
================================================================================
Unicode Char
================================================================================
\u611B
--------------------------------------------------------------------------------
(source
(char_lit))

@ -0,0 +1,34 @@
================================================================================
Simple Comment
================================================================================
; a comment
--------------------------------------------------------------------------------
(source
(comment))
================================================================================
Two semicolons
================================================================================
;; another comment
--------------------------------------------------------------------------------
(source
(comment))
================================================================================
Multiple lines
================================================================================
;; first line
;; second line
--------------------------------------------------------------------------------
(source
(comment)
(comment))

@ -0,0 +1,25 @@
================================================================================
Simple Deref
================================================================================
@x
--------------------------------------------------------------------------------
(source
(derefing_lit
(sym_lit (sym_name))))
================================================================================
Deref of Call
================================================================================
@(ping y)
--------------------------------------------------------------------------------
(source
(derefing_lit
(list_lit
(sym_lit (sym_name))
(sym_lit (sym_name)))))

@ -0,0 +1,68 @@
================================================================================
Discard Number
================================================================================
#_ 1
--------------------------------------------------------------------------------
(source
(dis_expr
(num_lit)))
================================================================================
Discard List
================================================================================
#_ (+ 1 1)
--------------------------------------------------------------------------------
(source
(dis_expr
(list_lit
(sym_lit (sym_name))
(num_lit)
(num_lit))))
================================================================================
Discard Map
================================================================================
#_ {:a 1
:b 2}
--------------------------------------------------------------------------------
(source
(dis_expr
(map_lit
(kwd_lit (kwd_name))
(num_lit)
(kwd_lit (kwd_name))
(num_lit))))
================================================================================
Discard Multiple
================================================================================
(let [x 1
#_ #_ y 2]
(+ x 2))
--------------------------------------------------------------------------------
(source
(list_lit
(sym_lit (sym_name))
(vec_lit
(sym_lit (sym_name))
(num_lit)
(dis_expr
(dis_expr
(sym_lit (sym_name)))
(num_lit)))
(list_lit
(sym_lit (sym_name))
(sym_lit (sym_name))
(num_lit))))

@ -0,0 +1,14 @@
================================================================================
Not Officially Supported
================================================================================
#=(+ 1 1)
--------------------------------------------------------------------------------
(source
(evaling_lit
(list_lit
(sym_lit (sym_name))
(num_lit)
(num_lit))))

@ -0,0 +1,102 @@
================================================================================
Keyword
================================================================================
:smile
--------------------------------------------------------------------------------
(source
(kwd_lit
(kwd_name)))
================================================================================
Keyword with Prefix
================================================================================
:fun/day
--------------------------------------------------------------------------------
(source
(kwd_lit
(kwd_ns)
(kwd_name)))
================================================================================
Autoresolving Keyword
================================================================================
::run
--------------------------------------------------------------------------------
(source
(kwd_lit
(kwd_name)))
================================================================================
Autoresolving Aliased Keyword
================================================================================
::slow/dance
--------------------------------------------------------------------------------
(source
(kwd_lit
(kwd_ns)
(kwd_name)))
================================================================================
Division Symbol Keyword
================================================================================
:/
--------------------------------------------------------------------------------
(source
(kwd_lit
(kwd_name)))
================================================================================
Namespaced Division Symbol Keyword
================================================================================
:clojure.core//
--------------------------------------------------------------------------------
(source
(kwd_lit
(kwd_ns)
(kwd_name)))
================================================================================
Autoresolving Division Symbol Keyword
================================================================================
::/
--------------------------------------------------------------------------------
(source
(kwd_lit
(kwd_name)))
================================================================================
Autoresolving Aliased Division Symbol Keyword
================================================================================
::clojure//
--------------------------------------------------------------------------------
(source
(kwd_lit
(kwd_ns)
(kwd_name)))

@ -0,0 +1,101 @@
================================================================================
Empty List
================================================================================
()
--------------------------------------------------------------------------------
(source
(list_lit))
================================================================================
List with Keywords
================================================================================
(:a :b :c)
--------------------------------------------------------------------------------
(source
(list_lit
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))))
================================================================================
Call with Anonymous Function
================================================================================
(#(+ % 1) 1)
--------------------------------------------------------------------------------
(source
(list_lit
(anon_fn_lit
(sym_lit (sym_name))
(sym_lit (sym_name))
(num_lit))
(num_lit)))
================================================================================
Map Lookup
================================================================================
({:a 1} :a)
--------------------------------------------------------------------------------
(source
(list_lit
(map_lit
(kwd_lit (kwd_name))
(num_lit))
(kwd_lit (kwd_name))))
================================================================================
Map Lookup Alternate
================================================================================
(:b {:b 2})
--------------------------------------------------------------------------------
(source
(list_lit
(kwd_lit (kwd_name))
(map_lit
(kwd_lit (kwd_name))
(num_lit))))
================================================================================
Set Lookup
================================================================================
(#{:c :e} :e)
--------------------------------------------------------------------------------
(source
(list_lit
(set_lit
(kwd_lit (kwd_name))
(kwd_lit (kwd_name)))
(kwd_lit (kwd_name))))
================================================================================
Call with Symbol with Metadata
================================================================================
(.get ^ByteBuffer b)
--------------------------------------------------------------------------------
(source
(list_lit
(sym_lit (sym_name))
(sym_lit
(meta_lit
(sym_lit (sym_name)))
(sym_name))))

@ -0,0 +1,66 @@
================================================================================
Empty Map
================================================================================
{}
--------------------------------------------------------------------------------
(source
(map_lit))
================================================================================
Simple Map
================================================================================
{:a 1 :b 2}
--------------------------------------------------------------------------------
(source
(map_lit
(kwd_lit (kwd_name))
(num_lit)
(kwd_lit (kwd_name))
(num_lit)))
================================================================================
Deeper Map
================================================================================
{:paths ["src"]
:deps {clj-kondo/clj-kondo {:mvn/version "2020.09.09"}}}
--------------------------------------------------------------------------------
(source
(map_lit
(kwd_lit (kwd_name))
(vec_lit
(str_lit))
(kwd_lit (kwd_name))
(map_lit
(sym_lit
(sym_ns)
(sym_name))
(map_lit
(kwd_lit
(kwd_ns)
(kwd_name))
(str_lit)))))
================================================================================
Map with Comma
================================================================================
{:x 1,
:y 2}
--------------------------------------------------------------------------------
(source
(map_lit
(kwd_lit (kwd_name))
(num_lit)
(kwd_lit (kwd_name))
(num_lit)))

@ -0,0 +1,137 @@
================================================================================
Symbol Metadata
================================================================================
^String []
--------------------------------------------------------------------------------
(source
(vec_lit
(meta_lit
(sym_lit
(sym_name)))))
================================================================================
Keyword Metadata
================================================================================
^:private {}
--------------------------------------------------------------------------------
(source
(map_lit
(meta_lit
(kwd_lit
(kwd_name)))))
================================================================================
String Metadata
================================================================================
^"gnarly" {}
--------------------------------------------------------------------------------
(source
(map_lit
(meta_lit
(str_lit))))
================================================================================
Map Metadata
================================================================================
^{:x 0 :y 1} #{}
--------------------------------------------------------------------------------
(source
(set_lit
(meta_lit
(map_lit
(kwd_lit
(kwd_name))
(num_lit)
(kwd_lit
(kwd_name))
(num_lit)))))
================================================================================
Reader Conditional Metadata
================================================================================
^#?(:clj "vanilla" :cljr "strawberry" :cljs "chocolate") []
--------------------------------------------------------------------------------
(source
(vec_lit
(meta_lit
(read_cond_lit
(kwd_lit
(kwd_name))
(str_lit)
(kwd_lit
(kwd_name))
(str_lit)
(kwd_lit
(kwd_name))
(str_lit)))))
================================================================================
Multiple Bits of Metadata
================================================================================
^:wake ^:sit ^:sleep #{}
--------------------------------------------------------------------------------
(source
(set_lit
(meta_lit
(kwd_lit
(kwd_name)))
(meta_lit
(kwd_lit
(kwd_name)))
(meta_lit
(kwd_lit
(kwd_name)))))
================================================================================
Tagged Literal Metadata
================================================================================
^#/(data) thing
--------------------------------------------------------------------------------
(source
(sym_lit
(meta_lit
(tagged_or_ctor_lit
(sym_lit
(sym_name))
(list_lit
(sym_lit
(sym_name)))))
(sym_name)))
================================================================================
Evaling Literal Metadata
================================================================================
^#=(keyword "a") []
--------------------------------------------------------------------------------
(source
(vec_lit
(meta_lit
(evaling_lit
(list_lit
(sym_lit
(sym_name))
(str_lit))))))

@ -0,0 +1,10 @@
================================================================================
Nil
================================================================================
nil
--------------------------------------------------------------------------------
(source
(nil_lit))

@ -0,0 +1,66 @@
================================================================================
Simple Namespace Map
================================================================================
#:prefix{:a 1 :b 2}
--------------------------------------------------------------------------------
(source
(ns_map_lit
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))
(num_lit)
(kwd_lit (kwd_name))
(num_lit)))
================================================================================
Nested Namespace Maps
================================================================================
#:outer{:first "Terence"
:last "Tao"
:area #:inner{:name "Mathematics"}}
--------------------------------------------------------------------------------
(source
(ns_map_lit
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))
(str_lit)
(kwd_lit (kwd_name))
(str_lit)
(kwd_lit (kwd_name))
(ns_map_lit
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))
(str_lit))))
================================================================================
Autoresolving Namespace Map
================================================================================
#::{}
--------------------------------------------------------------------------------
(source
(ns_map_lit
(auto_res_mark)))
================================================================================
Namespace Map that Autoresolves with Alias
================================================================================
#::s{:x 1 :y 2}
--------------------------------------------------------------------------------
(source
(ns_map_lit
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))
(num_lit)
(kwd_lit (kwd_name))
(num_lit)))

@ -0,0 +1,241 @@
================================================================================
Integer
================================================================================
1
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Negative Integer
================================================================================
-2
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
BigInt Integer
================================================================================
11N
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
BigDecimal Integer
================================================================================
99M
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Hex
================================================================================
0xaB
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Negative Hex
================================================================================
-0xFF
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Shouting Hex
================================================================================
0XA
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
BigInt Hex
================================================================================
0XeN
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Octal
================================================================================
013
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Negative Octal
================================================================================
-027
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
BigInt Octal
================================================================================
0377N
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Radix
================================================================================
2r0101010001
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Negative Radix
================================================================================
-10r256
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Shouting Radix
================================================================================
36RBREATHESL0WLY
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Ratio
================================================================================
22/7
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Negative Ratio
================================================================================
-1/2
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Double
================================================================================
1.0
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Negative Double
================================================================================
-2.71828
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Double with Exponent
================================================================================
3e8
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Shouting Double with Exponent
================================================================================
1E9
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
Double with Negative Exponent
================================================================================
2e-1
--------------------------------------------------------------------------------
(source
(num_lit))
================================================================================
BigDecimal Double with Exponent
================================================================================
3e1415926535M
--------------------------------------------------------------------------------
(source
(num_lit))

@ -0,0 +1,91 @@
================================================================================
Symbol Metadata
================================================================================
#^String []
--------------------------------------------------------------------------------
(source
(vec_lit
(old_meta_lit
(sym_lit (sym_name)))))
================================================================================
Keyword Metadata
================================================================================
#^:private {}
--------------------------------------------------------------------------------
(source
(map_lit
(old_meta_lit
(kwd_lit (kwd_name)))))
================================================================================
String Metadata
================================================================================
#^"gnarly" {}
--------------------------------------------------------------------------------
(source
(map_lit
(old_meta_lit
(str_lit))))
================================================================================
Map Metadata
================================================================================
#^{:x 0 :y 1} #{}
--------------------------------------------------------------------------------
(source
(set_lit
(old_meta_lit
(map_lit
(kwd_lit (kwd_name))
(num_lit)
(kwd_lit (kwd_name))
(num_lit)))))
================================================================================
Reader Conditional Metadata
================================================================================
#^#?(:clj "vanilla" :cljr "strawberry" :cljs "chocolate") []
--------------------------------------------------------------------------------
(source
(vec_lit
(old_meta_lit
(read_cond_lit
(kwd_lit (kwd_name))
(str_lit)
(kwd_lit (kwd_name))
(str_lit)
(kwd_lit (kwd_name))
(str_lit)))))
================================================================================
Multiple Bits of Metadata
================================================================================
#^:wake #^:sit #^:sleep #{}
--------------------------------------------------------------------------------
(source
(set_lit
(old_meta_lit
(kwd_lit (kwd_name)))
(old_meta_lit
(kwd_lit (kwd_name)))
(old_meta_lit
(kwd_lit (kwd_name)))))

@ -0,0 +1,26 @@
================================================================================
Quoted Symbol
================================================================================
'a-sym
--------------------------------------------------------------------------------
(source
(quoting_lit
(sym_lit (sym_name))))
================================================================================
Quoted List
================================================================================
'(1 2 3)
--------------------------------------------------------------------------------
(source
(quoting_lit
(list_lit
(num_lit)
(num_lit)
(num_lit))))

@ -0,0 +1,18 @@
================================================================================
Platform Reader Conditional
================================================================================
#?(:clj :clj
:cljr :cljr
:cljs :cljs)
--------------------------------------------------------------------------------
(source
(read_cond_lit
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))))

@ -0,0 +1,21 @@
================================================================================
Simple Regular Expression
================================================================================
#"."
--------------------------------------------------------------------------------
(source
(regex_lit))
================================================================================
Hex Digits Regular Expression
================================================================================
#"[0-9a-fA-F]+"
--------------------------------------------------------------------------------
(source
(regex_lit))

@ -0,0 +1,41 @@
================================================================================
Empty Set
================================================================================
#{}
--------------------------------------------------------------------------------
(source
(set_lit))
================================================================================
Simple Set
================================================================================
#{:i :j :k}
--------------------------------------------------------------------------------
(source
(set_lit
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))
(kwd_lit (kwd_name))))
================================================================================
Nested Sets
================================================================================
#{#{1} #{#{0} 2}}
--------------------------------------------------------------------------------
(source
(set_lit
(set_lit
(num_lit))
(set_lit
(set_lit
(num_lit))
(num_lit))))

@ -0,0 +1,27 @@
================================================================================
Splicing Reader Conditional
================================================================================
(list '*
#?@(:clj [x y] :cljr [i j] :cljs [a b]))
--------------------------------------------------------------------------------
(source
(list_lit
(sym_lit (sym_name))
(quoting_lit
(sym_lit (sym_name)))
(splicing_read_cond_lit
(kwd_lit (kwd_name))
(vec_lit
(sym_lit (sym_name))
(sym_lit (sym_name)))
(kwd_lit (kwd_name))
(vec_lit
(sym_lit (sym_name))
(sym_lit (sym_name)))
(kwd_lit (kwd_name))
(vec_lit
(sym_lit (sym_name))
(sym_lit (sym_name))))))

@ -0,0 +1,33 @@
================================================================================
Simple String
================================================================================
"hello there"
--------------------------------------------------------------------------------
(source
(str_lit))
================================================================================
String with Escapes
================================================================================
"first line\nsecond\tline"
--------------------------------------------------------------------------------
(source
(str_lit))
================================================================================
Multiline String
================================================================================
"this is the first line
and what is this one?"
--------------------------------------------------------------------------------
(source
(str_lit))

@ -0,0 +1,63 @@
================================================================================
Simple Symbol
================================================================================
def
--------------------------------------------------------------------------------
(source
(sym_lit (sym_name)))
================================================================================
Symbol with Prefix
================================================================================
clojure.string/blank?
--------------------------------------------------------------------------------
(source
(sym_lit
(sym_ns)
(sym_name)))
================================================================================
Division Symbol
================================================================================
/
--------------------------------------------------------------------------------
(source
(sym_lit
(sym_name)))
================================================================================
Namespaced Division Symbol
================================================================================
clojure.core//
--------------------------------------------------------------------------------
(source
(sym_lit
(sym_ns)
(sym_name)))
================================================================================
Division Symbol followed by delimiter
================================================================================
(+ - * /)
--------------------------------------------------------------------------------
(source
(list_lit
(sym_lit (sym_name))
(sym_lit (sym_name))
(sym_lit (sym_name))
(sym_lit (sym_name))))

@ -0,0 +1,55 @@
================================================================================
Inf
================================================================================
##Inf
--------------------------------------------------------------------------------
(source
(sym_val_lit
(sym_lit
(sym_name))))
================================================================================
-Inf
================================================================================
##-Inf
--------------------------------------------------------------------------------
(source
(sym_val_lit
(sym_lit
(sym_name))))
================================================================================
NaN
================================================================================
##NaN
--------------------------------------------------------------------------------
(source
(sym_val_lit
(sym_lit
(sym_name))))
================================================================================
Symbolic Value Literal with Evaling Literal
================================================================================
###=(identity NaN)
--------------------------------------------------------------------------------
(source
(sym_val_lit
(evaling_lit
(list_lit
(sym_lit
(sym_name))
(sym_lit
(sym_name))))))

@ -0,0 +1,27 @@
================================================================================
Syntax Quoted Symbol
================================================================================
`a-sym
--------------------------------------------------------------------------------
(source
(syn_quoting_lit
(sym_lit (sym_name))))
================================================================================
Syntax Quoted List
================================================================================
`(+ ~a 1)
--------------------------------------------------------------------------------
(source
(syn_quoting_lit
(list_lit
(sym_lit (sym_name))
(unquoting_lit
(sym_lit (sym_name)))
(num_lit))))

@ -0,0 +1,44 @@
================================================================================
Tagged Literal
================================================================================
#uuid "00000000-0000-0000-0000-000000000000"
--------------------------------------------------------------------------------
(source
(tagged_or_ctor_lit
(sym_lit (sym_name))
(str_lit)))
================================================================================
Constructor
================================================================================
#user.Fun [1 2]
--------------------------------------------------------------------------------
(source
(tagged_or_ctor_lit
(sym_lit (sym_name))
(vec_lit
(num_lit)
(num_lit))))
================================================================================
Constructor Alternate
================================================================================
#user.Fun {:a 1 :b 2}
--------------------------------------------------------------------------------
(source
(tagged_or_ctor_lit
(sym_lit (sym_name))
(map_lit
(kwd_lit (kwd_name))
(num_lit)
(kwd_lit (kwd_name))
(num_lit))))

@ -0,0 +1,75 @@
================================================================================
Unquote Splicing into List
================================================================================
`(+ ~@(list 2 3))
--------------------------------------------------------------------------------
(source
(syn_quoting_lit
(list_lit
(sym_lit (sym_name))
(unquote_splicing_lit
(list_lit
(sym_lit (sym_name))
(num_lit)
(num_lit))))))
================================================================================
Unquote Splicing into Vector
================================================================================
`[:a ~@(list :b :c)]
--------------------------------------------------------------------------------
(source
(syn_quoting_lit
(vec_lit
(kwd_lit (kwd_name))
(unquote_splicing_lit
(list_lit
(sym_lit (sym_name))
(kwd_lit (kwd_name))
(kwd_lit (kwd_name)))))))
================================================================================
Unquote Splicing into Set
================================================================================
`#{:i ~@(list :j :k)}
--------------------------------------------------------------------------------
(source
(syn_quoting_lit
(set_lit
(kwd_lit (kwd_name))
(unquote_splicing_lit
(list_lit
(sym_lit (sym_name))
(kwd_lit (kwd_name))
(kwd_lit (kwd_name)))))))
================================================================================
Unquote Splicing into Map
================================================================================
`{~@(list :a 1) ~@(list :b 2)}
--------------------------------------------------------------------------------
(source
(syn_quoting_lit
(map_lit
(unquote_splicing_lit
(list_lit
(sym_lit (sym_name))
(kwd_lit (kwd_name))
(num_lit)))
(unquote_splicing_lit
(list_lit
(sym_lit (sym_name))
(kwd_lit (kwd_name))
(num_lit))))))

@ -0,0 +1,30 @@
================================================================================
Unquoting Symbol
================================================================================
`~a
--------------------------------------------------------------------------------
(source
(syn_quoting_lit
(unquoting_lit
(sym_lit (sym_name)))))
================================================================================
Unquoting List
================================================================================
`(dec ~(+ 1 a))
--------------------------------------------------------------------------------
(source
(syn_quoting_lit
(list_lit
(sym_lit (sym_name))
(unquoting_lit
(list_lit
(sym_lit (sym_name))
(num_lit)
(sym_lit (sym_name)))))))

@ -0,0 +1,29 @@
================================================================================
Var Quoting a Symbol
================================================================================
#'my-sym
--------------------------------------------------------------------------------
(source
(var_quoting_lit
(sym_lit (sym_name))))
================================================================================
Var Quoting with Reader Conditional
================================================================================
#'#?(:clj my-sym :cljr your-sym :cljs their-sym)
--------------------------------------------------------------------------------
(source
(var_quoting_lit
(read_cond_lit
(kwd_lit (kwd_name))
(sym_lit (sym_name))
(kwd_lit (kwd_name))
(sym_lit (sym_name))
(kwd_lit (kwd_name))
(sym_lit (sym_name)))))

@ -0,0 +1,48 @@
================================================================================
Empty Vector
================================================================================
[]
--------------------------------------------------------------------------------
(source
(vec_lit))
================================================================================
Vector with Numbers
================================================================================
[1 1 2 3 5 8]
--------------------------------------------------------------------------------
(source
(vec_lit
(num_lit)
(num_lit)
(num_lit)
(num_lit)
(num_lit)
(num_lit)))
================================================================================
Vector with Different Types
================================================================================
[:a 1 'fun {:x 1 :y 2} #{}]
--------------------------------------------------------------------------------
(source
(vec_lit
(kwd_lit (kwd_name))
(num_lit)
(quoting_lit
(sym_lit (sym_name)))
(map_lit
(kwd_lit (kwd_name))
(num_lit)
(kwd_lit (kwd_name))
(num_lit))
(set_lit)))