jsf.jsf (16834B)
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 37 =Conditional +Precond +Preproc 38 =Parameter +Ident 39 =Keyword 40 =Color +Type 41 =ColorRef 42 =State +Ident 43 =Subr +Ident 44 =Constant 45 =Number +Constant 46 =String +Constant 47 =StringEscape +Escape +String 48 =Bad 49 50 51 52 53 ################## 54 # Initial States # 55 ################## 56 57 # This is a dummy state that simply jumps to comment_or_bad. It is here so that 58 # when this file calls itself with the STRINGS parameter defined, comment_or_bad 59 # will effectively be the initial state. comment_or_bad should be the initial 60 # state because strings and istrings options can only be used as the last option 61 # of a transition. 62 .ifdef STRINGS 63 :strings_initial Idle 64 * comment_or_bad noeat 65 .endif 66 67 # Each new line (that is not considered bad from the beginning) begins in the 68 # idle state. The first non-whitespace character determines what the rest of 69 # the line should contain. Following a strings or istrings option, only strings 70 # and comments are allowed until the word "done" denotes the end of the list. 71 :idle Idle 72 * bad noeat 73 " \t\n" idle 74 .ifdef STRINGS 75 .else 76 "-" sync_lines_first 77 "." conditional_first mark recolor=-1 78 "=" color_definition_first 79 ":" state_first 80 "*&%" special_character recolor=-1 81 .endif 82 "\"" string recolor=-1 83 .ifdef STRINGS 84 "\i" special_word mark recolor=-1 buffer 85 .endif 86 "#" comment recolor=-1 87 88 89 ############## 90 # Sync Lines # 91 ############## 92 93 # Following a '-' should be either the number of sync lines or nothing (meaning 94 # unlimited). Nothing else other than a comment should appear on the same line. 95 .ifdef STRINGS 96 # A sync lines directive should not appear between "[i]strings" and "done". 97 .else 98 # If we see a non-digit or a '0', then we have seen the entire sync lines 99 # directive. The only thing that may appear on the rest of the line is a 100 # comment. Otherwise there may be more digits in the number. 101 :sync_lines_first Number 102 * comment_or_bad noeat 103 "0" comment_or_bad 104 "1-9" sync_lines 105 106 # Highlight the remainder of the number. 107 :sync_lines Number 108 * comment_or_bad noeat 109 "0-9" sync_lines 110 .endif 111 112 113 ########################## 114 # Conditional Directives # 115 ########################## 116 117 # Following a '.' should be a conditional directive. 118 .ifdef STRINGS 119 # A conditional directive should not appear between "[i]strings" and "done". 120 .else 121 # Start buffering the conditional directive. 122 :conditional_first Conditional 123 * conditional noeat buffer 124 125 # Recognize the set of conditional directives. 126 :conditional Idle 127 * conditional_unknown noeat strings 128 "ifdef" ifdef_color 129 "else" conditional_color 130 "endif" conditional_color 131 "subr" subr_color 132 "end" conditional_color 133 done 134 "\c" conditional 135 136 # We encountered what looks like a conditional directive but is unrecognized as 137 # such. 138 :conditional_unknown Idle 139 .ifdef CHECKING 140 * bad_line recolormark noeat 141 .else 142 * comment_or_bad noeat 143 .endif 144 145 # We saw a conditional directive that does not take an argument. Nothing else 146 # other than a comment should appear on the same line. 147 :conditional_color Conditional 148 * comment_or_bad noeat 149 150 # We saw a ".ifdef" which must be followed by a parameter. 151 :ifdef_color Conditional 152 * need_parameter noeat 153 154 # We loop over whitespace until we see the first character of the parameter. 155 :need_parameter Idle 156 * bad noeat 157 " \t" need_parameter 158 "\i" parameter recolor=-1 159 160 # Now we highlight the remainder of the parameter. 161 :parameter Parameter 162 * comment_or_bad noeat 163 "\c" parameter 164 165 # The following three states are identical to the previous three except the 166 # color. 167 :subr_color Conditional 168 * need_subr noeat 169 170 :need_subr Idle 171 * bad noeat 172 " \t" need_subr 173 "\i" subr recolor=-1 174 175 :subr Subr 176 * comment_or_bad noeat 177 "\c" subr 178 .endif 179 180 181 #################### 182 # Color Definition # 183 #################### 184 185 # Following an '=' should be a color definition. 186 .ifdef STRINGS 187 # Color definitions should not appear between "[i]strings" and "done". 188 .else 189 # A color name must have at least one character. 190 :color_definition_first Color 191 * color_definition 192 " \t#\n" bad noeat 193 194 # Highlight any remaining characters until we see whitespace, a comment, or a 195 # newline. 196 :color_definition Color 197 * color_definition 198 " \t#\n" colors_ws noeat 199 200 # The color name may be followed by zero or more standard colors or attributes, 201 # ending in a comment or newline. 202 :colors_ws Idle 203 * color_bad recolor=-1 204 " \t" colors_ws 205 "+" color_ref recolor=-1 206 "#\n" comment noeat 207 208 :color_ref ColorRef 209 * colors_ws noeat 210 "\c" color_ref 211 212 # We have encountered something that is not recognized as a standard color or 213 # attribute. Continue to highlight characters as Bad until we see whitespace, a 214 # comment, or a newline. 215 :color_bad Bad 216 * color_bad 217 " \t#\n" colors_ws noeat 218 .endif 219 220 221 ######### 222 # State # 223 ######### 224 225 # Following a ':' should be a state definition. 226 .ifdef STRINGS 227 # New states should not appear between "[i]strings" and "done". 228 .else 229 # A state name must begin with an alpha character or an underscore. 230 :state_first State 231 * bad noeat 232 "\i" state 233 234 # Subsequent characters in a state name must be alpha-numeric or underscores. 235 :state State 236 * bad noeat 237 "\c" state 238 " \t" need_state_color recolor=-1 239 240 # A state must have a color. 241 :need_state_color Idle 242 * state_color recolor=-1 243 " \t" need_state_color 244 "#\n" bad noeat 245 246 # Highlight any remaining characters until we see whitespace, a comment, or a 247 # newline. 248 :state_color Color 249 * state_color 250 " \t" context_ws recolor=-1 251 "#\n" comment_or_bad noeat 252 253 # Following the state color, there might be one or more contexts. Loop over 254 # whitespace until we find something else. 255 :context_ws Idle 256 * comment_or_bad noeat 257 " \t" context_ws 258 "\i" context mark recolor=-1 buffer 259 260 # Here we recognize the possible contexts. 261 :context Idle 262 * context_unknown noeat strings 263 "comment" context_color 264 "string" context_color 265 done 266 "\c" context 267 268 # We encountered what looks like a context but is unrecognized as such. 269 :context_unknown Idle 270 .ifdef CHECKING 271 * context_bad recolormark noeat 272 .else 273 * context_ws noeat 274 .endif 275 276 # We encountered a valid context. 277 :context_color Keyword 278 * context_ws noeat 279 280 # We saw something that is not a valid context name with checking enabled. 281 # Continue to highlight it as Bad until we see whitespace or a comment. 282 :context_bad Bad 283 * context_bad 284 " \t#\n" context_ws noeat 285 .endif 286 287 288 ############## 289 # Transition # 290 ############## 291 292 # A state transition starts with a '*', an '&', or a string. 293 .ifdef STRINGS 294 # Transitions must start with a string between "[i]strings" and "done". 295 .else 296 # We saw either a '*' or an '&'. Now we need the next state. 297 :special_character Keyword 298 * need_next_state noeat 299 .endif 300 301 # We are in a string. Continue until we see the close quote or a newline. 302 # Highlight escaped characters within the string differently. They start with a 303 # '\'. 304 :string String string 305 * string 306 "\\" escape recolor=-1 307 "\"" need_next_state 308 .ifdef CHECKING 309 "\n" bad 310 .else 311 "\n" bad noeat 312 .endif 313 314 # Highlight an escaped character within a string. 315 :escape StringEscape string 316 * string 317 318 # Loop over whitespace until we see the first character of the next state. 319 :need_next_state Idle 320 * bad noeat 321 " \t" need_next_state 322 "\i" next_state recolor=-1 323 324 # Now we highlight the remainder of the next state. 325 :next_state State 326 * bad noeat 327 "\c" next_state 328 " \t" options_ws 329 "#\n" comment noeat 330 331 # Following the next state should be zero or more options. Loop over whitespace 332 # until we find an option, comment, or newline. 333 :options_ws Idle 334 * option_bad recolor=-1 335 " \t" options_ws 336 "\i" option mark recolor=-1 buffer 337 "#\n" comment noeat 338 339 # Here we recognize the possible options. The strings and istrings options 340 # cannot be used between "[i]strings" and "done". Since conditional directives 341 # cannot be used between "[i]strings" and "done" either, the list must be 342 # duplicated, once without and once with the strings and istrings options. 343 :option Idle 344 .ifdef STRINGS 345 * option_unknown recolormark noeat strings 346 "noeat" option_color 347 "recolor" recolor_color 348 "mark" option_color 349 "markend" option_color 350 "recolormark" option_color 351 "buffer" option_color 352 "save_c" option_color 353 "save_s" option_color 354 "hold" option_color 355 "call" call_color 356 "return" option_color 357 "reset" option_color 358 done 359 .else 360 * option_unknown recolormark noeat strings 361 "noeat" option_color 362 "recolor" recolor_color 363 "mark" option_color 364 "markend" option_color 365 "recolormark" option_color 366 "buffer" option_color 367 "save_c" option_color 368 "save_s" option_color 369 "strings" strings_color 370 "istrings" strings_color 371 "hold" option_color 372 "call" call_color 373 "return" option_color 374 "reset" option_color 375 done 376 .endif 377 "\c" option 378 379 # We encountered what looks like an option but is unrecognized as such. 380 :option_unknown Idle 381 .ifdef CHECKING 382 * option_bad recolormark noeat 383 .else 384 * options_ws noeat 385 .endif 386 387 # We have encountered an option that does not take an argument. Highlight it 388 # and continue to look for more options. 389 :option_color Keyword 390 * options_ws noeat 391 392 .ifdef STRINGS 393 # The strings and istrings options cannot be used between "[i]strings" and 394 # "done". 395 .else 396 # The strings and istrings options are followed by a list of transitions. 397 # Rather than duplicate all of the states that highlight transitions, we call 398 # this entire file as a subroutine and use the STRINGS parameter to disable 399 # everything else and enable the done keyword. We return to the comment_or_bad 400 # state since we will return after seeing the done keyword, and nothing but a 401 # comment should follow the done keyword. 402 :strings_color Keyword 403 * comment_or_bad noeat call=jsf(STRINGS) 404 .endif 405 406 # Highlight the recolor option. 407 :recolor_color Keyword 408 * recolor_equal noeat 409 410 # The recolor option must be followed by an '='. Loop over whitespace until we 411 # find one. 412 :recolor_equal Idle 413 .ifdef CHECKING 414 * option_bad recolormark noeat 415 .else 416 * options_ws noeat 417 .endif 418 " \t" recolor_equal 419 "=" recolor_minus mark 420 421 # The recolor option takes an integer argument, and that integer must be 422 # negative. Thus the '=' must be followed by a minus sign. Loop over 423 # whitespace until we find one. 424 :recolor_minus Idle 425 .ifdef CHECKING 426 * option_bad recolormark noeat 427 .else 428 * options_ws noeat 429 .endif 430 " \t" recolor_minus 431 "-" recolor_amount_first mark recolor=-1 432 433 # The first digit of the argument to recolor must be non-zero. 434 :recolor_amount_first Number 435 .ifdef CHECKING 436 * option_bad recolormark noeat 437 .else 438 * options_ws recolormark noeat 439 "0" option_bad recolormark noeat 440 .endif 441 "1-9" recolor_amount 442 443 # Keep highlighting digits until we see something else. 444 :recolor_amount Number 445 * option_bad recolormark recolor=-1 446 "0-9" recolor_amount 447 " \t#\n" options_ws noeat 448 449 # Highlight the call option. 450 :call_color Keyword 451 * call_equal noeat 452 453 # The call option must be followed by an '='. Loop over whitespace until we 454 # find one. 455 :call_equal Idle 456 .ifdef CHECKING 457 * option_bad recolormark noeat 458 .else 459 * options_ws noeat 460 .endif 461 " \t" call_equal 462 "=" call_file_or_dot mark 463 464 # The first part of the argument to the call option is the name of the file 465 # containing the subroutine or a '.', implying the current file. Loop over 466 # whitespace until we see one of those two things. 467 :call_file_or_dot Idle 468 .ifdef CHECKING 469 * option_bad recolormark noeat 470 .else 471 * options_ws noeat 472 .endif 473 " \t" call_file_or_dot 474 "\i" call_file mark recolor=-1 475 "." call_dot mark 476 477 # Highlight the remainder of the file name. The file name can be followed by a 478 # '.', which must then be followed by the name of a subroutine, or by a list of 479 # parameters in parentheses. The '.', if present, cannot have whitespace on 480 # either side. 481 :call_file Subr 482 .ifdef CHECKING 483 * option_bad recolormark noeat 484 .else 485 * options_ws noeat 486 .endif 487 "\c" call_file 488 "." call_dot mark recolor=-1 489 " \t(" call_open_paren noeat 490 491 # We saw a '.'. The next character must start the name of a subroutine. 492 :call_dot Idle 493 .ifdef CHECKING 494 * option_bad recolormark noeat 495 .else 496 * options_ws noeat 497 .endif 498 "(" call_dot_bad recolormark noeat 499 "\i" call_subr mark recolor=-1 500 501 # We have seen a dot followed by an open parenthesis. A dot must be followed by 502 # a subroutine name. Highlight the dot as Bad. 503 :call_dot_bad Bad 504 * call_open_paren noeat 505 506 # Highlight the remainder of the subroutine name. Following the subroutine name 507 # must be a list of parameters in parentheses, possibly preceded by whitespace. 508 :call_subr Subr 509 .ifdef CHECKING 510 * option_bad recolormark noeat 511 .else 512 * options_ws noeat 513 .endif 514 "\c" call_subr 515 " \t(" call_open_paren noeat 516 517 # Loop over whitespace until we find the open parenthesis. 518 :call_open_paren Idle 519 .ifdef CHECKING 520 * option_bad recolormark noeat 521 .else 522 * options_ws noeat 523 .endif 524 " \t" call_open_paren 525 "(" call_parameters_ws 526 527 # The list of parameters is delimited by whitespace. Loop over whitespace until 528 # we find either the beginning of a parameter or a close parenthesis. We should 529 # not see a comment or newline since the list should be terminated by a close 530 # parenthesis. 531 :call_parameters_ws Idle 532 * call_parameter_bad recolor=-1 533 " \t" call_parameters_ws 534 "-" call_parameter_undef 535 "\i" call_parameter recolor=-1 536 ")" options_ws 537 "#\n" bad noeat 538 539 # We saw a "-". The next character should start the parameter being undefined. 540 :call_parameter_undef Parameter 541 * call_parameters_ws noeat 542 "\i" call_parameter recolor=-2 543 544 # Highlight the remainder of the parameter. 545 :call_parameter Parameter 546 * call_parameters_ws noeat 547 "\c" call_parameter 548 549 # We saw something that is not a valid parameter name. Continue to highlight it 550 # as Bad until we see whitespace. 551 :call_parameter_bad Bad 552 * call_parameter_bad 553 ") \t#\n" call_parameters_ws noeat 554 555 # We saw something that is not a valid option name. Continue to highlight it as 556 # Bad until we see whitespace or a comment. 557 :option_bad Bad 558 * option_bad 559 " \t#\n" options_ws noeat 560 561 562 ######## 563 # Done # 564 ######## 565 566 .ifdef STRINGS 567 # The special word, "done", can only be used after a strings or istrings option. 568 # Recognize the done keyword. 569 :special_word Idle 570 * bad_line recolormark noeat strings 571 "done" done_color 572 done 573 "\c" special_word 574 575 # Highlight the done keyword and return to highlighting things normally, since 576 # the list of strings has been terminated. 577 :done_color Keyword 578 * comment_or_bad return noeat 579 .endif 580 581 582 ################## 583 # Comment or Bad # 584 ################## 585 586 # We have seen everything that should appear on the current line except an 587 # optional comment. Loop over whitespace until we find a comment or newline. 588 :comment_or_bad Idle 589 * bad noeat 590 " \t" comment_or_bad 591 "#\n" comment noeat 592 593 594 ########### 595 # Comment # 596 ########### 597 598 # Continue to highlight the comment until the end of the line. 599 :comment Comment comment 600 * comment 601 "BFHNTX" comment noeat call=comment_todo.comment_todo() 602 "\n" idle 603 604 605 ####### 606 # Bad # 607 ####### 608 609 .ifdef CHECKING 610 # We have encountered incorrect syntax. Loop over whitespace until we see the 611 # first visible character. Highlight that character and the rest of the line as 612 # Bad. 613 :bad Bad 614 * bad_line 615 " \t\n" bad 616 .else 617 # When not performing strict checking, don't go searching for the next visible 618 # character to highlight as Bad. Simply highlight the rest of the line as Bad, 619 # even if it is invisible. 620 :bad Bad 621 * bad_line noeat 622 .endif 623 624 # Continue to highlight everything as Bad until the end of the line. 625 :bad_line Bad 626 * bad_line 627 "\n" idle