erlang.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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 CHAR_LITERAL = {
  78. scope: 'string',
  79. match: /\$(\\([^0-9]|[0-9]{1,3}|)|.)/,
  80. };
  81. const BLOCK_STATEMENTS = {
  82. beginKeywords: 'fun receive if try case',
  83. end: 'end',
  84. keywords: ERLANG_RESERVED
  85. };
  86. BLOCK_STATEMENTS.contains = [
  87. COMMENT,
  88. NAMED_FUN,
  89. hljs.inherit(hljs.APOS_STRING_MODE, { className: '' }),
  90. BLOCK_STATEMENTS,
  91. FUNCTION_CALL,
  92. hljs.QUOTE_STRING_MODE,
  93. NUMBER,
  94. TUPLE,
  95. VAR1,
  96. VAR2,
  97. RECORD_ACCESS,
  98. CHAR_LITERAL
  99. ];
  100. const BASIC_MODES = [
  101. COMMENT,
  102. NAMED_FUN,
  103. BLOCK_STATEMENTS,
  104. FUNCTION_CALL,
  105. hljs.QUOTE_STRING_MODE,
  106. NUMBER,
  107. TUPLE,
  108. VAR1,
  109. VAR2,
  110. RECORD_ACCESS,
  111. CHAR_LITERAL
  112. ];
  113. FUNCTION_CALL.contains[1].contains = BASIC_MODES;
  114. TUPLE.contains = BASIC_MODES;
  115. RECORD_ACCESS.contains[1].contains = BASIC_MODES;
  116. const DIRECTIVES = [
  117. "-module",
  118. "-record",
  119. "-undef",
  120. "-export",
  121. "-ifdef",
  122. "-ifndef",
  123. "-author",
  124. "-copyright",
  125. "-doc",
  126. "-vsn",
  127. "-import",
  128. "-include",
  129. "-include_lib",
  130. "-compile",
  131. "-define",
  132. "-else",
  133. "-endif",
  134. "-file",
  135. "-behaviour",
  136. "-behavior",
  137. "-spec"
  138. ];
  139. const PARAMS = {
  140. className: 'params',
  141. begin: '\\(',
  142. end: '\\)',
  143. contains: BASIC_MODES
  144. };
  145. return {
  146. name: 'Erlang',
  147. aliases: [ 'erl' ],
  148. keywords: ERLANG_RESERVED,
  149. illegal: '(</|\\*=|\\+=|-=|/\\*|\\*/|\\(\\*|\\*\\))',
  150. contains: [
  151. {
  152. className: 'function',
  153. begin: '^' + BASIC_ATOM_RE + '\\s*\\(',
  154. end: '->',
  155. returnBegin: true,
  156. illegal: '\\(|#|//|/\\*|\\\\|:|;',
  157. contains: [
  158. PARAMS,
  159. hljs.inherit(hljs.TITLE_MODE, { begin: BASIC_ATOM_RE })
  160. ],
  161. starts: {
  162. end: ';|\\.',
  163. keywords: ERLANG_RESERVED,
  164. contains: BASIC_MODES
  165. }
  166. },
  167. COMMENT,
  168. {
  169. begin: '^-',
  170. end: '\\.',
  171. relevance: 0,
  172. excludeEnd: true,
  173. returnBegin: true,
  174. keywords: {
  175. $pattern: '-' + hljs.IDENT_RE,
  176. keyword: DIRECTIVES.map(x => `${x}|1.5`).join(" ")
  177. },
  178. contains: [ PARAMS ]
  179. },
  180. NUMBER,
  181. hljs.QUOTE_STRING_MODE,
  182. RECORD_ACCESS,
  183. VAR1,
  184. VAR2,
  185. TUPLE,
  186. CHAR_LITERAL,
  187. { begin: /\.$/ } // relevance booster
  188. ]
  189. };
  190. }
  191. export { erlang as default };