[d24f17c] | 1 | /*
|
---|
| 2 | Language: XQuery
|
---|
| 3 | Author: Dirk Kirsten <dk@basex.org>
|
---|
| 4 | Contributor: Duncan Paterson
|
---|
| 5 | Description: Supports XQuery 3.1 including XQuery Update 3, so also XPath (as it is a superset)
|
---|
| 6 | Refactored to process xml constructor syntax and function-bodies. Added missing data-types, xpath operands, inbuilt functions, and query prologs
|
---|
| 7 | Website: https://www.w3.org/XML/Query/
|
---|
| 8 | Category: functional
|
---|
| 9 | Audit: 2020
|
---|
| 10 | */
|
---|
| 11 |
|
---|
| 12 | /** @type LanguageFn */
|
---|
| 13 | function xquery(_hljs) {
|
---|
| 14 | // see https://www.w3.org/TR/xquery/#id-terminal-delimitation
|
---|
| 15 | const KEYWORDS =
|
---|
| 16 | 'module schema namespace boundary-space preserve no-preserve strip default collation base-uri ordering context decimal-format decimal-separator copy-namespaces empty-sequence except exponent-separator external grouping-separator inherit no-inherit lax minus-sign per-mille percent schema-attribute schema-element strict unordered zero-digit ' +
|
---|
| 17 | 'declare import option function validate variable ' +
|
---|
| 18 | 'for at in let where order group by return if then else ' +
|
---|
| 19 | 'tumbling sliding window start when only end previous next stable ' +
|
---|
| 20 | 'ascending descending allowing empty greatest least some every satisfies switch case typeswitch try catch ' +
|
---|
| 21 | 'and or to union intersect instance of treat as castable cast map array ' +
|
---|
| 22 | 'delete insert into replace value rename copy modify update';
|
---|
| 23 |
|
---|
| 24 | // Node Types (sorted by inheritance)
|
---|
| 25 | // atomic types (sorted by inheritance)
|
---|
| 26 | const TYPE =
|
---|
| 27 | 'item document-node node attribute document element comment namespace namespace-node processing-instruction text construction ' +
|
---|
| 28 | 'xs:anyAtomicType xs:untypedAtomic xs:duration xs:time xs:decimal xs:float xs:double xs:gYearMonth xs:gYear xs:gMonthDay xs:gMonth xs:gDay xs:boolean xs:base64Binary xs:hexBinary xs:anyURI xs:QName xs:NOTATION xs:dateTime xs:dateTimeStamp xs:date xs:string xs:normalizedString xs:token xs:language xs:NMTOKEN xs:Name xs:NCName xs:ID xs:IDREF xs:ENTITY xs:integer xs:nonPositiveInteger xs:negativeInteger xs:long xs:int xs:short xs:byte xs:nonNegativeInteger xs:unisignedLong xs:unsignedInt xs:unsignedShort xs:unsignedByte xs:positiveInteger xs:yearMonthDuration xs:dayTimeDuration';
|
---|
| 29 |
|
---|
| 30 | const LITERAL =
|
---|
| 31 | 'eq ne lt le gt ge is ' +
|
---|
| 32 | 'self:: child:: descendant:: descendant-or-self:: attribute:: following:: following-sibling:: parent:: ancestor:: ancestor-or-self:: preceding:: preceding-sibling:: ' +
|
---|
| 33 | 'NaN';
|
---|
| 34 |
|
---|
| 35 | // functions (TODO: find regex for op: without breaking build)
|
---|
| 36 | const BUILT_IN = {
|
---|
| 37 | className: 'built_in',
|
---|
| 38 | variants: [
|
---|
| 39 | {
|
---|
| 40 | begin: /\barray:/,
|
---|
| 41 | end: /(?:append|filter|flatten|fold-(?:left|right)|for-each(?:-pair)?|get|head|insert-before|join|put|remove|reverse|size|sort|subarray|tail)\b/
|
---|
| 42 | },
|
---|
| 43 | {
|
---|
| 44 | begin: /\bmap:/,
|
---|
| 45 | end: /(?:contains|entry|find|for-each|get|keys|merge|put|remove|size)\b/
|
---|
| 46 | },
|
---|
| 47 | {
|
---|
| 48 | begin: /\bmath:/,
|
---|
| 49 | end: /(?:a(?:cos|sin|tan[2]?)|cos|exp(?:10)?|log(?:10)?|pi|pow|sin|sqrt|tan)\b/
|
---|
| 50 | },
|
---|
| 51 | {
|
---|
| 52 | begin: /\bop:/,
|
---|
| 53 | end: /\(/,
|
---|
| 54 | excludeEnd: true
|
---|
| 55 | },
|
---|
| 56 | {
|
---|
| 57 | begin: /\bfn:/,
|
---|
| 58 | end: /\(/,
|
---|
| 59 | excludeEnd: true
|
---|
| 60 | },
|
---|
| 61 | // do not highlight inbuilt strings as variable or xml element names
|
---|
| 62 | {
|
---|
| 63 | begin: /[^</$:'"-]\b(?:abs|accumulator-(?:after|before)|adjust-(?:date(?:Time)?|time)-to-timezone|analyze-string|apply|available-(?:environment-variables|system-properties)|avg|base-uri|boolean|ceiling|codepoints?-(?:equal|to-string)|collation-key|collection|compare|concat|contains(?:-token)?|copy-of|count|current(?:-)?(?:date(?:Time)?|time|group(?:ing-key)?|output-uri|merge-(?:group|key))?data|dateTime|days?-from-(?:date(?:Time)?|duration)|deep-equal|default-(?:collation|language)|distinct-values|document(?:-uri)?|doc(?:-available)?|element-(?:available|with-id)|empty|encode-for-uri|ends-with|environment-variable|error|escape-html-uri|exactly-one|exists|false|filter|floor|fold-(?:left|right)|for-each(?:-pair)?|format-(?:date(?:Time)?|time|integer|number)|function-(?:arity|available|lookup|name)|generate-id|has-children|head|hours-from-(?:dateTime|duration|time)|id(?:ref)?|implicit-timezone|in-scope-prefixes|index-of|innermost|insert-before|iri-to-uri|json-(?:doc|to-xml)|key|lang|last|load-xquery-module|local-name(?:-from-QName)?|(?:lower|upper)-case|matches|max|minutes-from-(?:dateTime|duration|time)|min|months?-from-(?:date(?:Time)?|duration)|name(?:space-uri-?(?:for-prefix|from-QName)?)?|nilled|node-name|normalize-(?:space|unicode)|not|number|one-or-more|outermost|parse-(?:ietf-date|json)|path|position|(?:prefix-from-)?QName|random-number-generator|regex-group|remove|replace|resolve-(?:QName|uri)|reverse|root|round(?:-half-to-even)?|seconds-from-(?:dateTime|duration|time)|snapshot|sort|starts-with|static-base-uri|stream-available|string-?(?:join|length|to-codepoints)?|subsequence|substring-?(?:after|before)?|sum|system-property|tail|timezone-from-(?:date(?:Time)?|time)|tokenize|trace|trans(?:form|late)|true|type-available|unordered|unparsed-(?:entity|text)?-?(?:public-id|uri|available|lines)?|uri-collection|xml-to-json|years?-from-(?:date(?:Time)?|duration)|zero-or-one)\b/
|
---|
| 64 | },
|
---|
| 65 | {
|
---|
| 66 | begin: /\blocal:/,
|
---|
| 67 | end: /\(/,
|
---|
| 68 | excludeEnd: true
|
---|
| 69 | },
|
---|
| 70 | {
|
---|
| 71 | begin: /\bzip:/,
|
---|
| 72 | end: /(?:zip-file|(?:xml|html|text|binary)-entry| (?:update-)?entries)\b/
|
---|
| 73 | },
|
---|
| 74 | {
|
---|
| 75 | begin: /\b(?:util|db|functx|app|xdmp|xmldb):/,
|
---|
| 76 | end: /\(/,
|
---|
| 77 | excludeEnd: true
|
---|
| 78 | }
|
---|
| 79 | ]
|
---|
| 80 | };
|
---|
| 81 |
|
---|
| 82 | const TITLE = {
|
---|
| 83 | className: 'title',
|
---|
| 84 | begin: /\bxquery version "[13]\.[01]"\s?(?:encoding ".+")?/,
|
---|
| 85 | end: /;/
|
---|
| 86 | };
|
---|
| 87 |
|
---|
| 88 | const VAR = {
|
---|
| 89 | className: 'variable',
|
---|
| 90 | begin: /[$][\w\-:]+/
|
---|
| 91 | };
|
---|
| 92 |
|
---|
| 93 | const NUMBER = {
|
---|
| 94 | className: 'number',
|
---|
| 95 | begin: /(\b0[0-7_]+)|(\b0x[0-9a-fA-F_]+)|(\b[1-9][0-9_]*(\.[0-9_]+)?)|[0_]\b/,
|
---|
| 96 | relevance: 0
|
---|
| 97 | };
|
---|
| 98 |
|
---|
| 99 | const STRING = {
|
---|
| 100 | className: 'string',
|
---|
| 101 | variants: [
|
---|
| 102 | {
|
---|
| 103 | begin: /"/,
|
---|
| 104 | end: /"/,
|
---|
| 105 | contains: [
|
---|
| 106 | {
|
---|
| 107 | begin: /""/,
|
---|
| 108 | relevance: 0
|
---|
| 109 | }
|
---|
| 110 | ]
|
---|
| 111 | },
|
---|
| 112 | {
|
---|
| 113 | begin: /'/,
|
---|
| 114 | end: /'/,
|
---|
| 115 | contains: [
|
---|
| 116 | {
|
---|
| 117 | begin: /''/,
|
---|
| 118 | relevance: 0
|
---|
| 119 | }
|
---|
| 120 | ]
|
---|
| 121 | }
|
---|
| 122 | ]
|
---|
| 123 | };
|
---|
| 124 |
|
---|
| 125 | const ANNOTATION = {
|
---|
| 126 | className: 'meta',
|
---|
| 127 | begin: /%[\w\-:]+/
|
---|
| 128 | };
|
---|
| 129 |
|
---|
| 130 | const COMMENT = {
|
---|
| 131 | className: 'comment',
|
---|
| 132 | begin: /\(:/,
|
---|
| 133 | end: /:\)/,
|
---|
| 134 | relevance: 10,
|
---|
| 135 | contains: [
|
---|
| 136 | {
|
---|
| 137 | className: 'doctag',
|
---|
| 138 | begin: /@\w+/
|
---|
| 139 | }
|
---|
| 140 | ]
|
---|
| 141 | };
|
---|
| 142 |
|
---|
| 143 | // see https://www.w3.org/TR/xquery/#id-computedConstructors
|
---|
| 144 | // mocha: computed_inbuilt
|
---|
| 145 | // see https://www.regexpal.com/?fam=99749
|
---|
| 146 | const COMPUTED = {
|
---|
| 147 | beginKeywords: 'element attribute comment document processing-instruction',
|
---|
| 148 | end: /\{/,
|
---|
| 149 | excludeEnd: true
|
---|
| 150 | };
|
---|
| 151 |
|
---|
| 152 | // mocha: direct_method
|
---|
| 153 | const DIRECT = {
|
---|
| 154 | begin: /<([\w._:-]+)(\s+\S*=('|").*('|"))?>/,
|
---|
| 155 | end: /(\/[\w._:-]+>)/,
|
---|
| 156 | subLanguage: 'xml',
|
---|
| 157 | contains: [
|
---|
| 158 | {
|
---|
| 159 | begin: /\{/,
|
---|
| 160 | end: /\}/,
|
---|
| 161 | subLanguage: 'xquery'
|
---|
| 162 | },
|
---|
| 163 | 'self'
|
---|
| 164 | ]
|
---|
| 165 | };
|
---|
| 166 |
|
---|
| 167 | const CONTAINS = [
|
---|
| 168 | VAR,
|
---|
| 169 | BUILT_IN,
|
---|
| 170 | STRING,
|
---|
| 171 | NUMBER,
|
---|
| 172 | COMMENT,
|
---|
| 173 | ANNOTATION,
|
---|
| 174 | TITLE,
|
---|
| 175 | COMPUTED,
|
---|
| 176 | DIRECT
|
---|
| 177 | ];
|
---|
| 178 |
|
---|
| 179 | return {
|
---|
| 180 | name: 'XQuery',
|
---|
| 181 | aliases: [
|
---|
| 182 | 'xpath',
|
---|
| 183 | 'xq'
|
---|
| 184 | ],
|
---|
| 185 | case_insensitive: false,
|
---|
| 186 | illegal: /(proc)|(abstract)|(extends)|(until)|(#)/,
|
---|
| 187 | keywords: {
|
---|
| 188 | $pattern: /[a-zA-Z$][a-zA-Z0-9_:-]*/,
|
---|
| 189 | keyword: KEYWORDS,
|
---|
| 190 | type: TYPE,
|
---|
| 191 | literal: LITERAL
|
---|
| 192 | },
|
---|
| 193 | contains: CONTAINS
|
---|
| 194 | };
|
---|
| 195 | }
|
---|
| 196 |
|
---|
| 197 | module.exports = xquery;
|
---|