sjs_highlight_rules.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Distributed under the BSD license:
  3. *
  4. * Copyright (c) 2010, Ajax.org B.V.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * * Neither the name of Ajax.org B.V. nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * ***** END LICENSE BLOCK ***** */
  30. define(function(require, exports, module) {
  31. "use strict";
  32. var oop = require("../lib/oop");
  33. var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
  34. var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
  35. var SJSHighlightRules = function() {
  36. var parent = new JavaScriptHighlightRules({noES6: true});
  37. var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
  38. "u[0-9a-fA-F]{4}|" + // unicode
  39. "[0-2][0-7]{0,2}|" + // oct
  40. "3[0-6][0-7]?|" + // oct
  41. "37[0-7]?|" + // oct
  42. "[4-7][0-7]?|" + //oct
  43. ".)";
  44. var contextAware = function(f) {
  45. f.isContextAware = true;
  46. return f;
  47. };
  48. var ctxBegin = function(opts) {
  49. return {
  50. token: opts.token,
  51. regex: opts.regex,
  52. next: contextAware(function(currentState, stack) {
  53. if (stack.length === 0)
  54. stack.unshift(currentState);
  55. stack.unshift(opts.next);
  56. return opts.next;
  57. }),
  58. };
  59. };
  60. var ctxEnd = function(opts) {
  61. return {
  62. token: opts.token,
  63. regex: opts.regex,
  64. next: contextAware(function(currentState, stack) {
  65. stack.shift();
  66. return stack[0] || "start";
  67. }),
  68. };
  69. };
  70. this.$rules = parent.$rules;
  71. this.$rules.no_regex = [
  72. {
  73. token: "keyword",
  74. regex: "(waitfor|or|and|collapse|spawn|retract)\\b"
  75. },
  76. {
  77. token: "keyword.operator",
  78. regex: "(->|=>|\\.\\.)"
  79. },
  80. {
  81. token: "variable.language",
  82. regex: "(hold|default)\\b"
  83. },
  84. ctxBegin({
  85. token: "string",
  86. regex: "`",
  87. next: "bstring"
  88. }),
  89. ctxBegin({
  90. token: "string",
  91. regex: '"',
  92. next: "qqstring"
  93. }),
  94. ctxBegin({
  95. token: "string",
  96. regex: '"',
  97. next: "qqstring"
  98. }),
  99. {
  100. token: ["paren.lparen", "text", "paren.rparen"],
  101. regex: "(\\{)(\\s*)(\\|)",
  102. next: "block_arguments",
  103. }
  104. ].concat(this.$rules.no_regex);
  105. this.$rules.block_arguments = [
  106. {
  107. token: "paren.rparen",
  108. regex: "\\|",
  109. next: "no_regex",
  110. }
  111. ].concat(this.$rules.function_arguments);
  112. this.$rules.bstring = [
  113. {
  114. token : "constant.language.escape",
  115. regex : escapedRe
  116. },
  117. {
  118. token : "string",
  119. regex : "\\\\$",
  120. next: "bstring"
  121. },
  122. ctxBegin({
  123. token : "paren.lparen",
  124. regex : "\\$\\{",
  125. next: "string_interp"
  126. }),
  127. ctxBegin({
  128. token : "paren.lparen",
  129. regex : "\\$",
  130. next: "bstring_interp_single"
  131. }),
  132. ctxEnd({
  133. token : "string",
  134. regex : "`",
  135. }),
  136. {
  137. defaultToken: "string"
  138. }
  139. ];
  140. this.$rules.qqstring = [
  141. {
  142. token : "constant.language.escape",
  143. regex : escapedRe
  144. },
  145. {
  146. token : "string",
  147. regex : "\\\\$",
  148. next: "qqstring",
  149. },
  150. ctxBegin({
  151. token : "paren.lparen",
  152. regex : "#\\{",
  153. next: "string_interp"
  154. }),
  155. ctxEnd({
  156. token : "string",
  157. regex : '"',
  158. }),
  159. {
  160. defaultToken: "string"
  161. }
  162. ];
  163. // collect all context-aware (or stateless), brace-less
  164. // states. This gives us most normal highlighting
  165. // for use within interpreted contexts
  166. // without interfering with context nesting
  167. var embeddableRules = [];
  168. for (var i=0; i < this.$rules.no_regex.length; i++) {
  169. var rule = this.$rules.no_regex[i];
  170. var token = String(rule.token);
  171. if (token.indexOf('paren') == -1 && (!rule.next || rule.next.isContextAware)) {
  172. embeddableRules.push(rule);
  173. }
  174. };
  175. this.$rules.string_interp = [
  176. ctxEnd({
  177. token: "paren.rparen",
  178. regex: "\\}"
  179. }),
  180. ctxBegin({
  181. token: "paren.lparen",
  182. regex: '{',
  183. next: "string_interp"
  184. })
  185. ].concat(embeddableRules);
  186. // backtick strings can have single interpolation, which accept
  187. // \w+ followed by an optional set of function call parens
  188. this.$rules.bstring_interp_single = [
  189. {
  190. token: ["identifier", "paren.lparen"],
  191. regex: '(\\w+)(\\()',
  192. next: 'bstring_interp_single_call'
  193. },
  194. // identifier-only match ends this interp
  195. ctxEnd({
  196. token : "identifier",
  197. regex : "\\w*",
  198. })
  199. ];
  200. // the call part of a bstring_interp_single
  201. // is terminated by a close paren `)`, but
  202. // can have nested parens.
  203. this.$rules.bstring_interp_single_call = [
  204. ctxBegin({
  205. token: "paren.lparen",
  206. regex: "\\(",
  207. next: "bstring_interp_single_call"
  208. }),
  209. ctxEnd({
  210. token: "paren.rparen",
  211. regex: "\\)"
  212. })
  213. ].concat(embeddableRules);
  214. }
  215. oop.inherits(SJSHighlightRules, TextHighlightRules);
  216. exports.SJSHighlightRules = SJSHighlightRules;
  217. });