blob: 775f498dfb6b77ca67866bbdc2eb39c7b454abc5 [file] [log] [blame]
Doug Kearns68a89472024-01-05 17:59:04 +01001" Vim syntax file
2" Language: Modula-2 (R10)
3" Maintainer: B.Kowarsch <trijezdci@moc.liamg>
4" Last Change: 2020 June 18 (moved repository from bb to github)
5
6" ----------------------------------------------------
7" THIS FILE IS LICENSED UNDER THE VIM LICENSE
8" see https://github.com/vim/vim/blob/master/LICENSE
9" ----------------------------------------------------
10
11" Remarks:
12" Vim Syntax files are available for the following Modula-2 dialects:
13" * for the PIM dialect : m2pim.vim
14" * for the ISO dialect : m2iso.vim
15" * for the R10 dialect : m2r10.vim (this file)
16
17" -----------------------------------------------------------------------------
18" This syntax description follows the Modula-2 Revision 2010 language report
19" (Kowarsch and Sutcliffe, 2015) available at http://modula-2.info/m2r10.
20" -----------------------------------------------------------------------------
21
22" Parameters:
23"
24" Vim's filetype script recognises Modula-2 dialect tags within the first 200
25" lines of Modula-2 .def and .mod input files. The script sets filetype and
26" dialect automatically when a valid dialect tag is found in the input file.
27" The dialect tag for the R10 dialect is (*!m2r10*). It is recommended to put
28" the tag immediately after the module header in the Modula-2 input file.
29"
30" Example:
31" DEFINITION MODULE Foolib; (*!m2r10*)
32"
33" Variable g:modula2_default_dialect sets the default Modula-2 dialect when the
34" dialect cannot be determined from the contents of the Modula-2 input file:
35" if defined and set to 'm2r10', the default dialect is R10.
36"
37" Variable g:modula2_r10_allow_lowline controls support for lowline in identifiers:
38" if defined and set to a non-zero value, they are recognised, otherwise not
39"
40" Variables may be defined in Vim startup file .vimrc
41"
42" Examples:
43" let g:modula2_default_dialect = 'm2r10'
44" let g:modula2_r10_allow_lowline = 1
45
46
47if exists("b:current_syntax")
48 finish
49endif
50
51" Modula-2 is case sensitive
52syn case match
53
54
55" -----------------------------------------------------------------------------
56" Reserved Words
57" -----------------------------------------------------------------------------
58" Note: MODULE, PROCEDURE and END are defined separately further below
59syn keyword modula2Resword ALIAS AND ARGLIST ARRAY BEGIN CASE CONST COPY DEFINITION
60syn keyword modula2Resword DIV DO ELSE ELSIF EXIT FOR FROM GENLIB IF IMPLEMENTATION
61syn keyword modula2Resword IMPORT IN LOOP MOD NEW NOT OF OPAQUE OR POINTER READ
62syn keyword modula2Resword RECORD RELEASE REPEAT RETAIN RETURN SET THEN TO TYPE
63syn keyword modula2Resword UNTIL VAR WHILE WRITE YIELD
64
65
66" -----------------------------------------------------------------------------
67" Schroedinger's Tokens
68" -----------------------------------------------------------------------------
69syn keyword modula2SchroedToken CAPACITY COROUTINE LITERAL
70
71
72" -----------------------------------------------------------------------------
73" Builtin Constant Identifiers
74" -----------------------------------------------------------------------------
75syn keyword modula2ConstIdent NIL FALSE TRUE
76
77
78" -----------------------------------------------------------------------------
79" Builtin Type Identifiers
80" -----------------------------------------------------------------------------
81syn keyword modula2TypeIdent BOOLEAN CHAR UNICHAR OCTET
82syn keyword modula2TypeIdent CARDINAL LONGCARD INTEGER LONGINT REAL LONGREAL
83
84
85" -----------------------------------------------------------------------------
86" Builtin Procedure and Function Identifiers
87" -----------------------------------------------------------------------------
88syn keyword modula2ProcIdent APPEND INSERT REMOVE SORT SORTNEW
89syn keyword modula2FuncIdent CHR ORD ODD ABS SGN MIN MAX LOG2 POW2 ENTIER
90syn keyword modula2FuncIdent PRED SUCC PTR COUNT LENGTH
91
92
93" -----------------------------------------------------------------------------
94" Builtin Macro Identifiers
95" -----------------------------------------------------------------------------
96syn keyword modula2MacroIdent NOP TMIN TMAX TSIZE TLIMIT
97
98
99" -----------------------------------------------------------------------------
100" Builtin Primitives
101" -----------------------------------------------------------------------------
102syn keyword modula2PrimitiveIdent SXF VAL STORE VALUE SEEK SUBSET
103
104
105" -----------------------------------------------------------------------------
106" Unsafe Facilities via Pseudo-Module UNSAFE
107" -----------------------------------------------------------------------------
108syn keyword modula2UnsafeIdent UNSAFE BYTE WORD LONGWORD OCTETSEQ
109syn keyword modula2UnsafeIdent ADD SUB INC DEC SETBIT HALT
110syn keyword modula2UnsafeIdent ADR CAST BIT SHL SHR BWNOT BWAND BWOR
111
112
113" -----------------------------------------------------------------------------
114" Non-Portable Language Extensions
115" -----------------------------------------------------------------------------
116syn keyword modula2NonPortableIdent ASSEMBLER ASM REG
117
118
119" -----------------------------------------------------------------------------
120" User Defined Identifiers
121" -----------------------------------------------------------------------------
122syn match modula2Ident "[a-zA-Z][a-zA-Z0-9]*\(_\)\@!"
123syn match modula2LowLineIdent "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)\+"
124
125syn match modula2ReswordDo "\(TO\)\@<!DO"
126syn match modula2ReswordTo "TO\(\sDO\)\@!"
127
128" TODO: support for OpenVMS reswords and identifiers which may include $ and %
129
130
131" -----------------------------------------------------------------------------
132" String Literals
133" -----------------------------------------------------------------------------
134syn region modula2String start=/"/ end=/"/ oneline
135syn region modula2String start="\(^\|\s\|[({=<>&#,]\|\[\)\@<='" end=/'/ oneline
136
137
138" -----------------------------------------------------------------------------
139" Numeric Literals
140" -----------------------------------------------------------------------------
141syn match modula2Base2Num "0b[01]\+\('[01]\+\)*"
142syn match modula2Base16Num "0[ux][0-9A-F]\+\('[0-9A-F]\+\)*"
143
144"| *** VMSCRIPT BUG ALERT ***
145"| The regular expression below causes errors when split into separate strings
146"|
147"| syn match modula2Base10Num
148"| \ "\(\(0[bux]\@!\|[1-9]\)[0-9]*\('[0-9]\+\)*\)" .
149"| \ "\(\.[0-9]\+\('[0-9]\+\)*\(e[+-]\?[0-9]\+\('[0-9]\+\)*\)\?\)\?"
150"|
151"| E475: Invalid argument: modula2Base10Num "\(\(0[bux]\@!\|[1-9]\)[0-9]*\('[0-9]\+\)*\)"
152"| . "\(\.[0-9]\+\('[0-9]\+\)*\(e[+-]\?[0-9]\+\('[0-9]\+\)*\)\?\)\?"
153"|
154"| However, the same regular expression works just fine as a sole string.
155"|
156"| As a consequence, we have no choice but to put it all into a single line
157"| which greatly diminishes readability and thereby increases the opportunity
158"| for error during maintenance. Ideally, regular expressions should be split
159"| into small human readable pieces with interleaved comments that explain
160"| precisely what each piece is doing. Vimscript imposes poor design. :-(
161
162syn match modula2Base10Num
163 \ "\(\(0[bux]\@!\|[1-9]\)[0-9]*\('[0-9]\+\)*\)\(\.[0-9]\+\('[0-9]\+\)*\(e[+-]\?[0-9]\+\('[0-9]\+\)*\)\?\)\?"
164
165
166" -----------------------------------------------------------------------------
167" Punctuation
168" -----------------------------------------------------------------------------
169syn match modula2Punctuation
170 \ "\.\|[,:;]\|\*\|[/+-]\|\#\|[=<>&]\|\^\|\[\|\]\|(\(\*\)\@!\|[){}]"
171
172
173" -----------------------------------------------------------------------------
174" Pragmas
175" -----------------------------------------------------------------------------
176syn region modula2Pragma start="<\*" end="\*>"
177 \ contains = modula2PragmaKey, modula2TechDebtPragma
178syn keyword modula2PragmaKey contained MSG IF ELSIF ELSE END INLINE NOINLINE OUT
179syn keyword modula2PragmaKey contained GENERATED ENCODING ALIGN PADBITS NORETURN
180syn keyword modula2PragmaKey contained PURITY SINGLEASSIGN LOWLATENCY VOLATILE
181syn keyword modula2PragmaKey contained FORWARD ADDR FFI FFIDENT
182
183syn match modula2DialectTag "(\*!m2r10\(+[a-z0-9]\+\)\?\*)"
184
185
186" -----------------------------------------------------------------------------
187" Line Comments
188" -----------------------------------------------------------------------------
189syn region modula2Comment start=/^!/ end=/$/ oneline
190
191
192" -----------------------------------------------------------------------------
193" Block Comments
194" -----------------------------------------------------------------------------
195syn region modula2Comment
196 \ start="\(END\s\)\@<!(\*\(!m2r10\(+[a-z0-9]\+\)\?\*)\)\@!" end="\*)"
197 \ contains = modula2Comment, modula2CommentKey, modula2TechDebtMarker
198
199syn match modula2CommentKey
200 \ "[Aa]uthor[s]\?\|[Cc]opyright\|[Ll]icense\|[Ss]ynopsis" contained
201syn match modula2CommentKey
202 \ "\([Pp]re\|[Pp]ost\|[Ee]rror\)\-condition[s]\?:" contained
203
204
205" -----------------------------------------------------------------------------
206" Block Statement Tails
207" -----------------------------------------------------------------------------
208syn match modula2ReswordEnd
209 \ "END" nextgroup = modula2StmtTailComment skipwhite
210syn match modula2StmtTailComment
211 \ "(\*\s\(IF\|CASE\|FOR\|LOOP\|WHILE\)\s\*)" contained
212
213
214" -----------------------------------------------------------------------------
215" Technical Debt Markers
216" -----------------------------------------------------------------------------
217syn match modula2ToDoHeader "TO DO"
218
219syn match modula2ToDoTail
220 \ "END\(\s(\*\sTO DO\s\*)\)\@=" nextgroup = modula2ToDoTailComment skipwhite
221syntax match modula2ToDoTailComment "(\*\sTO DO\s\*)" contained
222
223" contained within pragma
224syn keyword modula2TechDebtPragma contained DEPRECATED
225
226" contained within comment
227syn keyword modula2TechDebtMarker contained FIXME
228
229
230" -----------------------------------------------------------------------------
231" Disabled Code Sections
232" -----------------------------------------------------------------------------
233syn region modula2DisabledCode start="^?<" end="^>?"
234
235
236" -----------------------------------------------------------------------------
237" Headers
238" -----------------------------------------------------------------------------
239" !!! this section must be second last !!!
240
241" module header
242syn match modula2ModuleHeader
243 \ "\(MODULE\|BLUEPRINT\)\( [A-Z][a-zA-Z0-9]*\)\?"
244 \ contains = modula2ReswordModule, modula2ReswordBlueprint, modula2ModuleIdent
245
246syn match modula2ModuleIdent
247 \ "[A-Z][a-zA-Z0-9]*" contained
248
249syn match modula2ModuleTail
250 \ "END [A-Z][a-zA-Z0-9]*\.$"
251 \ contains = modula2ReswordEnd, modula2ModuleIdent, modula2Punctuation
252
253" procedure, sole occurrence
254syn match modula2ProcedureHeader
255 \ "PROCEDURE\(\s\[\|\s[a-zA-Z]\)\@!" contains = modula2ReswordProcedure
256
257" procedure header
258syn match modula2ProcedureHeader
259 \ "PROCEDURE [a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*"
260 \ contains = modula2ReswordProcedure,
261 \ modula2ProcedureIdent, modula2ProcedureLowlineIdent, modula2IllegalChar, modula2IllegalIdent
262
263" procedure binding to operator
264syn match modula2ProcedureHeader
265 \ "PROCEDURE \[[+-\*/\\=<>]\] [a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*"
266 \ contains = modula2ReswordProcedure, modula2Punctuation,
267 \ modula2ProcedureIdent, modula2ProcedureLowlineIdent, modula2IllegalChar, modula2IllegalIdent
268
269" procedure binding to builtin
270syn match modula2ProcedureHeader
271 \ "PROCEDURE \[[A-Z]\+\(:\([#\*,]\|++\|--\)\?\)\?\] [a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*"
272 \ contains = modula2ReswordProcedure,
273 \ modula2Punctuation, modula2Resword, modula2SchroedToken,
274 \ modula2ProcIdent, modula2FuncIdent, modula2PrimitiveIdent,
275 \ modula2ProcedureIdent, modula2ProcedureLowlineIdent, modula2IllegalChar, modula2IllegalIdent
276
277syn match modula2ProcedureIdent
278 \ "\([a-zA-Z]\)\([a-zA-Z0-9]*\)" contained
279
280syn match modula2ProcedureLowlineIdent
281 \ "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)\+" contained
282
283syn match modula2ProcedureTail
284 \ "END [a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*;$"
285 \ contains = modula2ReswordEnd,
286 \ modula2ProcedureIdent, modula2ProcedureLowLineIdent,
287 \ modula2Punctuation, modula2IllegalChar, modula2IllegalIdent
288
289syn keyword modula2ReswordModule contained MODULE
290syn keyword modula2ReswordBlueprint contained BLUEPRINT
291syn keyword modula2ReswordProcedure contained PROCEDURE
292syn keyword modula2ReswordEnd contained END
293
294
295" -----------------------------------------------------------------------------
296" Illegal Symbols
297" -----------------------------------------------------------------------------
298" !!! this section must be last !!!
299
300" any '`' '~' '@' '$' '%'
301syn match modula2IllegalChar "[`~@$%]"
302
303" any solitary sequence of '_'
304syn match modula2IllegalChar "\<_\+\>"
305
306" any '?' at start of line if not followed by '<'
307syn match modula2IllegalChar "^?\(<\)\@!"
308
309" any '?' not following '>' at start of line
310syn match modula2IllegalChar "\(\(^>\)\|\(^\)\)\@<!?"
311
312" any identifiers with leading occurrences of '_'
313syn match modula2IllegalIdent "_\+[a-zA-Z][a-zA-Z0-9]*\(_\+[a-zA-Z0-9]*\)*"
314
315" any identifiers containing consecutive occurences of '_'
316syn match modula2IllegalIdent
317 \ "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*\(__\+[a-zA-Z0-9]\+\(_[a-zA-Z0-9]\+\)*\)\+"
318
319" any identifiers with trailing occurrences of '_'
320syn match modula2IllegalIdent "[a-zA-Z][a-zA-Z0-9]*\(_\+[a-zA-Z0-9]\+\)*_\+\>"
321
322
323" -----------------------------------------------------------------------------
324" Define Rendering Styles
325" -----------------------------------------------------------------------------
326
327" highlight default link modula2PredefIdentStyle Keyword
328" highlight default link modula2ConstIdentStyle modula2PredefIdentStyle
329" highlight default link modula2TypeIdentStyle modula2PredefIdentStyle
330" highlight default link modula2ProcIdentStyle modula2PredefIdentStyle
331" highlight default link modula2FuncIdentStyle modula2PredefIdentStyle
332" highlight default link modula2MacroIdentStyle modula2PredefIdentStyle
333
334highlight default link modula2ConstIdentStyle Constant
335highlight default link modula2TypeIdentStyle Type
336highlight default link modula2ProcIdentStyle Function
337highlight default link modula2FuncIdentStyle Function
338highlight default link modula2MacroIdentStyle Function
339highlight default link modula2PrimitiveIdentStyle Function
340highlight default link modula2UnsafeIdentStyle Question
341highlight default link modula2NonPortableIdentStyle Question
342highlight default link modula2StringLiteralStyle String
343highlight default link modula2CommentStyle Comment
344highlight default link modula2PragmaStyle PreProc
345highlight default link modula2PragmaKeyStyle PreProc
346highlight default link modula2DialectTagStyle SpecialComment
347highlight default link modula2TechDebtMarkerStyle SpecialComment
348highlight default link modula2ReswordStyle Keyword
349highlight default link modula2HeaderIdentStyle Function
350highlight default link modula2UserDefIdentStyle Normal
351highlight default link modula2NumericLiteralStyle Number
352highlight default link modula2PunctuationStyle Delimiter
353highlight default link modula2CommentKeyStyle SpecialComment
354highlight default link modula2DisabledCodeStyle NonText
355
356
357" -----------------------------------------------------------------------------
358" Assign Rendering Styles
359" -----------------------------------------------------------------------------
360
361" headers
362highlight default link modula2ModuleIdent modula2HeaderIdentStyle
363highlight default link modula2ProcedureIdent modula2HeaderIdentStyle
364highlight default link modula2ModuleHeader modula2HeaderIdentStyle
365highlight default link modula2ModuleTail Normal
366highlight default link modula2ProcedureHeader Normal
367highlight default link modula2ProcedureTail Normal
368
369" lowline identifiers are rendered as errors if g:modula2_r10_allow_lowline is unset
370if exists("g:modula2_r10_allow_lowline")
371 if g:modula2_r10_allow_lowline != 0
372 highlight default link modula2ProcedureLowlineIdent modula2HeaderIdentStyle
373 else
374 highlight default link modula2ProcedureLowlineIdent Error
375 endif
376else
377 highlight default link modula2ProcedureLowlineIdent modula2HeaderIdentStyle
378endif
379
380" reserved words
381highlight default link modula2Resword modula2ReswordStyle
382highlight default link modula2ReswordModule modula2ReswordStyle
383highlight default link modula2ReswordProcedure modula2ReswordStyle
384highlight default link modula2ReswordEnd modula2ReswordStyle
385highlight default link modula2ReswordDo modula2ReswordStyle
386highlight default link modula2ReswordTo modula2ReswordStyle
387highlight default link modula2SchroedToken modula2ReswordStyle
388
389" predefined identifiers
390highlight default link modula2ConstIdent modula2ConstIdentStyle
391highlight default link modula2TypeIdent modula2TypeIdentStyle
392highlight default link modula2ProcIdent modula2ProcIdentStyle
393highlight default link modula2FuncIdent modula2FuncIdentStyle
394highlight default link modula2MacroIdent modula2MacroIdentStyle
395highlight default link modula2PrimitiveIdent modula2PrimitiveIdentStyle
396
397" unsafe and non-portable identifiers
398highlight default link modula2UnsafeIdent modula2UnsafeIdentStyle
399highlight default link modula2NonPortableIdent modula2NonPortableIdentStyle
400
401" user defined identifiers
402highlight default link modula2Ident modula2UserDefIdentStyle
403
404" lowline identifiers are rendered as errors if g:modula2_r10_allow_lowline is unset
405if exists("g:modula2_r10_allow_lowline")
406 if g:modula2_r10_allow_lowline != 0
407 highlight default link modula2LowLineIdent modula2UserDefIdentStyle
408 else
409 highlight default link modula2LowLineIdent Error
410 endif
411else
412 highlight default link modula2LowLineIdent modula2UserDefIdentStyle
413endif
414
415" literals
416highlight default link modula2String modula2StringLiteralStyle
417highlight default link modula2Base2Num modula2NumericLiteralStyle
418highlight default link modula2Base10Num modula2NumericLiteralStyle
419highlight default link modula2Base16Num modula2NumericLiteralStyle
420
421" punctuation
422highlight default link modula2Punctuation modula2PunctuationStyle
423
424" pragmas
425highlight default link modula2Pragma modula2PragmaStyle
426highlight default link modula2PragmaKey modula2PragmaKeyStyle
427highlight default link modula2DialectTag modula2DialectTagStyle
428
429" comments
430highlight default link modula2Comment modula2CommentStyle
431highlight default link modula2CommentKey modula2CommentKeyStyle
432highlight default link modula2ToDoTailComment modula2CommentStyle
433highlight default link modula2StmtTailComment modula2CommentStyle
434
435" technical debt markers
436highlight default link modula2ToDoHeader modula2TechDebtMarkerStyle
437highlight default link modula2ToDoTail modula2TechDebtMarkerStyle
438highlight default link modula2TechDebtPragma modula2TechDebtMarkerStyle
439
440" disabled code
441highlight default link modula2DisabledCode modula2DisabledCodeStyle
442
443" illegal symbols
444highlight default link modula2IllegalChar Error
445highlight default link modula2IllegalIdent Error
446
447
448let b:current_syntax = "modula2"
449
450" vim: ts=4
451
452" END OF FILE