xquery.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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. /** @type LanguageFn */
  12. function xquery(_hljs) {
  13. // see https://www.w3.org/TR/xquery/#id-terminal-delimitation
  14. const KEYWORDS =
  15. '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 ' +
  16. 'declare import option function validate variable ' +
  17. 'for at in let where order group by return if then else ' +
  18. 'tumbling sliding window start when only end previous next stable ' +
  19. 'ascending descending allowing empty greatest least some every satisfies switch case typeswitch try catch ' +
  20. 'and or to union intersect instance of treat as castable cast map array ' +
  21. 'delete insert into replace value rename copy modify update';
  22. // Node Types (sorted by inheritance)
  23. // atomic types (sorted by inheritance)
  24. const TYPE =
  25. 'item document-node node attribute document element comment namespace namespace-node processing-instruction text construction ' +
  26. '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';
  27. const LITERAL =
  28. 'eq ne lt le gt ge is ' +
  29. 'self:: child:: descendant:: descendant-or-self:: attribute:: following:: following-sibling:: parent:: ancestor:: ancestor-or-self:: preceding:: preceding-sibling:: ' +
  30. 'NaN';
  31. // functions (TODO: find regex for op: without breaking build)
  32. const BUILT_IN = {
  33. className: 'built_in',
  34. variants: [
  35. {
  36. begin: /\barray:/,
  37. end: /(?:append|filter|flatten|fold-(?:left|right)|for-each(?:-pair)?|get|head|insert-before|join|put|remove|reverse|size|sort|subarray|tail)\b/
  38. },
  39. {
  40. begin: /\bmap:/,
  41. end: /(?:contains|entry|find|for-each|get|keys|merge|put|remove|size)\b/
  42. },
  43. {
  44. begin: /\bmath:/,
  45. end: /(?:a(?:cos|sin|tan[2]?)|cos|exp(?:10)?|log(?:10)?|pi|pow|sin|sqrt|tan)\b/
  46. },
  47. {
  48. begin: /\bop:/,
  49. end: /\(/,
  50. excludeEnd: true
  51. },
  52. {
  53. begin: /\bfn:/,
  54. end: /\(/,
  55. excludeEnd: true
  56. },
  57. // do not highlight inbuilt strings as variable or xml element names
  58. {
  59. 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/
  60. },
  61. {
  62. begin: /\blocal:/,
  63. end: /\(/,
  64. excludeEnd: true
  65. },
  66. {
  67. begin: /\bzip:/,
  68. end: /(?:zip-file|(?:xml|html|text|binary)-entry| (?:update-)?entries)\b/
  69. },
  70. {
  71. begin: /\b(?:util|db|functx|app|xdmp|xmldb):/,
  72. end: /\(/,
  73. excludeEnd: true
  74. }
  75. ]
  76. };
  77. const TITLE = {
  78. className: 'title',
  79. begin: /\bxquery version "[13]\.[01]"\s?(?:encoding ".+")?/,
  80. end: /;/
  81. };
  82. const VAR = {
  83. className: 'variable',
  84. begin: /[$][\w\-:]+/
  85. };
  86. const NUMBER = {
  87. className: 'number',
  88. begin: /(\b0[0-7_]+)|(\b0x[0-9a-fA-F_]+)|(\b[1-9][0-9_]*(\.[0-9_]+)?)|[0_]\b/,
  89. relevance: 0
  90. };
  91. const STRING = {
  92. className: 'string',
  93. variants: [
  94. {
  95. begin: /"/,
  96. end: /"/,
  97. contains: [
  98. {
  99. begin: /""/,
  100. relevance: 0
  101. }
  102. ]
  103. },
  104. {
  105. begin: /'/,
  106. end: /'/,
  107. contains: [
  108. {
  109. begin: /''/,
  110. relevance: 0
  111. }
  112. ]
  113. }
  114. ]
  115. };
  116. const ANNOTATION = {
  117. className: 'meta',
  118. begin: /%[\w\-:]+/
  119. };
  120. const COMMENT = {
  121. className: 'comment',
  122. begin: /\(:/,
  123. end: /:\)/,
  124. relevance: 10,
  125. contains: [
  126. {
  127. className: 'doctag',
  128. begin: /@\w+/
  129. }
  130. ]
  131. };
  132. // see https://www.w3.org/TR/xquery/#id-computedConstructors
  133. // mocha: computed_inbuilt
  134. // see https://www.regexpal.com/?fam=99749
  135. const COMPUTED = {
  136. beginKeywords: 'element attribute comment document processing-instruction',
  137. end: /\{/,
  138. excludeEnd: true
  139. };
  140. // mocha: direct_method
  141. const DIRECT = {
  142. begin: /<([\w._:-]+)(\s+\S*=('|").*('|"))?>/,
  143. end: /(\/[\w._:-]+>)/,
  144. subLanguage: 'xml',
  145. contains: [
  146. {
  147. begin: /\{/,
  148. end: /\}/,
  149. subLanguage: 'xquery'
  150. },
  151. 'self'
  152. ]
  153. };
  154. const CONTAINS = [
  155. VAR,
  156. BUILT_IN,
  157. STRING,
  158. NUMBER,
  159. COMMENT,
  160. ANNOTATION,
  161. TITLE,
  162. COMPUTED,
  163. DIRECT
  164. ];
  165. return {
  166. name: 'XQuery',
  167. aliases: [
  168. 'xpath',
  169. 'xq'
  170. ],
  171. case_insensitive: false,
  172. illegal: /(proc)|(abstract)|(extends)|(until)|(#)/,
  173. keywords: {
  174. $pattern: /[a-zA-Z$][a-zA-Z0-9_:-]*/,
  175. keyword: KEYWORDS,
  176. type: TYPE,
  177. literal: LITERAL
  178. },
  179. contains: CONTAINS
  180. };
  181. }
  182. module.exports = xquery;