├── dist └── index.d.ts ├── .npmignore ├── src ├── index.js ├── props.js └── clojure.grammar ├── .gitignore ├── rollup.config.js ├── .github └── workflows │ └── main.yml ├── README.md ├── test ├── test-clojure.js └── expression.txt ├── CHANGELOG.md ├── LICENSE └── package.json /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import {Parser} from "@lezer/lr" 2 | 3 | export const parser: Parser 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | .idea 3 | debug 4 | .github 5 | nextjournal-lezer-clojure-*.tgz 6 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import {parser} from "./parser" 2 | import * as props from "./props" 3 | 4 | export {parser, props} 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /src/parser.* 3 | .tern-* 4 | /dist 5 | .idea 6 | debug 7 | nextjournal-lezer-clojure-*.tgz 8 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import nodeResolve from "@rollup/plugin-node-resolve" 2 | 3 | export default { 4 | input: "./src/index.js", 5 | output: [{ 6 | format: "cjs", 7 | file: "./dist/index.cjs" 8 | }, { 9 | format: "es", 10 | file: "./dist/index.es.js" 11 | }], 12 | external(id) { return !/^[\.\/]/.test(id) }, 13 | plugins: [ 14 | nodeResolve() 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/props.js: -------------------------------------------------------------------------------- 1 | import {NodeProp} from "@lezer/common" 2 | 3 | // TODO: naïvely restored to previoius NodeProp.flag() behaviour. Can we do any better? 4 | let flag = () => new NodeProp({deserialize: str => true}) 5 | 6 | export const coll = flag() 7 | export const prefixColl = flag() 8 | export const prefixEdge = flag() 9 | export const sameEdge = flag() 10 | export const prefixContainer = flag() 11 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: push 3 | jobs: 4 | test: 5 | name: Test 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout 9 | uses: actions/checkout@v2 10 | 11 | - name: Setup NodeJS 12 | uses: actions/setup-node@v3 13 | 14 | - name: NPM Install 15 | run: npm install 16 | 17 | - name: Run tests 18 | run: npm run build-debug && npm run test 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @nextjournal/lezer-clojure [![NPM version](https://img.shields.io/npm/v/@nextjournal/lezer-clojure.svg)](https://www.npmjs.com/package/@nextjournal/lezer-clojure) 2 | 3 | This is a Clojure grammar for the 4 | [lezer](https://lezer.codemirror.net/) parser system. 5 | 6 | The code is licensed under an ISC license. 7 | 8 | # Dev 9 | 10 | To watch & test, with [entr](http://eradman.com/entrproject/) installed run `npm run watch` 11 | 12 | # Previous Package Name 13 | 14 | This package has been previously released (unscoped) as [lezer-clojure](https://www.npmjs.com/package/lezer-clojure). 15 | -------------------------------------------------------------------------------- /test/test-clojure.js: -------------------------------------------------------------------------------- 1 | import {parser} from "../dist/index.es.js" 2 | import {fileTests} from "@lezer/generator/dist/test" 3 | 4 | import * as fs from "fs" 5 | import * as path from "path" 6 | import { fileURLToPath } from 'url'; 7 | let caseDir = path.dirname(fileURLToPath(import.meta.url)) 8 | 9 | for (let file of fs.readdirSync(caseDir)) { 10 | if (!/\.txt$/.test(file)) continue 11 | 12 | let name = /^[^\.]*/.exec(file)[0] 13 | describe(name, () => { 14 | for (let {name, run} of fileTests(fs.readFileSync(path.join(caseDir, file), "utf8"), file)) 15 | it(name, () => run(parser)) 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.0.0-rc.2 (2022-07-06) 4 | * Add namespace forms 5 | 6 | ## 1.0.0-rc.1 (2022-07-05) 7 | * Reintroduce constructor call Syntax 8 | * Refine allowed Reader Tags 9 | * Make skip-next-form play well with prefixed expressions 10 | 11 | ## 1.0.0-rc.0 (2022-06-30) 12 | * Upgrade to Lezer parser to v1.0.0 13 | * Remove constructor call syntax 14 | * Improve char detection (#17) 15 | 16 | ## 0.1.10 (2020-12-07) 17 | * Upgrade Lezer to v0.13 18 | * Extend grammar to include more #-prefixed expressions (#5) 19 | * Deflike expressions with metadata 20 | * Operator for first element in a list 21 | 22 | ## 0.1.0 (2020-10-20) 23 | * First release 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Nextjournal GmbH. 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose 4 | with or without fee is hereby granted, provided that the above copyright notice 5 | and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 9 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 11 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 12 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 13 | THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@nextjournal/lezer-clojure", 3 | "version": "1.0.0", 4 | "description": "lezer-based Clojure(Script) grammar", 5 | "main": "dist/index.cjs", 6 | "author": "Martin Kavalar ", 7 | "license": "ISC", 8 | "type": "module", 9 | "exports": { 10 | "import": "./dist/index.es.js", 11 | "require": "./dist/index.cjs" 12 | }, 13 | "module": "dist/index.es.js", 14 | "types": "dist/index.d.ts", 15 | "devDependencies": { 16 | "@rollup/plugin-node-resolve": "^13.3.0", 17 | "@lezer/generator": "^1.0.0", 18 | "mocha": "^10.0.0", 19 | "rollup": "^2.75.7" 20 | }, 21 | "dependencies": { 22 | "@lezer/lr": "^1.0.0" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "git+https://github.com/nextjournal/lezer-clojure.git" 27 | }, 28 | "scripts": { 29 | "build": "lezer-generator src/clojure.grammar -o src/parser && rollup -c", 30 | "build-debug": "lezer-generator src/clojure.grammar --names -o src/parser && rollup -c", 31 | "prepare": "npm run build", 32 | "test": "mocha --experimental-modules test/test-*.js", 33 | "on-change": "npm run build && npm run test", 34 | "watch": "git ls-files | entr npm run on-change" 35 | }, 36 | "bugs": { 37 | "url": "https://github.com/nextjournal/lezer-clojure/issues" 38 | }, 39 | "homepage": "https://github.com/nextjournal/lezer-clojure#readme", 40 | "directories": { 41 | "test": "test" 42 | }, 43 | "keywords": [ 44 | "lezer", 45 | "clojure" 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /src/clojure.grammar: -------------------------------------------------------------------------------- 1 | @external prop prefixColl from "./props" 2 | @external prop coll from "./props" 3 | @external prop prefixEdge from "./props" 4 | @external prop sameEdge from "./props" 5 | @external prop prefixContainer from "./props" 6 | 7 | @top Program { expression* } 8 | 9 | @skip { whitespace | LineComment | Discard } 10 | 11 | expression { Boolean | Nil | Deref | Quote | SyntaxQuote | Unquote | UnquoteSplice | Symbol | Number | Keyword | List | Vector | Map | String | Character | Set | NamespacedMap | RegExp | Var | ReaderConditional | SymbolicValue | AnonymousFunction | Meta | TaggedLiteral | ConstructorCall } 12 | Discard { "#_" expression } 13 | @precedence { docString @left, operator @left, meta @right} 14 | 15 | listContents { 16 | defList { defLikeWithMeta varNameWithMeta (DocString expression+ | expression+)? } | 17 | nsList { nsWithMeta varNameWithMeta (DocString expression* | expression*) } | 18 | anyList { operatorWithMeta? expression* } 19 | } 20 | 21 | DocString { !docString String } 22 | List[coll] { "(" listContents ")" } 23 | Vector[coll] { "[" expression* "]" } 24 | Map[coll] { "{" expression* "}" } 25 | VarName { Symbol } 26 | 27 | @skip {} { 28 | ReaderTag { "#" readerTagIdent } 29 | ConstructorPrefix[prefixEdge] { "#" qualifiedJavaIdent } 30 | 31 | SymbolicValue { "##" ident } 32 | Set[prefixColl] { "#" Map } 33 | AnonymousFunction[prefixColl] { "#" List } 34 | 35 | KeywordPrefix[prefixEdge] { "#" keyword } 36 | NamespacedMap[prefixColl] { KeywordPrefix Map } 37 | 38 | RegExp[prefixColl] { "#" String } 39 | Var[prefixColl] { "#'" Symbol } 40 | ReaderConditional[prefixColl] { "#?" (List | Deref) } 41 | ReaderMetadata[prefixColl] { "#^" expression } 42 | Metadata[prefixColl] { "^" expression } 43 | String { '"' StringContent? '"' } 44 | } 45 | 46 | Meta[prefixContainer] { (Metadata | ReaderMetadata) !meta t } 47 | TaggedLiteral[prefixContainer] { ReaderTag t } 48 | 49 | // https://clojure.org/reference/reader#_deftype_defrecord_and_constructor_calls_version_1_3_and_later 50 | ConstructorCall[prefixContainer] { ConstructorPrefix (Map | Vector) } 51 | 52 | Deref[prefixColl] { "@" expression } 53 | Quote[prefixColl] { "'" expression } 54 | SyntaxQuote[prefixColl] { "`" expression } 55 | Unquote[prefixColl] { "~" expression } 56 | UnquoteSplice[prefixColl] { "~@" expression } 57 | operatorWithMeta { Operator | Meta } 58 | defLikeWithMeta { DefLike | Meta } 59 | nsWithMeta { NS | Meta } 60 | varNameWithMeta { VarName | Meta } 61 | 62 | Operator { !operator Symbol } 63 | 64 | @tokens { 65 | 66 | 67 | "[" 68 | "{" 69 | "(" 70 | 71 | "#"[prefixEdge] 72 | "##"[prefixEdge] 73 | "#'"[prefixEdge] 74 | "#?"[prefixEdge] 75 | "#^"[prefixEdge] 76 | "#_"[prefixEdge] 77 | 78 | '"'[sameEdge, closedBy='"', openedBy='"'] 79 | "'"[prefixEdge] 80 | "`"[prefixEdge] 81 | "~"[prefixEdge] 82 | "~@"[prefixEdge] 83 | "^"[prefixEdge] 84 | "@"[prefixEdge] 85 | 86 | 87 | "]" 88 | "}" 89 | ")" 90 | 91 | whitespace { (std.whitespace | ",")+ } 92 | 93 | LineComment { ";" ![\n]* } 94 | 95 | // https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.8 96 | // class or constructor names 97 | javaIdentStart { std.asciiLetter | "_" | "$" | $[\u{a1}-\u{10ff}] } 98 | javaIdentChar { javaIdentStart | std.digit } 99 | javaIdent { javaIdentStart javaIdentChar* } 100 | qualifiedJavaIdent { javaIdent ("." javaIdent)+ } 101 | 102 | // reader tags cannot contain dots 103 | readerTagIdentStart { std.asciiLetter | $[<>&%_=?!*+\-$\u{a1}-\u{10ff}] } 104 | readerTagIdentChar { readerTagIdentStart | "/" | std.digit } 105 | readerTagIdent { readerTagIdentStart readerTagIdentChar* } 106 | 107 | identStart { std.asciiLetter | $[<>&%._=?!*+\-$\u{a1}-\u{10ff}/] } 108 | identChar { identStart | std.digit | ":" | "'" | "#" | "/"} 109 | ident { identStart identChar* } 110 | Symbol { ident } 111 | 112 | keyword { ":" ":"? ident? } // the invalid token :: can also be considered as a keyword 113 | Keyword { keyword } 114 | 115 | Number { 116 | ("+" | "-")? (std.digit+ ("." std.digit* "M"?)? | "." std.digit+) (("e" | "E") ("+" | "-")? std.digit+ "M"?)? | 117 | ("+" | "-")? std.digit+ ("M" | "N") | 118 | ("+" | "-")? std.digit+ "/" std.digit+ | 119 | ("+" | "-")? "0x" (std.digit | $[a-fA-F])+ | 120 | "0b" $[01]+ | 121 | "0o" $[0-7]+ 122 | } 123 | @precedence { Number, qualifiedJavaIdent, readerTagIdent, Symbol } 124 | 125 | StringContent { 126 | (!["] | "\\" _)+ 127 | } 128 | 129 | unicodeChar { "u" $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F]} 130 | octalChar { "o" $[0-3]? $[0-7] $[0-7]? } 131 | specialChar { "newline" | "space" | "tab" | "formfeed" | "backspace" | "return" } 132 | singleChar { ![\n] } 133 | Character { "\\" ( octalChar | unicodeChar | singleChar | specialChar ) } 134 | 135 | } 136 | 137 | Boolean { @specialize } 138 | Nil { @specialize } 139 | DefLike[@dynamicPrecedence=1] { @extend } 140 | NS[@dynamicPrecedence=2] { @extend } 141 | 142 | @detectDelim 143 | -------------------------------------------------------------------------------- /test/expression.txt: -------------------------------------------------------------------------------- 1 | # Add 2 | (+ 1 2) 3 | ==> 4 | Program(List(Operator(Symbol),Number,Number)) 5 | 6 | # Numbers 7 | 42 +42 -42 8 | ==> 9 | Program(Number,Number,Number) 10 | 11 | # Number BigInt 12 | 42N +42N -42N 0 0N 13 | ==> 14 | Program(Number,Number,Number,Number,Number) 15 | 16 | # Number Leading Zero 17 | 042 +042 -042 18 | ==> 19 | Program(Number,Number,Number) 20 | 21 | # Number BigInt 22 | 9223372036854775808 -9223372036854775808 10000000000000000000000000000000000000000000000000 -10000000000000000000000000000000000000000000000000 23 | ==> 24 | Program(Number,Number,Number,Number) 25 | 26 | # Number Exponentials 27 | 0x42e +0x42e -0x42e 28 | ==> 29 | Program(Number,Number,Number) 30 | 31 | # Number Floating 32 | 42.23 +42.23 -42.23 33 | ==> 34 | Program(Number,Number,Number) 35 | 36 | # Number Floating 37 | 42.23 +42.23 -42.23 38 | ==> 39 | Program(Number,Number,Number) 40 | 41 | # Number BigDecimal 42 | 42.23M +42.23M -42.23M 43 | ==> 44 | Program(Number,Number,Number) 45 | 46 | # Number BigDecimal 2 47 | 1.0M +1.0M -1.0M +0.0M +0.M 0M -0.0M -0.M 48 | ==> 49 | Program(Number,Number,Number,Number,Number,Number,Number,Number) 50 | 51 | # Number Floating e 52 | 42.2e3 +42.2e+3 -42.2e-3 53 | ==> 54 | Program(Number,Number,Number) 55 | 56 | # Number Floating e3M 57 | 42.2e3M +42.2e+3M -42.2e-3M 58 | ==> 59 | Program(Number,Number,Number) 60 | 61 | # Number Double 62 | +1.0e+1 +1.e+1 +1e+1 +1.0e1 +1.e1 +1e1 63 | ==> 64 | Program(Number,Number,Number,Number,Number,Number) 65 | 66 | # Number Double 2 67 | +1.0e-1 +1.e-1 +1e-1 -1.0e1 -1.e1 -1e1 -1.0e-1 -1.e-1 -1e-1 68 | ==> 69 | Program(Number,Number,Number,Number,Number,Number,Number,Number,Number) 70 | 71 | # Number Double 3 72 | +1.0 +1. 1.0 1. +0.0 0.0 -0.0 +0. -0. -1.0 -1. 73 | ==> 74 | Program(Number,Number,Number,Number,Number,Number,Number,Number,Number,Number,Number) 75 | 76 | # Number Ratio 77 | 4/2 +4/2 -4/2 78 | ==> 79 | Program(Number,Number,Number) 80 | 81 | # Literals 82 | () {} [] 83 | ==> 84 | Program(List, Map, Vector) 85 | 86 | # Sharps 87 | #{} #"\d" #:kw{} #::{} 88 | ==> 89 | Program(Set(Map), RegExp(String(StringContent)), NamespacedMap(KeywordPrefix,Map), NamespacedMap(KeywordPrefix,Map)) 90 | 91 | # Symbols 92 | f1 foo/bar *+!-_? abc:def:ghi abc.def/ghi abc/def.ghi abc:def/ghi:jkl.mno a/ / 93 | ==> 94 | Program(Symbol,Symbol,Symbol,Symbol,Symbol,Symbol,Symbol,Symbol,Symbol) 95 | 96 | # Keywords 97 | :hi :hi/ho ::ho ::hi/ho :*+!-_? :abc:def:ghi 98 | ==> 99 | Program(Keyword,Keyword,Keyword,Keyword,Keyword,Keyword) 100 | 101 | # Boolean 102 | true false 103 | ==> 104 | Program(Boolean,Boolean) 105 | 106 | # Strings 107 | "hello" "and 108 | multiline" 109 | ==> 110 | Program(String(StringContent), String(StringContent)) 111 | 112 | # Nil 113 | nil 114 | ==> 115 | Program(Nil) 116 | 117 | # simple chars 118 | \a \b \n \r \s 119 | ==> 120 | Program(Character,Character,Character,Character,Character) 121 | 122 | # other chars 123 | \@ \; \[ \) \# \$ \' \\ \" 124 | ==> 125 | Program(Character,Character,Character,Character,Character,Character,Character,Character,Character) 126 | 127 | # unicode 128 | \u0194 \uFFFF 129 | ==> 130 | Program(Character,Character) 131 | 132 | # octal 133 | \o123 \o372 \o0 134 | ==> 135 | Program(Character, Character, Character) 136 | 137 | # special-case chars 138 | \newline \space \backspace \tab \formfeed \return 139 | ==> 140 | Program(Character,Character,Character,Character,Character,Character) 141 | 142 | # Line comments 143 | ;; comment 144 | ;; another comment 145 | ==> 146 | Program(LineComment, LineComment) 147 | 148 | # Discard next form 149 | :hello #_ :ignored 150 | ==> 151 | Program(Keyword, Discard(Keyword)) 152 | 153 | # Discard next two forms 154 | #_#_ :ignored also-ignored "not-ignored" 155 | ==> 156 | Program(Discard(Discard(Keyword), Symbol), String(StringContent)) 157 | 158 | # Discarded Tagged Literal 159 | #_#hello/world [1] :foo 160 | ==> 161 | Program(Discard("#_", TaggedLiteral(ReaderTag("#") Vector("[",Number,"]"))), Keyword) 162 | 163 | # Deref 164 | @hello 165 | ==> 166 | Program(Deref(Symbol)) 167 | 168 | # Quote 169 | 'bar 170 | ==> Program(Quote(Symbol)) 171 | 172 | # SyntaxQuote 173 | `(1) 174 | ==> Program(SyntaxQuote(List(Number))) 175 | 176 | # SyntaxQuote Unquote 177 | `(vector ~x) 178 | ==> Program(SyntaxQuote(List(Operator(Symbol),Unquote(Symbol)))) 179 | 180 | # SyntaxQuote Unquote-Splice 181 | `(~@x) 182 | ==> Program(SyntaxQuote(List(UnquoteSplice(Symbol)))) 183 | 184 | # Meta 185 | ^{:hello :world} :my-expr #^String :more ^:dynamic :test 186 | ==> Program(Meta(Metadata(Map(Keyword,Keyword)),Keyword),Meta(ReaderMetadata(Symbol),Keyword),Meta(Metadata(Keyword),Keyword)) 187 | 188 | # Meta Multiple 189 | ^:dynamic ^ints obj 190 | ==> Program(Meta(Metadata(Keyword),Meta(Metadata(Symbol),Symbol))) 191 | 192 | # Meta Operator 193 | (^:dynamic + 1) 194 | ==> Program(List(Meta(Metadata(Keyword),Operator(Symbol)), Number)) 195 | 196 | # Meta Multiple Operator 197 | (^:dynamic ^ints + 1 2) 198 | ==> Program(List(Meta(Metadata(Keyword),Meta(Metadata(Symbol),Operator(Symbol))), Number, Number)) 199 | 200 | 201 | # Var 202 | #'hello 203 | ==> Program(Var(Symbol)) 204 | 205 | # Reader Conditional 206 | #?(:cljs "hello") #?@(:cljs ["hello"]) 207 | ==> Program(ReaderConditional("#?", List(Keyword,String(StringContent))),ReaderConditional(Deref(List(Keyword,Vector(String(StringContent)))))) 208 | 209 | # Built-in Tagged Literal 210 | #uuid "31d20ceb-c7c2-40bb-9bd5-1e1e05f57ea1" 211 | ==> Program(TaggedLiteral(ReaderTag("#"), String(StringContent))) 212 | 213 | # Reader Tag with namespace 214 | #my/foo [1] 215 | ==> Program(TaggedLiteral(ReaderTag("#"),Vector("[",Number,"]"))) 216 | 217 | # Tagged Literal with multiple tags 218 | #tag/one #tag/two [] 219 | ==> Program(TaggedLiteral(ReaderTag("#"), TaggedLiteral(ReaderTag("#"), Vector))) 220 | 221 | # Symbolic Value 222 | ##Inf, ##-Inf 223 | ==> Program(SymbolicValue, SymbolicValue) 224 | 225 | # Anonymous Function 226 | #(inc %) 227 | ==> Program(AnonymousFunction("#", List(Operator(Symbol), Symbol))) 228 | 229 | # Unbalanced map 230 | {:x} 231 | ==> Program(Map(Keyword)) 232 | 233 | # Gensym 234 | sym# 235 | ==> Program(Symbol) 236 | 237 | # Earmuffs and channel macros 238 | *sym* >! Program(Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol, Symbol) 240 | 241 | # Def 242 | (def foo) 243 | ==> Program(List("(",DefLike,VarName(Symbol),")")) 244 | 245 | # Def + String 246 | (defn foo "string") 247 | ==> Program(List(DefLike,VarName(Symbol),String(StringContent))) 248 | 249 | # Def + DocString 250 | (defn foo "string" :bar) 251 | ==> Program(List(DefLike,VarName(Symbol),DocString(String(StringContent)),Keyword)) 252 | 253 | # Meta Multiple Def 254 | (^:hello ^world def foo) 255 | ==> Program(List(Meta(Metadata(Keyword),Meta(Metadata(Symbol),DefLike)), VarName(Symbol))) 256 | 257 | # Meta Multiple VarName 258 | (def ^:static ^clojure.lang.ChunkBuffer chunk-buffer) 259 | ==> Program(List(DefLike,Meta(Metadata(Keyword),Meta(Metadata(Symbol),VarName(Symbol))))) 260 | 261 | # Def Defn 262 | (def defn (fn [])) 263 | ==> Program(List(DefLike,VarName(Symbol),List(Operator(Symbol),Vector))) 264 | 265 | # Defonce 266 | (defonce default "doc" default) 267 | ==> Program(List(DefLike,VarName(Symbol),DocString(String(StringContent)),Symbol)) 268 | 269 | # Def Default 270 | (def default bar) 271 | ==> Program(List(DefLike,VarName(Symbol),Symbol)) 272 | 273 | # Defmacro 274 | (defmacro ..) 275 | ==> Program(List(DefLike,VarName(Symbol))) 276 | 277 | # Division 278 | / 279 | ==> Program(Symbol) 280 | 281 | # Constructor Call with Vector 282 | #my.klass_or_type_or_record[:a :b :c] 283 | ==> Program(ConstructorCall(ConstructorPrefix("#"),Vector("[",Keyword,Keyword,Keyword,"]"))) 284 | 285 | # Constructor Call with Vector 286 | #my.γωνστρυγτωρ[:a :b :c] 287 | ==> Program(ConstructorCall(ConstructorPrefix("#"),Vector("[",Keyword,Keyword,Keyword,"]"))) 288 | 289 | # Constructor Call with Record 290 | #my.record{:a 1, :b 2} 291 | ==> Program(ConstructorCall(ConstructorPrefix("#"),Map("{",Keyword,Number,Keyword,Number,"}"))) 292 | 293 | # Constructor with Reader Tags 294 | #read/this #my.constructor [] #read/that #my.record {} 295 | ==> Program(TaggedLiteral(ReaderTag("#"),ConstructorCall(ConstructorPrefix("#"),Vector("[","]"))), 296 | TaggedLiteral(ReaderTag("#"),ConstructorCall(ConstructorPrefix("#"),Map("{","}")))) 297 | 298 | # Namespace Form 299 | (ns some.ns.name 300 | "This is a docstring" 301 | (:require [foo.bar] 302 | [ban.dan])) 303 | ==> Program(List(NS,VarName(Symbol),DocString(String(StringContent)),List(Keyword,Vector(Symbol),Vector(Symbol)))) 304 | 305 | 306 | # Namespace Form with Meta 307 | (ns ^:reload some.ns.name 308 | "This is a docstring" 309 | (:require [foo.bar] 310 | [ban.dan])) 311 | ==> Program(List(NS,Meta(Metadata(Keyword), VarName(Symbol)),DocString(String(StringContent)),List(Keyword,Vector(Symbol),Vector(Symbol)))) 312 | 313 | 314 | # Namespace with just a docstring 315 | (ns simple.ns "docstring") 316 | 317 | ==> Program(List(NS, VarName(Symbol), DocString(String(StringContent)))) 318 | 319 | # Namespace simplest form 320 | (ns very.simple) 321 | ==> Program(List(NS, VarName(Symbol))) 322 | 323 | # Namespace with attributes 324 | (ns cljdocs.example.core 325 | "This is a doc string, FYI :D" 326 | {:author "John Doe"}) 327 | ==> Program(List(NS, VarName(Symbol), DocString(String(StringContent)), Map(Keyword, String(StringContent)))) 328 | --------------------------------------------------------------------------------