dotfiles

My dotfiles.
git clone git://git.ryanmj.xyz/dotfiles.git
Log | Files | Refs | LICENSE

jsf.jsf (21493B)


      1 # JOE Syntax-Highlighting Description
      2 #                 for
      3 # JOE Syntax-Highlighting Descriptions
      4 #
      5 # Author: Charles J. Tabony
      6 # Date:   2007-2-13
      7 #
      8 # This is a highlighting description for files like this one.
      9 #
     10 # When CHECKING is defined, it is very aggressive about error checking.  The
     11 # idea is that anywhere the highlighted file contains a syntax error, at least
     12 # one visible character should be highlighted as Bad.  While that feature is
     13 # useful for finding syntax errors, it is annoying when editing a file, since
     14 # nearly everything is an error until you finish typing it.
     15 #
     16 # In order to not annoy people by default, but keep the option of strictly
     17 # checking syntax, I predicated the stricter checking on the CHECKING parameter. 
     18 # By default, things that are incomplete are generally not marked as errors. 
     19 # Only things that appear to be actual mistakes are highlighted as Bad.  To
     20 # enable the stricter checking, one can highlight the file with the jsf_check
     21 # syntax.  jsf_check.jsf simply calls the entire jsf.jsf file with CHECKING
     22 # defined.
     23 #
     24 # The idea is for authors of a jsf file to edit their file, highlight it with
     25 # jsf_check, and then look for any red characters.  That way they can check for
     26 # syntax errors before testing the changes.
     27 
     28 
     29 
     30 
     31 #####################
     32 # Color Definitions #
     33 #####################
     34 
     35 =Idle
     36 =Comment	green
     37 =Conditional	blue
     38 =Parameter	bold blue
     39 =Keyword	bold
     40 =Color		yellow
     41 =StandardColor	bold
     42 =State
     43 =Subr		magenta
     44 =Literal	cyan
     45 =Escape		bold cyan
     46 =Bad		bold red
     47 
     48 
     49 
     50 
     51 ##################
     52 # Initial States #
     53 ##################
     54 
     55 # This is a dummy state that simply jumps to comment_or_bad.  It is here so that
     56 # when this file calls itself with the STRINGS parameter defined, comment_or_bad
     57 # will effectively be the initial state.  comment_or_bad should be the initial
     58 # state because strings and istrings options can only be used as the last option
     59 # of a transition.
     60 .ifdef STRINGS
     61 :strings_initial Idle
     62 	*		comment_or_bad		noeat
     63 .endif
     64 
     65 # Each new line (that is not considered bad from the beginning) begins in the
     66 # idle state.  The first non-whitespace character determines what the rest of
     67 # the line should contain.  Following a strings or istrings option, only strings
     68 # and comments are allowed until the word "done" denotes the end of the list.
     69 :idle Idle
     70 	*		bad			noeat
     71 	" \t\n"		idle
     72 .ifdef STRINGS
     73 .else
     74 	"-"		sync_lines_first
     75 	"."		conditional_first	mark recolor=-1
     76 	"="		color_definition_first
     77 	":"		state_first
     78 	"*&%"		special_character	recolor=-1
     79 .endif
     80 	"\""		string			recolor=-1
     81 .ifdef STRINGS
     82 	"\i"		special_word		mark recolor=-1 buffer
     83 .endif
     84 	"#"		comment			recolor=-1
     85 
     86 
     87 ##############
     88 # Sync Lines #
     89 ##############
     90 
     91 # Following a '-' should be either the number of sync lines or nothing (meaning
     92 # unlimited).  Nothing else other than a comment should appear on the same line.
     93 .ifdef STRINGS
     94 # A sync lines directive should not appear between "[i]strings" and "done".
     95 .else
     96 # If we see a non-digit or a '0', then we have seen the entire sync lines
     97 # directive.  The only thing that may appear on the rest of the line is a
     98 # comment.  Otherwise there may be more digits in the number.
     99 :sync_lines_first Literal
    100 	*		comment_or_bad		noeat
    101 	"0"		comment_or_bad
    102 	"1-9"		sync_lines
    103 
    104 # Highlight the remainder of the number.
    105 :sync_lines Literal
    106 	*		comment_or_bad		noeat
    107 	"0-9"		sync_lines
    108 .endif
    109 
    110 
    111 ##########################
    112 # Conditional Directives #
    113 ##########################
    114 
    115 # Following a '.' should be a conditional directive.
    116 .ifdef STRINGS
    117 # A conditional directive should not appear between "[i]strings" and "done".
    118 .else
    119 # Start buffering the conditional directive.
    120 :conditional_first Conditional
    121 	*		conditional		noeat buffer
    122 
    123 # Recognize the set of conditional directives.
    124 :conditional Idle
    125 	*		conditional_unknown	noeat strings
    126 	"ifdef"		ifdef_color
    127 	"else"		conditional_color
    128 	"endif"		conditional_color
    129 	"subr"		subr_color
    130 	"end"		conditional_color
    131 	done
    132 	"\c"		conditional
    133 
    134 # We encountered what looks like a conditional directive but is unrecognized as
    135 # such.
    136 :conditional_unknown Idle
    137 .ifdef CHECKING
    138 	*		bad_line		recolormark noeat
    139 .else
    140 	*		comment_or_bad		noeat
    141 .endif
    142 
    143 # We saw a conditional directive that does not take an argument.  Nothing else
    144 # other than a comment should appear on the same line.
    145 :conditional_color Conditional
    146 	*		comment_or_bad		noeat
    147 
    148 # We saw a ".ifdef" which must be followed by a parameter.
    149 :ifdef_color Conditional
    150 	*		need_parameter		noeat
    151 
    152 # We loop over whitespace until we see the first character of the parameter.
    153 :need_parameter Idle
    154 	*		bad			noeat
    155 	" \t"		need_parameter
    156 	"\i"		parameter		recolor=-1
    157 
    158 # Now we highlight the remainder of the parameter.
    159 :parameter Parameter
    160 	*		comment_or_bad		noeat
    161 	"\c"		parameter
    162 
    163 # The following three states are identical to the previous three except the
    164 # color.
    165 :subr_color Conditional
    166 	*		need_subr		noeat
    167 
    168 :need_subr Idle
    169 	*		bad			noeat
    170 	" \t"		need_subr
    171 	"\i"		subr			recolor=-1
    172 
    173 :subr Subr
    174 	*		comment_or_bad		noeat
    175 	"\c"		subr
    176 .endif
    177 
    178 
    179 ####################
    180 # Color Definition #
    181 ####################
    182 
    183 # Following an '=' should be a color definition.
    184 .ifdef STRINGS
    185 # Color definitions should not appear between "[i]strings" and "done".
    186 .else
    187 # A color name must have at least one character.
    188 :color_definition_first Color
    189 	*		color_definition
    190 	" \t#\n"	bad			noeat
    191 
    192 # Highlight any remaining characters until we see whitespace, a comment, or a
    193 # newline.
    194 :color_definition Color
    195 	*		color_definition
    196 	" \t#\n"	colors_ws		noeat
    197 
    198 # The color name may be followed by zero or more standard colors or attributes,
    199 # ending in a comment or newline.
    200 :colors_ws Idle
    201 	*		color_bad		recolor=-1
    202 	" \t"		colors_ws
    203 	"\i"		color			mark recolor=-1 buffer
    204 	"#\n"		comment			noeat
    205 
    206 # Here we recognize the attributes and standard color names.  None of the
    207 # attributes or standard color names contain a digit except fg_NNN and bg_NNN,
    208 # which are handled specially below.
    209 :color Idle
    210 	*		color_unknown		noeat strings
    211 	"inverse"	color_color
    212 	"underline"	color_color
    213 	"bold"		color_color
    214 	"italic"	color_color
    215 	"blink"		color_color
    216 	"dim"		color_color
    217 	"white"		color_color
    218 	"cyan"		color_color
    219 	"magenta"	color_color
    220 	"blue"		color_color
    221 	"yellow"	color_color
    222 	"green"		color_color
    223 	"red"		color_color
    224 	"black"		color_color
    225 	"bg_white"	color_color
    226 	"bg_cyan"	color_color
    227 	"bg_magenta"	color_color
    228 	"bg_blue"	color_color
    229 	"bg_yellow"	color_color
    230 	"bg_green"	color_color
    231 	"bg_red"	color_color
    232 	"bg_black"	color_color
    233 	"WHITE"		color_color
    234 	"CYAN"		color_color
    235 	"MAGENTA"	color_color
    236 	"BLUE"		color_color
    237 	"YELLOW"	color_color
    238 	"GREEN"		color_color
    239 	"RED"		color_color
    240 	"BLACK"		color_color
    241 	"bg_WHITE"	color_color
    242 	"bg_CYAN"	color_color
    243 	"bg_MAGENTA"	color_color
    244 	"bg_BLUE"	color_color
    245 	"bg_YELLOW"	color_color
    246 	"bg_GREEN"	color_color
    247 	"bg_RED"	color_color
    248 	"bg_BLACK"	color_color
    249 	"fg_"		color_number_first
    250 	"bg_"		color_number_first
    251 	done
    252 	"\c"		color
    253 
    254 # We encountered what looks like a standard color but is unrecognized as such.
    255 :color_unknown Idle
    256 .ifdef CHECKING
    257 	*		color_bad		recolormark noeat
    258 .else
    259 	*		colors_ws		noeat
    260 .endif
    261 
    262 # Here we have seen either "fg_" or "bg_".  We now expect to find a number. The
    263 # number should either be a one to two digit number, representing greyscale
    264 # intensity, in the range 0-23, or a three digit number, where each digit is in
    265 # the range 0-5 and represents the intensity of red, green, and blue
    266 # respectively.
    267 :color_number_first Idle
    268 .ifdef CHECKING
    269 	*		color_bad		recolormark noeat
    270 .else
    271 	*		color_bad		noeat
    272 .endif
    273 	"0"		color_zero
    274 	"1"		color_one
    275 	"2"		color_two
    276 	"3-5"		color_number_second
    277 	"6-9"		color_end
    278 
    279 # The first digit is a zero, thus we either have a greyscale intensity of 0, in
    280 # which case we should not see any more digits, or we have the first RGB digit,
    281 # in which case we should see two more ditits in the range 0-5.
    282 :color_zero Idle
    283 .ifdef CHECKING
    284 	*		color_bad		recolormark noeat
    285 .else
    286 	*		color_bad		noeat
    287 .endif
    288 	"0-5"		color_rgb_third
    289 	" \t#\n"	color_color		recolormark noeat
    290 
    291 # The first digit is a one.  If we see whitespace or a comment, then we have a
    292 # greyscale intensity of 1.  If we see a digit 6-9, then we have a greyscale
    293 # intensity of 16-19.  If we see a digit 0-5, then we either have a greyscale
    294 # intensity of 10-15 or an RGB value.
    295 :color_one Idle
    296 .ifdef CHECKING
    297 	*		color_bad		recolormark noeat
    298 .else
    299 	*		color_bad		noeat
    300 .endif
    301 	"0-5"		color_number_third
    302 	"6-9"		color_end
    303 	" \t#\n"	color_color		recolormark noeat
    304 
    305 # The first digit is a two.  If we see whitespace or a comment, then we have a
    306 # greyscale intensity of 2.  If we see a digit 4-5, then we have the first two
    307 # digits of an RGB value.  If we see a digit 0-3, then we either have a
    308 # greyscale intensity of 20-23 or an RGB value.
    309 :color_two Idle
    310 .ifdef CHECKING
    311 	*		color_bad		recolormark noeat
    312 .else
    313 	*		color_bad		noeat
    314 .endif
    315 	"0-3"		color_number_third
    316 	"4-5"		color_rgb_third
    317 	" \t#\n"	color_color		recolormark noeat
    318 
    319 # We have seen one digit that could be either the greyscale intensity or the
    320 # first RGB digit.  If we see any more digits, they we must have an RGB value,
    321 # because otherwise the number would be outside the range 0-23.
    322 :color_number_second Idle
    323 .ifdef CHECKING
    324 	*		color_bad		recolormark noeat
    325 .else
    326 	*		color_bad		noeat
    327 .endif
    328 	"0-5"		color_rgb_third
    329 	" \t#\n"	color_color		recolormark noeat
    330 
    331 # We have seen two digits that could be either the greyscale intensity or the
    332 # first two RGB digits.  If we see any more digits, they we must have an RGB
    333 # value, because otherwise the number would be outside the range 0-23.
    334 :color_number_third Idle
    335 .ifdef CHECKING
    336 	*		color_bad		recolormark noeat
    337 .else
    338 	*		color_bad		noeat
    339 .endif
    340 	"0-5"		color_end
    341 	" \t#\n"	color_color		recolormark noeat
    342 
    343 # We have seen two digits, both 0-5, that either start with zero or are outside
    344 # the range 0-23.  Thus we expect a third 0-5 digit.
    345 :color_rgb_third Idle
    346 .ifdef CHECKING
    347 	*		color_bad		recolormark noeat
    348 .else
    349 	*		color_bad		noeat
    350 .endif
    351 	"0-5"		color_end
    352 
    353 # We have seen "fg_" or "bg_" followed by one to three digits.  Any more digits
    354 # would either be too many or make the number out of range.  We now expect to
    355 # see whitespace, a comment, or a newline.
    356 :color_end Idle
    357 .ifdef CHECKING
    358 	*		color_bad		recolormark noeat
    359 .else
    360 	*		color_bad		noeat
    361 .endif
    362 	" \t#\n"	color_color		recolormark noeat
    363 
    364 # This is a dummy state that simply provides the highlighting color for the
    365 # standard color or attribute and jumps to colors_ws without consuming any
    366 # characters.
    367 :color_color StandardColor
    368 	*		colors_ws		noeat
    369 
    370 # We have encountered something that is not recognized as a standard color or
    371 # attribute.  Continue to highlight characters as Bad until we see whitespace, a
    372 # comment, or a newline.
    373 :color_bad Bad
    374 	*		color_bad
    375 	" \t#\n"	colors_ws		noeat
    376 .endif
    377 
    378 
    379 #########
    380 # State #
    381 #########
    382 
    383 # Following a ':' should be a state definition.
    384 .ifdef STRINGS
    385 # New states should not appear between "[i]strings" and "done".
    386 .else
    387 # A state name must begin with an alpha character or an underscore.
    388 :state_first State
    389 	*		bad			noeat
    390 	"\i"		state
    391 
    392 # Subsequent characters in a state name must be alpha-numeric or underscores.
    393 :state State
    394 	*		bad			noeat
    395 	"\c"		state
    396 	" \t"		need_state_color	recolor=-1
    397 
    398 # A state must have a color.
    399 :need_state_color Idle
    400 	*		state_color		recolor=-1
    401 	" \t"		need_state_color
    402 	"#\n"		bad			noeat
    403 
    404 # Highlight any remaining characters until we see whitespace, a comment, or a
    405 # newline.
    406 :state_color Color
    407 	*		state_color
    408 	" \t"		context_ws		recolor=-1
    409 	"#\n"		comment_or_bad		noeat
    410 
    411 # Following the state color, there might be one or more contexts.  Loop over
    412 # whitespace until we find something else.
    413 :context_ws Idle
    414 	*		comment_or_bad		noeat
    415 	" \t"		context_ws
    416 	"\i"		context			mark recolor=-1 buffer
    417 
    418 # Here we recognize the possible contexts.
    419 :context Idle
    420 	*		context_unknown		noeat strings
    421 	"comment"	context_color
    422 	"string"	context_color
    423 	done
    424 	"\c"		context
    425 
    426 # We encountered what looks like a context but is unrecognized as such.
    427 :context_unknown Idle
    428 .ifdef CHECKING
    429 	*		context_bad		recolormark noeat
    430 .else
    431 	*		context_ws		noeat
    432 .endif
    433 
    434 # We encountered a valid context.
    435 :context_color Keyword
    436 	*		context_ws		noeat
    437 
    438 # We saw something that is not a valid context name with checking enabled.
    439 # Continue to highlight it as Bad until we see whitespace or a comment.
    440 :context_bad Bad
    441 	*		context_bad
    442 	" \t#\n"	context_ws		noeat
    443 .endif
    444 
    445 
    446 ##############
    447 # Transition #
    448 ##############
    449 
    450 # A state transition starts with a '*', an '&', or a string.
    451 .ifdef STRINGS
    452 # Transitions must start with a string between "[i]strings" and "done".
    453 .else
    454 # We saw either a '*' or an '&'.  Now we need the next state.
    455 :special_character Keyword
    456 	*		need_next_state		noeat
    457 .endif
    458 
    459 # We are in a string.  Continue until we see the close quote or a newline.
    460 # Highlight escaped characters within the string differently.  They start with a
    461 # '\'.
    462 :string Literal string
    463 	*		string
    464 	"\\"		escape			recolor=-1
    465 	"\""		need_next_state
    466 .ifdef CHECKING
    467 	"\n"		bad
    468 .else
    469 	"\n"		bad			noeat
    470 .endif
    471 
    472 # Highlight an escaped character within a string.
    473 :escape Escape string
    474 	*		string
    475 
    476 # Loop over whitespace until we see the first character of the next state.
    477 :need_next_state Idle
    478 	*		bad			noeat
    479 	" \t"		need_next_state
    480 	"\i"		next_state		recolor=-1
    481 
    482 # Now we highlight the remainder of the next state.
    483 :next_state State
    484 	*		bad			noeat
    485 	"\c"		next_state
    486 	" \t"		options_ws
    487 	"#\n"		comment			noeat
    488 
    489 # Following the next state should be zero or more options.  Loop over whitespace
    490 # until we find an option, comment, or newline.
    491 :options_ws Idle
    492 	*		option_bad		recolor=-1
    493 	" \t"		options_ws
    494 	"\i"		option			mark recolor=-1 buffer
    495 	"#\n"		comment			noeat
    496 
    497 # Here we recognize the possible options.  The strings and istrings options
    498 # cannot be used between "[i]strings" and "done".  Since conditional directives
    499 # cannot be used between "[i]strings" and "done" either, the list must be
    500 # duplicated, once without and once with the strings and istrings options.
    501 :option Idle
    502 .ifdef STRINGS
    503 	*		option_unknown		recolormark noeat strings
    504 	"noeat"		option_color
    505 	"recolor"	recolor_color
    506 	"mark"		option_color
    507 	"markend"	option_color
    508 	"recolormark"	option_color
    509 	"buffer"	option_color
    510 	"save_c"	option_color
    511 	"save_s"	option_color
    512 	"hold"		option_color
    513 	"call"		call_color
    514 	"return"	option_color
    515 	"reset"		option_color
    516 	done
    517 .else
    518 	*		option_unknown		recolormark noeat strings
    519 	"noeat"		option_color
    520 	"recolor"	recolor_color
    521 	"mark"		option_color
    522 	"markend"	option_color
    523 	"recolormark"	option_color
    524 	"buffer"	option_color
    525 	"save_c"	option_color
    526 	"save_s"	option_color
    527 	"strings"	strings_color
    528 	"istrings"	strings_color
    529 	"hold"		option_color
    530 	"call"		call_color
    531 	"return"	option_color
    532 	"reset"		option_color
    533 	done
    534 .endif
    535 	"\c"		option
    536 
    537 # We encountered what looks like an option but is unrecognized as such.
    538 :option_unknown Idle
    539 .ifdef CHECKING
    540 	*		option_bad		recolormark noeat
    541 .else
    542 	*		options_ws		noeat
    543 .endif
    544 
    545 # We have encountered an option that does not take an argument.  Highlight it
    546 # and continue to look for more options.
    547 :option_color Keyword
    548 	*		options_ws		noeat
    549 
    550 .ifdef STRINGS
    551 # The strings and istrings options cannot be used between "[i]strings" and
    552 # "done".
    553 .else
    554 # The strings and istrings options are followed by a list of transitions. 
    555 # Rather than duplicate all of the states that highlight transitions, we call
    556 # this entire file as a subroutine and use the STRINGS parameter to disable
    557 # everything else and enable the done keyword.  We return to the comment_or_bad
    558 # state since we will return after seeing the done keyword, and nothing but a
    559 # comment should follow the done keyword.
    560 :strings_color Keyword
    561 	*		comment_or_bad		noeat call=jsf(STRINGS)
    562 .endif
    563 
    564 # Highlight the recolor option.
    565 :recolor_color Keyword
    566 	*		recolor_equal		noeat
    567 
    568 # The recolor option must be followed by an '='.  Loop over whitespace until we
    569 # find one.
    570 :recolor_equal Idle
    571 .ifdef CHECKING
    572 	*		option_bad		recolormark noeat
    573 .else
    574 	*		options_ws		noeat
    575 .endif
    576 	" \t"		recolor_equal
    577 	"="		recolor_minus		mark
    578 
    579 # The recolor option takes an integer argument, and that integer must be
    580 # negative.  Thus the '=' must be followed by a minus sign.  Loop over
    581 # whitespace until we find one.
    582 :recolor_minus Idle
    583 .ifdef CHECKING
    584 	*		option_bad		recolormark noeat
    585 .else
    586 	*		options_ws		noeat
    587 .endif
    588 	" \t"		recolor_minus
    589 	"-"		recolor_amount_first	mark recolor=-1
    590 
    591 # The first digit of the argument to recolor must be non-zero.
    592 :recolor_amount_first Literal
    593 .ifdef CHECKING
    594 	*		option_bad		recolormark noeat
    595 .else
    596 	*		options_ws		recolormark noeat
    597 	"0"		option_bad		recolormark noeat
    598 .endif
    599 	"1-9"		recolor_amount
    600 
    601 # Keep highlighting digits until we see something else.
    602 :recolor_amount Literal
    603 	*		option_bad		recolormark recolor=-1
    604 	"0-9"		recolor_amount
    605 	" \t#\n"	options_ws		noeat
    606 
    607 # Highlight the call option.
    608 :call_color Keyword
    609 	*		call_equal		noeat
    610 
    611 # The call option must be followed by an '='.  Loop over whitespace until we
    612 # find one.
    613 :call_equal Idle
    614 .ifdef CHECKING
    615 	*		option_bad		recolormark noeat
    616 .else
    617 	*		options_ws		noeat
    618 .endif
    619 	" \t"		call_equal
    620 	"="		call_file_or_dot	mark
    621 
    622 # The first part of the argument to the call option is the name of the file
    623 # containing the subroutine or a '.', implying the current file.  Loop over
    624 # whitespace until we see one of those two things.
    625 :call_file_or_dot Idle
    626 .ifdef CHECKING
    627 	*		option_bad		recolormark noeat
    628 .else
    629 	*		options_ws		noeat
    630 .endif
    631 	" \t"		call_file_or_dot
    632 	"\i"		call_file		mark recolor=-1
    633 	"."		call_dot		mark
    634 
    635 # Highlight the remainder of the file name.  The file name can be followed by a
    636 # '.', which must then be followed by the name of a subroutine, or by a list of
    637 # parameters in parentheses.  The '.', if present, cannot have whitespace on
    638 # either side.
    639 :call_file Subr
    640 .ifdef CHECKING
    641 	*		option_bad		recolormark noeat
    642 .else
    643 	*		options_ws		noeat
    644 .endif
    645 	"\c"		call_file
    646 	"."		call_dot		mark recolor=-1
    647 	" \t("		call_open_paren		noeat
    648 
    649 # We saw a '.'.  The next character must start the name of a subroutine.
    650 :call_dot Idle
    651 .ifdef CHECKING
    652 	*		option_bad		recolormark noeat
    653 .else
    654 	*		options_ws		noeat
    655 .endif
    656 	"("		call_dot_bad		recolormark noeat
    657 	"\i"		call_subr		mark recolor=-1
    658 
    659 # We have seen a dot followed by an open parenthesis.  A dot must be followed by
    660 # a subroutine name.  Highlight the dot as Bad.
    661 :call_dot_bad Bad
    662 	*		call_open_paren		noeat
    663 
    664 # Highlight the remainder of the subroutine name.  Following the subroutine name
    665 # must be a list of parameters in parentheses, possibly preceded by whitespace.
    666 :call_subr Subr
    667 .ifdef CHECKING
    668 	*		option_bad		recolormark noeat
    669 .else
    670 	*		options_ws		noeat
    671 .endif
    672 	"\c"		call_subr
    673 	" \t("		call_open_paren		noeat
    674 
    675 # Loop over whitespace until we find the open parenthesis.
    676 :call_open_paren Idle
    677 .ifdef CHECKING
    678 	*		option_bad		recolormark noeat
    679 .else
    680 	*		options_ws		noeat
    681 .endif
    682 	" \t"		call_open_paren
    683 	"("		call_parameters_ws
    684 
    685 # The list of parameters is delimited by whitespace.  Loop over whitespace until
    686 # we find either the beginning of a parameter or a close parenthesis.  We should
    687 # not see a comment or newline since the list should be terminated by a close
    688 # parenthesis.
    689 :call_parameters_ws Idle
    690 	*		call_parameter_bad	recolor=-1
    691 	" \t"		call_parameters_ws
    692 	"-"		call_parameter_undef
    693 	"\i"		call_parameter		recolor=-1
    694 	")"		options_ws
    695 	"#\n"		bad			noeat
    696 
    697 # We saw a "-".  The next character should start the parameter being undefined.
    698 :call_parameter_undef Parameter
    699 	*		call_parameters_ws	noeat
    700 	"\i"		call_parameter		recolor=-2
    701 
    702 # Highlight the remainder of the parameter.
    703 :call_parameter Parameter
    704 	*		call_parameters_ws	noeat
    705 	"\c"		call_parameter
    706 
    707 # We saw something that is not a valid parameter name.  Continue to highlight it
    708 # as Bad until we see whitespace.
    709 :call_parameter_bad Bad
    710 	*		call_parameter_bad
    711 	") \t#\n"	call_parameters_ws	noeat
    712 
    713 # We saw something that is not a valid option name.  Continue to highlight it as
    714 # Bad until we see whitespace or a comment.
    715 :option_bad Bad
    716 	*		option_bad
    717 	" \t#\n"	options_ws		noeat
    718 
    719 
    720 ########
    721 # Done #
    722 ########
    723 
    724 .ifdef STRINGS
    725 # The special word, "done", can only be used after a strings or istrings option.
    726 # Recognize the done keyword.
    727 :special_word Idle
    728 	*		bad_line		recolormark noeat strings
    729 	"done"		done_color
    730 	done
    731 	"\c"		special_word
    732 
    733 # Highlight the done keyword and return to highlighting things normally, since
    734 # the list of strings has been terminated.
    735 :done_color Keyword
    736 	*		comment_or_bad		return noeat
    737 .endif
    738 
    739 
    740 ##################
    741 # Comment or Bad #
    742 ##################
    743 
    744 # We have seen everything that should appear on the current line except an
    745 # optional comment.  Loop over whitespace until we find a comment or newline.
    746 :comment_or_bad Idle
    747 	*		bad			noeat
    748 	" \t"		comment_or_bad
    749 	"#\n"		comment			noeat
    750 
    751 
    752 ###########
    753 # Comment #
    754 ###########
    755 
    756 # Continue to highlight the comment until the end of the line.
    757 :comment Comment comment
    758 	*		comment
    759 	"\n"		idle
    760 
    761 
    762 #######
    763 # Bad #
    764 #######
    765 
    766 .ifdef CHECKING
    767 # We have encountered incorrect syntax.  Loop over whitespace until we see the
    768 # first visible character.  Highlight that character and the rest of the line as
    769 # Bad.
    770 :bad Bad
    771 	*		bad_line
    772 	" \t\n"		bad
    773 .else
    774 # When not performing strict checking, don't go searching for the next visible
    775 # character to highlight as Bad.  Simply highlight the rest of the line as Bad,
    776 # even if it is invisible.
    777 :bad Bad
    778 	*		bad_line		noeat
    779 .endif
    780 
    781 # Continue to highlight everything as Bad until the end of the line.
    782 :bad_line Bad
    783 	*		bad_line
    784 	"\n"		idle