prism-sml.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // https://smlfamily.github.io/sml97-defn.pdf
  2. // https://people.mpi-sws.org/~rossberg/sml.html
  3. (function (Prism) {
  4. var keywords = /\b(?:abstype|and|andalso|as|case|datatype|do|else|end|eqtype|exception|fn|fun|functor|handle|if|in|include|infix|infixr|let|local|nonfix|of|op|open|orelse|raise|rec|sharing|sig|signature|struct|structure|then|type|val|where|while|with|withtype)\b/i;
  5. Prism.languages.sml = {
  6. // allow one level of nesting
  7. 'comment': /\(\*(?:[^*(]|\*(?!\))|\((?!\*)|\(\*(?:[^*(]|\*(?!\))|\((?!\*))*\*\))*\*\)/,
  8. 'string': {
  9. pattern: /#?"(?:[^"\\]|\\.)*"/,
  10. greedy: true
  11. },
  12. 'class-name': [
  13. {
  14. // This is only an approximation since the real grammar is context-free
  15. //
  16. // Why the main loop so complex?
  17. // The main loop is approximately the same as /(?:\s*(?:[*,]|->)\s*<TERMINAL>)*/ which is, obviously, a lot
  18. // simpler. The difference is that if a comma is the last iteration of the loop, then the terminal must be
  19. // followed by a long identifier.
  20. pattern: RegExp(
  21. /((?:^|[^:]):\s*)<TERMINAL>(?:\s*(?:(?:\*|->)\s*<TERMINAL>|,\s*<TERMINAL>(?:(?=<NOT-LAST>)|(?!<NOT-LAST>)\s+<LONG-ID>)))*/.source
  22. .replace(/<NOT-LAST>/g, function () { return /\s*(?:[*,]|->)/.source; })
  23. .replace(/<TERMINAL>/g, function () {
  24. return /(?:'[\w']*|<LONG-ID>|\((?:[^()]|\([^()]*\))*\)|\{(?:[^{}]|\{[^{}]*\})*\})(?:\s+<LONG-ID>)*/.source;
  25. })
  26. .replace(/<LONG-ID>/g, function () { return /(?!<KEYWORD>)[a-z\d_][\w'.]*/.source; })
  27. .replace(/<KEYWORD>/g, function () { return keywords.source; }),
  28. 'i'
  29. ),
  30. lookbehind: true,
  31. greedy: true,
  32. inside: null // see below
  33. },
  34. {
  35. pattern: /((?:^|[^\w'])(?:datatype|exception|functor|signature|structure|type)\s+)[a-z_][\w'.]*/i,
  36. lookbehind: true
  37. }
  38. ],
  39. 'function': {
  40. pattern: /((?:^|[^\w'])fun\s+)[a-z_][\w'.]*/i,
  41. lookbehind: true
  42. },
  43. 'keyword': keywords,
  44. 'variable': {
  45. pattern: /(^|[^\w'])'[\w']*/,
  46. lookbehind: true,
  47. },
  48. 'number': /~?\b(?:\d+(?:\.\d+)?(?:e~?\d+)?|0x[\da-f]+)\b/i,
  49. 'word': {
  50. pattern: /\b0w(?:\d+|x[\da-f]+)\b/i,
  51. alias: 'constant'
  52. },
  53. 'boolean': /\b(?:false|true)\b/i,
  54. 'operator': /\.\.\.|:[>=:]|=>?|->|[<>]=?|[!+\-*/^#|@~]/,
  55. 'punctuation': /[(){}\[\].:,;]/
  56. };
  57. Prism.languages.sml['class-name'][0].inside = Prism.languages.sml;
  58. Prism.languages.smlnj = Prism.languages.sml;
  59. }(Prism));