├── .gitignore ├── example.clj ├── index.js ├── .travis.yml ├── binding.gyp ├── .editorconfig ├── corpus ├── metadata.txt ├── interop.txt ├── macros.txt ├── keywords-and-symbols.txt ├── comments.txt ├── collections.txt ├── misc.txt ├── literals.txt └── functions.txt ├── package.json ├── src ├── binding.cc ├── tree_sitter │ └── parser.h └── grammar.json ├── LICENSE.md ├── sandbox.js ├── README.md └── grammar.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | *.log 4 | *.diff 5 | parser.exp 6 | parser.lib 7 | parser.obj 8 | -------------------------------------------------------------------------------- /example.clj: -------------------------------------------------------------------------------- 1 | (ns foo) 2 | 3 | true 4 | nil 5 | false 6 | 7 | 8 | (defn- foo [] 9 | [:div "hello"] 10 | (conj) 11 | (bar)) 12 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | try { 2 | module.exports = require("./build/Release/tree_sitter_clojure_binding"); 3 | } catch (error) { 4 | try { 5 | module.exports = require("./build/Debug/tree_sitter_clojure_binding"); 6 | } catch (_) { 7 | throw error 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | sudo: false 4 | 5 | node_js: 6 | - "node" 7 | 8 | compiler: clang-3.6 9 | 10 | env: 11 | - CXX=clang-3.6 12 | 13 | addons: 14 | apt: 15 | sources: 16 | - llvm-toolchain-precise-3.6 17 | - ubuntu-toolchain-r-test 18 | packages: 19 | - clang-3.6 20 | 21 | branches: 22 | only: 23 | - master 24 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_clojure_binding", 5 | "include_dirs": [ 6 | " (http://chrisoakman.com/)", 3 | "name": "tree-sitter-clojure", 4 | "version": "0.4.0", 5 | "description": "Clojure grammar for tree-sitter", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/oakmac/tree-sitter-clojure.git" 9 | }, 10 | "main": "index.js", 11 | "scripts": { 12 | "build": "tree-sitter generate && node-gyp build", 13 | "test": "tree-sitter test" 14 | }, 15 | "license": "MIT", 16 | "dependencies": { 17 | "nan": "^2.12.1" 18 | }, 19 | "devDependencies": { 20 | "highlight-tree-sitter": "^1.0.0", 21 | "tree-sitter-cli": "^0.14.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /corpus/keywords-and-symbols.txt: -------------------------------------------------------------------------------- 1 | ===================================== 2 | Keywords - :foo 3 | ===================================== 4 | 5 | :a 6 | :foo 7 | :rubber-baby-buggy-bumper! 8 | :j3_!:7 9 | :HELICOPTER 10 | :+fiduciary+ 11 | :use-smart-mode? 12 | 13 | ::foo 14 | ::foo/bar 15 | 16 | --- 17 | 18 | (program 19 | (keyword) 20 | (keyword) 21 | (keyword) 22 | (keyword) 23 | (keyword) 24 | (keyword) 25 | (keyword) 26 | 27 | (keyword (qualified_keyword)) 28 | (keyword (qualified_keyword)) 29 | ) 30 | 31 | ===================================== 32 | Symbols - foo 33 | ===================================== 34 | 35 | a 36 | foo 37 | rubber-baby-buggy-bumper! 38 | j3_!:7 39 | HELICOPTER 40 | +fiduciary+ 41 | 42 | a/b 43 | foo/bar 44 | 45 | --- 46 | 47 | (program 48 | (symbol) 49 | (symbol) 50 | (symbol) 51 | (symbol) 52 | (symbol) 53 | (symbol) 54 | 55 | (symbol (qualified_symbol)) 56 | (symbol (qualified_symbol)) 57 | ) 58 | -------------------------------------------------------------------------------- /src/binding.cc: -------------------------------------------------------------------------------- 1 | #include "tree_sitter/parser.h" 2 | #include 3 | #include "nan.h" 4 | 5 | using namespace v8; 6 | 7 | extern "C" TSLanguage * tree_sitter_clojure(); 8 | 9 | namespace { 10 | 11 | NAN_METHOD(New) {} 12 | 13 | void Init(Handle exports, Handle module) { 14 | Local tpl = Nan::New(New); 15 | tpl->SetClassName(Nan::New("Language").ToLocalChecked()); 16 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 17 | 18 | Local constructor = tpl->GetFunction(); 19 | Local instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked(); 20 | Nan::SetInternalFieldPointer(instance, 0, tree_sitter_clojure()); 21 | 22 | instance->Set(Nan::New("name").ToLocalChecked(), Nan::New("clojure").ToLocalChecked()); 23 | module->Set(Nan::New("exports").ToLocalChecked(), instance); 24 | } 25 | 26 | NODE_MODULE(tree_sitter_clojure_binding, Init) 27 | 28 | } // namespace 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Chris Oakman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /sandbox.js: -------------------------------------------------------------------------------- 1 | // Sandbox 2 | // (pretty-print tree from given text) 3 | 4 | const text = ` 5 | (defn foo 6 | "hello, this is a docstring" 7 | [a b] 8 | (let [sum (+ a b) 9 | prod (* a b)] 10 | {:sum sum 11 | :prod prod})) 12 | `; 13 | 14 | const { partialSexp, fullSexp, printSexp } = require("highlight-tree-sitter"); 15 | const Parser = require("tree-sitter"); 16 | const Clojure = require("./index.js"); 17 | const parser = new Parser(); 18 | parser.setLanguage(Clojure); 19 | const tree = parser.parse(text); 20 | const partial = partialSexp(tree); 21 | const full = fullSexp(text, tree); 22 | 23 | console.log(` 24 | ====================================================================== 25 | Parsing text: 26 | ====================================================================== 27 | ${text} 28 | 29 | ====================================================================== 30 | Partial Tree: 31 | ====================================================================== 32 | ${printSexp(partial)} 33 | 34 | ====================================================================== 35 | Full Tree: 36 | ====================================================================== 37 | ${printSexp(full)} 38 | `); 39 | -------------------------------------------------------------------------------- /corpus/comments.txt: -------------------------------------------------------------------------------- 1 | ===================================== 2 | Comments - semicolon ; 3 | ===================================== 4 | 5 | ; foo 6 | ;; foo 7 | 8 | --- 9 | 10 | (program 11 | (comment (semicolon)) 12 | (comment (semicolon))) 13 | 14 | ===================================== 15 | Comments - shebang line #! 16 | ===================================== 17 | 18 | #!/usr/bin/env 19 | #! #{} :foo 20 | 21 | --- 22 | 23 | (program 24 | (comment (shebang_line)) 25 | (comment (shebang_line)) 26 | ) 27 | 28 | ===================================== 29 | Comments - ignore form #_ 30 | ===================================== 31 | 32 | (#_ nil true) 33 | #_["a" "b"] 34 | #_ #{"a" "b"} 35 | ["a" "b" #_:z "d"] 36 | ["a" "b" #_ #{} "d"] 37 | 38 | --- 39 | 40 | (program 41 | (list (comment (ignore_form (nil))) (boolean (true))) 42 | (comment (ignore_form (vector (string) (string)))) 43 | (comment (ignore_form (set (string) (string)))) 44 | (vector (string) 45 | (string) 46 | (comment (ignore_form (keyword))) 47 | (string)) 48 | (vector (string) 49 | (string) 50 | (comment (ignore_form (set))) 51 | (string)) 52 | ) 53 | 54 | ===================================== 55 | Comments - comment macro (comment) 56 | ===================================== 57 | 58 | (comment) 59 | ( comment "foo") 60 | 61 | ["a" (comment 62 | "b") "c"] 63 | 64 | ["a" (comment (foo ())) "c"] 65 | 66 | --- 67 | 68 | (program 69 | (comment (comment_macro)) 70 | (comment (comment_macro (string))) 71 | 72 | (vector (string) (comment (comment_macro (string))) (string)) 73 | 74 | (vector (string) (comment (comment_macro (list (symbol) (list)))) (string)) 75 | ) 76 | -------------------------------------------------------------------------------- /corpus/collections.txt: -------------------------------------------------------------------------------- 1 | ===================================== 2 | List - () 3 | ===================================== 4 | 5 | () 6 | ("a" "b" "c") 7 | (:a {:a "a"}) 8 | 9 | --- 10 | 11 | (program 12 | (list) 13 | (list (string) (string) (string)) 14 | (list (keyword) 15 | (hash_map (keyword) (string)))) 16 | 17 | ===================================== 18 | Vector - [] 19 | ===================================== 20 | 21 | [] 22 | [true] 23 | ["a" :b 3] 24 | 25 | --- 26 | 27 | (program 28 | (vector) 29 | (vector (boolean (true))) 30 | (vector (string) (keyword) (number (number_long)))) 31 | 32 | ===================================== 33 | Hash Map - {} 34 | ===================================== 35 | 36 | {} 37 | {:a "a"} 38 | {"x" :x, "y" :y, "z" :z} 39 | 40 | --- 41 | 42 | (program 43 | (hash_map) 44 | (hash_map (keyword) (string)) 45 | (hash_map (string) (keyword) 46 | (string) (keyword) 47 | (string) (keyword)) 48 | ) 49 | 50 | ===================================== 51 | Namespace Map - #::{} #:foo{} 52 | ===================================== 53 | 54 | #::{} 55 | #::{:a 1, :b 2} 56 | 57 | #:person{} 58 | #:foo-bar{:a "a"} 59 | 60 | --- 61 | 62 | (program 63 | (hash_map (namespace_map)) 64 | (hash_map (namespace_map 65 | (keyword) (number (number_long)) 66 | (keyword) (number (number_long)))) 67 | 68 | (hash_map (namespace_map)) 69 | (hash_map (namespace_map (keyword) (string))) 70 | ) 71 | 72 | ===================================== 73 | Sets - #{} 74 | ===================================== 75 | 76 | #{} 77 | #{true} 78 | #{true false} 79 | #{"a", "b", nil} 80 | 81 | --- 82 | 83 | (program 84 | (set) 85 | (set (boolean (true))) 86 | (set (boolean (true)) (boolean (false))) 87 | (set (string) (string) (nil))) 88 | -------------------------------------------------------------------------------- /corpus/misc.txt: -------------------------------------------------------------------------------- 1 | ===================================== 2 | Quote - '() (quote) 3 | ===================================== 4 | 5 | '() 6 | '"a" 7 | '("a" "b" "c") 8 | 9 | (quote ()) 10 | (quote "a") 11 | (quote ("a" "b" "c")) 12 | 13 | --- 14 | 15 | (program 16 | (quote (list)) 17 | (quote (string)) 18 | (quote (list (string) (string) (string))) 19 | 20 | (quote (list)) 21 | (quote (string)) 22 | (quote (list (string) (string) (string))) 23 | ) 24 | 25 | ===================================== 26 | Deref - @ 27 | ===================================== 28 | 29 | @foo 30 | @ foo 31 | @(identity foo) 32 | 33 | --- 34 | 35 | (program 36 | (deref (symbol)) 37 | (deref (symbol)) 38 | (deref (list (symbol) (symbol))) 39 | ) 40 | 41 | ===================================== 42 | Symbolic Value - ##Inf, ##-Inf, ##NaN 43 | ===================================== 44 | 45 | [##Inf, 2, 3] 46 | ##-Inf 47 | (+ 8 ## NaN) 48 | ## Inf 49 | 50 | --- 51 | 52 | (program 53 | (vector (symbolic_value (infinity)) 54 | (number (number_long)) 55 | (number (number_long))) 56 | (symbolic_value (negative_infinity)) 57 | (list (symbol) 58 | (number (number_long)) 59 | (symbolic_value (not_a_number))) 60 | (symbolic_value (infinity)) 61 | ) 62 | 63 | ===================================== 64 | Tagged Literal - #inst, #uuid, #foo/bar 65 | ===================================== 66 | 67 | #inst "foo" 68 | #uuid :bar 69 | # js 'hello 70 | #foo/bar [1 2 3] 71 | 72 | --- 73 | 74 | (program 75 | (tagged_literal (string)) 76 | (tagged_literal (keyword)) 77 | (tagged_literal (quote (symbol))) 78 | (tagged_literal (vector 79 | (number (number_long)) 80 | (number (number_long)) 81 | (number (number_long))))) 82 | 83 | 84 | ===================================== 85 | Reader Conditional - #? #?@ 86 | ===================================== 87 | 88 | #?(:clj (Clojure expression) 89 | :cljs (ClojureScript expression) 90 | :cljr (ClojureCLR expression) 91 | :default (fallthrough expression)) 92 | 93 | (list #?@(:clj ["a"] 94 | :cljs [:a])) 95 | 96 | --- 97 | 98 | (program 99 | (reader_conditional 100 | (keyword) (list (symbol) (symbol)) 101 | (keyword) (list (symbol) (symbol)) 102 | (keyword) (list (symbol) (symbol)) 103 | (keyword) (list (symbol) (symbol))) 104 | 105 | (list 106 | (symbol) 107 | (reader_conditional 108 | (keyword) (vector (string)) 109 | (keyword) (vector (keyword)))) 110 | ) 111 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-clojure [![Build Status](https://travis-ci.org/oakmac/tree-sitter-clojure.svg?branch=master)](https://travis-ci.org/oakmac/tree-sitter-clojure) 2 | 3 | > **Dec 2022 Update:** You may want to check out [sogaiu tree-sitter-clojure](https://github.com/sogaiu/tree-sitter-clojure). I believe it is the most complete tree-sitter grammar for Clojure. 4 | 5 | This repo contains a [tree-sitter] grammar for [Clojure] and [ClojureScript]. 6 | 7 | [tree-sitter]:https://tree-sitter.github.io/tree-sitter/ 8 | [Clojure]:https://clojure.org/ 9 | [ClojureScript]:https://clojurescript.org/ 10 | 11 | ## About 12 | 13 | [Tree-sitter] is an ambitious new library for language syntax highlighting being 14 | used by the [Atom] editor and GitHub.com. Tree-sitter uses language grammars 15 | instead of regular expressions and supports fast updates as the user is typing 16 | (similar to many persistent data structure operations in Clojure). 17 | 18 | You can read more about tree-sitter on [the website]. 19 | 20 | [Tree-sitter]:https://github.com/tree-sitter/tree-sitter 21 | [Atom]:https://atom.io/ 22 | [the website]:http://tree-sitter.github.io/tree-sitter/ 23 | 24 | ## Design Considerations 25 | 26 | - Clojure, ClojureScript, and `.cljc` as first class citizens 27 | - When in doubt, be more specific 28 | - we may put more information than strictly required into the AST 29 | - this gives editors / integrations the option to highlight what they want 30 | 31 | ## FAQ 32 | 33 | #### Is tree-sitter-clojure only for Atom? 34 | 35 | No. Tree-sitter is open source and has bindings to C, so it can be used in many 36 | environments. 37 | 38 | #### How can I use this project with my favorite editor? 39 | 40 | Unfortunately, there is not a "one size fits all" solution here. 41 | 42 | Every integration will be different, depending largely on how the target 43 | environment / tool supports syntax highlighting, extensions, etc. Please see the 44 | documentation for your editor and the [tree-sitter source] for more information. 45 | 46 | [tree-sitter source]:https://github.com/tree-sitter/tree-sitter 47 | 48 | ## Development 49 | 50 | Make sure [Node.js] and [npm] are installed, then from the command line: 51 | 52 | ```sh 53 | # first-time install step: 54 | # > creates the node_modules folder 55 | # > builds tree-sitter 56 | npm install 57 | 58 | # build the grammar 59 | npm run build 60 | 61 | # test the corpus 62 | npm run test 63 | ``` 64 | 65 | Please see the [installing the tools] section on the tree-sitter website for 66 | more information. [This comment](https://github.com/oakmac/tree-sitter-clojure/issues/17#issuecomment-441665543) may also be helpful in getting started. 67 | 68 | [installing the tools]:https://tree-sitter.github.io/tree-sitter/creating-parsers#installing-the-tools 69 | 70 | ## License 71 | 72 | [MIT](LICENSE.md) 73 | 74 | [Node.js]:https://nodejs.org/ 75 | [npm]:https://www.npmjs.com/get-npm 76 | -------------------------------------------------------------------------------- /corpus/literals.txt: -------------------------------------------------------------------------------- 1 | ===================================== 2 | nil + booleans 3 | ===================================== 4 | 5 | nil 6 | true 7 | false 8 | 9 | --- 10 | 11 | (program 12 | (nil) 13 | (boolean (true)) 14 | (boolean (false))) 15 | 16 | ===================================== 17 | Numbers 18 | ===================================== 19 | 20 | 42 21 | +1 22 | -5 23 | +0 24 | 0xff 25 | 2r111 26 | 040 27 | 36rCRAZY 28 | 29 | 4.23e9 30 | 4.23e-9 31 | 4.23e+9 32 | 40.3e6 33 | 40.3e-6 34 | 1.234 35 | 0.123456 36 | .12345 37 | 1e4 38 | 0.2e-2 39 | 0.0e-4 40 | .2e-2 41 | 42 | +83N 43 | 4N 44 | -27362746264274623285736757364838535636343463N 45 | 46 | 0.01M 47 | -4.2M 48 | 49 | 3/2 50 | +4/5 51 | -7/11 52 | 53 | --- 54 | 55 | (program 56 | (number (number_long)) 57 | (number (number_long)) 58 | (number (number_long)) 59 | (number (number_long)) 60 | (number (number_long)) 61 | (number (number_long)) 62 | (number (number_long)) 63 | (number (number_long)) 64 | 65 | (number (number_double)) 66 | (number (number_double)) 67 | (number (number_double)) 68 | (number (number_double)) 69 | (number (number_double)) 70 | (number (number_double)) 71 | (number (number_double)) 72 | (number (number_double)) 73 | (number (number_double)) 74 | (number (number_double)) 75 | (number (number_double)) 76 | (number (number_double)) 77 | 78 | (number (number_bigint)) 79 | (number (number_bigint)) 80 | (number (number_bigint)) 81 | 82 | (number (number_bigdecimal)) 83 | (number (number_bigdecimal)) 84 | 85 | (number (number_ratio)) 86 | (number (number_ratio)) 87 | (number (number_ratio)) 88 | ) 89 | 90 | ===================================== 91 | Characters - \a 92 | ===================================== 93 | 94 | \a 95 | \7 96 | \Z 97 | \} 98 | 99 | \newline 100 | \space 101 | \tab 102 | \formfeed 103 | \backspace 104 | \return 105 | 106 | \u2202 107 | \u03a9 108 | \u00A1 109 | 110 | \o3 111 | \o41 112 | \o256 113 | 114 | --- 115 | 116 | (program 117 | (character) 118 | (character) 119 | (character) 120 | (character) 121 | 122 | (character) 123 | (character) 124 | (character) 125 | (character) 126 | (character) 127 | (character) 128 | 129 | (character) 130 | (character) 131 | (character) 132 | 133 | (character) 134 | (character) 135 | (character)) 136 | 137 | ===================================== 138 | Strings - "" 139 | ===================================== 140 | 141 | "" 142 | "\"" 143 | "abc" 144 | "'" 145 | "i am a multi-line 146 | string\"" 147 | 148 | --- 149 | 150 | (program 151 | (string) 152 | (string) 153 | (string) 154 | (string) 155 | (string) 156 | ) 157 | 158 | ===================================== 159 | Regular Expressions - #"" 160 | ===================================== 161 | 162 | #"" 163 | #"\"" 164 | #"pattern" 165 | #"(\w+)\s(\w+)" 166 | 167 | --- 168 | 169 | (program 170 | (regex) 171 | (regex) 172 | (regex) 173 | (regex)) 174 | -------------------------------------------------------------------------------- /corpus/functions.txt: -------------------------------------------------------------------------------- 1 | ===================================== 2 | anonymous fn 3 | ===================================== 4 | 5 | (fn []) 6 | 7 | ( fn [y] nil ) 8 | 9 | (fn 10 | ([x] x) 11 | ([x y] (+ x y))) 12 | 13 | --- 14 | 15 | (program 16 | (anonymous_function 17 | (params (vector))) 18 | 19 | (anonymous_function 20 | (params (vector (symbol))) 21 | (function_body (nil))) 22 | 23 | (anonymous_function 24 | (params (vector (symbol))) 25 | (function_body (symbol)) 26 | 27 | (params (vector (symbol) (symbol))) 28 | (function_body (list (symbol) (symbol) (symbol)))) 29 | ) 30 | 31 | ===================================== 32 | anonymous fn with name 33 | ===================================== 34 | 35 | (fn foo []) 36 | 37 | ( fn bar [y] nil ) 38 | 39 | (fn biz 40 | ([x] x) 41 | ([x y] (+ x y))) 42 | 43 | --- 44 | 45 | (program 46 | (anonymous_function 47 | (function_name (symbol)) 48 | (params (vector))) 49 | 50 | (anonymous_function 51 | (function_name (symbol)) 52 | (params (vector (symbol))) 53 | (function_body (nil))) 54 | 55 | (anonymous_function 56 | (function_name (symbol)) 57 | 58 | (params (vector (symbol))) 59 | (function_body (symbol)) 60 | 61 | (params (vector (symbol) (symbol))) 62 | (function_body (list (symbol) (symbol) (symbol)))) 63 | ) 64 | 65 | ===================================== 66 | function shorthand 67 | ===================================== 68 | 69 | #() 70 | 71 | #(conj [] "a") 72 | 73 | #(swap! % inc) 74 | 75 | #(conj [] %1 %2 %3 %&) 76 | 77 | --- 78 | 79 | (program 80 | (shorthand_function) 81 | 82 | (shorthand_function 83 | (symbol) (vector) (string)) 84 | 85 | (shorthand_function 86 | (symbol) (shorthand_function_arg) (symbol)) 87 | 88 | (shorthand_function 89 | (symbol) 90 | (vector) 91 | (shorthand_function_arg) 92 | (shorthand_function_arg) 93 | (shorthand_function_arg) 94 | (shorthand_function_arg)) 95 | ) 96 | 97 | ===================================== 98 | defn, defn- 99 | ===================================== 100 | 101 | (defn foo []) 102 | 103 | (defn- foo [x] 4) 104 | 105 | (defn foo 106 | ([] "zero arity") 107 | ([x y] "multi arity")) 108 | 109 | --- 110 | 111 | (program 112 | (defn 113 | (function_name (symbol)) 114 | (params (vector))) 115 | 116 | (defn 117 | (function_name (symbol)) 118 | (params (vector (symbol))) 119 | (function_body (number (number_long)))) 120 | 121 | (defn 122 | (function_name (symbol)) 123 | 124 | (params (vector)) 125 | (function_body (string)) 126 | 127 | (params (vector (symbol) (symbol))) 128 | (function_body (string))) 129 | ) 130 | 131 | ===================================== 132 | defn with docstring and attr-map 133 | ===================================== 134 | 135 | (defn foo "foo" []) 136 | 137 | (defn flatten 138 | "Takes any nested combination of sequential things (lists, vectors, 139 | etc.) and returns their contents as a single, flat sequence. 140 | (flatten nil) returns an empty sequence." 141 | {:added "1.2" 142 | :static true} 143 | [] 144 | 7) 145 | 146 | --- 147 | 148 | (program 149 | (defn 150 | (function_name (symbol)) 151 | (docstring (string)) 152 | (params (vector))) 153 | 154 | (defn 155 | (function_name (symbol)) 156 | (docstring (string)) 157 | (attr_map 158 | (hash_map (keyword) (string) 159 | (keyword) (boolean (true)))) 160 | 161 | (params (vector)) 162 | (function_body (number (number_long)))) 163 | ) 164 | 165 | ===================================== 166 | defn with metadata 167 | ===================================== 168 | 169 | (defn ^:private ^Boolean always-true 170 | "private function that returns a boolean value" 171 | [] 172 | true) 173 | 174 | (defn ^{:foo "bar"} always-false 175 | [] 176 | false) 177 | 178 | --- 179 | 180 | (program 181 | (defn 182 | (metadata 183 | (metadata_shorthand) 184 | (metadata_shorthand)) 185 | (function_name (symbol)) 186 | (docstring (string)) 187 | (params (vector)) 188 | (function_body 189 | (boolean (true)))) 190 | 191 | (defn 192 | (metadata 193 | (hash_map (keyword) (string))) 194 | (function_name (symbol)) 195 | (params (vector)) 196 | (function_body 197 | (boolean (false)))) 198 | ) 199 | -------------------------------------------------------------------------------- /src/tree_sitter/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_PARSER_H_ 2 | #define TREE_SITTER_PARSER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define ts_builtin_sym_error ((TSSymbol)-1) 13 | #define ts_builtin_sym_end 0 14 | #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 15 | 16 | #ifndef TREE_SITTER_RUNTIME_H_ 17 | typedef uint16_t TSSymbol; 18 | typedef struct TSLanguage TSLanguage; 19 | #endif 20 | 21 | typedef uint16_t TSStateId; 22 | 23 | typedef struct { 24 | bool visible : 1; 25 | bool named : 1; 26 | } TSSymbolMetadata; 27 | 28 | typedef struct TSLexer TSLexer; 29 | 30 | struct TSLexer { 31 | int32_t lookahead; 32 | TSSymbol result_symbol; 33 | void (*advance)(TSLexer *, bool); 34 | void (*mark_end)(TSLexer *); 35 | uint32_t (*get_column)(TSLexer *); 36 | bool (*is_at_included_range_start)(TSLexer *); 37 | }; 38 | 39 | typedef enum { 40 | TSParseActionTypeShift, 41 | TSParseActionTypeReduce, 42 | TSParseActionTypeAccept, 43 | TSParseActionTypeRecover, 44 | } TSParseActionType; 45 | 46 | typedef struct { 47 | union { 48 | struct { 49 | TSStateId state; 50 | bool extra : 1; 51 | bool repetition : 1; 52 | }; 53 | struct { 54 | TSSymbol symbol; 55 | int16_t dynamic_precedence; 56 | uint8_t child_count; 57 | uint8_t alias_sequence_id; 58 | }; 59 | } params; 60 | TSParseActionType type : 4; 61 | } TSParseAction; 62 | 63 | typedef struct { 64 | uint16_t lex_state; 65 | uint16_t external_lex_state; 66 | } TSLexMode; 67 | 68 | typedef union { 69 | TSParseAction action; 70 | struct { 71 | uint8_t count; 72 | bool reusable : 1; 73 | }; 74 | } TSParseActionEntry; 75 | 76 | struct TSLanguage { 77 | uint32_t version; 78 | uint32_t symbol_count; 79 | uint32_t alias_count; 80 | uint32_t token_count; 81 | uint32_t external_token_count; 82 | const char **symbol_names; 83 | const TSSymbolMetadata *symbol_metadata; 84 | const uint16_t *parse_table; 85 | const TSParseActionEntry *parse_actions; 86 | const TSLexMode *lex_modes; 87 | const TSSymbol *alias_sequences; 88 | uint16_t max_alias_sequence_length; 89 | bool (*lex_fn)(TSLexer *, TSStateId); 90 | bool (*keyword_lex_fn)(TSLexer *, TSStateId); 91 | TSSymbol keyword_capture_token; 92 | struct { 93 | const bool *states; 94 | const TSSymbol *symbol_map; 95 | void *(*create)(); 96 | void (*destroy)(void *); 97 | bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 98 | unsigned (*serialize)(void *, char *); 99 | void (*deserialize)(void *, const char *, unsigned); 100 | } external_scanner; 101 | }; 102 | 103 | /* 104 | * Lexer Macros 105 | */ 106 | 107 | #define START_LEXER() \ 108 | bool result = false; \ 109 | int32_t lookahead; \ 110 | next_state: \ 111 | lookahead = lexer->lookahead; 112 | 113 | #define ADVANCE(state_value) \ 114 | { \ 115 | lexer->advance(lexer, false); \ 116 | state = state_value; \ 117 | goto next_state; \ 118 | } 119 | 120 | #define SKIP(state_value) \ 121 | { \ 122 | lexer->advance(lexer, true); \ 123 | state = state_value; \ 124 | goto next_state; \ 125 | } 126 | 127 | #define ACCEPT_TOKEN(symbol_value) \ 128 | result = true; \ 129 | lexer->result_symbol = symbol_value; \ 130 | lexer->mark_end(lexer); 131 | 132 | #define END_STATE() return result; 133 | 134 | /* 135 | * Parse Table Macros 136 | */ 137 | 138 | #define STATE(id) id 139 | 140 | #define ACTIONS(id) id 141 | 142 | #define SHIFT(state_value) \ 143 | { \ 144 | { \ 145 | .type = TSParseActionTypeShift, \ 146 | .params = {.state = state_value}, \ 147 | } \ 148 | } 149 | 150 | #define SHIFT_REPEAT(state_value) \ 151 | { \ 152 | { \ 153 | .type = TSParseActionTypeShift, \ 154 | .params = { \ 155 | .state = state_value, \ 156 | .repetition = true \ 157 | }, \ 158 | } \ 159 | } 160 | 161 | #define RECOVER() \ 162 | { \ 163 | { .type = TSParseActionTypeRecover } \ 164 | } 165 | 166 | #define SHIFT_EXTRA() \ 167 | { \ 168 | { \ 169 | .type = TSParseActionTypeShift, \ 170 | .params = {.extra = true} \ 171 | } \ 172 | } 173 | 174 | #define REDUCE(symbol_val, child_count_val, ...) \ 175 | { \ 176 | { \ 177 | .type = TSParseActionTypeReduce, \ 178 | .params = { \ 179 | .symbol = symbol_val, \ 180 | .child_count = child_count_val, \ 181 | __VA_ARGS__ \ 182 | } \ 183 | } \ 184 | } 185 | 186 | #define ACCEPT_INPUT() \ 187 | { \ 188 | { .type = TSParseActionTypeAccept } \ 189 | } 190 | 191 | #ifdef __cplusplus 192 | } 193 | #endif 194 | 195 | #endif // TREE_SITTER_PARSER_H_ 196 | -------------------------------------------------------------------------------- /grammar.js: -------------------------------------------------------------------------------- 1 | // Helpful links: 2 | // https://clojure.org/guides/learn/syntax 3 | // https://clojure.org/reference/reader 4 | // https://clojure.org/guides/weird_characters 5 | // https://github.com/venantius/glow/blob/master/resources/parsers/Clojure.g4 6 | // https://github.com/tree-sitter/tree-sitter-java/blob/master/grammar.js 7 | // https://github.com/atom/language-clojure/blob/master/grammars/clojure.cson 8 | // http://cljs.github.io/api/syntax/ 9 | // https://gist.github.com/Aerijo/df27228d70c633e088b0591b8857eeef 10 | // https://github.com/Tavistock/tree-sitter-clojure 11 | 12 | const DIGITS = token(sep1(/[0-9]+/, /_+/)) 13 | 14 | module.exports = grammar({ 15 | name: 'clojure', 16 | 17 | extras: $ => [ 18 | /(\s|,)/ // ignore whitespace and commas 19 | ], 20 | 21 | rules: { 22 | program: $ => repeat($._anything), 23 | 24 | _anything: $ => choice( 25 | $._literals, 26 | $.symbol, 27 | $.interop, 28 | $._functions, 29 | $.quote, 30 | $.comment, 31 | $.deref, 32 | 33 | $.syntax_quote, 34 | $.var_quote, 35 | 36 | $.unquote, 37 | $.unquote_splice, 38 | $.gensym, 39 | 40 | $.shorthand_function_arg, 41 | $.reader_conditional, 42 | ), 43 | 44 | _literals: $ => choice( 45 | $.nil, 46 | $.boolean, 47 | $.number, 48 | $.symbolic_value, 49 | $.character, 50 | $.string, 51 | $.regex, 52 | $.keyword, 53 | $._collection_literals, 54 | $.tagged_literal 55 | ), 56 | 57 | _collection_literals: $ => seq(optional($.metadata), choice( 58 | $.list, 59 | $.vector, 60 | $.hash_map, 61 | $.set 62 | )), 63 | 64 | // ------------------------------------------------------------------------- 65 | // nil + booleans 66 | // ------------------------------------------------------------------------- 67 | 68 | nil: $ => 'nil', 69 | boolean: $ => choice($.true, $.false), 70 | true: $ => 'true', 71 | false: $ => 'false', 72 | 73 | // ------------------------------------------------------------------------- 74 | // Numbers 75 | // ------------------------------------------------------------------------- 76 | 77 | number: $ => $._number, 78 | _number: $ => choice( 79 | $.number_long, 80 | $.number_double, 81 | $.number_bigint, 82 | $.number_bigdecimal, 83 | $.number_ratio 84 | ), 85 | 86 | number_long: $ => choice($._normal_long, $._number_hex, $._number_arbitrary_radix, $._number_octal), 87 | _normal_long: $ => /[-+]?\d+/, 88 | _number_hex: $ => /-?0[xX][0-9a-fA-F]+/, 89 | _number_arbitrary_radix: $ => /-?\d+[rR][0-9a-zA-Z]+/, 90 | _number_octal: $ => /-?0\d+/, 91 | 92 | number_double: $ => token( 93 | choice( 94 | seq(DIGITS, '.', optional(DIGITS), optional(seq((/[eE]/), optional(choice('-', '+')), DIGITS)), optional(/[fFdD]/)), 95 | seq('.', DIGITS, optional(seq((/[eE]/), optional(choice('-', '+')), DIGITS)), optional(/[fFdD]/)), 96 | seq(DIGITS, /[eE]/, optional(choice('-', '+')), DIGITS, optional(/[fFdD]/)), 97 | seq(DIGITS, optional(seq((/[eE]/), optional(choice('-', '+')), DIGITS)), (/[fFdD]/)) 98 | )), 99 | number_bigint: $ => /[-+]?\d+N/, 100 | number_bigdecimal: $ => /-?\d+\.\d+([eE][+-]?\d+)?M/, 101 | number_ratio: $ => /[-+]?\d+\/\d+/, 102 | 103 | // ------------------------------------------------------------------------- 104 | // Symbolic Value - ##Inf, ##-Inf, ##NaN 105 | // ------------------------------------------------------------------------- 106 | 107 | symbolic_value: $ => seq('##', choice($.infinity, $.negative_infinity, $.not_a_number)), 108 | infinity: $ => 'Inf', 109 | negative_infinity: $ => '-Inf', 110 | not_a_number: $ => 'NaN', 111 | 112 | // ------------------------------------------------------------------------- 113 | // Character - \a 114 | // ------------------------------------------------------------------------- 115 | 116 | character: $ => $._character, 117 | _character: $ => seq('\\', choice($._normal_char, $._special_char, $._unicode_char, $._octal_char)), 118 | _normal_char: $ => /./, 119 | _special_char: $ => choice('newline', 'space', 'tab', 'formfeed', 'backspace', 'return'), 120 | _unicode_char: $ => seq('u', $._hex_char, $._hex_char, $._hex_char, $._hex_char), 121 | _hex_char: $ => /[A-Fa-f0-9]/, 122 | _octal_char: $ => seq('o', $._octal_num), 123 | _octal_num: $ => choice(/[0-3][0-7][0-7]/, /[0-7][0-7]/, /[0-7]/), 124 | 125 | // ------------------------------------------------------------------------- 126 | // Strings - "" 127 | // ------------------------------------------------------------------------- 128 | 129 | string: $ => $._string, 130 | _string: $ => seq('"', repeat(choice('\\"', /[^"]/)), '"'), 131 | 132 | // ------------------------------------------------------------------------- 133 | // Regular Expressions - #"" 134 | // ------------------------------------------------------------------------- 135 | 136 | regex: $ => $._regex, 137 | _regex: $ => seq('#"', repeat(choice('\\"', /[^"\n\r]/)), '"'), 138 | 139 | // ------------------------------------------------------------------------- 140 | // Quote - '() (quote) 141 | // ------------------------------------------------------------------------- 142 | 143 | // NOTE: would it be useful to distinguish between these two? 144 | quote: $ => $._quote, 145 | _quote: $ => choice( 146 | seq("'", $._anything), 147 | seq('(quote', $._anything, ')') 148 | ), 149 | 150 | // ------------------------------------------------------------------------- 151 | // Keywords - :foo 152 | // ------------------------------------------------------------------------- 153 | 154 | keyword: $ => $._keyword, 155 | _keyword: $ => choice( 156 | $._unqualified_keyword, 157 | $.qualified_keyword 158 | ), 159 | 160 | _unqualified_keyword: $ => seq(':', $._keyword_chars), 161 | qualified_keyword: $ => choice( 162 | seq('::', $._keyword_chars), 163 | seq('::', $._keyword_chars, '/', $._keyword_chars) 164 | ), 165 | _keyword_chars: $ => /[a-zA-Z0-9\-_\!\+\.][a-zA-Z0-9\-_\!\+\.:\?]*/, 166 | 167 | // ------------------------------------------------------------------------- 168 | // Symbols - foo 169 | // ------------------------------------------------------------------------- 170 | 171 | symbol: $ => $._symbol, 172 | _symbol: $ => choice( 173 | $.threading_macro, 174 | $._symbol_chars, 175 | $.qualified_symbol 176 | ), 177 | 178 | threading_macro: $ => choice( 179 | '->', '->>', 180 | 'as->', 181 | 'some->', 'some->>', 182 | 'cond->', 'cond->>' 183 | ), 184 | 185 | // reference: https://clojure.org/reference/reader#_symbols 186 | _symbol_chars: $ => /[a-zA-Z\*\+\!\-_\?][a-zA-Z0-9\*\+\!\-_\?\':]*/, 187 | qualified_symbol: $ => $._qualified_symbol, 188 | _qualified_symbol: $ => seq($._symbol_chars, '/', $._symbol_chars), 189 | 190 | // ------------------------------------------------------------------------- 191 | // Interop - .foo .-foo java.blah.Klass. 192 | // ------------------------------------------------------------------------- 193 | 194 | interop: $ => choice($.member_access, $.field_access, $.new_class), 195 | member_access: $ => /\.[a-zA-Z_]\w*/, 196 | field_access: $ => /\.-[a-zA-Z_]\w*/, 197 | new_class: $ => /([a-zA-Z_]\w*\.)(\w+\.)*/, 198 | // TODO: "new" symbol, single dot, double dot, memfn, doto 199 | // https://github.com/oakmac/tree-sitter-clojure/issues/13 200 | 201 | // ------------------------------------------------------------------------- 202 | // List - () 203 | // ------------------------------------------------------------------------- 204 | 205 | list: $ => $._list, 206 | _list: $ => seq('(', repeat($._anything), ')'), 207 | 208 | // ------------------------------------------------------------------------- 209 | // Vector - [] 210 | // ------------------------------------------------------------------------- 211 | 212 | vector: $ => $._vector, 213 | _vector: $ => seq('[', repeat($._anything), ']'), 214 | 215 | // ------------------------------------------------------------------------- 216 | // Hash Map - {} 217 | // ------------------------------------------------------------------------- 218 | 219 | hash_map: $ => $._hash_map, 220 | _hash_map: $ => choice( 221 | seq('{', repeat($._hash_map_kv_pair), '}'), 222 | $.namespace_map 223 | ), 224 | namespace_map: $ => choice( 225 | seq('#::{', repeat($._hash_map_kv_pair), '}'), 226 | seq(/\#:[a-zA-Z\*\+\!\-_\?][a-zA-Z0-9\*\+\!\-_\?\':]*/, '{', repeat($._hash_map_kv_pair), '}') 227 | ), 228 | _hash_map_kv_pair: $ => seq($._hash_map_key, $._hash_map_value), 229 | _hash_map_key: $ => $._anything, 230 | _hash_map_value: $ => $._anything, 231 | 232 | // ------------------------------------------------------------------------- 233 | // Set - #{} 234 | // ------------------------------------------------------------------------- 235 | 236 | set: $ => $._set, 237 | _set: $ => seq('#{', repeat($._anything), '}'), 238 | 239 | // ------------------------------------------------------------------------- 240 | // Comments 241 | // ------------------------------------------------------------------------- 242 | 243 | comment: $ => choice($.semicolon, $.shebang_line, $.ignore_form, $.comment_macro), 244 | semicolon: $ => seq(';', /.*/), 245 | shebang_line: $ => seq('#!', /.*/), 246 | ignore_form: $ => seq('#_', $._anything), 247 | comment_macro: $ => seq('(', 'comment', repeat($._anything), ')'), 248 | 249 | // ------------------------------------------------------------------------- 250 | // Functions 251 | // ------------------------------------------------------------------------- 252 | 253 | _functions: $ => choice($.anonymous_function, $.shorthand_function, $.defn), 254 | 255 | anonymous_function: $ => seq('(', 'fn', optional($.function_name), $._after_the_fn_name, ')'), 256 | _after_the_fn_name: $ => choice($._single_arity_fn, $._multi_arity_fn), 257 | function_name: $ => $.symbol, 258 | _single_arity_fn: $ => seq($.params, optional($.function_body)), 259 | _multi_arity_fn: $ => repeat1(seq('(', $._single_arity_fn, ')')), 260 | 261 | // NOTE: I don't think we need to handle condition-map here explicitly 262 | // it will just be detected as (hash_map) inside the function body 263 | function_body: $ => repeat1($._anything), 264 | 265 | // NOTE: we can probably be more specific here than just "vector" 266 | params: $ => $.vector, 267 | 268 | shorthand_function: $ => seq('#(', repeat($._anything), ')'), 269 | shorthand_function_arg: $ => /%[1-9&]*/, 270 | 271 | defn: $ => seq('(', choice('defn', 'defn-'), 272 | optional($.metadata), 273 | $.function_name, 274 | optional($.docstring), 275 | optional($.attr_map), 276 | $._after_the_fn_name, ')'), 277 | docstring: $ => $.string, 278 | attr_map: $ => $.hash_map, 279 | 280 | // ------------------------------------------------------------------------- 281 | // Metadata 282 | // ------------------------------------------------------------------------- 283 | 284 | metadata: $ => choice(repeat1($.metadata_shorthand), $._metadata_map), 285 | _metadata_map: $ => seq('^', $.hash_map), 286 | // NOTE: would it be useful to expose these as separate node types? 287 | metadata_shorthand: $ => choice( 288 | seq('^:', $._keyword_chars), 289 | seq('^"', repeat(choice('\\"', /[^"]/)), '"'), 290 | seq('^', $._symbol_chars) 291 | ), 292 | 293 | // ------------------------------------------------------------------------- 294 | // Syntax Quote and macro-related friends 295 | // ------------------------------------------------------------------------- 296 | 297 | syntax_quote: $ => seq('`', $._anything), 298 | var_quote: $ => seq("#'", $.symbol), 299 | unquote: $ => seq('~', $._anything), 300 | unquote_splice: $ => seq('~@', $._anything), 301 | gensym: $ => /[a-zA-Z\*\+\!\-_\?][a-zA-Z0-9\*\+\!\-_\?\':]*\#/, 302 | 303 | // ------------------------------------------------------------------------- 304 | // Deref 305 | // ------------------------------------------------------------------------- 306 | 307 | // NOTE: presumably a list here would evaluate to something that can be derefed 308 | deref: $ => seq('@', choice($.symbol, $.list)), 309 | 310 | // ------------------------------------------------------------------------- 311 | // Tagged Literal - #inst, #uuid, #foo/bar 312 | // ------------------------------------------------------------------------- 313 | 314 | tagged_literal: $ => seq('#', choice($._symbol_chars, $._qualified_symbol), $._anything), 315 | 316 | // ------------------------------------------------------------------------- 317 | // Reader Conditional - #?, #?@ 318 | // ------------------------------------------------------------------------- 319 | 320 | // NOTE: maybe we should identify "clojure_part", "cljs_part", etc here? 321 | reader_conditional: $ => seq($._reader_conditional_symbol, '(', repeat(seq($.keyword, $._anything)), ')'), 322 | 323 | // NOTE: I don't think we really need to distinguish between these two 324 | _reader_conditional_symbol: $ => choice('#?', '#?@'), 325 | } 326 | }) 327 | 328 | function sep1 (rule, separator) { 329 | return seq(rule, repeat(seq(separator, rule))) 330 | } 331 | -------------------------------------------------------------------------------- /src/grammar.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clojure", 3 | "rules": { 4 | "program": { 5 | "type": "REPEAT", 6 | "content": { 7 | "type": "SYMBOL", 8 | "name": "_anything" 9 | } 10 | }, 11 | "_anything": { 12 | "type": "CHOICE", 13 | "members": [ 14 | { 15 | "type": "SYMBOL", 16 | "name": "_literals" 17 | }, 18 | { 19 | "type": "SYMBOL", 20 | "name": "symbol" 21 | }, 22 | { 23 | "type": "SYMBOL", 24 | "name": "interop" 25 | }, 26 | { 27 | "type": "SYMBOL", 28 | "name": "_functions" 29 | }, 30 | { 31 | "type": "SYMBOL", 32 | "name": "quote" 33 | }, 34 | { 35 | "type": "SYMBOL", 36 | "name": "comment" 37 | }, 38 | { 39 | "type": "SYMBOL", 40 | "name": "deref" 41 | }, 42 | { 43 | "type": "SYMBOL", 44 | "name": "syntax_quote" 45 | }, 46 | { 47 | "type": "SYMBOL", 48 | "name": "var_quote" 49 | }, 50 | { 51 | "type": "SYMBOL", 52 | "name": "unquote" 53 | }, 54 | { 55 | "type": "SYMBOL", 56 | "name": "unquote_splice" 57 | }, 58 | { 59 | "type": "SYMBOL", 60 | "name": "gensym" 61 | }, 62 | { 63 | "type": "SYMBOL", 64 | "name": "shorthand_function_arg" 65 | }, 66 | { 67 | "type": "SYMBOL", 68 | "name": "reader_conditional" 69 | } 70 | ] 71 | }, 72 | "_literals": { 73 | "type": "CHOICE", 74 | "members": [ 75 | { 76 | "type": "SYMBOL", 77 | "name": "nil" 78 | }, 79 | { 80 | "type": "SYMBOL", 81 | "name": "boolean" 82 | }, 83 | { 84 | "type": "SYMBOL", 85 | "name": "number" 86 | }, 87 | { 88 | "type": "SYMBOL", 89 | "name": "symbolic_value" 90 | }, 91 | { 92 | "type": "SYMBOL", 93 | "name": "character" 94 | }, 95 | { 96 | "type": "SYMBOL", 97 | "name": "string" 98 | }, 99 | { 100 | "type": "SYMBOL", 101 | "name": "regex" 102 | }, 103 | { 104 | "type": "SYMBOL", 105 | "name": "keyword" 106 | }, 107 | { 108 | "type": "SYMBOL", 109 | "name": "_collection_literals" 110 | }, 111 | { 112 | "type": "SYMBOL", 113 | "name": "tagged_literal" 114 | } 115 | ] 116 | }, 117 | "_collection_literals": { 118 | "type": "SEQ", 119 | "members": [ 120 | { 121 | "type": "CHOICE", 122 | "members": [ 123 | { 124 | "type": "SYMBOL", 125 | "name": "metadata" 126 | }, 127 | { 128 | "type": "BLANK" 129 | } 130 | ] 131 | }, 132 | { 133 | "type": "CHOICE", 134 | "members": [ 135 | { 136 | "type": "SYMBOL", 137 | "name": "list" 138 | }, 139 | { 140 | "type": "SYMBOL", 141 | "name": "vector" 142 | }, 143 | { 144 | "type": "SYMBOL", 145 | "name": "hash_map" 146 | }, 147 | { 148 | "type": "SYMBOL", 149 | "name": "set" 150 | } 151 | ] 152 | } 153 | ] 154 | }, 155 | "nil": { 156 | "type": "STRING", 157 | "value": "nil" 158 | }, 159 | "boolean": { 160 | "type": "CHOICE", 161 | "members": [ 162 | { 163 | "type": "SYMBOL", 164 | "name": "true" 165 | }, 166 | { 167 | "type": "SYMBOL", 168 | "name": "false" 169 | } 170 | ] 171 | }, 172 | "true": { 173 | "type": "STRING", 174 | "value": "true" 175 | }, 176 | "false": { 177 | "type": "STRING", 178 | "value": "false" 179 | }, 180 | "number": { 181 | "type": "SYMBOL", 182 | "name": "_number" 183 | }, 184 | "_number": { 185 | "type": "CHOICE", 186 | "members": [ 187 | { 188 | "type": "SYMBOL", 189 | "name": "number_long" 190 | }, 191 | { 192 | "type": "SYMBOL", 193 | "name": "number_double" 194 | }, 195 | { 196 | "type": "SYMBOL", 197 | "name": "number_bigint" 198 | }, 199 | { 200 | "type": "SYMBOL", 201 | "name": "number_bigdecimal" 202 | }, 203 | { 204 | "type": "SYMBOL", 205 | "name": "number_ratio" 206 | } 207 | ] 208 | }, 209 | "number_long": { 210 | "type": "CHOICE", 211 | "members": [ 212 | { 213 | "type": "SYMBOL", 214 | "name": "_normal_long" 215 | }, 216 | { 217 | "type": "SYMBOL", 218 | "name": "_number_hex" 219 | }, 220 | { 221 | "type": "SYMBOL", 222 | "name": "_number_arbitrary_radix" 223 | }, 224 | { 225 | "type": "SYMBOL", 226 | "name": "_number_octal" 227 | } 228 | ] 229 | }, 230 | "_normal_long": { 231 | "type": "PATTERN", 232 | "value": "[-+]?\\d+" 233 | }, 234 | "_number_hex": { 235 | "type": "PATTERN", 236 | "value": "-?0[xX][0-9a-fA-F]+" 237 | }, 238 | "_number_arbitrary_radix": { 239 | "type": "PATTERN", 240 | "value": "-?\\d+[rR][0-9a-zA-Z]+" 241 | }, 242 | "_number_octal": { 243 | "type": "PATTERN", 244 | "value": "-?0\\d+" 245 | }, 246 | "number_double": { 247 | "type": "TOKEN", 248 | "content": { 249 | "type": "CHOICE", 250 | "members": [ 251 | { 252 | "type": "SEQ", 253 | "members": [ 254 | { 255 | "type": "TOKEN", 256 | "content": { 257 | "type": "SEQ", 258 | "members": [ 259 | { 260 | "type": "PATTERN", 261 | "value": "[0-9]+" 262 | }, 263 | { 264 | "type": "REPEAT", 265 | "content": { 266 | "type": "SEQ", 267 | "members": [ 268 | { 269 | "type": "PATTERN", 270 | "value": "_+" 271 | }, 272 | { 273 | "type": "PATTERN", 274 | "value": "[0-9]+" 275 | } 276 | ] 277 | } 278 | } 279 | ] 280 | } 281 | }, 282 | { 283 | "type": "STRING", 284 | "value": "." 285 | }, 286 | { 287 | "type": "CHOICE", 288 | "members": [ 289 | { 290 | "type": "TOKEN", 291 | "content": { 292 | "type": "SEQ", 293 | "members": [ 294 | { 295 | "type": "PATTERN", 296 | "value": "[0-9]+" 297 | }, 298 | { 299 | "type": "REPEAT", 300 | "content": { 301 | "type": "SEQ", 302 | "members": [ 303 | { 304 | "type": "PATTERN", 305 | "value": "_+" 306 | }, 307 | { 308 | "type": "PATTERN", 309 | "value": "[0-9]+" 310 | } 311 | ] 312 | } 313 | } 314 | ] 315 | } 316 | }, 317 | { 318 | "type": "BLANK" 319 | } 320 | ] 321 | }, 322 | { 323 | "type": "CHOICE", 324 | "members": [ 325 | { 326 | "type": "SEQ", 327 | "members": [ 328 | { 329 | "type": "PATTERN", 330 | "value": "[eE]" 331 | }, 332 | { 333 | "type": "CHOICE", 334 | "members": [ 335 | { 336 | "type": "CHOICE", 337 | "members": [ 338 | { 339 | "type": "STRING", 340 | "value": "-" 341 | }, 342 | { 343 | "type": "STRING", 344 | "value": "+" 345 | } 346 | ] 347 | }, 348 | { 349 | "type": "BLANK" 350 | } 351 | ] 352 | }, 353 | { 354 | "type": "TOKEN", 355 | "content": { 356 | "type": "SEQ", 357 | "members": [ 358 | { 359 | "type": "PATTERN", 360 | "value": "[0-9]+" 361 | }, 362 | { 363 | "type": "REPEAT", 364 | "content": { 365 | "type": "SEQ", 366 | "members": [ 367 | { 368 | "type": "PATTERN", 369 | "value": "_+" 370 | }, 371 | { 372 | "type": "PATTERN", 373 | "value": "[0-9]+" 374 | } 375 | ] 376 | } 377 | } 378 | ] 379 | } 380 | } 381 | ] 382 | }, 383 | { 384 | "type": "BLANK" 385 | } 386 | ] 387 | }, 388 | { 389 | "type": "CHOICE", 390 | "members": [ 391 | { 392 | "type": "PATTERN", 393 | "value": "[fFdD]" 394 | }, 395 | { 396 | "type": "BLANK" 397 | } 398 | ] 399 | } 400 | ] 401 | }, 402 | { 403 | "type": "SEQ", 404 | "members": [ 405 | { 406 | "type": "STRING", 407 | "value": "." 408 | }, 409 | { 410 | "type": "TOKEN", 411 | "content": { 412 | "type": "SEQ", 413 | "members": [ 414 | { 415 | "type": "PATTERN", 416 | "value": "[0-9]+" 417 | }, 418 | { 419 | "type": "REPEAT", 420 | "content": { 421 | "type": "SEQ", 422 | "members": [ 423 | { 424 | "type": "PATTERN", 425 | "value": "_+" 426 | }, 427 | { 428 | "type": "PATTERN", 429 | "value": "[0-9]+" 430 | } 431 | ] 432 | } 433 | } 434 | ] 435 | } 436 | }, 437 | { 438 | "type": "CHOICE", 439 | "members": [ 440 | { 441 | "type": "SEQ", 442 | "members": [ 443 | { 444 | "type": "PATTERN", 445 | "value": "[eE]" 446 | }, 447 | { 448 | "type": "CHOICE", 449 | "members": [ 450 | { 451 | "type": "CHOICE", 452 | "members": [ 453 | { 454 | "type": "STRING", 455 | "value": "-" 456 | }, 457 | { 458 | "type": "STRING", 459 | "value": "+" 460 | } 461 | ] 462 | }, 463 | { 464 | "type": "BLANK" 465 | } 466 | ] 467 | }, 468 | { 469 | "type": "TOKEN", 470 | "content": { 471 | "type": "SEQ", 472 | "members": [ 473 | { 474 | "type": "PATTERN", 475 | "value": "[0-9]+" 476 | }, 477 | { 478 | "type": "REPEAT", 479 | "content": { 480 | "type": "SEQ", 481 | "members": [ 482 | { 483 | "type": "PATTERN", 484 | "value": "_+" 485 | }, 486 | { 487 | "type": "PATTERN", 488 | "value": "[0-9]+" 489 | } 490 | ] 491 | } 492 | } 493 | ] 494 | } 495 | } 496 | ] 497 | }, 498 | { 499 | "type": "BLANK" 500 | } 501 | ] 502 | }, 503 | { 504 | "type": "CHOICE", 505 | "members": [ 506 | { 507 | "type": "PATTERN", 508 | "value": "[fFdD]" 509 | }, 510 | { 511 | "type": "BLANK" 512 | } 513 | ] 514 | } 515 | ] 516 | }, 517 | { 518 | "type": "SEQ", 519 | "members": [ 520 | { 521 | "type": "TOKEN", 522 | "content": { 523 | "type": "SEQ", 524 | "members": [ 525 | { 526 | "type": "PATTERN", 527 | "value": "[0-9]+" 528 | }, 529 | { 530 | "type": "REPEAT", 531 | "content": { 532 | "type": "SEQ", 533 | "members": [ 534 | { 535 | "type": "PATTERN", 536 | "value": "_+" 537 | }, 538 | { 539 | "type": "PATTERN", 540 | "value": "[0-9]+" 541 | } 542 | ] 543 | } 544 | } 545 | ] 546 | } 547 | }, 548 | { 549 | "type": "PATTERN", 550 | "value": "[eE]" 551 | }, 552 | { 553 | "type": "CHOICE", 554 | "members": [ 555 | { 556 | "type": "CHOICE", 557 | "members": [ 558 | { 559 | "type": "STRING", 560 | "value": "-" 561 | }, 562 | { 563 | "type": "STRING", 564 | "value": "+" 565 | } 566 | ] 567 | }, 568 | { 569 | "type": "BLANK" 570 | } 571 | ] 572 | }, 573 | { 574 | "type": "TOKEN", 575 | "content": { 576 | "type": "SEQ", 577 | "members": [ 578 | { 579 | "type": "PATTERN", 580 | "value": "[0-9]+" 581 | }, 582 | { 583 | "type": "REPEAT", 584 | "content": { 585 | "type": "SEQ", 586 | "members": [ 587 | { 588 | "type": "PATTERN", 589 | "value": "_+" 590 | }, 591 | { 592 | "type": "PATTERN", 593 | "value": "[0-9]+" 594 | } 595 | ] 596 | } 597 | } 598 | ] 599 | } 600 | }, 601 | { 602 | "type": "CHOICE", 603 | "members": [ 604 | { 605 | "type": "PATTERN", 606 | "value": "[fFdD]" 607 | }, 608 | { 609 | "type": "BLANK" 610 | } 611 | ] 612 | } 613 | ] 614 | }, 615 | { 616 | "type": "SEQ", 617 | "members": [ 618 | { 619 | "type": "TOKEN", 620 | "content": { 621 | "type": "SEQ", 622 | "members": [ 623 | { 624 | "type": "PATTERN", 625 | "value": "[0-9]+" 626 | }, 627 | { 628 | "type": "REPEAT", 629 | "content": { 630 | "type": "SEQ", 631 | "members": [ 632 | { 633 | "type": "PATTERN", 634 | "value": "_+" 635 | }, 636 | { 637 | "type": "PATTERN", 638 | "value": "[0-9]+" 639 | } 640 | ] 641 | } 642 | } 643 | ] 644 | } 645 | }, 646 | { 647 | "type": "CHOICE", 648 | "members": [ 649 | { 650 | "type": "SEQ", 651 | "members": [ 652 | { 653 | "type": "PATTERN", 654 | "value": "[eE]" 655 | }, 656 | { 657 | "type": "CHOICE", 658 | "members": [ 659 | { 660 | "type": "CHOICE", 661 | "members": [ 662 | { 663 | "type": "STRING", 664 | "value": "-" 665 | }, 666 | { 667 | "type": "STRING", 668 | "value": "+" 669 | } 670 | ] 671 | }, 672 | { 673 | "type": "BLANK" 674 | } 675 | ] 676 | }, 677 | { 678 | "type": "TOKEN", 679 | "content": { 680 | "type": "SEQ", 681 | "members": [ 682 | { 683 | "type": "PATTERN", 684 | "value": "[0-9]+" 685 | }, 686 | { 687 | "type": "REPEAT", 688 | "content": { 689 | "type": "SEQ", 690 | "members": [ 691 | { 692 | "type": "PATTERN", 693 | "value": "_+" 694 | }, 695 | { 696 | "type": "PATTERN", 697 | "value": "[0-9]+" 698 | } 699 | ] 700 | } 701 | } 702 | ] 703 | } 704 | } 705 | ] 706 | }, 707 | { 708 | "type": "BLANK" 709 | } 710 | ] 711 | }, 712 | { 713 | "type": "PATTERN", 714 | "value": "[fFdD]" 715 | } 716 | ] 717 | } 718 | ] 719 | } 720 | }, 721 | "number_bigint": { 722 | "type": "PATTERN", 723 | "value": "[-+]?\\d+N" 724 | }, 725 | "number_bigdecimal": { 726 | "type": "PATTERN", 727 | "value": "-?\\d+\\.\\d+([eE][+-]?\\d+)?M" 728 | }, 729 | "number_ratio": { 730 | "type": "PATTERN", 731 | "value": "[-+]?\\d+\\/\\d+" 732 | }, 733 | "symbolic_value": { 734 | "type": "SEQ", 735 | "members": [ 736 | { 737 | "type": "STRING", 738 | "value": "##" 739 | }, 740 | { 741 | "type": "CHOICE", 742 | "members": [ 743 | { 744 | "type": "SYMBOL", 745 | "name": "infinity" 746 | }, 747 | { 748 | "type": "SYMBOL", 749 | "name": "negative_infinity" 750 | }, 751 | { 752 | "type": "SYMBOL", 753 | "name": "not_a_number" 754 | } 755 | ] 756 | } 757 | ] 758 | }, 759 | "infinity": { 760 | "type": "STRING", 761 | "value": "Inf" 762 | }, 763 | "negative_infinity": { 764 | "type": "STRING", 765 | "value": "-Inf" 766 | }, 767 | "not_a_number": { 768 | "type": "STRING", 769 | "value": "NaN" 770 | }, 771 | "character": { 772 | "type": "SYMBOL", 773 | "name": "_character" 774 | }, 775 | "_character": { 776 | "type": "SEQ", 777 | "members": [ 778 | { 779 | "type": "STRING", 780 | "value": "\\" 781 | }, 782 | { 783 | "type": "CHOICE", 784 | "members": [ 785 | { 786 | "type": "SYMBOL", 787 | "name": "_normal_char" 788 | }, 789 | { 790 | "type": "SYMBOL", 791 | "name": "_special_char" 792 | }, 793 | { 794 | "type": "SYMBOL", 795 | "name": "_unicode_char" 796 | }, 797 | { 798 | "type": "SYMBOL", 799 | "name": "_octal_char" 800 | } 801 | ] 802 | } 803 | ] 804 | }, 805 | "_normal_char": { 806 | "type": "PATTERN", 807 | "value": "." 808 | }, 809 | "_special_char": { 810 | "type": "CHOICE", 811 | "members": [ 812 | { 813 | "type": "STRING", 814 | "value": "newline" 815 | }, 816 | { 817 | "type": "STRING", 818 | "value": "space" 819 | }, 820 | { 821 | "type": "STRING", 822 | "value": "tab" 823 | }, 824 | { 825 | "type": "STRING", 826 | "value": "formfeed" 827 | }, 828 | { 829 | "type": "STRING", 830 | "value": "backspace" 831 | }, 832 | { 833 | "type": "STRING", 834 | "value": "return" 835 | } 836 | ] 837 | }, 838 | "_unicode_char": { 839 | "type": "SEQ", 840 | "members": [ 841 | { 842 | "type": "STRING", 843 | "value": "u" 844 | }, 845 | { 846 | "type": "SYMBOL", 847 | "name": "_hex_char" 848 | }, 849 | { 850 | "type": "SYMBOL", 851 | "name": "_hex_char" 852 | }, 853 | { 854 | "type": "SYMBOL", 855 | "name": "_hex_char" 856 | }, 857 | { 858 | "type": "SYMBOL", 859 | "name": "_hex_char" 860 | } 861 | ] 862 | }, 863 | "_hex_char": { 864 | "type": "PATTERN", 865 | "value": "[A-Fa-f0-9]" 866 | }, 867 | "_octal_char": { 868 | "type": "SEQ", 869 | "members": [ 870 | { 871 | "type": "STRING", 872 | "value": "o" 873 | }, 874 | { 875 | "type": "SYMBOL", 876 | "name": "_octal_num" 877 | } 878 | ] 879 | }, 880 | "_octal_num": { 881 | "type": "CHOICE", 882 | "members": [ 883 | { 884 | "type": "PATTERN", 885 | "value": "[0-3][0-7][0-7]" 886 | }, 887 | { 888 | "type": "PATTERN", 889 | "value": "[0-7][0-7]" 890 | }, 891 | { 892 | "type": "PATTERN", 893 | "value": "[0-7]" 894 | } 895 | ] 896 | }, 897 | "string": { 898 | "type": "SYMBOL", 899 | "name": "_string" 900 | }, 901 | "_string": { 902 | "type": "SEQ", 903 | "members": [ 904 | { 905 | "type": "STRING", 906 | "value": "\"" 907 | }, 908 | { 909 | "type": "REPEAT", 910 | "content": { 911 | "type": "CHOICE", 912 | "members": [ 913 | { 914 | "type": "STRING", 915 | "value": "\\\"" 916 | }, 917 | { 918 | "type": "PATTERN", 919 | "value": "[^\"]" 920 | } 921 | ] 922 | } 923 | }, 924 | { 925 | "type": "STRING", 926 | "value": "\"" 927 | } 928 | ] 929 | }, 930 | "regex": { 931 | "type": "SYMBOL", 932 | "name": "_regex" 933 | }, 934 | "_regex": { 935 | "type": "SEQ", 936 | "members": [ 937 | { 938 | "type": "STRING", 939 | "value": "#\"" 940 | }, 941 | { 942 | "type": "REPEAT", 943 | "content": { 944 | "type": "CHOICE", 945 | "members": [ 946 | { 947 | "type": "STRING", 948 | "value": "\\\"" 949 | }, 950 | { 951 | "type": "PATTERN", 952 | "value": "[^\"\\n\\r]" 953 | } 954 | ] 955 | } 956 | }, 957 | { 958 | "type": "STRING", 959 | "value": "\"" 960 | } 961 | ] 962 | }, 963 | "quote": { 964 | "type": "SYMBOL", 965 | "name": "_quote" 966 | }, 967 | "_quote": { 968 | "type": "CHOICE", 969 | "members": [ 970 | { 971 | "type": "SEQ", 972 | "members": [ 973 | { 974 | "type": "STRING", 975 | "value": "'" 976 | }, 977 | { 978 | "type": "SYMBOL", 979 | "name": "_anything" 980 | } 981 | ] 982 | }, 983 | { 984 | "type": "SEQ", 985 | "members": [ 986 | { 987 | "type": "STRING", 988 | "value": "(quote" 989 | }, 990 | { 991 | "type": "SYMBOL", 992 | "name": "_anything" 993 | }, 994 | { 995 | "type": "STRING", 996 | "value": ")" 997 | } 998 | ] 999 | } 1000 | ] 1001 | }, 1002 | "keyword": { 1003 | "type": "SYMBOL", 1004 | "name": "_keyword" 1005 | }, 1006 | "_keyword": { 1007 | "type": "CHOICE", 1008 | "members": [ 1009 | { 1010 | "type": "SYMBOL", 1011 | "name": "_unqualified_keyword" 1012 | }, 1013 | { 1014 | "type": "SYMBOL", 1015 | "name": "qualified_keyword" 1016 | } 1017 | ] 1018 | }, 1019 | "_unqualified_keyword": { 1020 | "type": "SEQ", 1021 | "members": [ 1022 | { 1023 | "type": "STRING", 1024 | "value": ":" 1025 | }, 1026 | { 1027 | "type": "SYMBOL", 1028 | "name": "_keyword_chars" 1029 | } 1030 | ] 1031 | }, 1032 | "qualified_keyword": { 1033 | "type": "CHOICE", 1034 | "members": [ 1035 | { 1036 | "type": "SEQ", 1037 | "members": [ 1038 | { 1039 | "type": "STRING", 1040 | "value": "::" 1041 | }, 1042 | { 1043 | "type": "SYMBOL", 1044 | "name": "_keyword_chars" 1045 | } 1046 | ] 1047 | }, 1048 | { 1049 | "type": "SEQ", 1050 | "members": [ 1051 | { 1052 | "type": "STRING", 1053 | "value": "::" 1054 | }, 1055 | { 1056 | "type": "SYMBOL", 1057 | "name": "_keyword_chars" 1058 | }, 1059 | { 1060 | "type": "STRING", 1061 | "value": "/" 1062 | }, 1063 | { 1064 | "type": "SYMBOL", 1065 | "name": "_keyword_chars" 1066 | } 1067 | ] 1068 | } 1069 | ] 1070 | }, 1071 | "_keyword_chars": { 1072 | "type": "PATTERN", 1073 | "value": "[a-zA-Z0-9\\-\\_\\!\\+\\.][a-zA-Z0-9\\-\\_\\!\\+\\.\\:\\?]*" 1074 | }, 1075 | "symbol": { 1076 | "type": "SYMBOL", 1077 | "name": "_symbol" 1078 | }, 1079 | "_symbol": { 1080 | "type": "CHOICE", 1081 | "members": [ 1082 | { 1083 | "type": "SYMBOL", 1084 | "name": "threading_macro" 1085 | }, 1086 | { 1087 | "type": "SYMBOL", 1088 | "name": "_symbol_chars" 1089 | }, 1090 | { 1091 | "type": "SYMBOL", 1092 | "name": "qualified_symbol" 1093 | } 1094 | ] 1095 | }, 1096 | "threading_macro": { 1097 | "type": "CHOICE", 1098 | "members": [ 1099 | { 1100 | "type": "STRING", 1101 | "value": "->" 1102 | }, 1103 | { 1104 | "type": "STRING", 1105 | "value": "->>" 1106 | }, 1107 | { 1108 | "type": "STRING", 1109 | "value": "as->" 1110 | }, 1111 | { 1112 | "type": "STRING", 1113 | "value": "some->" 1114 | }, 1115 | { 1116 | "type": "STRING", 1117 | "value": "some->>" 1118 | }, 1119 | { 1120 | "type": "STRING", 1121 | "value": "cond->" 1122 | }, 1123 | { 1124 | "type": "STRING", 1125 | "value": "cond->>" 1126 | } 1127 | ] 1128 | }, 1129 | "_symbol_chars": { 1130 | "type": "PATTERN", 1131 | "value": "[a-zA-Z\\*\\+\\!\\-\\_\\?][a-zA-Z0-9\\*\\+\\!\\-\\_\\?\\'\\:]*" 1132 | }, 1133 | "qualified_symbol": { 1134 | "type": "SYMBOL", 1135 | "name": "_qualified_symbol" 1136 | }, 1137 | "_qualified_symbol": { 1138 | "type": "SEQ", 1139 | "members": [ 1140 | { 1141 | "type": "SYMBOL", 1142 | "name": "_symbol_chars" 1143 | }, 1144 | { 1145 | "type": "STRING", 1146 | "value": "/" 1147 | }, 1148 | { 1149 | "type": "SYMBOL", 1150 | "name": "_symbol_chars" 1151 | } 1152 | ] 1153 | }, 1154 | "interop": { 1155 | "type": "CHOICE", 1156 | "members": [ 1157 | { 1158 | "type": "SYMBOL", 1159 | "name": "member_access" 1160 | }, 1161 | { 1162 | "type": "SYMBOL", 1163 | "name": "field_access" 1164 | }, 1165 | { 1166 | "type": "SYMBOL", 1167 | "name": "new_class" 1168 | } 1169 | ] 1170 | }, 1171 | "member_access": { 1172 | "type": "PATTERN", 1173 | "value": "\\.[a-zA-Z_]\\w*" 1174 | }, 1175 | "field_access": { 1176 | "type": "PATTERN", 1177 | "value": "\\.-[a-zA-Z_]\\w*" 1178 | }, 1179 | "new_class": { 1180 | "type": "PATTERN", 1181 | "value": "([a-zA-Z_]\\w*\\.)(\\w+\\.)*" 1182 | }, 1183 | "list": { 1184 | "type": "SYMBOL", 1185 | "name": "_list" 1186 | }, 1187 | "_list": { 1188 | "type": "SEQ", 1189 | "members": [ 1190 | { 1191 | "type": "STRING", 1192 | "value": "(" 1193 | }, 1194 | { 1195 | "type": "REPEAT", 1196 | "content": { 1197 | "type": "SYMBOL", 1198 | "name": "_anything" 1199 | } 1200 | }, 1201 | { 1202 | "type": "STRING", 1203 | "value": ")" 1204 | } 1205 | ] 1206 | }, 1207 | "vector": { 1208 | "type": "SYMBOL", 1209 | "name": "_vector" 1210 | }, 1211 | "_vector": { 1212 | "type": "SEQ", 1213 | "members": [ 1214 | { 1215 | "type": "STRING", 1216 | "value": "[" 1217 | }, 1218 | { 1219 | "type": "REPEAT", 1220 | "content": { 1221 | "type": "SYMBOL", 1222 | "name": "_anything" 1223 | } 1224 | }, 1225 | { 1226 | "type": "STRING", 1227 | "value": "]" 1228 | } 1229 | ] 1230 | }, 1231 | "hash_map": { 1232 | "type": "SYMBOL", 1233 | "name": "_hash_map" 1234 | }, 1235 | "_hash_map": { 1236 | "type": "CHOICE", 1237 | "members": [ 1238 | { 1239 | "type": "SEQ", 1240 | "members": [ 1241 | { 1242 | "type": "STRING", 1243 | "value": "{" 1244 | }, 1245 | { 1246 | "type": "REPEAT", 1247 | "content": { 1248 | "type": "SYMBOL", 1249 | "name": "_hash_map_kv_pair" 1250 | } 1251 | }, 1252 | { 1253 | "type": "STRING", 1254 | "value": "}" 1255 | } 1256 | ] 1257 | }, 1258 | { 1259 | "type": "SYMBOL", 1260 | "name": "namespace_map" 1261 | } 1262 | ] 1263 | }, 1264 | "namespace_map": { 1265 | "type": "CHOICE", 1266 | "members": [ 1267 | { 1268 | "type": "SEQ", 1269 | "members": [ 1270 | { 1271 | "type": "STRING", 1272 | "value": "#::{" 1273 | }, 1274 | { 1275 | "type": "REPEAT", 1276 | "content": { 1277 | "type": "SYMBOL", 1278 | "name": "_hash_map_kv_pair" 1279 | } 1280 | }, 1281 | { 1282 | "type": "STRING", 1283 | "value": "}" 1284 | } 1285 | ] 1286 | }, 1287 | { 1288 | "type": "SEQ", 1289 | "members": [ 1290 | { 1291 | "type": "PATTERN", 1292 | "value": "\\#\\:[a-zA-Z\\*\\+\\!\\-\\_\\?][a-zA-Z0-9\\*\\+\\!\\-\\_\\?\\'\\:]*" 1293 | }, 1294 | { 1295 | "type": "STRING", 1296 | "value": "{" 1297 | }, 1298 | { 1299 | "type": "REPEAT", 1300 | "content": { 1301 | "type": "SYMBOL", 1302 | "name": "_hash_map_kv_pair" 1303 | } 1304 | }, 1305 | { 1306 | "type": "STRING", 1307 | "value": "}" 1308 | } 1309 | ] 1310 | } 1311 | ] 1312 | }, 1313 | "_hash_map_kv_pair": { 1314 | "type": "SEQ", 1315 | "members": [ 1316 | { 1317 | "type": "SYMBOL", 1318 | "name": "_hash_map_key" 1319 | }, 1320 | { 1321 | "type": "SYMBOL", 1322 | "name": "_hash_map_value" 1323 | } 1324 | ] 1325 | }, 1326 | "_hash_map_key": { 1327 | "type": "SYMBOL", 1328 | "name": "_anything" 1329 | }, 1330 | "_hash_map_value": { 1331 | "type": "SYMBOL", 1332 | "name": "_anything" 1333 | }, 1334 | "set": { 1335 | "type": "SYMBOL", 1336 | "name": "_set" 1337 | }, 1338 | "_set": { 1339 | "type": "SEQ", 1340 | "members": [ 1341 | { 1342 | "type": "STRING", 1343 | "value": "#{" 1344 | }, 1345 | { 1346 | "type": "REPEAT", 1347 | "content": { 1348 | "type": "SYMBOL", 1349 | "name": "_anything" 1350 | } 1351 | }, 1352 | { 1353 | "type": "STRING", 1354 | "value": "}" 1355 | } 1356 | ] 1357 | }, 1358 | "comment": { 1359 | "type": "CHOICE", 1360 | "members": [ 1361 | { 1362 | "type": "SYMBOL", 1363 | "name": "semicolon" 1364 | }, 1365 | { 1366 | "type": "SYMBOL", 1367 | "name": "shebang_line" 1368 | }, 1369 | { 1370 | "type": "SYMBOL", 1371 | "name": "ignore_form" 1372 | }, 1373 | { 1374 | "type": "SYMBOL", 1375 | "name": "comment_macro" 1376 | } 1377 | ] 1378 | }, 1379 | "semicolon": { 1380 | "type": "SEQ", 1381 | "members": [ 1382 | { 1383 | "type": "STRING", 1384 | "value": ";" 1385 | }, 1386 | { 1387 | "type": "PATTERN", 1388 | "value": ".*" 1389 | } 1390 | ] 1391 | }, 1392 | "shebang_line": { 1393 | "type": "SEQ", 1394 | "members": [ 1395 | { 1396 | "type": "STRING", 1397 | "value": "#!" 1398 | }, 1399 | { 1400 | "type": "PATTERN", 1401 | "value": ".*" 1402 | } 1403 | ] 1404 | }, 1405 | "ignore_form": { 1406 | "type": "SEQ", 1407 | "members": [ 1408 | { 1409 | "type": "STRING", 1410 | "value": "#_" 1411 | }, 1412 | { 1413 | "type": "SYMBOL", 1414 | "name": "_anything" 1415 | } 1416 | ] 1417 | }, 1418 | "comment_macro": { 1419 | "type": "SEQ", 1420 | "members": [ 1421 | { 1422 | "type": "STRING", 1423 | "value": "(" 1424 | }, 1425 | { 1426 | "type": "STRING", 1427 | "value": "comment" 1428 | }, 1429 | { 1430 | "type": "REPEAT", 1431 | "content": { 1432 | "type": "SYMBOL", 1433 | "name": "_anything" 1434 | } 1435 | }, 1436 | { 1437 | "type": "STRING", 1438 | "value": ")" 1439 | } 1440 | ] 1441 | }, 1442 | "_functions": { 1443 | "type": "CHOICE", 1444 | "members": [ 1445 | { 1446 | "type": "SYMBOL", 1447 | "name": "anonymous_function" 1448 | }, 1449 | { 1450 | "type": "SYMBOL", 1451 | "name": "shorthand_function" 1452 | }, 1453 | { 1454 | "type": "SYMBOL", 1455 | "name": "defn" 1456 | } 1457 | ] 1458 | }, 1459 | "anonymous_function": { 1460 | "type": "SEQ", 1461 | "members": [ 1462 | { 1463 | "type": "STRING", 1464 | "value": "(" 1465 | }, 1466 | { 1467 | "type": "STRING", 1468 | "value": "fn" 1469 | }, 1470 | { 1471 | "type": "CHOICE", 1472 | "members": [ 1473 | { 1474 | "type": "SYMBOL", 1475 | "name": "function_name" 1476 | }, 1477 | { 1478 | "type": "BLANK" 1479 | } 1480 | ] 1481 | }, 1482 | { 1483 | "type": "SYMBOL", 1484 | "name": "_after_the_fn_name" 1485 | }, 1486 | { 1487 | "type": "STRING", 1488 | "value": ")" 1489 | } 1490 | ] 1491 | }, 1492 | "_after_the_fn_name": { 1493 | "type": "CHOICE", 1494 | "members": [ 1495 | { 1496 | "type": "SYMBOL", 1497 | "name": "_single_arity_fn" 1498 | }, 1499 | { 1500 | "type": "SYMBOL", 1501 | "name": "_multi_arity_fn" 1502 | } 1503 | ] 1504 | }, 1505 | "function_name": { 1506 | "type": "SYMBOL", 1507 | "name": "symbol" 1508 | }, 1509 | "_single_arity_fn": { 1510 | "type": "SEQ", 1511 | "members": [ 1512 | { 1513 | "type": "SYMBOL", 1514 | "name": "params" 1515 | }, 1516 | { 1517 | "type": "CHOICE", 1518 | "members": [ 1519 | { 1520 | "type": "SYMBOL", 1521 | "name": "function_body" 1522 | }, 1523 | { 1524 | "type": "BLANK" 1525 | } 1526 | ] 1527 | } 1528 | ] 1529 | }, 1530 | "_multi_arity_fn": { 1531 | "type": "REPEAT1", 1532 | "content": { 1533 | "type": "SEQ", 1534 | "members": [ 1535 | { 1536 | "type": "STRING", 1537 | "value": "(" 1538 | }, 1539 | { 1540 | "type": "SYMBOL", 1541 | "name": "_single_arity_fn" 1542 | }, 1543 | { 1544 | "type": "STRING", 1545 | "value": ")" 1546 | } 1547 | ] 1548 | } 1549 | }, 1550 | "function_body": { 1551 | "type": "REPEAT1", 1552 | "content": { 1553 | "type": "SYMBOL", 1554 | "name": "_anything" 1555 | } 1556 | }, 1557 | "params": { 1558 | "type": "SYMBOL", 1559 | "name": "vector" 1560 | }, 1561 | "shorthand_function": { 1562 | "type": "SEQ", 1563 | "members": [ 1564 | { 1565 | "type": "STRING", 1566 | "value": "#(" 1567 | }, 1568 | { 1569 | "type": "REPEAT", 1570 | "content": { 1571 | "type": "SYMBOL", 1572 | "name": "_anything" 1573 | } 1574 | }, 1575 | { 1576 | "type": "STRING", 1577 | "value": ")" 1578 | } 1579 | ] 1580 | }, 1581 | "shorthand_function_arg": { 1582 | "type": "PATTERN", 1583 | "value": "%[1-9&]*" 1584 | }, 1585 | "defn": { 1586 | "type": "SEQ", 1587 | "members": [ 1588 | { 1589 | "type": "STRING", 1590 | "value": "(" 1591 | }, 1592 | { 1593 | "type": "CHOICE", 1594 | "members": [ 1595 | { 1596 | "type": "STRING", 1597 | "value": "defn" 1598 | }, 1599 | { 1600 | "type": "STRING", 1601 | "value": "defn-" 1602 | } 1603 | ] 1604 | }, 1605 | { 1606 | "type": "CHOICE", 1607 | "members": [ 1608 | { 1609 | "type": "SYMBOL", 1610 | "name": "metadata" 1611 | }, 1612 | { 1613 | "type": "BLANK" 1614 | } 1615 | ] 1616 | }, 1617 | { 1618 | "type": "SYMBOL", 1619 | "name": "function_name" 1620 | }, 1621 | { 1622 | "type": "CHOICE", 1623 | "members": [ 1624 | { 1625 | "type": "SYMBOL", 1626 | "name": "docstring" 1627 | }, 1628 | { 1629 | "type": "BLANK" 1630 | } 1631 | ] 1632 | }, 1633 | { 1634 | "type": "CHOICE", 1635 | "members": [ 1636 | { 1637 | "type": "SYMBOL", 1638 | "name": "attr_map" 1639 | }, 1640 | { 1641 | "type": "BLANK" 1642 | } 1643 | ] 1644 | }, 1645 | { 1646 | "type": "SYMBOL", 1647 | "name": "_after_the_fn_name" 1648 | }, 1649 | { 1650 | "type": "STRING", 1651 | "value": ")" 1652 | } 1653 | ] 1654 | }, 1655 | "docstring": { 1656 | "type": "SYMBOL", 1657 | "name": "string" 1658 | }, 1659 | "attr_map": { 1660 | "type": "SYMBOL", 1661 | "name": "hash_map" 1662 | }, 1663 | "metadata": { 1664 | "type": "CHOICE", 1665 | "members": [ 1666 | { 1667 | "type": "REPEAT1", 1668 | "content": { 1669 | "type": "SYMBOL", 1670 | "name": "metadata_shorthand" 1671 | } 1672 | }, 1673 | { 1674 | "type": "SYMBOL", 1675 | "name": "_metadata_map" 1676 | } 1677 | ] 1678 | }, 1679 | "_metadata_map": { 1680 | "type": "SEQ", 1681 | "members": [ 1682 | { 1683 | "type": "STRING", 1684 | "value": "^" 1685 | }, 1686 | { 1687 | "type": "SYMBOL", 1688 | "name": "hash_map" 1689 | } 1690 | ] 1691 | }, 1692 | "metadata_shorthand": { 1693 | "type": "CHOICE", 1694 | "members": [ 1695 | { 1696 | "type": "SEQ", 1697 | "members": [ 1698 | { 1699 | "type": "STRING", 1700 | "value": "^:" 1701 | }, 1702 | { 1703 | "type": "SYMBOL", 1704 | "name": "_keyword_chars" 1705 | } 1706 | ] 1707 | }, 1708 | { 1709 | "type": "SEQ", 1710 | "members": [ 1711 | { 1712 | "type": "STRING", 1713 | "value": "^\"" 1714 | }, 1715 | { 1716 | "type": "REPEAT", 1717 | "content": { 1718 | "type": "CHOICE", 1719 | "members": [ 1720 | { 1721 | "type": "STRING", 1722 | "value": "\\\"" 1723 | }, 1724 | { 1725 | "type": "PATTERN", 1726 | "value": "[^\"]" 1727 | } 1728 | ] 1729 | } 1730 | }, 1731 | { 1732 | "type": "STRING", 1733 | "value": "\"" 1734 | } 1735 | ] 1736 | }, 1737 | { 1738 | "type": "SEQ", 1739 | "members": [ 1740 | { 1741 | "type": "STRING", 1742 | "value": "^" 1743 | }, 1744 | { 1745 | "type": "SYMBOL", 1746 | "name": "_symbol_chars" 1747 | } 1748 | ] 1749 | } 1750 | ] 1751 | }, 1752 | "syntax_quote": { 1753 | "type": "SEQ", 1754 | "members": [ 1755 | { 1756 | "type": "STRING", 1757 | "value": "`" 1758 | }, 1759 | { 1760 | "type": "SYMBOL", 1761 | "name": "_anything" 1762 | } 1763 | ] 1764 | }, 1765 | "var_quote": { 1766 | "type": "SEQ", 1767 | "members": [ 1768 | { 1769 | "type": "STRING", 1770 | "value": "#'" 1771 | }, 1772 | { 1773 | "type": "SYMBOL", 1774 | "name": "symbol" 1775 | } 1776 | ] 1777 | }, 1778 | "unquote": { 1779 | "type": "SEQ", 1780 | "members": [ 1781 | { 1782 | "type": "STRING", 1783 | "value": "~" 1784 | }, 1785 | { 1786 | "type": "SYMBOL", 1787 | "name": "_anything" 1788 | } 1789 | ] 1790 | }, 1791 | "unquote_splice": { 1792 | "type": "SEQ", 1793 | "members": [ 1794 | { 1795 | "type": "STRING", 1796 | "value": "~@" 1797 | }, 1798 | { 1799 | "type": "SYMBOL", 1800 | "name": "_anything" 1801 | } 1802 | ] 1803 | }, 1804 | "gensym": { 1805 | "type": "PATTERN", 1806 | "value": "[a-zA-Z\\*\\+\\!\\-\\_\\?][a-zA-Z0-9\\*\\+\\!\\-\\_\\?\\'\\:]*\\#" 1807 | }, 1808 | "deref": { 1809 | "type": "SEQ", 1810 | "members": [ 1811 | { 1812 | "type": "STRING", 1813 | "value": "@" 1814 | }, 1815 | { 1816 | "type": "CHOICE", 1817 | "members": [ 1818 | { 1819 | "type": "SYMBOL", 1820 | "name": "symbol" 1821 | }, 1822 | { 1823 | "type": "SYMBOL", 1824 | "name": "list" 1825 | } 1826 | ] 1827 | } 1828 | ] 1829 | }, 1830 | "tagged_literal": { 1831 | "type": "SEQ", 1832 | "members": [ 1833 | { 1834 | "type": "STRING", 1835 | "value": "#" 1836 | }, 1837 | { 1838 | "type": "CHOICE", 1839 | "members": [ 1840 | { 1841 | "type": "SYMBOL", 1842 | "name": "_symbol_chars" 1843 | }, 1844 | { 1845 | "type": "SYMBOL", 1846 | "name": "_qualified_symbol" 1847 | } 1848 | ] 1849 | } 1850 | ] 1851 | }, 1852 | "reader_conditional": { 1853 | "type": "SEQ", 1854 | "members": [ 1855 | { 1856 | "type": "SYMBOL", 1857 | "name": "_reader_conditional_symbol" 1858 | }, 1859 | { 1860 | "type": "STRING", 1861 | "value": "(" 1862 | }, 1863 | { 1864 | "type": "REPEAT", 1865 | "content": { 1866 | "type": "SEQ", 1867 | "members": [ 1868 | { 1869 | "type": "SYMBOL", 1870 | "name": "keyword" 1871 | }, 1872 | { 1873 | "type": "SYMBOL", 1874 | "name": "_anything" 1875 | } 1876 | ] 1877 | } 1878 | }, 1879 | { 1880 | "type": "STRING", 1881 | "value": ")" 1882 | } 1883 | ] 1884 | }, 1885 | "_reader_conditional_symbol": { 1886 | "type": "CHOICE", 1887 | "members": [ 1888 | { 1889 | "type": "STRING", 1890 | "value": "#?" 1891 | }, 1892 | { 1893 | "type": "STRING", 1894 | "value": "#?@" 1895 | } 1896 | ] 1897 | } 1898 | }, 1899 | "extras": [ 1900 | { 1901 | "type": "PATTERN", 1902 | "value": "(\\s|,)" 1903 | } 1904 | ], 1905 | "conflicts": [], 1906 | "externals": [], 1907 | "inline": [] 1908 | } --------------------------------------------------------------------------------