lectures.alex.balgavy.eu

Lecture notes from university.
git clone git://git.alex.balgavy.eu/lectures.alex.balgavy.eu.git
Log | Files | Refs | Submodules

ASP.sublime-syntax (29117B)


      1 %YAML 1.2
      2 ---
      3 # http://www.sublimetext.com/docs/3/syntax.html
      4 name: ASP
      5 file_extensions:
      6   - asa # asp is handled by HTML-ASP.sublime-syntax
      7 scope: source.asp
      8 variables:
      9   apostrophe_comment_begin: "'"
     10   rem_comment_begin: '\b(?i:REM)\b'
     11   whitespace_or_end_of_statement: '(?=\s|$|:|{{apostrophe_comment_begin}}|{{rem_comment_begin}}|%>)'
     12   identifier: '[a-zA-Z]\w*|\[(?:(?!%>|\]).)*(?:\]|(\n|(?=%>)))' # reserved words can be used if enclosed in square brackets, as can other characters not normally accepted
     13   comparison_operators: '[=><]'
     14   math_operators: '(?:[+*^&/\\-]|\b(?i:Mod)\b)'
     15   logical_operators: '\b(?i:And|Not|Or|Xor|Is)\b'
     16   operators: '{{comparison_operators}}|{{math_operators}}|{{logical_operators}}'
     17   literal_number_hex: '(&[hH])\h+(&)?(?={{whitespace_or_end_of_statement}}|{{operators}}|[,)_])'
     18   literal_number_decimal: '(?:(?:\d+\.\d*|\.?\d+)(?i:e[+-]?\d+)?)(?={{whitespace_or_end_of_statement}}|{{operators}}|[,)_])'
     19   reserved_words: '\b(?i:Class|Sub|Function|Const|Dim|ReDim|Public|Private|End|Preserve|Select|Case|If|Else|ElseIf|Then|For|Each|Next|ByRef|ByVal|Set|Call|New|Option|With|To|In|While|Wend|Until|Loop|On|GoTo|Resume|Let|Get|Exit|Do)\b' # Default|Step|Error|Property are not reserved words
     20   keywords: '\b(?i:Empty|False|Nothing|Null|True)\b'
     21   constants: '\b(?i:vbTrue|vbFalse|vbCr|vbCrLf|vbFormFeed|vbLf|vbNewLine|vbNullChar|vbNullString|vbTab|vbVerticalTab|vbBinaryCompare|vbTextCompare|vbSunday|vbMonday|vbTuesday|vbWednesday|vbThursday|vbFriday|vbSaturday|vbUseSystemDayOfWeek|vbFirstJan1|vbFirstFourDays|vbFirstFullWeek|vbGeneralDate|vbLongDate|vbShortDate|vbLongTime|vbShortTime|vbObjectError|vbEmpty|vbNull|vbInteger|vbLong|vbSingle|vbDouble|vbCurrency|vbDate|vbString|vbObject|vbError|vbBoolean|vbVariant|vbDataObject|vbDecimal|vbByte|vbArray|vbOkCancel|vbOkOnly|vbYesNo|vbYesNoCancel|vbAbortRetryIgnore|vbRetryCancel|vbYes|vbNo|vbAbort|vbCancel|vbIgnore|vbRetry|vbCritical|vbExclamation|vbInformation|vbQuestion|vbDefaultButton[123])\b'
     22   functions: '\b(?i:Abs|Array|Add|Asc|Atn|CBool|CByte|CCur|CDate|CDbl|Chr|CInt|CLng|Conversions|Cos|CreateObject|CSng|CStr|Date|DateAdd|DateDiff|DatePart|DateSerial|DateValue|Day|Derived|Math|Escape|Eval|Exists|Exp|Filter|FormatCurrency|FormatDateTime|FormatNumber|FormatPercent|GetLocale|GetObject|GetRef|Hex|Hour|InputBox|InStr|InStrRev|Int|Fix|IsArray|IsDate|IsEmpty|IsNull|IsNumeric|IsObject|Item|Items|Join|Keys|LBound|LCase|Left|Len|LoadPicture|Log|LTrim|RTrim|Trim|Maths|Mid|Minute|Month|MonthName|MsgBox|Now|Oct|Remove|RemoveAll|Replace|RGB|Right|Rnd|Round|ScriptEngine|ScriptEngineBuildVersion|ScriptEngineMajorVersion|ScriptEngineMinorVersion|Second|SetLocale|Sgn|Sin|Space|Split|Sqr|StrComp|String|StrReverse|Tan|Time|TimeSerial|TimeValue|TypeName|UBound|UCase|Unescape|VarType|Weekday|WeekdayName|Year)\b'
     23   asp_builtin_classes: '\b(?i:Application|ObjectContext|Request|Response|Server|Session)\b'
     24   asp_builtin_events: '\b(?i:Application_OnEnd|Application_OnStart|OnTransactionAbort|OnTransactionCommit|Session_OnEnd|Session_OnStart)\b'
     25   class_magic_funcs: '\b(?i:Class_Initialize|Class_Terminate)\b'
     26 
     27 contexts:
     28   root_asp:
     29     - match: '(?=%>)'
     30       pop: true
     31 
     32   main:
     33     - match: '\b(?i:End){{whitespace_or_end_of_statement}}'
     34       scope: invalid.illegal.unexpected-token.asp
     35     - match: '(?i:Option\s+Explicit)'
     36       scope: keyword.asp
     37     - include: definitions
     38     - include: statements
     39 
     40   comments:
     41     - match: '{{apostrophe_comment_begin}}'
     42       scope: punctuation.definition.comment.asp
     43       push:
     44         - meta_scope: comment.line.apostrophe.asp
     45         - include: root_asp
     46         - match: \n
     47           pop: true
     48     - match: '{{rem_comment_begin}}'
     49       scope: punctuation.definition.comment.asp
     50       push:
     51         - meta_scope: comment.line.rem.asp
     52         - include: root_asp
     53         - match: \n
     54           pop: true
     55 
     56   line_continuation_char:
     57     - match: '\b_'
     58       scope: punctuation.separator.continuation.line.asp
     59       push:
     60         - match: '\S.*'
     61           scope: invalid.illegal.expected-end-of-line.asp
     62         - match: $
     63           set:
     64             - match: '(?=\S)' # for VBS, use ^, but ASP allows multiple whitespace-only lines after the _, so we use (?=\S)
     65               pop: true
     66 
     67   allow_line_continuation:
     68     - match: '[\t ]+'
     69       scope: ''
     70     - include: line_continuation_char
     71     - include: comments
     72 
     73   not_end_of_statement:
     74     - match: ':'
     75       scope: invalid.illegal.unexpected-end-of-statement.asp
     76       pop: true
     77     - match: \n
     78       scope: invalid.illegal.unexpected-end-of-statement.asp
     79       pop: true
     80     - match: '{{rem_comment_begin}}|{{apostrophe_comment_begin}}'
     81       set:
     82         - meta_scope: invalid.illegal.unexpected-end-of-statement.asp
     83         - match: \n
     84           pop: true
     85     - include: allow_line_continuation
     86 
     87   expect_not_end_of_statement:
     88     - match: '' # this match pattern has been added to disable the illegal highlighting where a statement ends unexpectedly - to more closely match other syntaxes
     89       pop: true
     90     - include: not_end_of_statement
     91     - match: '\s*(?=\S)'
     92       pop: true
     93 
     94   expect_identifier_member_reference:
     95     - match: '\s*({{identifier}})'
     96       captures:
     97         1: variable.other.member.asp
     98       pop: true
     99     - match: '' # this match pattern has been added to disable the illegal highlighting where a statement ends unexpectedly - to more closely match other syntaxes
    100       pop: true
    101     - include: unexpected_token
    102 
    103   expect_identifier_reference:
    104     - match: '\s*({{identifier}})'
    105       captures:
    106         1: variable.other.asp
    107       #  2: invalid.illegal.unclosed-variable-identifier.asp
    108       pop: true
    109     - match: '' # this match pattern has been added to disable the illegal highlighting where a statement ends unexpectedly - to more closely match other syntaxes
    110       pop: true
    111     - include: unexpected_token
    112 
    113   inside_string:
    114     - meta_scope: string.quoted.double.asp
    115     - include: root_asp
    116     - match: \n
    117       scope: invalid.illegal.unclosed-string.asp
    118       pop: true
    119     - match: '""'
    120       scope: constant.character.escape.apostrophe.asp
    121     - match: '"'
    122       scope: punctuation.definition.string.end.asp
    123       pop: true
    124 
    125   illegal_names:
    126     - match: '{{keywords}}|{{constants}}|{{reserved_words}}|{{functions}}|{{asp_builtin_classes}}'
    127       scope: invalid.illegal.name.asp
    128       pop: true
    129 
    130   allow_statement_separator:
    131     - match: ':'
    132       scope: punctuation.terminator.statement.asp
    133       pop: true
    134 
    135   unexpected_token:
    136     - match: \n
    137       scope: invalid.illegal.missing-token.asp
    138       pop: true
    139     - match: '\S+'
    140       scope: invalid.illegal.unexpected-token.asp
    141       pop: true
    142 
    143   statements:
    144     - include: variable_definitions
    145     - include: allow_line_continuation
    146     - match: '\b(?i:On\s+Error\s+)'
    147       scope: storage.type.asp
    148       push:
    149         - include: not_end_of_statement
    150         - match: '\b(?i:Resume\s+Next){{whitespace_or_end_of_statement}}'
    151           scope: storage.type.asp
    152           pop: true
    153         - match: '\b(?i:Goto\s+0){{whitespace_or_end_of_statement}}'
    154           scope: storage.type.asp
    155           pop: true
    156         - include: unexpected_token
    157     - match: '\b(?i:Randomize\s+Timer){{whitespace_or_end_of_statement}}'
    158       scope: storage.type.asp
    159     - match: '\b(?i:(Call)|(Set)){{whitespace_or_end_of_statement}}'
    160       captures:
    161         1: keyword.other.call.asp
    162         2: keyword.other.set.asp
    163       push: expect_identifier_reference
    164     - match: '\b(?i:Exit\s+(?:Sub|Function|Property|For|Do)){{whitespace_or_end_of_statement}}'
    165       scope: keyword.control.flow.asp
    166     - include: control_flow
    167     - include: expression
    168 
    169   definitions:
    170     - include: class_definitions
    171     - include: method_definitions
    172     - include: variable_definitions
    173 
    174   class_definitions:
    175     - match: '\b(?i:Class)[ \t]+'
    176       scope: storage.type.asp
    177       push: class_name
    178 
    179   class_name:
    180     - meta_scope: meta.class.asp meta.class.identifier.asp
    181     - include: allow_line_continuation
    182     - include: illegal_names
    183     - match: '{{identifier}}'
    184       scope: entity.name.class.asp
    185       set: inside_class
    186     - include: unexpected_token
    187 
    188   inside_class:
    189     - meta_content_scope: meta.class.asp meta.class.body.asp
    190     - match: '\b(?i:End){{whitespace_or_end_of_statement}}'
    191       set:
    192         - meta_scope: meta.class.asp meta.class.body.asp storage.type.class.end.asp
    193         - include: allow_line_continuation
    194         - match: '\b(?i:Class){{whitespace_or_end_of_statement}}'
    195           pop: true
    196         - include: unexpected_token
    197     - include: method_definitions
    198     - match: '\b((?i:Public(?:\s+Default)?|Private)\s+)?((?i:Property)){{whitespace_or_end_of_statement}}'
    199       captures:
    200         1: storage.modifier.asp
    201         2: storage.type.function.asp
    202       push:
    203         - meta_scope: meta.method.asp meta.method.identifier.asp
    204         - meta_content_scope: storage.type.function.asp
    205         - include: not_end_of_statement
    206         - match: '\b(?i:Get|Let|Set){{whitespace_or_end_of_statement}}'
    207           set: [inside_method_without_meta, method_name_without_meta]
    208         - include: unexpected_token
    209     - include: variable_definitions
    210     - include: allow_line_continuation
    211     - match: '\S' # only field/method/property definitions allowed inside a class definition
    212       scope: invalid.illegal.unexpected-token.asp
    213 
    214   inside_method_without_meta:
    215     - match: ''
    216       set: inside_method
    217 
    218   method_name_without_meta:
    219     - match: ''
    220       set: method_name
    221 
    222   variable_definitions:
    223     - match: '\b(?i:(?:(?:Public|Private)\s+)?Const){{whitespace_or_end_of_statement}}'
    224       scope: storage.modifier.asp
    225       push: constant_body
    226     - match: '\b(?i:Dim|ReDim(?:\s+Preserve)?){{whitespace_or_end_of_statement}}'
    227       scope: storage.modifier.asp
    228       push: dim_body
    229     - match: '\b(?i:Private|Public(?!\s+Default))\s+(?!(?i:Function|Sub|Property))'
    230       scope: storage.modifier.asp
    231       push: dim_body
    232 
    233   constant_body:
    234     - include: not_end_of_statement
    235     - include: illegal_names
    236     - match: '{{identifier}}'
    237       scope: entity.name.constant.asp
    238       set:
    239         - include: not_end_of_statement
    240         - match: '\s*(=)\s*'
    241           captures:
    242             1: keyword.operator.assignment.asp
    243           set: [constant_separator, constant_value]
    244     - include: unexpected_token
    245 
    246   constant_separator:
    247     - match: '\s*(,)\s*'
    248       captures:
    249         1: punctuation.separator.variable-declaration.asp
    250       set: constant_body
    251     - include: allow_statement_separator
    252     - match: ''
    253       pop: true
    254 
    255   constant_value:
    256     #- include: not_end_of_statement # this include has been commented out to disable the illegal highlighting where a statement ends unexpectedly - to more closely match other syntaxes
    257     - include: allow_line_continuation # as the above include has been commented out, this one has been added in it's place
    258     - match: '{{whitespace_or_end_of_statement}}' # as the above include has been commented out, this match pattern has been added to pop at the end of the logical statement
    259       pop: true
    260     - match: '{{literal_number_hex}}'
    261       scope: constant.numeric.integer.hexadecimal.asp
    262       captures:
    263         1: punctuation.definition.numeric.hexadecimal.asp
    264         2: punctuation.definition.numeric.hexadecimal.asp
    265       pop: true
    266     - match: '{{literal_number_decimal}}'
    267       scope: constant.numeric.float.decimal.asp
    268       pop: true
    269     - match: '{{constants}}'
    270       scope: constant.language.asp
    271       pop: true
    272     - match: '{{keywords}}'
    273       scope: support.type.vb.asp # maybe should be keyword or constant?
    274       pop: true
    275     - match: '"'
    276       scope: punctuation.definition.string.begin.asp
    277       set: inside_string
    278     - include: unexpected_token
    279 
    280   dim_body:
    281     - include: not_end_of_statement
    282     - include: illegal_names
    283     - match: '{{identifier}}'
    284       scope: variable.other.asp
    285       set:
    286         - include: allow_line_continuation
    287         - match: '\('
    288           scope: punctuation.section.array.begin.asp
    289           push:
    290             - meta_scope: meta.array.definition.asp
    291             - include: not_end_of_statement
    292             - match: \)
    293               scope: punctuation.section.array.end.asp
    294               pop: true
    295             - include: expression
    296             - match: ','
    297               scope: punctuation.separator.array.asp
    298         - match: '\s*(,)\s*'
    299           captures:
    300             1: punctuation.separator.variable-declaration.asp
    301           set: dim_body
    302         - match: ''
    303           pop: true
    304     - include: unexpected_token
    305 
    306   method_definitions:
    307     - match: '\b((?i:Public(?:\s+Default)?|Private)\s+)?((?i:Sub|Function)){{whitespace_or_end_of_statement}}'
    308       captures:
    309         0: meta.method.asp meta.method.identifier.asp
    310         1: storage.modifier.asp
    311         2: storage.type.function.asp
    312       push: [inside_method_without_meta, method_name_without_meta]
    313 
    314   method_name:
    315     - meta_content_scope: meta.method.asp meta.method.identifier.asp
    316     - include: allow_line_continuation
    317     - include: illegal_names
    318     - match: '{{asp_builtin_events}}|{{class_magic_funcs}}'
    319       scope: entity.name.function.asp support.function.magic.event.asp
    320       set: after_method_name
    321     - match: '{{identifier}}'
    322       scope: entity.name.function.asp
    323       set: after_method_name
    324     - match: $
    325       set: inside_method
    326 
    327   after_method_name:
    328     - meta_content_scope: meta.method.asp meta.method.identifier.asp
    329     - match: \(
    330       scope: punctuation.section.parens.begin.asp
    331       set:
    332         - match: \)
    333           scope: meta.method.asp meta.method.identifier.asp punctuation.section.parens.end.asp
    334           pop: true
    335         - match: $
    336           set: not_end_of_statement
    337         - match: '(?=\S)'
    338           push:
    339             - meta_scope: meta.method.asp meta.method.identifier.asp
    340             - match: '(?=\)|$)'
    341               pop: true
    342             - include: not_end_of_statement
    343             - match: '((?i:ByRef|ByVal)\s+)?({{identifier}})'
    344               captures:
    345                 1: storage.modifier.reference.asp
    346                 2: variable.parameter.function.asp
    347               push:
    348                 - match: '\s*(\()(\))\s*'
    349                   captures:
    350                     1: punctuation.section.array.begin.asp
    351                     2: punctuation.section.array.end.asp
    352                   set: after_method_param_name
    353                 - include: after_method_param_name
    354             - match: '(?:(?![,)])\S)+'
    355               scope: invalid.illegal.unexpected-token.asp
    356     - match: '\s+'
    357     - match: ':'
    358       scope: meta.method.asp punctuation.terminator.statement.asp
    359       pop: true
    360     - include: allow_line_continuation
    361     - match: $
    362       pop: true
    363     - include: unexpected_token
    364 
    365   after_method_param_name:
    366     - match: '(?=\)|$)'
    367       pop: true
    368     - include: not_end_of_statement
    369     - match: '\s*(,)\s*'
    370       captures:
    371         1: punctuation.separator.parameter-declaration.asp
    372       pop: true
    373     - match: '(?:(?![,)])\S)+'
    374       scope: invalid.illegal.unexpected-token.asp
    375       pop: true
    376 
    377   inside_method:
    378     - meta_content_scope: meta.method.asp meta.method.body.asp
    379     - include: inside_block
    380     - match: '\b(?i:End){{whitespace_or_end_of_statement}}'
    381       scope: storage.type.function.end.asp
    382       set:
    383         - meta_content_scope: meta.method.asp storage.type.function.end.asp
    384         - include: allow_line_continuation
    385         - match: '\b(?i:Function|Sub|Property){{whitespace_or_end_of_statement}}'
    386           scope: meta.method.asp storage.type.function.end.asp
    387           pop: true
    388         - include: unexpected_token
    389     - include: statements
    390 
    391   control_flow:
    392     - match: '\b(?i:If){{whitespace_or_end_of_statement}}'
    393       scope: keyword.control.flow.asp
    394       push: then_could_be_block_or_single_line
    395     - match: '\b(?i:With){{whitespace_or_end_of_statement}}'
    396       scope: keyword.control.flow.asp
    397       push: [inside_control_flow_with, expression_until_end_of_statement, expect_not_end_of_statement]
    398     - match: '\b(?i:Select\s+Case){{whitespace_or_end_of_statement}}'
    399       scope: keyword.control.flow.asp
    400       push: [inside_control_flow_select, expression_until_end_of_statement, expect_not_end_of_statement]
    401     - match: '\b(?i:Do){{whitespace_or_end_of_statement}}'
    402       scope: meta.do.block.asp keyword.control.flow.asp
    403       push:
    404         - match: '\s+(?i:While|Until){{whitespace_or_end_of_statement}}'
    405           scope: keyword.control.flow.asp
    406           set: [inside_control_flow_do, expression_until_end_of_statement, expect_not_end_of_statement]
    407         - match: ''
    408           set: inside_control_flow_do
    409     - match: '\b(?i:While){{whitespace_or_end_of_statement}}'
    410       scope: keyword.control.flow.asp
    411       push: [inside_control_flow_while, expression_until_end_of_statement, expect_not_end_of_statement]
    412     - match: '\b(?i:For\s+Each){{whitespace_or_end_of_statement}}'
    413       scope: keyword.control.flow.asp
    414       push: [control_flow_foreach_in, expect_identifier_reference]
    415     - match: '\b(?i:For){{whitespace_or_end_of_statement}}'
    416       scope: keyword.control.flow.asp
    417       push: [control_flow_forto, expect_identifier_reference]
    418 
    419   then_could_be_block_or_single_line:
    420     - meta_content_scope: meta.between-if-and-then.asp
    421     - match: '[\t ]+'
    422       scope: '' # so that the meta_content_scope will apply to whitespace
    423     - match: '\b(?i:Then){{whitespace_or_end_of_statement}}'
    424       scope: keyword.control.flow.asp
    425       set:
    426         - match: '\s*(?=$|{{apostrophe_comment_begin}}|{{rem_comment_begin}}|%>)'
    427           set: inside_control_flow_if_block
    428         - match: '' # if the above didn't match, then it is a single line if block
    429           set: inside_control_flow_if_single_line
    430     #- include: not_end_of_statement # this include has been commented out to disable the illegal highlighting where a statement ends unexpectedly - to more closely match other syntaxes
    431     - match: '{{whitespace_or_end_of_statement}}' # the above commented out include has been replaced with this, to exit the if scope if there is no `Then` on the same logical line
    432       pop: true
    433     - include: expression
    434 
    435   elseif_then_block:
    436     - meta_content_scope: meta.between-if-and-then.asp
    437     - match: '\b(?i:Then){{whitespace_or_end_of_statement}}'
    438       scope: keyword.control.flow.asp
    439       set: inside_control_flow_if_block
    440     - include: expression
    441     - include: not_end_of_statement
    442 
    443   expression:
    444     - match: \)
    445       scope: invalid.illegal.stray-close-bracket.asp
    446     - match: '{{literal_number_hex}}'
    447       scope: constant.numeric.integer.hexadecimal.asp
    448       captures:
    449         1: punctuation.definition.numeric.hexadecimal.asp
    450         2: punctuation.definition.numeric.hexadecimal.asp
    451     - match: '{{literal_number_decimal}}'
    452       scope: constant.numeric.float.decimal.asp
    453     - match: '{{constants}}'
    454       scope: support.type.vb.asp # maybe this should be constant.language.asp
    455     - match: '{{functions}}'
    456       scope: support.function.vb.asp # TODO: scope opening and closing parens i.e. LBound(var_name) but needs to handle (ignore) nested parens LBound((var_name)). Will also apply to things like Response.Write below. Note that parens are optional (when return value is not used) i.e. on it's own line, `LBound var_name` is valid. In other cases the parens can't be accurately scoped, because we don't know if they are for array access or method params
    457     - match: '{{keywords}}'
    458       scope: storage.type.asp
    459     - include: operators
    460     - match: '\b(?i:New){{whitespace_or_end_of_statement}}'
    461       scope: keyword.other.new.asp
    462       push: expect_identifier_reference
    463     - match: '{{reserved_words}}'
    464       scope: invalid.illegal.unexpected-token.literal.asp
    465     - match: '"'
    466       scope: punctuation.definition.string.begin.asp
    467       push: inside_string
    468     - match: '\b((?i:Request))\b(?:(?i:(\.)\s*(?:(BinaryRead)|(ClientCertificate|Cookies|Form|QueryString|ServerVariables)|(TotalBytes)))\b)?'
    469       captures: # https://msdn.microsoft.com/en-us/library/ms524948%28v=vs.90%29.aspx
    470         1: support.class.asp
    471         2: punctuation.accessor.dot.asp
    472         3: support.function.asp
    473         4: support.class.collection.asp
    474         5: support.property.asp
    475     - match: '\b((?i:Response))\b(?:(?i:(\.)\s*(?:(AddHeader|AppendToLog|BinaryWrite|Clear|End|Flush|Redirect|Write)|(Buffer|CacheControl|Charset|CodePage|ContentType|Expires|ExpiresAbsolute|IsClientConnected|LCID|PICS|Status)|(Cookies)))\b)?'
    476       captures: # https://msdn.microsoft.com/en-us/library/ms525405%28v=vs.90%29.aspx
    477         1: support.class.asp
    478         2: punctuation.accessor.dot.asp
    479         3: support.function.asp
    480         4: support.property.asp
    481         5: support.class.collection.asp
    482     - match: '\b((?i:Server))\b(?:(?i:(\.)\s*(?:(CreateObject|Execute|GetLastError|HTMLEncode|MapPath|Transfer|URLEncode)|(ScriptTimeout)))\b)?'
    483       captures: # https://msdn.microsoft.com/en-us/library/ms525541%28v=vs.90%29.aspx
    484         1: support.class.asp
    485         2: punctuation.accessor.dot.asp
    486         3: support.function.asp
    487         4: support.property.asp
    488     - match: '\b((?i:Server))\b(?:(?i:(\.)\s*(?:(Abandon)|(CodePage|LCID|SessionID|Timeout)|(Contents|StaticObjects)))\b)?'
    489       captures: # https://msdn.microsoft.com/en-us/library/ms524319%28v=vs.90%29.aspx
    490         1: support.class.asp
    491         2: punctuation.accessor.dot.asp
    492         3: support.function.asp
    493         4: support.property.asp
    494         5: support.class.collection.asp
    495     - match: '\b((?i:ObjectContext))\b(?:(?i:(\.)\s*(SetAbort|SetComplete))\b)?'
    496       captures: # https://msdn.microsoft.com/en-us/library/ms525667%28v=vs.90%29.aspx
    497         1: support.class.asp
    498         2: punctuation.accessor.dot.asp
    499         3: support.function.asp
    500     - match: '\b((?i:Application))\b(?:(?i:(\.)\s*(?:(Lock|Unlock)|(Contents|StaticObjects)))\b)?'
    501       captures: # https://msdn.microsoft.com/en-us/library/ms524319%28v=vs.90%29.aspx
    502         1: support.class.asp
    503         2: punctuation.accessor.dot.asp
    504         3: support.function.asp
    505         4: support.class.collection.asp
    506     - match: '{{identifier}}'
    507       captures:
    508         0: variable.other.asp
    509         #1: invalid.illegal.unclosed-variable-identifier.asp
    510       push:
    511         - match: '\s+(?=\.)'
    512           scope: invalid.illegal.unexpected-token.asp # . punctuation accessor must come immediately after an identifier
    513           pop: true
    514         - match: ''
    515           pop: true
    516     - match: \(
    517       scope: punctuation.section.parens.begin.asp
    518       push: inside_parens
    519     - include: allow_line_continuation
    520 
    521   inside_parens:
    522     - match: \)
    523       scope: punctuation.section.parens.end.asp
    524       pop: true
    525     - match: '\s+' # this match pattern has been added to disable the illegal highlighting where a statement ends unexpectedly - to more closely match other syntaxes
    526       scope: ''
    527     - match: '{{whitespace_or_end_of_statement}}' # this match pattern has been added to disable the illegal highlighting where a statement ends unexpectedly - to more closely match other syntaxes
    528       pop: true
    529     - match: $\n
    530       scope: invalid.illegal.missing-close-bracket.asp
    531       pop: true
    532     - include: expression
    533 
    534   operators:
    535     - match: '(?i:Is\s+Not\b)' # the correct syntax is: If Not (x Is y) Then ' the parens are optional but make it clearer
    536       scope: invalid.illegal.unexpected-token.asp
    537     - match: '{{math_operators}}\s*=' # ASP does not support shorthand
    538       scope: invalid.illegal.unexpected-token.asp
    539     - match: '><' # ASP not equal comparison is <>
    540       scope: invalid.illegal.unexpected-token.asp
    541     - match: '({{math_operators}}|{{comparison_operators}})|({{logical_operators}})'
    542       captures:
    543         1: keyword.operator.asp
    544         2: keyword.operator.logical.asp
    545       push: expect_not_end_of_statement
    546     - match: ':'
    547       scope: punctuation.terminator.statement.asp
    548     - match: (\.)(\.)?
    549       captures:
    550         1: punctuation.accessor.dot.asp
    551         2: invalid.illegal.unexpected-token.asp
    552       push: expect_identifier_member_reference
    553 
    554   inside_control_flow_with:
    555     - meta_scope: meta.with.block.asp
    556     - include: inside_block
    557     - match: '\b(?i:End){{whitespace_or_end_of_statement}}'
    558       set:
    559         - meta_scope: keyword.control.flow.asp
    560         - include: allow_line_continuation
    561         - match: '\b(?i:With){{whitespace_or_end_of_statement}}'
    562           pop: true
    563         - include: unexpected_token
    564     - include: statements
    565 
    566   inside_control_flow_if_single_line:
    567     - meta_scope: meta.if.line.asp
    568     - match: $
    569       pop: true
    570     - include: inside_control_flow_if_common
    571 
    572   inside_control_flow_if_block:
    573     - meta_scope: meta.if.block.asp
    574     - match: '\b(?i:ElseIf){{whitespace_or_end_of_statement}}'
    575       scope: keyword.control.flow.asp
    576       set: elseif_then_block
    577     - match: '\b(?i:End){{whitespace_or_end_of_statement}}'
    578       set:
    579         - meta_scope: keyword.control.flow.asp
    580         - include: allow_line_continuation
    581         - match: '\b(?i:If){{whitespace_or_end_of_statement}}'
    582           pop: true
    583         - include: unexpected_token
    584     - include: inside_control_flow_if_common
    585 
    586   inside_control_flow_if_common:
    587     - include: inside_block
    588     - match: '\b(?i:Else){{whitespace_or_end_of_statement}}'
    589       scope: keyword.control.flow.asp
    590       # the else retains the block or single line mode of the opening if statement, so we don't set a different context
    591     - include: statements
    592 
    593   inside_control_flow_select:
    594     - meta_scope: meta.select.block.asp
    595     - include: inside_block
    596     - match: '\b(?i:End){{whitespace_or_end_of_statement}}'
    597       set:
    598         - meta_scope: keyword.control.flow.asp
    599         - include: allow_line_continuation
    600         - match: '\b(?i:Select){{whitespace_or_end_of_statement}}'
    601           pop: true
    602         - include: unexpected_token
    603     - match: '\b(?i:Case\s+Else){{whitespace_or_end_of_statement}}'
    604       scope: keyword.control.flow.asp
    605     - match: '\b(?i:Case){{whitespace_or_end_of_statement}}'
    606       scope: keyword.control.flow.asp
    607       push: [expression_until_end_of_statement, expect_not_end_of_statement]
    608     - include: statements
    609 
    610   expression_until_end_of_statement:
    611     - include: allow_statement_separator
    612     - include: root_asp
    613     - match: $
    614       pop: true
    615     - include: expression
    616 
    617   inside_control_flow_do:
    618     - meta_scope: meta.do.block.asp
    619     - include: inside_block
    620     - match: '\b(?i:Loop){{whitespace_or_end_of_statement}}'
    621       set:
    622         - meta_scope: keyword.control.flow.asp
    623         - include: allow_line_continuation
    624         - match: '\b(?i:While|Until){{whitespace_or_end_of_statement}}'
    625           set: expression_until_end_of_statement
    626         - match: ''
    627           pop: true
    628     - include: statements
    629 
    630   inside_control_flow_while:
    631     - meta_scope: meta.while.block.asp
    632     - include: inside_block
    633     - match: '\b(?i:Wend){{whitespace_or_end_of_statement}}'
    634       scope: keyword.control.flow.asp
    635       pop: true
    636     - include: statements
    637 
    638   inside_control_flow_for:
    639     - meta_scope: meta.for.block.asp
    640     - include: inside_block
    641     - match: '\b(?i:Next){{whitespace_or_end_of_statement}}'
    642       scope: keyword.control.flow.asp
    643       pop: true
    644     - include: statements
    645 
    646   control_flow_foreach_in:
    647     - meta_scope: meta.for.block.asp
    648     - match: '\b(?i:In){{whitespace_or_end_of_statement}}'
    649       scope: keyword.control.flow.asp
    650       set: [inside_control_flow_for, expression_until_end_of_statement]
    651 
    652   control_flow_forto:
    653     - meta_scope: meta.for.block.asp
    654     - match: '\b(?i:To){{whitespace_or_end_of_statement}}'
    655       scope: keyword.control.flow.asp
    656       set: [inside_control_flow_for, for_after_to, expect_not_end_of_statement]
    657     - include: not_end_of_statement
    658     - include: expression
    659 
    660   for_after_to:
    661     - match: '\b(?i:Step){{whitespace_or_end_of_statement}}'
    662       scope: keyword.control.flow.asp
    663       set: [expression_until_end_of_statement, expect_not_end_of_statement]
    664     - include: expression_until_end_of_statement
    665 
    666   inside_block:
    667     - match: '%>'
    668       scope: punctuation.section.embedded.end.inside-block.asp
    669       push:
    670         - clear_scopes: true
    671         - meta_scope: text.html.asp
    672         - match: '<%=?'
    673           scope: punctuation.section.embedded.begin.inside-block.asp
    674           pop: true
    675         - match: '\s+$' # eat whitespace so that the lookahead on the next match pattern can match the next line if appropriate
    676           push:
    677             - match: ^
    678               pop: true
    679         - match: '(\s*")?(?=[^<>]*>|\s+\w+=\s*")' # if the next occurrence of a < or > is a >, we are inside a tag. If it looks like an attribute is being defined, we are probably in a tag
    680           scope: string.quoted.double.html punctuation.definition.string.end.html
    681           push: # use a push and an include so that the root scope (text.html.basic) isn't applied
    682             - meta_scope: meta.tag.after-embedded-asp.any.html
    683             - match: '>'
    684               scope: punctuation.definition.tag.end.html
    685               set: scope:text.html.asp#html
    686             - include: scope:text.html.basic#tag-attributes
    687           with_prototype:
    688             - match: '(?=<%)'
    689               pop: true
    690         - match: ''
    691           push: scope:text.html.asp#html
    692           with_prototype:
    693             - match: '(?=<%)'
    694               pop: true