|
1 # -*- coding: utf-8 -*- |
|
2 """ |
|
3 pygments.lexers.rebol |
|
4 ~~~~~~~~~~~~~~~~~~~~~ |
|
5 |
|
6 Lexers for the REBOL and related languages. |
|
7 |
|
8 :copyright: Copyright 2006-2017 by the Pygments team, see AUTHORS. |
|
9 :license: BSD, see LICENSE for details. |
|
10 """ |
|
11 |
|
12 import re |
|
13 |
|
14 from pygments.lexer import RegexLexer, bygroups |
|
15 from pygments.token import Text, Comment, Operator, Keyword, Name, String, \ |
|
16 Number, Generic, Whitespace |
|
17 |
|
18 __all__ = ['RebolLexer', 'RedLexer'] |
|
19 |
|
20 |
|
21 class RebolLexer(RegexLexer): |
|
22 """ |
|
23 A `REBOL <http://www.rebol.com/>`_ lexer. |
|
24 |
|
25 .. versionadded:: 1.1 |
|
26 """ |
|
27 name = 'REBOL' |
|
28 aliases = ['rebol'] |
|
29 filenames = ['*.r', '*.r3', '*.reb'] |
|
30 mimetypes = ['text/x-rebol'] |
|
31 |
|
32 flags = re.IGNORECASE | re.MULTILINE |
|
33 |
|
34 escape_re = r'(?:\^\([0-9a-f]{1,4}\)*)' |
|
35 |
|
36 def word_callback(lexer, match): |
|
37 word = match.group() |
|
38 |
|
39 if re.match(".*:$", word): |
|
40 yield match.start(), Generic.Subheading, word |
|
41 elif re.match( |
|
42 r'(native|alias|all|any|as-string|as-binary|bind|bound\?|case|' |
|
43 r'catch|checksum|comment|debase|dehex|exclude|difference|disarm|' |
|
44 r'either|else|enbase|foreach|remove-each|form|free|get|get-env|if|' |
|
45 r'in|intersect|loop|minimum-of|maximum-of|mold|new-line|' |
|
46 r'new-line\?|not|now|prin|print|reduce|compose|construct|repeat|' |
|
47 r'reverse|save|script\?|set|shift|switch|throw|to-hex|trace|try|' |
|
48 r'type\?|union|unique|unless|unprotect|unset|until|use|value\?|' |
|
49 r'while|compress|decompress|secure|open|close|read|read-io|' |
|
50 r'write-io|write|update|query|wait|input\?|exp|log-10|log-2|' |
|
51 r'log-e|square-root|cosine|sine|tangent|arccosine|arcsine|' |
|
52 r'arctangent|protect|lowercase|uppercase|entab|detab|connected\?|' |
|
53 r'browse|launch|stats|get-modes|set-modes|to-local-file|' |
|
54 r'to-rebol-file|encloak|decloak|create-link|do-browser|bind\?|' |
|
55 r'hide|draw|show|size-text|textinfo|offset-to-caret|' |
|
56 r'caret-to-offset|local-request-file|rgb-to-hsv|hsv-to-rgb|' |
|
57 r'crypt-strength\?|dh-make-key|dh-generate-key|dh-compute-key|' |
|
58 r'dsa-make-key|dsa-generate-key|dsa-make-signature|' |
|
59 r'dsa-verify-signature|rsa-make-key|rsa-generate-key|' |
|
60 r'rsa-encrypt)$', word): |
|
61 yield match.start(), Name.Builtin, word |
|
62 elif re.match( |
|
63 r'(add|subtract|multiply|divide|remainder|power|and~|or~|xor~|' |
|
64 r'minimum|maximum|negate|complement|absolute|random|head|tail|' |
|
65 r'next|back|skip|at|pick|first|second|third|fourth|fifth|sixth|' |
|
66 r'seventh|eighth|ninth|tenth|last|path|find|select|make|to|copy\*|' |
|
67 r'insert|remove|change|poke|clear|trim|sort|min|max|abs|cp|' |
|
68 r'copy)$', word): |
|
69 yield match.start(), Name.Function, word |
|
70 elif re.match( |
|
71 r'(error|source|input|license|help|install|echo|Usage|with|func|' |
|
72 r'throw-on-error|function|does|has|context|probe|\?\?|as-pair|' |
|
73 r'mod|modulo|round|repend|about|set-net|append|join|rejoin|reform|' |
|
74 r'remold|charset|array|replace|move|extract|forskip|forall|alter|' |
|
75 r'first+|also|take|for|forever|dispatch|attempt|what-dir|' |
|
76 r'change-dir|clean-path|list-dir|dirize|rename|split-path|delete|' |
|
77 r'make-dir|delete-dir|in-dir|confirm|dump-obj|upgrade|what|' |
|
78 r'build-tag|process-source|build-markup|decode-cgi|read-cgi|' |
|
79 r'write-user|save-user|set-user-name|protect-system|parse-xml|' |
|
80 r'cvs-date|cvs-version|do-boot|get-net-info|desktop|layout|' |
|
81 r'scroll-para|get-face|alert|set-face|uninstall|unfocus|' |
|
82 r'request-dir|center-face|do-events|net-error|decode-url|' |
|
83 r'parse-header|parse-header-date|parse-email-addrs|import-email|' |
|
84 r'send|build-attach-body|resend|show-popup|hide-popup|open-events|' |
|
85 r'find-key-face|do-face|viewtop|confine|find-window|' |
|
86 r'insert-event-func|remove-event-func|inform|dump-pane|dump-face|' |
|
87 r'flag-face|deflag-face|clear-fields|read-net|vbug|path-thru|' |
|
88 r'read-thru|load-thru|do-thru|launch-thru|load-image|' |
|
89 r'request-download|do-face-alt|set-font|set-para|get-style|' |
|
90 r'set-style|make-face|stylize|choose|hilight-text|hilight-all|' |
|
91 r'unlight-text|focus|scroll-drag|clear-face|reset-face|scroll-face|' |
|
92 r'resize-face|load-stock|load-stock-block|notify|request|flash|' |
|
93 r'request-color|request-pass|request-text|request-list|' |
|
94 r'request-date|request-file|dbug|editor|link-relative-path|' |
|
95 r'emailer|parse-error)$', word): |
|
96 yield match.start(), Keyword.Namespace, word |
|
97 elif re.match( |
|
98 r'(halt|quit|do|load|q|recycle|call|run|ask|parse|view|unview|' |
|
99 r'return|exit|break)$', word): |
|
100 yield match.start(), Name.Exception, word |
|
101 elif re.match('REBOL$', word): |
|
102 yield match.start(), Generic.Heading, word |
|
103 elif re.match("to-.*", word): |
|
104 yield match.start(), Keyword, word |
|
105 elif re.match(r'(\+|-|\*|/|//|\*\*|and|or|xor|=\?|=|==|<>|<|>|<=|>=)$', |
|
106 word): |
|
107 yield match.start(), Operator, word |
|
108 elif re.match(r".*\?$", word): |
|
109 yield match.start(), Keyword, word |
|
110 elif re.match(r".*\!$", word): |
|
111 yield match.start(), Keyword.Type, word |
|
112 elif re.match("'.*", word): |
|
113 yield match.start(), Name.Variable.Instance, word # lit-word |
|
114 elif re.match("#.*", word): |
|
115 yield match.start(), Name.Label, word # issue |
|
116 elif re.match("%.*", word): |
|
117 yield match.start(), Name.Decorator, word # file |
|
118 else: |
|
119 yield match.start(), Name.Variable, word |
|
120 |
|
121 tokens = { |
|
122 'root': [ |
|
123 (r'[^R]+', Comment), |
|
124 (r'REBOL\s+\[', Generic.Strong, 'script'), |
|
125 (r'R', Comment) |
|
126 ], |
|
127 'script': [ |
|
128 (r'\s+', Text), |
|
129 (r'#"', String.Char, 'char'), |
|
130 (r'#\{[0-9a-f]*\}', Number.Hex), |
|
131 (r'2#\{', Number.Hex, 'bin2'), |
|
132 (r'64#\{[0-9a-z+/=\s]*\}', Number.Hex), |
|
133 (r'"', String, 'string'), |
|
134 (r'\{', String, 'string2'), |
|
135 (r';#+.*\n', Comment.Special), |
|
136 (r';\*+.*\n', Comment.Preproc), |
|
137 (r';.*\n', Comment), |
|
138 (r'%"', Name.Decorator, 'stringFile'), |
|
139 (r'%[^(^{")\s\[\]]+', Name.Decorator), |
|
140 (r'[+-]?([a-z]{1,3})?\$\d+(\.\d+)?', Number.Float), # money |
|
141 (r'[+-]?\d+\:\d+(\:\d+)?(\.\d+)?', String.Other), # time |
|
142 (r'\d+[\-/][0-9a-z]+[\-/]\d+(\/\d+\:\d+((\:\d+)?' |
|
143 r'([.\d+]?([+-]?\d+:\d+)?)?)?)?', String.Other), # date |
|
144 (r'\d+(\.\d+)+\.\d+', Keyword.Constant), # tuple |
|
145 (r'\d+X\d+', Keyword.Constant), # pair |
|
146 (r'[+-]?\d+(\'\d+)?([.,]\d*)?E[+-]?\d+', Number.Float), |
|
147 (r'[+-]?\d+(\'\d+)?[.,]\d*', Number.Float), |
|
148 (r'[+-]?\d+(\'\d+)?', Number), |
|
149 (r'[\[\]()]', Generic.Strong), |
|
150 (r'[a-z]+[^(^{"\s:)]*://[^(^{"\s)]*', Name.Decorator), # url |
|
151 (r'mailto:[^(^{"@\s)]+@[^(^{"@\s)]+', Name.Decorator), # url |
|
152 (r'[^(^{"@\s)]+@[^(^{"@\s)]+', Name.Decorator), # email |
|
153 (r'comment\s"', Comment, 'commentString1'), |
|
154 (r'comment\s\{', Comment, 'commentString2'), |
|
155 (r'comment\s\[', Comment, 'commentBlock'), |
|
156 (r'comment\s[^(\s{"\[]+', Comment), |
|
157 (r'/[^(^{")\s/[\]]*', Name.Attribute), |
|
158 (r'([^(^{")\s/[\]]+)(?=[:({"\s/\[\]])', word_callback), |
|
159 (r'<[\w:.-]*>', Name.Tag), |
|
160 (r'<[^(<>\s")]+', Name.Tag, 'tag'), |
|
161 (r'([^(^{")\s]+)', Text), |
|
162 ], |
|
163 'string': [ |
|
164 (r'[^(^")]+', String), |
|
165 (escape_re, String.Escape), |
|
166 (r'[(|)]+', String), |
|
167 (r'\^.', String.Escape), |
|
168 (r'"', String, '#pop'), |
|
169 ], |
|
170 'string2': [ |
|
171 (r'[^(^{})]+', String), |
|
172 (escape_re, String.Escape), |
|
173 (r'[(|)]+', String), |
|
174 (r'\^.', String.Escape), |
|
175 (r'\{', String, '#push'), |
|
176 (r'\}', String, '#pop'), |
|
177 ], |
|
178 'stringFile': [ |
|
179 (r'[^(^")]+', Name.Decorator), |
|
180 (escape_re, Name.Decorator), |
|
181 (r'\^.', Name.Decorator), |
|
182 (r'"', Name.Decorator, '#pop'), |
|
183 ], |
|
184 'char': [ |
|
185 (escape_re + '"', String.Char, '#pop'), |
|
186 (r'\^."', String.Char, '#pop'), |
|
187 (r'."', String.Char, '#pop'), |
|
188 ], |
|
189 'tag': [ |
|
190 (escape_re, Name.Tag), |
|
191 (r'"', Name.Tag, 'tagString'), |
|
192 (r'[^(<>\r\n")]+', Name.Tag), |
|
193 (r'>', Name.Tag, '#pop'), |
|
194 ], |
|
195 'tagString': [ |
|
196 (r'[^(^")]+', Name.Tag), |
|
197 (escape_re, Name.Tag), |
|
198 (r'[(|)]+', Name.Tag), |
|
199 (r'\^.', Name.Tag), |
|
200 (r'"', Name.Tag, '#pop'), |
|
201 ], |
|
202 'tuple': [ |
|
203 (r'(\d+\.)+', Keyword.Constant), |
|
204 (r'\d+', Keyword.Constant, '#pop'), |
|
205 ], |
|
206 'bin2': [ |
|
207 (r'\s+', Number.Hex), |
|
208 (r'([01]\s*){8}', Number.Hex), |
|
209 (r'\}', Number.Hex, '#pop'), |
|
210 ], |
|
211 'commentString1': [ |
|
212 (r'[^(^")]+', Comment), |
|
213 (escape_re, Comment), |
|
214 (r'[(|)]+', Comment), |
|
215 (r'\^.', Comment), |
|
216 (r'"', Comment, '#pop'), |
|
217 ], |
|
218 'commentString2': [ |
|
219 (r'[^(^{})]+', Comment), |
|
220 (escape_re, Comment), |
|
221 (r'[(|)]+', Comment), |
|
222 (r'\^.', Comment), |
|
223 (r'\{', Comment, '#push'), |
|
224 (r'\}', Comment, '#pop'), |
|
225 ], |
|
226 'commentBlock': [ |
|
227 (r'\[', Comment, '#push'), |
|
228 (r'\]', Comment, '#pop'), |
|
229 (r'"', Comment, "commentString1"), |
|
230 (r'\{', Comment, "commentString2"), |
|
231 (r'[^(\[\]"{)]+', Comment), |
|
232 ], |
|
233 } |
|
234 |
|
235 def analyse_text(text): |
|
236 """ |
|
237 Check if code contains REBOL header and so it probably not R code |
|
238 """ |
|
239 if re.match(r'^\s*REBOL\s*\[', text, re.IGNORECASE): |
|
240 # The code starts with REBOL header |
|
241 return 1.0 |
|
242 elif re.search(r'\s*REBOL\s*[', text, re.IGNORECASE): |
|
243 # The code contains REBOL header but also some text before it |
|
244 return 0.5 |
|
245 |
|
246 |
|
247 class RedLexer(RegexLexer): |
|
248 """ |
|
249 A `Red-language <http://www.red-lang.org/>`_ lexer. |
|
250 |
|
251 .. versionadded:: 2.0 |
|
252 """ |
|
253 name = 'Red' |
|
254 aliases = ['red', 'red/system'] |
|
255 filenames = ['*.red', '*.reds'] |
|
256 mimetypes = ['text/x-red', 'text/x-red-system'] |
|
257 |
|
258 flags = re.IGNORECASE | re.MULTILINE |
|
259 |
|
260 escape_re = r'(?:\^\([0-9a-f]{1,4}\)*)' |
|
261 |
|
262 def word_callback(lexer, match): |
|
263 word = match.group() |
|
264 |
|
265 if re.match(".*:$", word): |
|
266 yield match.start(), Generic.Subheading, word |
|
267 elif re.match(r'(if|unless|either|any|all|while|until|loop|repeat|' |
|
268 r'foreach|forall|func|function|does|has|switch|' |
|
269 r'case|reduce|compose|get|set|print|prin|equal\?|' |
|
270 r'not-equal\?|strict-equal\?|lesser\?|greater\?|lesser-or-equal\?|' |
|
271 r'greater-or-equal\?|same\?|not|type\?|stats|' |
|
272 r'bind|union|replace|charset|routine)$', word): |
|
273 yield match.start(), Name.Builtin, word |
|
274 elif re.match(r'(make|random|reflect|to|form|mold|absolute|add|divide|multiply|negate|' |
|
275 r'power|remainder|round|subtract|even\?|odd\?|and~|complement|or~|xor~|' |
|
276 r'append|at|back|change|clear|copy|find|head|head\?|index\?|insert|' |
|
277 r'length\?|next|pick|poke|remove|reverse|select|sort|skip|swap|tail|tail\?|' |
|
278 r'take|trim|create|close|delete|modify|open|open\?|query|read|rename|' |
|
279 r'update|write)$', word): |
|
280 yield match.start(), Name.Function, word |
|
281 elif re.match(r'(yes|on|no|off|true|false|tab|cr|lf|newline|escape|slash|sp|space|null|' |
|
282 r'none|crlf|dot|null-byte)$', word): |
|
283 yield match.start(), Name.Builtin.Pseudo, word |
|
284 elif re.match(r'(#system-global|#include|#enum|#define|#either|#if|#import|#export|' |
|
285 r'#switch|#default|#get-definition)$', word): |
|
286 yield match.start(), Keyword.Namespace, word |
|
287 elif re.match(r'(system|halt|quit|quit-return|do|load|q|recycle|call|run|ask|parse|' |
|
288 r'raise-error|return|exit|break|alias|push|pop|probe|\?\?|spec-of|body-of|' |
|
289 r'quote|forever)$', word): |
|
290 yield match.start(), Name.Exception, word |
|
291 elif re.match(r'(action\?|block\?|char\?|datatype\?|file\?|function\?|get-path\?|zero\?|' |
|
292 r'get-word\?|integer\?|issue\?|lit-path\?|lit-word\?|logic\?|native\?|' |
|
293 r'op\?|paren\?|path\?|refinement\?|set-path\?|set-word\?|string\?|unset\?|' |
|
294 r'any-struct\?|none\?|word\?|any-series\?)$', word): |
|
295 yield match.start(), Keyword, word |
|
296 elif re.match(r'(JNICALL|stdcall|cdecl|infix)$', word): |
|
297 yield match.start(), Keyword.Namespace, word |
|
298 elif re.match("to-.*", word): |
|
299 yield match.start(), Keyword, word |
|
300 elif re.match(r'(\+|-\*\*|-|\*\*|//|/|\*|and|or|xor|=\?|===|==|=|<>|<=|>=|' |
|
301 r'<<<|>>>|<<|>>|<|>%)$', word): |
|
302 yield match.start(), Operator, word |
|
303 elif re.match(r".*\!$", word): |
|
304 yield match.start(), Keyword.Type, word |
|
305 elif re.match("'.*", word): |
|
306 yield match.start(), Name.Variable.Instance, word # lit-word |
|
307 elif re.match("#.*", word): |
|
308 yield match.start(), Name.Label, word # issue |
|
309 elif re.match("%.*", word): |
|
310 yield match.start(), Name.Decorator, word # file |
|
311 elif re.match(":.*", word): |
|
312 yield match.start(), Generic.Subheading, word # get-word |
|
313 else: |
|
314 yield match.start(), Name.Variable, word |
|
315 |
|
316 tokens = { |
|
317 'root': [ |
|
318 (r'[^R]+', Comment), |
|
319 (r'Red/System\s+\[', Generic.Strong, 'script'), |
|
320 (r'Red\s+\[', Generic.Strong, 'script'), |
|
321 (r'R', Comment) |
|
322 ], |
|
323 'script': [ |
|
324 (r'\s+', Text), |
|
325 (r'#"', String.Char, 'char'), |
|
326 (r'#\{[0-9a-f\s]*\}', Number.Hex), |
|
327 (r'2#\{', Number.Hex, 'bin2'), |
|
328 (r'64#\{[0-9a-z+/=\s]*\}', Number.Hex), |
|
329 (r'([0-9a-f]+)(h)((\s)|(?=[\[\]{}"()]))', |
|
330 bygroups(Number.Hex, Name.Variable, Whitespace)), |
|
331 (r'"', String, 'string'), |
|
332 (r'\{', String, 'string2'), |
|
333 (r';#+.*\n', Comment.Special), |
|
334 (r';\*+.*\n', Comment.Preproc), |
|
335 (r';.*\n', Comment), |
|
336 (r'%"', Name.Decorator, 'stringFile'), |
|
337 (r'%[^(^{")\s\[\]]+', Name.Decorator), |
|
338 (r'[+-]?([a-z]{1,3})?\$\d+(\.\d+)?', Number.Float), # money |
|
339 (r'[+-]?\d+\:\d+(\:\d+)?(\.\d+)?', String.Other), # time |
|
340 (r'\d+[\-/][0-9a-z]+[\-/]\d+(/\d+:\d+((:\d+)?' |
|
341 r'([\.\d+]?([+-]?\d+:\d+)?)?)?)?', String.Other), # date |
|
342 (r'\d+(\.\d+)+\.\d+', Keyword.Constant), # tuple |
|
343 (r'\d+X\d+', Keyword.Constant), # pair |
|
344 (r'[+-]?\d+(\'\d+)?([.,]\d*)?E[+-]?\d+', Number.Float), |
|
345 (r'[+-]?\d+(\'\d+)?[.,]\d*', Number.Float), |
|
346 (r'[+-]?\d+(\'\d+)?', Number), |
|
347 (r'[\[\]()]', Generic.Strong), |
|
348 (r'[a-z]+[^(^{"\s:)]*://[^(^{"\s)]*', Name.Decorator), # url |
|
349 (r'mailto:[^(^{"@\s)]+@[^(^{"@\s)]+', Name.Decorator), # url |
|
350 (r'[^(^{"@\s)]+@[^(^{"@\s)]+', Name.Decorator), # email |
|
351 (r'comment\s"', Comment, 'commentString1'), |
|
352 (r'comment\s\{', Comment, 'commentString2'), |
|
353 (r'comment\s\[', Comment, 'commentBlock'), |
|
354 (r'comment\s[^(\s{"\[]+', Comment), |
|
355 (r'/[^(^{^")\s/[\]]*', Name.Attribute), |
|
356 (r'([^(^{^")\s/[\]]+)(?=[:({"\s/\[\]])', word_callback), |
|
357 (r'<[\w:.-]*>', Name.Tag), |
|
358 (r'<[^(<>\s")]+', Name.Tag, 'tag'), |
|
359 (r'([^(^{")\s]+)', Text), |
|
360 ], |
|
361 'string': [ |
|
362 (r'[^(^")]+', String), |
|
363 (escape_re, String.Escape), |
|
364 (r'[(|)]+', String), |
|
365 (r'\^.', String.Escape), |
|
366 (r'"', String, '#pop'), |
|
367 ], |
|
368 'string2': [ |
|
369 (r'[^(^{})]+', String), |
|
370 (escape_re, String.Escape), |
|
371 (r'[(|)]+', String), |
|
372 (r'\^.', String.Escape), |
|
373 (r'\{', String, '#push'), |
|
374 (r'\}', String, '#pop'), |
|
375 ], |
|
376 'stringFile': [ |
|
377 (r'[^(^")]+', Name.Decorator), |
|
378 (escape_re, Name.Decorator), |
|
379 (r'\^.', Name.Decorator), |
|
380 (r'"', Name.Decorator, '#pop'), |
|
381 ], |
|
382 'char': [ |
|
383 (escape_re + '"', String.Char, '#pop'), |
|
384 (r'\^."', String.Char, '#pop'), |
|
385 (r'."', String.Char, '#pop'), |
|
386 ], |
|
387 'tag': [ |
|
388 (escape_re, Name.Tag), |
|
389 (r'"', Name.Tag, 'tagString'), |
|
390 (r'[^(<>\r\n")]+', Name.Tag), |
|
391 (r'>', Name.Tag, '#pop'), |
|
392 ], |
|
393 'tagString': [ |
|
394 (r'[^(^")]+', Name.Tag), |
|
395 (escape_re, Name.Tag), |
|
396 (r'[(|)]+', Name.Tag), |
|
397 (r'\^.', Name.Tag), |
|
398 (r'"', Name.Tag, '#pop'), |
|
399 ], |
|
400 'tuple': [ |
|
401 (r'(\d+\.)+', Keyword.Constant), |
|
402 (r'\d+', Keyword.Constant, '#pop'), |
|
403 ], |
|
404 'bin2': [ |
|
405 (r'\s+', Number.Hex), |
|
406 (r'([01]\s*){8}', Number.Hex), |
|
407 (r'\}', Number.Hex, '#pop'), |
|
408 ], |
|
409 'commentString1': [ |
|
410 (r'[^(^")]+', Comment), |
|
411 (escape_re, Comment), |
|
412 (r'[(|)]+', Comment), |
|
413 (r'\^.', Comment), |
|
414 (r'"', Comment, '#pop'), |
|
415 ], |
|
416 'commentString2': [ |
|
417 (r'[^(^{})]+', Comment), |
|
418 (escape_re, Comment), |
|
419 (r'[(|)]+', Comment), |
|
420 (r'\^.', Comment), |
|
421 (r'\{', Comment, '#push'), |
|
422 (r'\}', Comment, '#pop'), |
|
423 ], |
|
424 'commentBlock': [ |
|
425 (r'\[', Comment, '#push'), |
|
426 (r'\]', Comment, '#pop'), |
|
427 (r'"', Comment, "commentString1"), |
|
428 (r'\{', Comment, "commentString2"), |
|
429 (r'[^(\[\]"{)]+', Comment), |
|
430 ], |
|
431 } |