@external prop prefixColl from "./props" @external prop coll from "./props" @external prop prefixEdge from "./props" @external prop sameEdge from "./props" @external prop prefixContainer from "./props" @top Program { expression* } @skip { whitespace | LineComment | Discard } 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 } Discard { "#_" expression } @precedence { docString @left, operator @left, meta @right} listContents { defList { defLikeWithMeta varNameWithMeta (DocString expression+ | expression+)? } | nsList { nsWithMeta varNameWithMeta (DocString expression* | expression*) } | anyList { operatorWithMeta? expression* } } DocString { !docString String } List[coll] { "(" listContents ")" } Vector[coll] { "[" expression* "]" } Map[coll] { "{" expression* "}" } VarName { Symbol } @skip {} { ReaderTag { "#" readerTagIdent } ConstructorPrefix[prefixEdge] { "#" qualifiedJavaIdent } SymbolicValue { "##" ident } Set[prefixColl] { "#" Map } AnonymousFunction[prefixColl] { "#" List } KeywordPrefix[prefixEdge] { "#" keyword } NamespacedMap[prefixColl] { KeywordPrefix Map } RegExp[prefixColl] { "#" String } Var[prefixColl] { "#'" Symbol } ReaderConditional[prefixColl] { "#?" (List | Deref) } ReaderMetadata[prefixColl] { "#^" expression } Metadata[prefixColl] { "^" expression } String { '"' StringContent? '"' } } Meta[prefixContainer] { (Metadata | ReaderMetadata) !meta t } TaggedLiteral[prefixContainer] { ReaderTag t } // https://clojure.org/reference/reader#_deftype_defrecord_and_constructor_calls_version_1_3_and_later ConstructorCall[prefixContainer] { ConstructorPrefix (Map | Vector) } Deref[prefixColl] { "@" expression } Quote[prefixColl] { "'" expression } SyntaxQuote[prefixColl] { "`" expression } Unquote[prefixColl] { "~" expression } UnquoteSplice[prefixColl] { "~@" expression } operatorWithMeta { Operator | Meta } defLikeWithMeta { DefLike | Meta } nsWithMeta { NS | Meta } varNameWithMeta { VarName | Meta } Operator { !operator Symbol } @tokens { "[" "{" "(" "#"[prefixEdge] "##"[prefixEdge] "#'"[prefixEdge] "#?"[prefixEdge] "#^"[prefixEdge] "#_"[prefixEdge] '"'[sameEdge, closedBy='"', openedBy='"'] "'"[prefixEdge] "`"[prefixEdge] "~"[prefixEdge] "~@"[prefixEdge] "^"[prefixEdge] "@"[prefixEdge] "]" "}" ")" whitespace { (std.whitespace | ",")+ } LineComment { ";" ![\n]* } // https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.8 // class or constructor names javaIdentStart { std.asciiLetter | "_" | "$" | $[\u{a1}-\u{10ff}] } javaIdentChar { javaIdentStart | std.digit } javaIdent { javaIdentStart javaIdentChar* } qualifiedJavaIdent { javaIdent ("." javaIdent)+ } // reader tags cannot contain dots readerTagIdentStart { std.asciiLetter | $[<>&%_=?!*+\-$\u{a1}-\u{10ff}] } readerTagIdentChar { readerTagIdentStart | "/" | std.digit } readerTagIdent { readerTagIdentStart readerTagIdentChar* } identStart { std.asciiLetter | $[<>&%._=?!*+\-$\u{a1}-\u{10ff}/] } identChar { identStart | std.digit | ":" | "'" | "#" | "/"} ident { identStart identChar* } Symbol { ident } keyword { ":" ":"? ident? } // the invalid token :: can also be considered as a keyword Keyword { keyword } Number { ("+" | "-")? (std.digit+ ("." std.digit* "M"?)? | "." std.digit+) (("e" | "E") ("+" | "-")? std.digit+ "M"?)? | ("+" | "-")? std.digit+ ("M" | "N") | ("+" | "-")? std.digit+ "/" std.digit+ | ("+" | "-")? "0x" (std.digit | $[a-fA-F])+ | "0b" $[01]+ | "0o" $[0-7]+ } @precedence { Number, qualifiedJavaIdent, readerTagIdent, Symbol } StringContent { (!["] | "\\" _)+ } unicodeChar { "u" $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F] $[0-9a-fA-F]} octalChar { "o" $[0-3]? $[0-7] $[0-7]? } specialChar { "newline" | "space" | "tab" | "formfeed" | "backspace" | "return" } singleChar { ![\n] } Character { "\\" ( octalChar | unicodeChar | singleChar | specialChar ) } } Boolean { @specialize } Nil { @specialize } DefLike[@dynamicPrecedence=1] { @extend } NS[@dynamicPrecedence=2] { @extend } @detectDelim