UNPKG

8.68 kBJavaScriptView Raw
1/*
2Language: XQuery
3Author: Dirk Kirsten <dk@basex.org>
4Contributor: Duncan Paterson
5Description: Supports XQuery 3.1 including XQuery Update 3, so also XPath (as it is a superset)
6Refactored to process xml constructor syntax and function-bodies. Added missing data-types, xpath operands, inbuilt functions, and query prologs
7Website: https://www.w3.org/XML/Query/
8Category: functional
9Audit: 2020
10*/
11
12/** @type LanguageFn */
13function xquery(_hljs) {
14 // see https://www.w3.org/TR/xquery/#id-terminal-delimitation
15 const KEYWORDS = [
16 "module",
17 "schema",
18 "namespace",
19 "boundary-space",
20 "preserve",
21 "no-preserve",
22 "strip",
23 "default",
24 "collation",
25 "base-uri",
26 "ordering",
27 "context",
28 "decimal-format",
29 "decimal-separator",
30 "copy-namespaces",
31 "empty-sequence",
32 "except",
33 "exponent-separator",
34 "external",
35 "grouping-separator",
36 "inherit",
37 "no-inherit",
38 "lax",
39 "minus-sign",
40 "per-mille",
41 "percent",
42 "schema-attribute",
43 "schema-element",
44 "strict",
45 "unordered",
46 "zero-digit",
47 "declare",
48 "import",
49 "option",
50 "function",
51 "validate",
52 "variable",
53 "for",
54 "at",
55 "in",
56 "let",
57 "where",
58 "order",
59 "group",
60 "by",
61 "return",
62 "if",
63 "then",
64 "else",
65 "tumbling",
66 "sliding",
67 "window",
68 "start",
69 "when",
70 "only",
71 "end",
72 "previous",
73 "next",
74 "stable",
75 "ascending",
76 "descending",
77 "allowing",
78 "empty",
79 "greatest",
80 "least",
81 "some",
82 "every",
83 "satisfies",
84 "switch",
85 "case",
86 "typeswitch",
87 "try",
88 "catch",
89 "and",
90 "or",
91 "to",
92 "union",
93 "intersect",
94 "instance",
95 "of",
96 "treat",
97 "as",
98 "castable",
99 "cast",
100 "map",
101 "array",
102 "delete",
103 "insert",
104 "into",
105 "replace",
106 "value",
107 "rename",
108 "copy",
109 "modify",
110 "update"
111 ];
112
113 // Node Types (sorted by inheritance)
114 // atomic types (sorted by inheritance)
115 const TYPES = [
116 "item",
117 "document-node",
118 "node",
119 "attribute",
120 "document",
121 "element",
122 "comment",
123 "namespace",
124 "namespace-node",
125 "processing-instruction",
126 "text",
127 "construction",
128 "xs:anyAtomicType",
129 "xs:untypedAtomic",
130 "xs:duration",
131 "xs:time",
132 "xs:decimal",
133 "xs:float",
134 "xs:double",
135 "xs:gYearMonth",
136 "xs:gYear",
137 "xs:gMonthDay",
138 "xs:gMonth",
139 "xs:gDay",
140 "xs:boolean",
141 "xs:base64Binary",
142 "xs:hexBinary",
143 "xs:anyURI",
144 "xs:QName",
145 "xs:NOTATION",
146 "xs:dateTime",
147 "xs:dateTimeStamp",
148 "xs:date",
149 "xs:string",
150 "xs:normalizedString",
151 "xs:token",
152 "xs:language",
153 "xs:NMTOKEN",
154 "xs:Name",
155 "xs:NCName",
156 "xs:ID",
157 "xs:IDREF",
158 "xs:ENTITY",
159 "xs:integer",
160 "xs:nonPositiveInteger",
161 "xs:negativeInteger",
162 "xs:long",
163 "xs:int",
164 "xs:short",
165 "xs:byte",
166 "xs:nonNegativeInteger",
167 "xs:unisignedLong",
168 "xs:unsignedInt",
169 "xs:unsignedShort",
170 "xs:unsignedByte",
171 "xs:positiveInteger",
172 "xs:yearMonthDuration",
173 "xs:dayTimeDuration"
174 ];
175
176 const LITERALS = [
177 "eq",
178 "ne",
179 "lt",
180 "le",
181 "gt",
182 "ge",
183 "is",
184 "self::",
185 "child::",
186 "descendant::",
187 "descendant-or-self::",
188 "attribute::",
189 "following::",
190 "following-sibling::",
191 "parent::",
192 "ancestor::",
193 "ancestor-or-self::",
194 "preceding::",
195 "preceding-sibling::",
196 "NaN"
197 ];
198
199 // functions (TODO: find regex for op: without breaking build)
200 const BUILT_IN = {
201 className: 'built_in',
202 variants: [
203 {
204 begin: /\barray:/,
205 end: /(?:append|filter|flatten|fold-(?:left|right)|for-each(?:-pair)?|get|head|insert-before|join|put|remove|reverse|size|sort|subarray|tail)\b/
206 },
207 {
208 begin: /\bmap:/,
209 end: /(?:contains|entry|find|for-each|get|keys|merge|put|remove|size)\b/
210 },
211 {
212 begin: /\bmath:/,
213 end: /(?:a(?:cos|sin|tan[2]?)|cos|exp(?:10)?|log(?:10)?|pi|pow|sin|sqrt|tan)\b/
214 },
215 {
216 begin: /\bop:/,
217 end: /\(/,
218 excludeEnd: true
219 },
220 {
221 begin: /\bfn:/,
222 end: /\(/,
223 excludeEnd: true
224 },
225 // do not highlight inbuilt strings as variable or xml element names
226 {
227 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/
228 },
229 {
230 begin: /\blocal:/,
231 end: /\(/,
232 excludeEnd: true
233 },
234 {
235 begin: /\bzip:/,
236 end: /(?:zip-file|(?:xml|html|text|binary)-entry| (?:update-)?entries)\b/
237 },
238 {
239 begin: /\b(?:util|db|functx|app|xdmp|xmldb):/,
240 end: /\(/,
241 excludeEnd: true
242 }
243 ]
244 };
245
246 const TITLE = {
247 className: 'title',
248 begin: /\bxquery version "[13]\.[01]"\s?(?:encoding ".+")?/,
249 end: /;/
250 };
251
252 const VAR = {
253 className: 'variable',
254 begin: /[$][\w\-:]+/
255 };
256
257 const NUMBER = {
258 className: 'number',
259 begin: /(\b0[0-7_]+)|(\b0x[0-9a-fA-F_]+)|(\b[1-9][0-9_]*(\.[0-9_]+)?)|[0_]\b/,
260 relevance: 0
261 };
262
263 const STRING = {
264 className: 'string',
265 variants: [
266 {
267 begin: /"/,
268 end: /"/,
269 contains: [
270 {
271 begin: /""/,
272 relevance: 0
273 }
274 ]
275 },
276 {
277 begin: /'/,
278 end: /'/,
279 contains: [
280 {
281 begin: /''/,
282 relevance: 0
283 }
284 ]
285 }
286 ]
287 };
288
289 const ANNOTATION = {
290 className: 'meta',
291 begin: /%[\w\-:]+/
292 };
293
294 const COMMENT = {
295 className: 'comment',
296 begin: /\(:/,
297 end: /:\)/,
298 relevance: 10,
299 contains: [
300 {
301 className: 'doctag',
302 begin: /@\w+/
303 }
304 ]
305 };
306
307 // see https://www.w3.org/TR/xquery/#id-computedConstructors
308 // mocha: computed_inbuilt
309 // see https://www.regexpal.com/?fam=99749
310 const COMPUTED = {
311 beginKeywords: 'element attribute comment document processing-instruction',
312 end: /\{/,
313 excludeEnd: true
314 };
315
316 // mocha: direct_method
317 const DIRECT = {
318 begin: /<([\w._:-]+)(\s+\S*=('|").*('|"))?>/,
319 end: /(\/[\w._:-]+>)/,
320 subLanguage: 'xml',
321 contains: [
322 {
323 begin: /\{/,
324 end: /\}/,
325 subLanguage: 'xquery'
326 },
327 'self'
328 ]
329 };
330
331 const CONTAINS = [
332 VAR,
333 BUILT_IN,
334 STRING,
335 NUMBER,
336 COMMENT,
337 ANNOTATION,
338 TITLE,
339 COMPUTED,
340 DIRECT
341 ];
342
343 return {
344 name: 'XQuery',
345 aliases: [
346 'xpath',
347 'xq'
348 ],
349 case_insensitive: false,
350 illegal: /(proc)|(abstract)|(extends)|(until)|(#)/,
351 keywords: {
352 $pattern: /[a-zA-Z$][a-zA-Z0-9_:-]*/,
353 keyword: KEYWORDS,
354 type: TYPES,
355 literal: LITERALS
356 },
357 contains: CONTAINS
358 };
359}
360
361export { xquery as default };