]> gitweb.factorcode.org Git - factor.git/blob - misc/vim/syntax/factor.vim
vim/syntax: Even more fixups.
[factor.git] / misc / vim / syntax / factor.vim
1 " Vim syntax file
2 " Language: Factor
3 " Maintainer: Alex Chapman <chapman.alex@gmail.com>
4 " Last Change: 2020 Jun 05
5 " Minimum Version: 600
6
7 " Factor |syntax| file guide & conventions:
8 "
9 " Inside |:comment|s, words in |bars| contain |:help| keywords.
10 "   |K| looks these up.
11 "
12 " Alignment columns should normally occur on multiples of 4.
13 " Align Vim syntax alternatives naturally. E.g.:
14 "   "syn match   ..."
15 "   "syn cluster ..."
16 "   "syn region  ..."
17 " Align |:syn-start|, |:syn-skip|, and |:syn-end| on their patterns.
18 " ":echo (col('.') - 1) % 4" is handy here.
19 "
20 " All syntax patterns (|:syn-pattern|) are "very magic" (|/\v|).
21 " Escape all literal [^[:alnum:]_-!:;] characters in these patterns.
22 " (Not escaping [-!:;] characters risks forward-incompatibility,
23 "   but fixes if an incompatibile Vim arises would be trivial,
24 "   and Factor likes these characters.)
25 "
26 " Syntax groups ending in "Error" match errors via |:syn-priority|,
27 "   and should normally |:hi-link| to "Error".
28 "
29 " Syntax groups named "{group-name}Trans" are |:syn-transparent|.
30 "
31 " |:syn-cluster|s named "{group-name}" mean to allow |:syn-contains| use of
32 "   |:syn-priority|-based error-detection.
33 " This still applies to clusters named "{group-name}Trans".
34 "
35 " Syntax groups "{group-name}Skip" have the form:
36 " "syn match {group-name}Skip /\v%(\_\s+%(!>.*)?)*/ contains=@factorComment nextgroup={group-name} transparent contained"
37 " Specifying "nextgroup={group-name}Skip skipempty" works like a Factor-aware
38 "   "nextgroup={group-name} skipwhite skipempty"
39 "   with required initial space (not optional).
40 " "{cluster-name}Skip" works similarly, but with "nextgroup=@{cluster-name}".
41 "
42 " Vim's syntax highlighting freaks at paired "/\v\(" and "/\v\)". ☹
43 " Switching into very nomagic (with "/\V(\v/" or "/\V)\v") averts that,
44 "   as non-escaped parentheses don't extend pattern regions.
45 "
46 " A handy testing command:
47 " "echo join(map(synstack(line('.'),col('.')),{sn->{i,s->{t->sn(s).(s==t?'':' ('.sn(t).')')}(synIDtrans(s))}}({s->synIDattr(s,'name')})),' -> ')"
48 "   Outputs in the form "hi<...> trans<...> lo<...>":
49 "     "hi": syntax group
50 "     "trans": transparent syntax group (if not applicable, same as "hi")
51 "     "lo": highlight group
52
53 if exists('b:current_syntax')
54   finish
55 endif
56
57 " Factor is case sensitive.
58 syn case match
59
60 " Make all of these characters part of a word (useful for skipping over words with w, e, and b)
61 let s:iskeyword = '!,@,33-35,%,$,38-64,A-Z,91-96,a-z,123-126,128-255'
62 let s:set_iskeyword = has('patch-7.4.1142') ? 'syn iskeyword ' :
63       \ 'setlocal iskeyword='
64 execute s:set_iskeyword . s:iskeyword
65
66 syn match   factorWord   /\v<\S+>/  contains=@factorWord transparent display
67 syn cluster factorClusterNoComment  contains=factorWord,@factorMultilineComment,@factorClusterValue,factorBoolean,factorBreakpoint,factorDeclaration,factorCallQuotation,factorExecute,factorCallNextMethod,@factorWordOps,factorAlien,factorSlot,factorTuple,factorErrorSyn,factorStruct
68 syn cluster factorCluster           contains=@factorComment,@factorClusterNoComment
69
70 " A crash course on Factor's lexer:
71 "
72 " The "lexer" vocabulary parses lines (arrays of strings) into tokens.
73 " Tokens are non-space strings, effectively words.
74 " "[ f skip ] call( i seq -- n )" finds the next space, erroring on tabs.
75 "   "t skip" finds the next non-space.
76 " The "lexer" class holds lex state.
77 " Lexer method "skip-word" advances to the next space (via "f skip"),
78 "     while also counting leading double quotation marks as their own words.
79 "   I.e., this advances to the end of the current token
80 "     (if currently at a token, otherwise nothing changes).
81 " Method "skip-blank" advances to the next non-space (via "t skip"),
82 "     while also skipping shebangs at the beginning of the first line.
83 "   I.e., this advances to the start of the next token
84 "     (if one is present, otherwise it advances to the line's end).
85 " "(parse-raw)" advances a lexer through an immediate token via "skip-word",
86 "   and returns the (sub)token advanced through.
87 "   Note that this will not advance a lexer at space,
88 "     and an empty string will be returned.
89 " "next-line" advances a lexer to the start of the next line,
90 "   adding an effectively empty line to the end (as an EOF state).
91 " "parse-raw" advances a lexer through the next token,
92 "   first via alternating "skip-blank" & "next-line" if the line ended,
93 "     then via "(parse-raw)",
94 "   and returns it if found, otherwise (i.e. upon EOF) returning "f".
95 "     Note that the lexer will be advanced to EOF if "f" is returned.
96 " Comments are (unprocessed) remainders of lines, after a "!" word.
97 " "parse-token" advances a lexer though the next token via "parse-raw",
98 "   then returns it if found, otherwise returning "f".
99 "   while also advancing through comments
100 "     via mutual recursion with "skip-comment".
101 "   "[ skip-comment ] call( lexer str -- str' )" tests if a token is "!",
102 "     returning that token if so,
103 "     otherwise first advancing a lexer to the next line via "next-line"
104 "         (i.e. discarding the rest of the current line)
105 "       and then advancing it via "parse-token" & returning that token,
106 "     ensuring the return of "parse-token"'s desired non-comment token.
107 " The "lexer" dynamic variable holds the ambient lexer.
108 " "?scan-token" advances the ambient lexer through the next token
109 "     via "parse-token",
110 "   and returns it if found, otherwise returning "f".
111 " "scan-token" advances the ambient lexer through the next token
112 "     via "?scan-token",
113 "   and returns it if found, otherwise throwing an exception.
114 " All other words in the "lexer" vocabulary read via "scan-token", if at all.
115 " So! To know when double quotes & exclamation marks aren't special,
116 "   grep for "parse-raw". (Mostly. To be certain, grep for "lexer".)
117
118 syn cluster factorComment           contains=factorComment
119 syn cluster factorCommentContents   contains=factorTodo,@Spell
120 syn match   factorTodo              /\v(TODO|FIXME|XXX):=/ contained
121
122 syn cluster factorDefnContents      contains=@factorCluster
123
124 syn region  factorDefn            start=/\v<%(SYNTAX|%(MACRO|MEMO|TYPED)?:?):>/                 matchgroup=factorDefnDelims     end=/\v<;>/ contains=factorDefnDelims,@factorDefnContents
125 syn region  factorDefnDelims      start=/\v<%(SYNTAX|%(MACRO|MEMO|TYPED)?:?):>/ end=/\v<\S+>/   contains=@factorComment nextgroup=factorStackEffectSkip skipempty contained
126 syn region  factorMethod          start=/\v<M:>/                                                matchgroup=factorMethodDelims     end=/\v<;>/ contains=factorMethodDelims,@factorDefnContents
127 syn region  factorMethodDelims    start=/\v<M:>/               skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\S+>/   contains=@factorComment skipempty keepend contained
128 syn region  factorLocalsMethod    start=/\v<M::>/                                               matchgroup=factorLocalsMethodDelims     end=/\v<;>/ contains=factorLocalsMethodDelims,@factorDefnContents
129 syn region  factorLocalsMethodDelims    start=/\v<M::>/        skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\S+>/   contains=@factorComment nextgroup=factorStackEffectSkip skipempty keepend contained
130 syn region  factorGeneric         start=/\v<%(GENERIC|MATH|PRIMITIVE):>/                        end=/\v<\S+>/   contains=@factorComment nextgroup=factorStackEffectSkip skipempty
131 syn region  factorGenericN matchgroup=factorGenericN  start=/\v<GENERIC\#:>/   skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\d+>/   contains=@factorComment nextgroup=factorStackEffectSkip skipempty keepend
132
133 syn region  factorPDefn           start=/\v<%(SYNTAX|%(MACRO|MEMO|TYPED)?:?):>/                 matchgroup=factorPDefnDelims    end=/\v<;>/ contains=factorPDefnDelims,@factorDefnContents contained
134 syn region  factorPDefnDelims     start=/\v<%(SYNTAX|%(MACRO|MEMO|TYPED)?:?):>/ end=/\v<\S+>/   contains=@factorComment nextgroup=factorStackEffectSkip skipempty contained
135 syn region  factorPMethod         start=/\v<M:>/                                                matchgroup=factorPMethodDelims  end=/\v<;>/ contains=factorPMethodDelims,@factorDefnContents contained
136 syn region  factorPMethodDelims   start=/\v<M:>/               skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\S+>/   contains=@factorComment skipempty keepend contained
137 syn region  factorPLocalsMethod   start=/\v<M::>/                                               matchgroup=factorPLocalsMethodDelims    end=/\v<;>/ contains=factorPLocalsMethodDelims,@factorDefnContents contained
138 syn region  factorPLocalsMethodDelims   start=/\v<M::>/        skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\S+>/   contains=@factorComment nextgroup=factorStackEffectSkip skipempty keepend contained
139 syn region  factorPGeneric        start=/\v<%(GENERIC|MATH|PRIMITIVE):>/                        end=/\v<\S+>/   contains=@factorComment nextgroup=factorStackEffectSkip skipempty contained
140 syn region  factorPGenericN matchgroup=factorPGenericN    start=/\v<GENERIC\#:>/   skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\d+>/ contains=@factorComment nextgroup=factorStackEffectSkip skipempty keepend contained
141
142 syn region  factorPrivate matchgroup=factorPrivate start=/\v<\<PRIVATE>/ end=/\v<PRIVATE\>>/ contains=@factorDefnContents,factorPDefn,factorPMethod,factorPLocalsMethod,factorPGeneric,factorPGenericN transparent
143
144 syn cluster factorClusterValue      contains=factorBreakpoint,factorBoolean,factorFrySpecifier,factorChar,@factorString,@factorNumber,factorBackslash,factorMBackslash,factorLiteral,factorLiteralBlock,@factorStackEffect,@factorQuotation,@factorArray
145
146 syn keyword factorBoolean           f t
147 syn keyword factorBreakpoint        B
148 syn keyword factorFrySpecifier      @ _ contained
149 syn keyword factorDeclaration       delimiter deprecated final flushable foldable inline recursive
150 syn match   factorCallQuotation     /\v<call\V(\v/me=e-1    nextgroup=@factorStackEffect
151 syn match   factorExecute           /\v<execute\V(\v/me=e-1 nextgroup=@factorStackEffect
152 syn keyword factorCallNextMethod    call-next-method
153
154 syn region  factorChar        start=/\v<CHAR:>/ end=/\v\S+>/
155
156 syn cluster factorString            contains=factorString,factorTriString,factorPrefixedString
157 syn match   factorEscape            /\v\\([\\astnrbvf0e\"]|u\x{6}|u\{\S+}|x\x{2})/  contained display
158 syn region  factorString            matchgroup=factorStringDelims         start=/\v<"/                 skip=/\v\\"/ end=/\v"/   contains=factorEscape
159 " Removed Factor syntax.
160 syn region  factorTriString         matchgroup=factorTriStringDelims      start=/\v<"""/               skip=/\v\\"/ end=/\v"""/ contains=factorEscape
161 syn region  factorPrefixedString    matchgroup=factorPrefixedStringDelims start=/\v<[^[:blank:]"]+">/  skip=/\v\\"/ end=/\v"/   contains=factorEscape
162
163 " Vocabulary: multiline
164 " This vocabulary reads the ambient lexer without "parse-raw".
165 syn cluster factorString            add=factorMultilineString,factorHereDocString,factorPrefixedMultilineString
166 syn region  factorMultilineString   matchgroup=factorMultilineStringDelims    start=/\v<\[\z(\={0,6})\[>/   end=/\v\]\z1\]/
167 syn region  factorHereDoc           matchgroup=factorHereDocDelims            start=/\v<STRING:\s+\S+>/     end=/\v^;$/
168 syn region  factorHereDocString     matchgroup=factorHereDocStringDelims      start=/\v<HEREDOC:\s+\z(.*)>/ end=/\v^\z1$/
169 syn region  factorPrefixedMultilineString matchgroup=factorPrefixedMultilineStringDelims  start=/\v<[^[\][:blank:]]+\[\z(\={0,6})\[>/   end=/\v\]\z1\]/
170 " These comments are normal syntax words, so no lexer privilege for them.
171 " (Hence, no "syn cluster factorComment" membership.)
172 syn cluster factorMultilineComment  contains=factorMultilineComment,factorMultilineCComment
173 syn region  factorMultilineComment  matchgroup=factorMultilineCommentDelims   start=/\v<!\[\z(\={0,6})\[>/  end=/\v\]\z1\]/ contains=@factorCommentContents keepend
174 syn region  factorMultilineCComment matchgroup=factorMultilineCCommentDelims  start=/\v<\/\*>/              end=/\v\*\//    contains=@factorCommentContents keepend
175
176 syn cluster factorReal                  contains=@factorInteger,@factorFloat,@factorRatio,@factorBin,@factorOct,@factorHex,factorNan
177 syn cluster factorNumber                contains=@factorReal,factorComplex
178 syn cluster factorInteger               contains=factorInteger
179 if !exists('g:factor_syn_no_error') " more general
180   syn cluster factorInteger             add=factorIntegerError
181   " + "\d|," with contained "\d"
182   syn match   factorIntegerError        /\v<[+-]=%(\d|,){-}\d%(\d|,)*>/
183 endif
184 " + "\d|," with leading "\d" and no trailing ","
185 syn match   factorInteger               /\v<[+-]=\d%(\d|,)*,@1<!>/
186 if !exists('g:factor_syn_no_error') " more general
187   syn cluster factorFloat               add=factorFloatError
188   syn match   factorFloatError          /\v<[+-]=%(\S{-}\d&%(\d|,)*%([eE][+-]=%(\d|,)*|\.%(\d|,)*%([eE][+-]=%(\d|,)*)?)|\.%(\d|,)+%([eE][+-]=%(\d|,)*)?)>/
189 endif
190 syn cluster factorFloat                 contains=factorFloat
191 " exponent is followed by valid integer of radix 10
192 " float of
193 "   {valid integer,
194 "     {"[eE]" exponent}
195 "     or {"." mantissa sep, ? "[eE]" exponent}}
196 "   or {"." mantissa sep, ? "[eE]" exponent}
197 syn match   factorFloat                 /\v<[+-]=%(\d%(\d|,)*,@1<!%([eE][+-]=\d%(\d|,)*,@1<!|\.%(\d%(\d|,)*,@1<!)?%([eE][+-]=\d%(\d|,)*,@1<!)?)|\.\d%(\d|,)*,@1<!%([eE][+-]=\d%(\d|,)*,@1<!)?)>/
198 syn cluster factorRatio                 contains=factorRatio
199 if !exists('g:factor_syn_no_error') " more general
200   syn cluster factorRatio               add=factorRatioError
201   syn match   factorRatioError          /\v<[+-]=%(\S{-}\d.{-}\/&%(\d|,)*\.?%(\d|,)*%([+-]%(\d|,)*)?)\/[+-]=%(\S{-}\d&%(\d|,)*\.?%(\d|,)*%([eE][+-]=%(\d|,)*)?)>/
202 endif
203 syn match   factorRatio                 /\v<([+-]=)\d%(\d|,)*,@1<!%(\1@=[+-](\d%(\d|,)*,@1<!)\/\2@!\d%(\d|,)*,@1<!|\/%(\d%(\d|,)*,@1<!%(\.%(\d%(\d|,)*,@1<!)?)?|\.\d%(\d|,)*,@1<!)%([eE][+-]=\d%(\d|,)*,@1<!)?)%(\/0)@2<!>/
204 syn region  factorComplex         start=/\v<C\{>/   end=/\v<\}>/    contains=@factorReal
205 syn cluster factorBin                   contains=factorBin
206 if !exists('g:factor_syn_no_error')
207   syn cluster factorBin                 add=factorBinError
208   syn match   factorBinError            /\v<[+-]=0[bB]%(\S{-}\w&%(\w|,)*\.?%(\w|,)*%([pP][+-]=%(\w|,)*)?)>/
209 endif
210 " basically a float, but with a radix and no integer case to not match
211 syn match   factorBin                   /\v<[+-]=0[bB]%([01][01,]*,@1<!%(\.%([01][01,]*,@1<!)?)?|\.[01][01,]*,@1<!)%([pP][+-]=\d%(\d|,)*,@1<!)?>/
212 syn cluster factorOct                   contains=factorOct
213 if !exists('g:factor_syn_no_error')
214   syn cluster factorOct                 add=factorOctError
215   syn match   factorOctError            /\v<[+-]=0[oO]%(\S{-}\o&%(\w|,)*\.?(\w|,)*%([pP][+-]=%(\w|,)*)?)>/
216 endif
217 syn match   factorOct                   /\v<[+-]=0[oO]%(\o%(\o|,)*,@1<!%(\.%(\o%(\o|,)*,@1<!)?)?|\.\o%(\o|,)*,@1<!)%([pP][+-]=\d%(\d|,)*,@1<!)?>/
218 syn cluster factorHexNoRadix            contains=factorHexNoRadix
219 syn cluster factorHex                   contains=factorHex
220 if !exists('g:factor_syn_no_error')
221   syn cluster factorHexNoRadix          add=factorHexNoRadixError
222   syn cluster factorHex                 add=factorHexError
223   syn match   factorHexNoRadixError     /\v<[+-]=%(\S{-}\x&%(\w|,)*\.?(\w|,)*%([pP][+-]=%(\w|,)*)?)>/   contained
224   syn match   factorHexError            /\v<[+-]=0[xX]%(\S{-}\x&%(\x|,)*\.?(\x|,)*%([pP][+-]=%(\w|,)*)?)>/
225 endif
226 syn match   factorHexNoRadix            /\v<[+-]=%(\x%(\x|,)*,@1<!%(\.%(\x%(\x|,)*,@1<!)?)?|\.\x%(\x|,)*,@1<!)%([pP][+-]=\d%(\d|,)*,@1<!)?>/  contained
227 syn match   factorHex                   /\v<[+-]=0[xX]%(\x%(\x|,)*,@1<!%(\.%(\x%(\x|,)*,@1<!)?)?|\.\x%(\x|,)*,@1<!)%([pP][+-]=\d%(\d|,)*,@1<!)?>/
228 syn region  factorNan matchgroup=factorNan    start=/\v<NAN:>/ matchgroup=NONE skip=/\v<!>.*/   end=/\v<\S+>/   contains=@factorComment,@factorHexNoRadix keepend
229
230 syn region  factorBackslash       start=/\v<\\>/                    end=/\v<\S+>/   contains=@factorComment
231 syn region  factorMBackslash      start=/\v<M\\>/  skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\S+>/   contains=@factorComment keepend
232 syn region  factorLiteral         start=/\v<\$>/                    end=/\v<\S+>/   contains=@factorComment
233 syn region  factorLiteralBlock    start=/\v<\$\[>/                  end=/\v<\]>/    contains=@factorComment
234
235 syn region  factorIn      start=/\v<IN:>/       end=/\v<\S+>/   contains=@factorComment
236 syn region  factorUse     start=/\v<USE:>/      end=/\v<\S+>/   contains=@factorComment
237 syn region  factorUnuse   start=/\v<UNUSE:>/    end=/\v<\S+>/   contains=@factorComment
238
239 syn region  factorUsing           start=/\v<USING:>/                        end=/\v<;>/     contains=@factorComment
240 syn region  factorQualified       start=/\v<QUALIFIED:>/                    end=/\v<\S+>/   contains=@factorComment
241 syn region  factorQualifiedWith   start=/\v<QUALIFIED-WITH:>/  skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\S+>/   contains=@factorComment keepend
242 syn region  factorExclude         start=/\v<EXCLUDE:>/                      end=/\v<;>/     contains=@factorComment
243 syn region  factorFrom            start=/\v<FROM:>/                         end=/\v<;>/     contains=@factorComment
244 syn region  factorRename          start=/\v<RENAME:>/      skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\S+%(\_\s+%(!>.*)?)+\=\>%(\_\s+%(!>.*)?)+\S+>/  contains=@factorComment keepend
245 syn region  factorSingletons      start=/\v<SINGLETONS:>/                   end=/\v<;>/     contains=@factorComment
246 syn region  factorSymbol          start=/\v<SYMBOL:>/                       end=/\v<\S+>/   contains=@factorComment
247 syn region  factorSymbols         start=/\v<SYMBOLS:>/                      end=/\v<;>/     contains=@factorComment
248 syn region  factorConstructor2    start=/\v<CONSTRUCTOR:>/                  end=/\v<;>/     contains=@factorComment
249 syn region  factorIntersection    start=/\v<INTERSECTION:>/                 end=/\v<;>/     contains=@factorComment
250 syn cluster factorSlotAttr              contains=factorSlotAttrInitial,factorSlotAttrReadOnly
251 syn cluster factorTupleSlotAttr         contains=@factorSlotAttr
252 syn match   factorTupleSlotName         /\v<\S+>/ nextgroup=factorTupleSlotClassSkip skipempty contained
253 syn match   factorTupleSlotNameSkip     /\v%(\_\s+%(!>.*)?)*/ contains=@factorComment nextgroup=factorTupleSlotName transparent contained
254 syn match   factorTupleSlotClass        /\v<\S+>/ nextgroup=factorTupleSlotAttrSkip skipempty contained
255 " a class is optional, so let an attribute take priority if present
256 syn match   factorTupleSlotClassSkip    /\v%(\_\s+%(!>.*)?)*/ contains=@factorComment nextgroup=factorTupleSlotClass,@factorTupleSlotAttr transparent contained
257 syn region  factorTupleSlot matchgroup=factorTupleSlotDelims  start=/\v<\{>/                end=/\v<\}>/    contains=@factorComment,factorTupleSlotName,@factorTupleSlotAttr contained
258 syn region  factorTuple matchgroup=factorTupleDelims          start=/\v<%(TUPLE|BUILTIN):>/ end=/\v<;>/     contains=@factorComment,factorTupleSlotName,factorTupleSlot
259 " Abnormally named because factor*Error is reserved for syntax errors.
260 syn region  factorErrorSyn        start=/\v<ERROR:>/            end=/\v<;>/     contains=@factorComment
261 syn region  factorUnion           start=/\v<UNION:>/            end=/\v<;>/     contains=@factorComment
262 syn cluster factorStructSlotAttr        contains=@factorSlotAttr,factorStructSlotAttrBits
263 syn match   factorStructSlotName        /\v<\S+>/ nextgroup=factorStructSlotTypeSkip skipempty contained
264 syn match   factorStructSlotNameSkip    /\v%(\_\s+%(!>.*)?)*/ contains=@factorComment nextgroup=factorStructSlotName contained transparent
265 syn match   factorStructSlotType        /\v<\S+>/ contained
266 syn match   factorStructSlotTypeSkip    /\v%(\_\s+%(!>.*)?)*/ contains=@factorComment nextgroup=factorStructSlotType contained transparent
267 syn region  factorStructSlot matchgroup=factorStructSlotDelims    start=/\v<\{>/     end=/\v<\}>/ contains=@factorComment,factorStructSlotName,@factorStructSlotAttr contained
268 syn region  factorStruct matchgroup=factorStructDelims            start=/\v<%(UNION-STRUCT|STRUCT):>/   end=/\v<;>/ contains=@factorComment,factorStructSlot
269
270 syn match   factorSlotAttrReadOnly      /\v<read-only>/ contained
271 syn match   factorSlotAttrInitial       /\v<initial:>%(\_\s+%(!>.*)?)+/ contains=@factorComment nextgroup=factorWord,@factorClusterValue contained
272 syn match   factorStructSlotAttrBits    /\v<bits:>%(\_\s+%(!>.*)?)+/    contains=@factorComment nextgroup=factorWord,@factorReal contained
273
274 syn region  factorConstant        start=/\v<CONSTANT:>/                 end=/\v<\S+>/   contains=@factorComment
275 syn region  factorAlias           start=/\v<ALIAS:>/     skip=/\v<!>.*/ end=/\v<\S+%(\_\s+%(!>.*)?)+\S+>/   contains=@factorComment keepend
276 syn region  factorSingleton       start=/\v<SINGLETON:>/                end=/\v<\S+>/   contains=@factorComment
277 syn region  factorPostpone        start=/\v<POSTPONE:>/                 end=/\v<\S+>/   contains=@factorComment
278 syn region  factorDefer           start=/\v<DEFER:>/                    end=/\v<\S+>/   contains=@factorComment
279 syn region  factorForget          start=/\v<FORGET:>/                   end=/\v<\S+>/   contains=@factorComment
280 syn region  factorMixin           start=/\v<MIXIN:>/                    end=/\v<\S+>/   contains=@factorComment
281 syn region  factorInstance        start=/\v<INSTANCE:>/    skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\S+>/   contains=@factorComment keepend
282 syn region  factorHook            start=/\v<HOOK:>/    skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\S+>/   contains=@factorComment nextgroup=factorStackEffectSkip skipempty keepend
283 syn region  factorMain            start=/\v<MAIN:>/                     end=/\v<\S+>/   contains=@factorComment
284 syn region  factorConstructor     start=/\v<C:>/       skip=/\v<!>.*/   end=/\v<\S+%(\_\s+%(!>.*)?)+\S+>/   contains=@factorComment keepend
285 syn region  factorAlien matchgroup=factorAlien start=/\v<ALIEN:>/ matchgroup=NONE   end=/\v<\S+>/  contains=@factorComment,@factorHexNoRadix
286 syn region  factorSlot            start=/\v<SLOT:>/                     end=/\v<\S+>/   contains=@factorComment
287
288 syn cluster factorWordOps   contains=factorConstant,factorAlias,factorSingleton,factorSingletons,factorSymbol,factorSymbols,factorPostpone,factorDefer,factorForget,factorMixin,factorInstance,factorHook,factorMain,factorConstructor
289
290 "TODO:
291 "misc:
292 " HELP:
293 " ARTICLE:
294 "literals:
295 " PRIMITIVE:
296
297 "C interface:
298 " C-ENUM:
299 " FUNCTION:
300 " TYPEDEF:
301 " LIBRARY:
302 "#\ "
303
304 if !exists('g:factor_syn_no_error')
305   syn match   factorStackEffectRequired /\v<\V(\@!\v\S+>/    contained
306 endif
307 syn cluster factorStackEffectContents   contains=@factorComment,factorStackEffectDelims,factorStackEffectVar,factorStackEffectType,factorStackEffectRowVar
308 syn cluster factorStackEffect           contains=factorStackEffect
309 " Erroring on stack effects without a "--" separator would be nice.
310 " Unfortunately, that sort of vacuous detection is above Vim's pay-grade,
311 "   especially when stack effects can be nested arbitrarily via types.
312 syn match   factorStackEffectSkip       /\v%(\_\s+%(!>.*)?)*/ contains=@factorComment nextgroup=factorStackEffectRequired,@factorStackEffect transparent contained
313 syn region  factorStackEffect       matchgroup=factorStackEffectDelims    start=/\v\V(\v>/  end=/\v<\V)\v>/ contains=@factorStackEffectContents
314 syn match   factorStackEffectVar        /\v<\S+>/           contained
315 " Note that ":!" parses to the "!" word and doesn't lex as a comment.
316 " Also, even though we take any value, the leading ":" breaking the word
317 "   boundary means a lot of our nicer syntax patterns don't match on
318 "   "factorStackEffectType".
319 " syn cluster factorStackEffectType contains=factorWord,@factorStackEffect
320 syn cluster factorStackEffectType       contains=factorWord,@factorClusterValue
321 syn match   factorStackEffectTypeSkip   /\v%(\_\s+%(!>.*)?)*/ contains=@factorComment nextgroup=@factorStackEffectType transparent contained
322 syn match   factorStackEffectVar        /\v<\S+:>/          nextgroup=factorStackEffectTypeSkip skipempty contained
323 syn match   factorStackEffectType       /\v<:/              nextgroup=@factorStackEffectType contained
324 syn match   factorStackEffectRowVar     /\v<\.\.\S+>/       contained
325 syn match   factorStackEffectRowVar     /\v<\.\.\S+:>/      nextgroup=factorStackEffectTypeSkip skipempty contained
326 syn match   factorStackEffectDelims     /\v<-->/            contained
327 if !exists('g:factor_syn_no_error')
328   syn cluster factorStackEffectContents add=factorStackEffectError
329   syn keyword factorStackEffectError    (                   contained
330 endif
331
332 " adapted from lisp.vim
333 if exists('g:factor_syn_no_rainbow')
334   syn cluster factorQuotation   contains=factorQuotation
335   syn region  factorQuotation      matchgroup=factorDelimiter start=/\v<%(%(%('|\$|)\[)|\[%(let|\|))>/  end=/\v<\]>/    contains=ALL
336 else
337   syn cluster factorQuotation   contains=factorQuotation0
338   syn region  factorQuotation0            matchgroup=hlLevel0 start=/\v<%(%(%('|\$|)\[)|\[%(let|\|))>/  end=/\v<\]>/    contains=@factorCluster,factorQuotation1,factorArray1
339   syn region  factorQuotation1 contained  matchgroup=hlLevel1 start=/\v<%(%(%('|\$|)\[)|\[%(let|\|))>/  end=/\v<\]>/    contains=@factorCluster,factorQuotation2,factorArray2
340   syn region  factorQuotation2 contained  matchgroup=hlLevel2 start=/\v<%(%(%('|\$|)\[)|\[%(let|\|))>/  end=/\v<\]>/    contains=@factorCluster,factorQuotation3,factorArray3
341   syn region  factorQuotation3 contained  matchgroup=hlLevel3 start=/\v<%(%(%('|\$|)\[)|\[%(let|\|))>/  end=/\v<\]>/    contains=@factorCluster,factorQuotation4,factorArray4
342   syn region  factorQuotation4 contained  matchgroup=hlLevel4 start=/\v<%(%(%('|\$|)\[)|\[%(let|\|))>/  end=/\v<\]>/    contains=@factorCluster,factorQuotation5,factorArray5
343   syn region  factorQuotation5 contained  matchgroup=hlLevel5 start=/\v<%(%(%('|\$|)\[)|\[%(let|\|))>/  end=/\v<\]>/    contains=@factorCluster,factorQuotation6,factorArray6
344   syn region  factorQuotation6 contained  matchgroup=hlLevel6 start=/\v<%(%(%('|\$|)\[)|\[%(let|\|))>/  end=/\v<\]>/    contains=@factorCluster,factorQuotation7,factorArray7
345   syn region  factorQuotation7 contained  matchgroup=hlLevel7 start=/\v<%(%(%('|\$|)\[)|\[%(let|\|))>/  end=/\v<\]>/    contains=@factorCluster,factorQuotation8,factorArray8
346   syn region  factorQuotation8 contained  matchgroup=hlLevel8 start=/\v<%(%(%('|\$|)\[)|\[%(let|\|))>/  end=/\v<\]>/    contains=@factorCluster,factorQuotation9,factorArray9
347   syn region  factorQuotation9 contained  matchgroup=hlLevel9 start=/\v<%(%(%('|\$|)\[)|\[%(let|\|))>/  end=/\v<\]>/    contains=@factorCluster,factorQuotation0,factorArray0
348 endif
349
350 if exists('g:factor_syn_no_rainbow')
351   syn cluster factorArray       contains=factorArray
352   syn region  factorArray          matchgroup=factorDelimiter start=/\v<%(\$|[-[:alnum:]]+)?\{>/        end=/\v<\}>/    contains=ALL
353 else
354   syn cluster factorArray       contains=factorArray0
355   syn region  factorArray0               matchgroup=hlLevel0 start=/\v<%(\$|[-[:alnum:]]+)?\{>/         end=/\v<\}>/    contains=@factorCluster,factorArray1,factorQuotation1
356   syn region  factorArray1     contained matchgroup=hlLevel1 start=/\v<%(\$|[-[:alnum:]]+)?\{>/         end=/\v<\}>/    contains=@factorCluster,factorArray2,factorQuotation2
357   syn region  factorArray2     contained matchgroup=hlLevel2 start=/\v<%(\$|[-[:alnum:]]+)?\{>/         end=/\v<\}>/    contains=@factorCluster,factorArray3,factorQuotation3
358   syn region  factorArray3     contained matchgroup=hlLevel3 start=/\v<%(\$|[-[:alnum:]]+)?\{>/         end=/\v<\}>/    contains=@factorCluster,factorArray4,factorQuotation4
359   syn region  factorArray4     contained matchgroup=hlLevel4 start=/\v<%(\$|[-[:alnum:]]+)?\{>/         end=/\v<\}>/    contains=@factorCluster,factorArray5,factorQuotation5
360   syn region  factorArray5     contained matchgroup=hlLevel5 start=/\v<%(\$|[-[:alnum:]]+)?\{>/         end=/\v<\}>/    contains=@factorCluster,factorArray6,factorQuotation6
361   syn region  factorArray6     contained matchgroup=hlLevel6 start=/\v<%(\$|[-[:alnum:]]+)?\{>/         end=/\v<\}>/    contains=@factorCluster,factorArray7,factorQuotation7
362   syn region  factorArray7     contained matchgroup=hlLevel7 start=/\v<%(\$|[-[:alnum:]]+)?\{>/         end=/\v<\}>/    contains=@factorCluster,factorArray8,factorQuotation8
363   syn region  factorArray8     contained matchgroup=hlLevel8 start=/\v<%(\$|[-[:alnum:]]+)?\{>/         end=/\v<\}>/    contains=@factorCluster,factorArray9,factorQuotation9
364   syn region  factorArray9     contained matchgroup=hlLevel9 start=/\v<%(\$|[-[:alnum:]]+)?\{>/         end=/\v<\}>/    contains=@factorCluster,factorArray0,factorQuotation0
365 endif
366
367 if !exists('g:factor_syn_no_error')
368   syn match   factorBracketError    /\v<\]>/
369   syn match   factorBracketError    /\v<\}>/
370 endif
371
372 function! FactorSynDefineComment() abort
373   syn match   factorComment         /\v<!>.*$/ contains=@factorCommentContents
374   syn match   factorShebang         /\v%^\#!.*$/ display
375   if !exists('g:factor_syn_no_error')
376     syn match   factorShebangError  /\v%^\#!\S+/
377   endif
378 endfunction
379
380 if !exists('g:factor_syn_no_comment')
381   call FactorSynDefineComment()
382 endif
383
384 " Syntax that bypasses comment lexing.
385 function! FactorSynDefineAfterComment() abort
386 endfunction
387
388 if !exists('g:factor_syn_no_after_comment')
389   call FactorSynDefineAfterComment()
390 endif
391
392 syn sync lines=100
393
394 if !exists('g:factor_syn_no_init')
395   command -nargs=+ -bar HiLink hi def link <args>
396
397   if !exists('g:factor_syn_no_error')
398     HiLink factorShebangError           Error
399     HiLink factorBracketError           Error
400     HiLink factorIntegerError           Error
401     HiLink factorFloatError             Error
402     HiLink factorRatioError             Error
403     HiLink factorBinError               Error
404     HiLink factorHexNoRadixError        Error
405     HiLink factorHexError               Error
406     HiLink factorOctError               Error
407     HiLink factorStackEffectRequired    Error
408     HiLink factorStackEffectError       Error
409   endif
410
411   HiLink   factorComment                Comment
412   HiLink   factorMultilineComment       factorComment
413   HiLink   factorMultilineCommentDelims factorMultilineComment
414   HiLink   factorMultilineCComment      factorComment
415   HiLink   factorMultilineCCommentDelims factorMultilineCComment
416   HiLink   factorShebang                PreProc
417   HiLink   factorStackEffect            Type
418   HiLink   factorStackEffectDelims      Delimiter
419   HiLink   factorStackEffectVar         Identifier
420   HiLink   factorStackEffectRowVar      factorStackEffectVar
421   HiLink   factorStackEffectType        Type
422   HiLink   factorTodo                   Todo
423   HiLink   factorInclude                Include
424   HiLink   factorWord                   Keyword
425   HiLink   factorCallQuotation          Keyword
426   HiLink   factorExecute                Keyword
427   HiLink   factorCallNextMethod         Keyword
428   HiLink   factorOperator               Operator
429   HiLink   factorFrySpecifier           Operator
430   HiLink   factorBoolean                Boolean
431   HiLink   factorBreakpoint             Debug
432   HiLink   factorDefnDelims             Typedef
433   HiLink   factorMethodDelims           Typedef
434   HiLink   factorLocalsMethodDelims     Typedef
435   HiLink   factorGeneric                Typedef
436   HiLink   factorGenericN               Typedef
437   HiLink   factorConstructor            Typedef
438   HiLink   factorConstructor2           Typedef
439   HiLink   factorPrivate                Special
440   HiLink   factorPDefnDelims            Special
441   HiLink   factorPMethodDelims          Special
442   HiLink   factorPLocalsMethodDelims    Special
443   HiLink   factorPGeneric               Special
444   HiLink   factorPGenericN              Special
445   HiLink   factorEscape                 SpecialChar
446   HiLink   factorString                 String
447   HiLink   factorStringDelims           factorString
448   HiLink   factorTriString              factorString
449   HiLink   factorTriStringDelims        factorTriString
450   HiLink   factorPrefixedString         factorString
451   HiLink   factorPrefixedStringDelims   factorPrefixedString
452   HiLink   factorMultilineString        factorString
453   HiLink   factorMultilineStringDelims  Typedef
454   HiLink   factorHereDoc                factorMultilineString
455   HiLink   factorHereDocDelims          factorMultilineStringDelims
456   HiLink   factorHereDocString          factorMultilineString
457   HiLink   factorHereDocStringDelims    factorMultilineStringDelims
458   HiLink   factorPrefixedMultilineString factorString
459   HiLink   factorPrefixedMultilineStringDelims factorMultilineStringDelims
460   HiLink   factorComplex                Number
461   HiLink   factorRatio                  Number
462   HiLink   factorBin                    Number
463   HiLink   factorHexNoRadix             Number
464   HiLink   factorHex                    Number
465   HiLink   factorNan                    Number
466   HiLink   factorOct                    Number
467   HiLink   factorFloat                  Float
468   HiLink   factorInteger                Number
469   HiLink   factorUsing                  Include
470   HiLink   factorQualified              Include
471   HiLink   factorQualifiedWith          Include
472   HiLink   factorExclude                Include
473   HiLink   factorFrom                   Include
474   HiLink   factorRename                 Include
475   HiLink   factorUse                    Include
476   HiLink   factorUnuse                  Include
477   HiLink   factorIn                     Define
478   HiLink   factorChar                   Character
479   HiLink   factorDelimiter              Delimiter
480   HiLink   factorBackslash              Special
481   HiLink   factorMBackslash             Special
482   HiLink   factorLiteral                Special
483   HiLink   factorLiteralBlock           Special
484   HiLink   factorDeclaration            Typedef
485   HiLink   factorSymbol                 Define
486   HiLink   factorSymbols                Define
487   HiLink   factorConstant               Define
488   HiLink   factorAlias                  Define
489   HiLink   factorSingleton              Define
490   HiLink   factorSingletons             Define
491   HiLink   factorMixin                  Typedef
492   HiLink   factorInstance               Typedef
493   HiLink   factorHook                   Typedef
494   HiLink   factorMain                   Define
495   HiLink   factorPostpone               Define
496   HiLink   factorDefer                  Define
497   HiLink   factorForget                 Define
498   HiLink   factorAlien                  Define
499   HiLink   factorSlot                   Define
500   HiLink   factorIntersection           Typedef
501   HiLink   factorSlot                   Typedef
502   HiLink   factorSlotDelims             factorSlot
503   HiLink   factorSlotName               Identifier
504   HiLink   factorSlotClass              Type
505   HiLink   factorSlotType               factorSlotClass
506   HiLink   factorSlotAttr               Special
507   HiLink   factorSlotAttrInitial        factorSlotAttr
508   HiLink   factorSlotAttrReadOnly       factorSlotAttr
509   HiLink   factorStructSlotAttr         factorSlotAttr
510   HiLink   factorStructSlotAttrBits     factorStructSlotAttr
511   HiLink   factorTuple                  Typedef
512   HiLink   factorTupleDelims            factorTuple
513   HiLink   factorTupleSlot              factorSlot
514   HiLink   factorTupleSlotDelims        factorSlotDelims
515   HiLink   factorTupleSlotName          factorSlotName
516   HiLink   factorTupleSlotClass         factorSlotClass
517   HiLink   factorErrorSyn               Typedef
518   HiLink   factorUnion                  Typedef
519   HiLink   factorStruct                 Typedef
520   HiLink   factorStructDelims           factorStruct
521   HiLink   factorStructSlot             factorSlot
522   HiLink   factorStructSlotDelims       factorSlotDelims
523   HiLink   factorStructSlotName         factorSlotName
524   HiLink   factorStructSlotType         factorSlotType
525
526   if &bg == 'dark'
527     hi   hlLevel0 ctermfg=red           guifg=red1
528     hi   hlLevel1 ctermfg=yellow        guifg=orange1
529     hi   hlLevel2 ctermfg=green         guifg=yellow1
530     hi   hlLevel3 ctermfg=cyan          guifg=greenyellow
531     hi   hlLevel4 ctermfg=magenta       guifg=green1
532     hi   hlLevel5 ctermfg=red           guifg=springgreen1
533     hi   hlLevel6 ctermfg=yellow        guifg=cyan1
534     hi   hlLevel7 ctermfg=green         guifg=slateblue1
535     hi   hlLevel8 ctermfg=cyan          guifg=magenta1
536     hi   hlLevel9 ctermfg=magenta       guifg=purple1
537   else
538     hi   hlLevel0 ctermfg=red           guifg=red3
539     hi   hlLevel1 ctermfg=darkyellow    guifg=orangered3
540     hi   hlLevel2 ctermfg=darkgreen     guifg=orange2
541     hi   hlLevel3 ctermfg=blue          guifg=yellow3
542     hi   hlLevel4 ctermfg=darkmagenta   guifg=olivedrab4
543     hi   hlLevel5 ctermfg=red           guifg=green4
544     hi   hlLevel6 ctermfg=darkyellow    guifg=paleturquoise3
545     hi   hlLevel7 ctermfg=darkgreen     guifg=deepskyblue4
546     hi   hlLevel8 ctermfg=blue          guifg=darkslateblue
547     hi   hlLevel9 ctermfg=darkmagenta   guifg=darkviolet
548   endif
549 endif
550 delcommand HiLink
551
552 let b:current_syntax = 'factor'
553
554 " vim: set ft=vim et sw=2 isk+=/,\\ :