erlang.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. Language: Erlang
  3. Description: Erlang is a general-purpose functional language, with strict evaluation, single assignment, and dynamic typing.
  4. Author: Nikolay Zakharov <nikolay.desh@gmail.com>, Dmitry Kovega <arhibot@gmail.com>
  5. Website: https://www.erlang.org
  6. Category: functional
  7. */
  8. /** @type LanguageFn */
  9. function erlang(hljs) {
  10. const BASIC_ATOM_RE = '[a-z\'][a-zA-Z0-9_\']*';
  11. const FUNCTION_NAME_RE = '(' + BASIC_ATOM_RE + ':' + BASIC_ATOM_RE + '|' + BASIC_ATOM_RE + ')';
  12. const ERLANG_RESERVED = {
  13. keyword:
  14. 'after and andalso|10 band begin bnot bor bsl bzr bxor case catch cond div end fun if '
  15. + 'let not of orelse|10 query receive rem try when xor',
  16. literal:
  17. 'false true'
  18. };
  19. const COMMENT = hljs.COMMENT('%', '$');
  20. const NUMBER = {
  21. className: 'number',
  22. begin: '\\b(\\d+(_\\d+)*#[a-fA-F0-9]+(_[a-fA-F0-9]+)*|\\d+(_\\d+)*(\\.\\d+(_\\d+)*)?([eE][-+]?\\d+)?)',
  23. relevance: 0
  24. };
  25. const NAMED_FUN = { begin: 'fun\\s+' + BASIC_ATOM_RE + '/\\d+' };
  26. const FUNCTION_CALL = {
  27. begin: FUNCTION_NAME_RE + '\\(',
  28. end: '\\)',
  29. returnBegin: true,
  30. relevance: 0,
  31. contains: [
  32. {
  33. begin: FUNCTION_NAME_RE,
  34. relevance: 0
  35. },
  36. {
  37. begin: '\\(',
  38. end: '\\)',
  39. endsWithParent: true,
  40. returnEnd: true,
  41. relevance: 0
  42. // "contains" defined later
  43. }
  44. ]
  45. };
  46. const TUPLE = {
  47. begin: /\{/,
  48. end: /\}/,
  49. relevance: 0
  50. // "contains" defined later
  51. };
  52. const VAR1 = {
  53. begin: '\\b_([A-Z][A-Za-z0-9_]*)?',
  54. relevance: 0
  55. };
  56. const VAR2 = {
  57. begin: '[A-Z][a-zA-Z0-9_]*',
  58. relevance: 0
  59. };
  60. const RECORD_ACCESS = {
  61. begin: '#' + hljs.UNDERSCORE_IDENT_RE,
  62. relevance: 0,
  63. returnBegin: true,
  64. contains: [
  65. {
  66. begin: '#' + hljs.UNDERSCORE_IDENT_RE,
  67. relevance: 0
  68. },
  69. {
  70. begin: /\{/,
  71. end: /\}/,
  72. relevance: 0
  73. // "contains" defined later
  74. }
  75. ]
  76. };
  77. const BLOCK_STATEMENTS = {
  78. beginKeywords: 'fun receive if try case',
  79. end: 'end',
  80. keywords: ERLANG_RESERVED
  81. };
  82. BLOCK_STATEMENTS.contains = [
  83. COMMENT,
  84. NAMED_FUN,
  85. hljs.inherit(hljs.APOS_STRING_MODE, { className: '' }),
  86. BLOCK_STATEMENTS,
  87. FUNCTION_CALL,
  88. hljs.QUOTE_STRING_MODE,
  89. NUMBER,
  90. TUPLE,
  91. VAR1,
  92. VAR2,
  93. RECORD_ACCESS
  94. ];
  95. const BASIC_MODES = [
  96. COMMENT,
  97. NAMED_FUN,
  98. BLOCK_STATEMENTS,
  99. FUNCTION_CALL,
  100. hljs.QUOTE_STRING_MODE,
  101. NUMBER,
  102. TUPLE,
  103. VAR1,
  104. VAR2,
  105. RECORD_ACCESS
  106. ];
  107. FUNCTION_CALL.contains[1].contains = BASIC_MODES;
  108. TUPLE.contains = BASIC_MODES;
  109. RECORD_ACCESS.contains[1].contains = BASIC_MODES;
  110. const DIRECTIVES = [
  111. "-module",
  112. "-record",
  113. "-undef",
  114. "-export",
  115. "-ifdef",
  116. "-ifndef",
  117. "-author",
  118. "-copyright",
  119. "-doc",
  120. "-vsn",
  121. "-import",
  122. "-include",
  123. "-include_lib",
  124. "-compile",
  125. "-define",
  126. "-else",
  127. "-endif",
  128. "-file",
  129. "-behaviour",
  130. "-behavior",
  131. "-spec"
  132. ];
  133. const PARAMS = {
  134. className: 'params',
  135. begin: '\\(',
  136. end: '\\)',
  137. contains: BASIC_MODES
  138. };
  139. return {
  140. name: 'Erlang',
  141. aliases: [ 'erl' ],
  142. keywords: ERLANG_RESERVED,
  143. illegal: '(</|\\*=|\\+=|-=|/\\*|\\*/|\\(\\*|\\*\\))',
  144. contains: [
  145. {
  146. className: 'function',
  147. begin: '^' + BASIC_ATOM_RE + '\\s*\\(',
  148. end: '->',
  149. returnBegin: true,
  150. illegal: '\\(|#|//|/\\*|\\\\|:|;',
  151. contains: [
  152. PARAMS,
  153. hljs.inherit(hljs.TITLE_MODE, { begin: BASIC_ATOM_RE })
  154. ],
  155. starts: {
  156. end: ';|\\.',
  157. keywords: ERLANG_RESERVED,
  158. contains: BASIC_MODES
  159. }
  160. },
  161. COMMENT,
  162. {
  163. begin: '^-',
  164. end: '\\.',
  165. relevance: 0,
  166. excludeEnd: true,
  167. returnBegin: true,
  168. keywords: {
  169. $pattern: '-' + hljs.IDENT_RE,
  170. keyword: DIRECTIVES.map(x => `${x}|1.5`).join(" ")
  171. },
  172. contains: [ PARAMS ]
  173. },
  174. NUMBER,
  175. hljs.QUOTE_STRING_MODE,
  176. RECORD_ACCESS,
  177. VAR1,
  178. VAR2,
  179. TUPLE,
  180. { begin: /\.$/ } // relevance booster
  181. ]
  182. };
  183. }
  184. module.exports = erlang;