You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

crystal.go 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. package c
  2. import (
  3. . "github.com/alecthomas/chroma" // nolint
  4. "github.com/alecthomas/chroma/lexers/internal"
  5. )
  6. // Crystal lexer.
  7. var Crystal = internal.Register(MustNewLexer(
  8. &Config{
  9. Name: "Crystal",
  10. Aliases: []string{"cr", "crystal"},
  11. Filenames: []string{"*.cr"},
  12. MimeTypes: []string{"text/x-crystal"},
  13. DotAll: true,
  14. },
  15. Rules{
  16. "root": {
  17. {`#.*?$`, CommentSingle, nil},
  18. {Words(``, `\b`, `abstract`, `asm`, `as`, `begin`, `break`, `case`, `do`, `else`, `elsif`, `end`, `ensure`, `extend`, `ifdef`, `if`, `include`, `instance_sizeof`, `next`, `of`, `pointerof`, `private`, `protected`, `rescue`, `return`, `require`, `sizeof`, `super`, `then`, `typeof`, `unless`, `until`, `when`, `while`, `with`, `yield`), Keyword, nil},
  19. {Words(``, `\b`, `true`, `false`, `nil`), KeywordConstant, nil},
  20. {`(module|lib)(\s+)([a-zA-Z_]\w*(?:::[a-zA-Z_]\w*)*)`, ByGroups(Keyword, Text, NameNamespace), nil},
  21. {`(def|fun|macro)(\s+)((?:[a-zA-Z_]\w*::)*)`, ByGroups(Keyword, Text, NameNamespace), Push("funcname")},
  22. {"def(?=[*%&^`~+-/\\[<>=])", Keyword, Push("funcname")},
  23. {`(class|struct|union|type|alias|enum)(\s+)((?:[a-zA-Z_]\w*::)*)`, ByGroups(Keyword, Text, NameNamespace), Push("classname")},
  24. {`(self|out|uninitialized)\b|(is_a|responds_to)\?`, KeywordPseudo, nil},
  25. {Words(``, `\b`, `debugger`, `record`, `pp`, `assert_responds_to`, `spawn`, `parallel`, `getter`, `setter`, `property`, `delegate`, `def_hash`, `def_equals`, `def_equals_and_hash`, `forward_missing_to`), NameBuiltinPseudo, nil},
  26. {`getter[!?]|property[!?]|__(DIR|FILE|LINE)__\b`, NameBuiltinPseudo, nil},
  27. {Words(`(?<!\.)`, `\b`, `Object`, `Value`, `Struct`, `Reference`, `Proc`, `Class`, `Nil`, `Symbol`, `Enum`, `Void`, `Bool`, `Number`, `Int`, `Int8`, `Int16`, `Int32`, `Int64`, `UInt8`, `UInt16`, `UInt32`, `UInt64`, `Float`, `Float32`, `Float64`, `Char`, `String`, `Pointer`, `Slice`, `Range`, `Exception`, `Regex`, `Mutex`, `StaticArray`, `Array`, `Hash`, `Set`, `Tuple`, `Deque`, `Box`, `Process`, `File`, `Dir`, `Time`, `Channel`, `Concurrent`, `Scheduler`, `abort`, `at_exit`, `caller`, `delay`, `exit`, `fork`, `future`, `get_stack_top`, `gets`, `lazy`, `loop`, `main`, `p`, `print`, `printf`, `puts`, `raise`, `rand`, `read_line`, `sleep`, `sprintf`, `system`, `with_color`), NameBuiltin, nil},
  28. {"(?<!\\w)(<<-?)([\"`\\']?)([a-zA-Z_]\\w*)(\\2)(.*?\\n)", StringHeredoc, nil},
  29. {`(<<-?)("|\')()(\2)(.*?\n)`, StringHeredoc, nil},
  30. {`__END__`, CommentPreproc, Push("end-part")},
  31. {`(?:^|(?<=[=<>~!:])|(?<=(?:\s|;)when\s)|(?<=(?:\s|;)or\s)|(?<=(?:\s|;)and\s)|(?<=\.index\s)|(?<=\.scan\s)|(?<=\.sub\s)|(?<=\.sub!\s)|(?<=\.gsub\s)|(?<=\.gsub!\s)|(?<=\.match\s)|(?<=(?:\s|;)if\s)|(?<=(?:\s|;)elsif\s)|(?<=^when\s)|(?<=^index\s)|(?<=^scan\s)|(?<=^sub\s)|(?<=^gsub\s)|(?<=^sub!\s)|(?<=^gsub!\s)|(?<=^match\s)|(?<=^if\s)|(?<=^elsif\s))(\s*)(/)`, ByGroups(Text, LiteralStringRegex), Push("multiline-regex")},
  32. {`(?<=\(|,|\[)/`, LiteralStringRegex, Push("multiline-regex")},
  33. {`(\s+)(/)(?![\s=])`, ByGroups(Text, LiteralStringRegex), Push("multiline-regex")},
  34. {`(0o[0-7]+(?:_[0-7]+)*(?:_?[iu][0-9]+)?)\b(\s*)([/?])?`, ByGroups(LiteralNumberOct, Text, Operator), nil},
  35. {`(0x[0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*(?:_?[iu][0-9]+)?)\b(\s*)([/?])?`, ByGroups(LiteralNumberHex, Text, Operator), nil},
  36. {`(0b[01]+(?:_[01]+)*(?:_?[iu][0-9]+)?)\b(\s*)([/?])?`, ByGroups(LiteralNumberBin, Text, Operator), nil},
  37. {`((?:0(?![0-9])|[1-9][\d_]*)(?:\.\d[\d_]*)(?:e[+-]?[0-9]+)?(?:_?f[0-9]+)?)(\s*)([/?])?`, ByGroups(LiteralNumberFloat, Text, Operator), nil},
  38. {`((?:0(?![0-9])|[1-9][\d_]*)(?:\.\d[\d_]*)?(?:e[+-]?[0-9]+)(?:_?f[0-9]+)?)(\s*)([/?])?`, ByGroups(LiteralNumberFloat, Text, Operator), nil},
  39. {`((?:0(?![0-9])|[1-9][\d_]*)(?:\.\d[\d_]*)?(?:e[+-]?[0-9]+)?(?:_?f[0-9]+))(\s*)([/?])?`, ByGroups(LiteralNumberFloat, Text, Operator), nil},
  40. {`(0\b|[1-9][\d]*(?:_\d+)*(?:_?[iu][0-9]+)?)\b(\s*)([/?])?`, ByGroups(LiteralNumberInteger, Text, Operator), nil},
  41. {`@@[a-zA-Z_]\w*`, NameVariableClass, nil},
  42. {`@[a-zA-Z_]\w*`, NameVariableInstance, nil},
  43. {`\$\w+`, NameVariableGlobal, nil},
  44. {"\\$[!@&`\\'+~=/\\\\,;.<>_*$?:\"^-]", NameVariableGlobal, nil},
  45. {`\$-[0adFiIlpvw]`, NameVariableGlobal, nil},
  46. {`::`, Operator, nil},
  47. Include("strings"),
  48. {`\?(\\[MC]-)*(\\([\\befnrtv#"\']|x[a-fA-F0-9]{1,2}|[0-7]{1,3})|\S)(?!\w)`, LiteralStringChar, nil},
  49. {`[A-Z][A-Z_]+\b`, NameConstant, nil},
  50. {`\{%`, LiteralStringInterpol, Push("in-macro-control")},
  51. {`\{\{`, LiteralStringInterpol, Push("in-macro-expr")},
  52. {`(@\[)(\s*)([A-Z]\w*)`, ByGroups(Operator, Text, NameDecorator), Push("in-attr")},
  53. {Words(`(\.|::)`, ``, `!=`, `!~`, `!`, `%`, `&&`, `&`, `**`, `*`, `+`, `-`, `/`, `<=>`, `<<`, `<=`, `<`, `===`, `==`, `=~`, `=`, `>=`, `>>`, `>`, `[]=`, `[]?`, `[]`, `^`, `||`, `|`, `~`), ByGroups(Operator, NameOperator), nil},
  54. {"(\\.|::)([a-zA-Z_]\\w*[!?]?|[*%&^`~+\\-/\\[<>=])", ByGroups(Operator, Name), nil},
  55. {`[a-zA-Z_]\w*(?:[!?](?!=))?`, Name, nil},
  56. {`(\[|\]\??|\*\*|<=>?|>=|<<?|>>?|=~|===|!~|&&?|\|\||\.{1,3})`, Operator, nil},
  57. {`[-+/*%=<>&!^|~]=?`, Operator, nil},
  58. {`[(){};,/?:\\]`, Punctuation, nil},
  59. {`\s+`, Text, nil},
  60. },
  61. "funcname": {
  62. {"(?:([a-zA-Z_]\\w*)(\\.))?([a-zA-Z_]\\w*[!?]?|\\*\\*?|[-+]@?|[/%&|^`~]|\\[\\]=?|<<|>>|<=?>|>=?|===?)", ByGroups(NameClass, Operator, NameFunction), Pop(1)},
  63. Default(Pop(1)),
  64. },
  65. "classname": {
  66. {`[A-Z_]\w*`, NameClass, nil},
  67. {`(\()(\s*)([A-Z_]\w*)(\s*)(\))`, ByGroups(Punctuation, Text, NameClass, Text, Punctuation), nil},
  68. Default(Pop(1)),
  69. },
  70. "in-intp": {
  71. {`\{`, LiteralStringInterpol, Push()},
  72. {`\}`, LiteralStringInterpol, Pop(1)},
  73. Include("root"),
  74. },
  75. "string-intp": {
  76. {`#\{`, LiteralStringInterpol, Push("in-intp")},
  77. },
  78. "string-escaped": {
  79. {`\\([\\befnstv#"\']|x[a-fA-F0-9]{1,2}|[0-7]{1,3})`, LiteralStringEscape, nil},
  80. },
  81. "string-intp-escaped": {
  82. Include("string-intp"),
  83. Include("string-escaped"),
  84. },
  85. "interpolated-regex": {
  86. Include("string-intp"),
  87. {`[\\#]`, LiteralStringRegex, nil},
  88. {`[^\\#]+`, LiteralStringRegex, nil},
  89. },
  90. "interpolated-string": {
  91. Include("string-intp"),
  92. {`[\\#]`, LiteralStringOther, nil},
  93. {`[^\\#]+`, LiteralStringOther, nil},
  94. },
  95. "multiline-regex": {
  96. Include("string-intp"),
  97. {`\\\\`, LiteralStringRegex, nil},
  98. {`\\/`, LiteralStringRegex, nil},
  99. {`[\\#]`, LiteralStringRegex, nil},
  100. {`[^\\/#]+`, LiteralStringRegex, nil},
  101. {`/[imsx]*`, LiteralStringRegex, Pop(1)},
  102. },
  103. "end-part": {
  104. {`.+`, CommentPreproc, Pop(1)},
  105. },
  106. "in-macro-control": {
  107. {`\{%`, LiteralStringInterpol, Push()},
  108. {`%\}`, LiteralStringInterpol, Pop(1)},
  109. {`for\b|in\b`, Keyword, nil},
  110. Include("root"),
  111. },
  112. "in-macro-expr": {
  113. {`\{\{`, LiteralStringInterpol, Push()},
  114. {`\}\}`, LiteralStringInterpol, Pop(1)},
  115. Include("root"),
  116. },
  117. "in-attr": {
  118. {`\[`, Operator, Push()},
  119. {`\]`, Operator, Pop(1)},
  120. Include("root"),
  121. },
  122. "strings": {
  123. {`\:@{0,2}[a-zA-Z_]\w*[!?]?`, LiteralStringSymbol, nil},
  124. {Words(`\:@{0,2}`, ``, `!=`, `!~`, `!`, `%`, `&&`, `&`, `**`, `*`, `+`, `-`, `/`, `<=>`, `<<`, `<=`, `<`, `===`, `==`, `=~`, `=`, `>=`, `>>`, `>`, `[]=`, `[]?`, `[]`, `^`, `||`, `|`, `~`), LiteralStringSymbol, nil},
  125. {`:'(\\\\|\\'|[^'])*'`, LiteralStringSymbol, nil},
  126. {`'(\\\\|\\'|[^']|\\[^'\\]+)'`, LiteralStringChar, nil},
  127. {`:"`, LiteralStringSymbol, Push("simple-sym")},
  128. {`([a-zA-Z_]\w*)(:)(?!:)`, ByGroups(LiteralStringSymbol, Punctuation), nil},
  129. {`"`, LiteralStringDouble, Push("simple-string")},
  130. {"(?<!\\.)`", LiteralStringBacktick, Push("simple-backtick")},
  131. {`%\{`, LiteralStringOther, Push("cb-intp-string")},
  132. {`%[wi]\{`, LiteralStringOther, Push("cb-string")},
  133. {`%r\{`, LiteralStringRegex, Push("cb-regex")},
  134. {`%\[`, LiteralStringOther, Push("sb-intp-string")},
  135. {`%[wi]\[`, LiteralStringOther, Push("sb-string")},
  136. {`%r\[`, LiteralStringRegex, Push("sb-regex")},
  137. {`%\(`, LiteralStringOther, Push("pa-intp-string")},
  138. {`%[wi]\(`, LiteralStringOther, Push("pa-string")},
  139. {`%r\(`, LiteralStringRegex, Push("pa-regex")},
  140. {`%<`, LiteralStringOther, Push("ab-intp-string")},
  141. {`%[wi]<`, LiteralStringOther, Push("ab-string")},
  142. {`%r<`, LiteralStringRegex, Push("ab-regex")},
  143. {`(%r([\W_]))((?:\\\2|(?!\2).)*)(\2[imsx]*)`, String, nil},
  144. {`(%[wi]([\W_]))((?:\\\2|(?!\2).)*)(\2)`, String, nil},
  145. {`(?<=[-+/*%=<>&!^|~,(])(\s*)(%([\t ])(?:(?:\\\3|(?!\3).)*)\3)`, ByGroups(Text, LiteralStringOther, None), nil},
  146. {`^(\s*)(%([\t ])(?:(?:\\\3|(?!\3).)*)\3)`, ByGroups(Text, LiteralStringOther, None), nil},
  147. {`(%([\[{(<]))((?:\\\2|(?!\2).)*)(\2)`, String, nil},
  148. },
  149. "simple-string": {
  150. Include("string-intp-escaped"),
  151. {`[^\\"#]+`, LiteralStringDouble, nil},
  152. {`[\\#]`, LiteralStringDouble, nil},
  153. {`"`, LiteralStringDouble, Pop(1)},
  154. },
  155. "simple-sym": {
  156. Include("string-escaped"),
  157. {`[^\\"#]+`, LiteralStringSymbol, nil},
  158. {`[\\#]`, LiteralStringSymbol, nil},
  159. {`"`, LiteralStringSymbol, Pop(1)},
  160. },
  161. "simple-backtick": {
  162. Include("string-intp-escaped"),
  163. {"[^\\\\`#]+", LiteralStringBacktick, nil},
  164. {`[\\#]`, LiteralStringBacktick, nil},
  165. {"`", LiteralStringBacktick, Pop(1)},
  166. },
  167. "cb-intp-string": {
  168. {`\\[\{]`, LiteralStringOther, nil},
  169. {`\{`, LiteralStringOther, Push()},
  170. {`\}`, LiteralStringOther, Pop(1)},
  171. Include("string-intp-escaped"),
  172. {`[\\#{}]`, LiteralStringOther, nil},
  173. {`[^\\#{}]+`, LiteralStringOther, nil},
  174. },
  175. "cb-string": {
  176. {`\\[\\{}]`, LiteralStringOther, nil},
  177. {`\{`, LiteralStringOther, Push()},
  178. {`\}`, LiteralStringOther, Pop(1)},
  179. {`[\\#{}]`, LiteralStringOther, nil},
  180. {`[^\\#{}]+`, LiteralStringOther, nil},
  181. },
  182. "cb-regex": {
  183. {`\\[\\{}]`, LiteralStringRegex, nil},
  184. {`\{`, LiteralStringRegex, Push()},
  185. {`\}[imsx]*`, LiteralStringRegex, Pop(1)},
  186. Include("string-intp"),
  187. {`[\\#{}]`, LiteralStringRegex, nil},
  188. {`[^\\#{}]+`, LiteralStringRegex, nil},
  189. },
  190. "sb-intp-string": {
  191. {`\\[\[]`, LiteralStringOther, nil},
  192. {`\[`, LiteralStringOther, Push()},
  193. {`\]`, LiteralStringOther, Pop(1)},
  194. Include("string-intp-escaped"),
  195. {`[\\#\[\]]`, LiteralStringOther, nil},
  196. {`[^\\#\[\]]+`, LiteralStringOther, nil},
  197. },
  198. "sb-string": {
  199. {`\\[\\\[\]]`, LiteralStringOther, nil},
  200. {`\[`, LiteralStringOther, Push()},
  201. {`\]`, LiteralStringOther, Pop(1)},
  202. {`[\\#\[\]]`, LiteralStringOther, nil},
  203. {`[^\\#\[\]]+`, LiteralStringOther, nil},
  204. },
  205. "sb-regex": {
  206. {`\\[\\\[\]]`, LiteralStringRegex, nil},
  207. {`\[`, LiteralStringRegex, Push()},
  208. {`\][imsx]*`, LiteralStringRegex, Pop(1)},
  209. Include("string-intp"),
  210. {`[\\#\[\]]`, LiteralStringRegex, nil},
  211. {`[^\\#\[\]]+`, LiteralStringRegex, nil},
  212. },
  213. "pa-intp-string": {
  214. {`\\[\(]`, LiteralStringOther, nil},
  215. {`\(`, LiteralStringOther, Push()},
  216. {`\)`, LiteralStringOther, Pop(1)},
  217. Include("string-intp-escaped"),
  218. {`[\\#()]`, LiteralStringOther, nil},
  219. {`[^\\#()]+`, LiteralStringOther, nil},
  220. },
  221. "pa-string": {
  222. {`\\[\\()]`, LiteralStringOther, nil},
  223. {`\(`, LiteralStringOther, Push()},
  224. {`\)`, LiteralStringOther, Pop(1)},
  225. {`[\\#()]`, LiteralStringOther, nil},
  226. {`[^\\#()]+`, LiteralStringOther, nil},
  227. },
  228. "pa-regex": {
  229. {`\\[\\()]`, LiteralStringRegex, nil},
  230. {`\(`, LiteralStringRegex, Push()},
  231. {`\)[imsx]*`, LiteralStringRegex, Pop(1)},
  232. Include("string-intp"),
  233. {`[\\#()]`, LiteralStringRegex, nil},
  234. {`[^\\#()]+`, LiteralStringRegex, nil},
  235. },
  236. "ab-intp-string": {
  237. {`\\[<]`, LiteralStringOther, nil},
  238. {`<`, LiteralStringOther, Push()},
  239. {`>`, LiteralStringOther, Pop(1)},
  240. Include("string-intp-escaped"),
  241. {`[\\#<>]`, LiteralStringOther, nil},
  242. {`[^\\#<>]+`, LiteralStringOther, nil},
  243. },
  244. "ab-string": {
  245. {`\\[\\<>]`, LiteralStringOther, nil},
  246. {`<`, LiteralStringOther, Push()},
  247. {`>`, LiteralStringOther, Pop(1)},
  248. {`[\\#<>]`, LiteralStringOther, nil},
  249. {`[^\\#<>]+`, LiteralStringOther, nil},
  250. },
  251. "ab-regex": {
  252. {`\\[\\<>]`, LiteralStringRegex, nil},
  253. {`<`, LiteralStringRegex, Push()},
  254. {`>[imsx]*`, LiteralStringRegex, Pop(1)},
  255. Include("string-intp"),
  256. {`[\\#<>]`, LiteralStringRegex, nil},
  257. {`[^\\#<>]+`, LiteralStringRegex, nil},
  258. },
  259. },
  260. ))