lectures.alex.balgavy.eu

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

Python.sublime-syntax (79945B)


      1 %YAML 1.2
      2 ---
      3 name: Python
      4 file_extensions:
      5   - py
      6   - py3
      7   - pyw
      8   - pyi
      9   - pyx
     10   - pyx.in
     11   - pxd
     12   - pxd.in
     13   - pxi
     14   - pxi.in
     15   - rpy
     16   - cpy
     17   - SConstruct
     18   - Sconstruct
     19   - sconstruct
     20   - SConscript
     21   - gyp
     22   - gypi
     23   - Snakefile
     24   - vpy
     25   - wscript
     26   - bazel
     27   - bzl
     28 first_line_match: ^#!\s*/.*\bpython(\d(\.\d)?)?\b
     29 scope: source.python
     30 
     31 variables:
     32   # We support unicode here because Python 3 is the future
     33   identifier_continue: '[[:alnum:]_]'
     34   identifier: '\b[[:alpha:]_]{{identifier_continue}}*\b'
     35   identifier_constant: '\b(?:[\p{Lu}_][\p{Lu}_\d]*)?[\p{Lu}]{2,}[\p{Lu}_\d]*\b'  # require 2 consecutive upper-case letters
     36   digits: (?:\d+(?:_\d+)*)
     37   exponent: (?:[eE][-+]?{{digits}})
     38   path: '({{identifier}}[ ]*\.[ ]*)*{{identifier}}'
     39   sql_indicator: \s*(?:SELECT|INSERT|UPDATE|DELETE|CREATE|REPLACE|ALTER|WITH)\b
     40   illegal_names: (?:and|as|assert|break|class|continue|def|del|elif|else|except|finally|for|from|global|if|import|in|is|lambda|not|or|pass|raise|return|try|while|with|yield)
     41   format_spec: |-
     42     (?x:
     43       (?:.? [<>=^])?     # fill align
     44       [ +-]?             # sign
     45       \#?                # alternate form
     46       # technically, octal and hexadecimal integers are also supported as 'width', but rarely used
     47       \d*                # width
     48       ,?                 # thousands separator
     49       (?:\.\d+)?         # precision
     50       [bcdeEfFgGnosxX%]? # type
     51     )
     52   strftime_spec: '(?:%(?:[aAwdbBGmyYHIpMSfzZjuUVWcxX%]|-[dmHIMSj]))'
     53   # This can be used in look-aheads to parse simple expressions.
     54   # Can't be recursive, because sregex doesn't support that,
     55   # so we're skipping parentheses.
     56   # Can't parse multiple lines as well, for obvious reasons
     57   simple_expression: |-
     58     (?x:
     59       \s+                      # whitespace
     60       | [urfb]*"(?:\\.|[^"])*" # strings
     61       | [urfb]*'(?:\\.|[^'])*' # ^
     62       | [\d.ej]+               # numerics
     63       | [+*/%@-] | // | and | or # operators
     64       | {{path}}               # a path
     65     )*
     66 
     67 
     68 contexts:
     69   main:
     70     - include: statements
     71 
     72   statements:
     73     - include: docstrings
     74     - include: line-statements
     75     - include: block-statements
     76     - include: classes
     77     - include: functions
     78     - include: modifiers
     79     - include: assignments
     80     - match: ;
     81       scope: punctuation.terminator.statement.python
     82     - include: expression-as-a-statement
     83 
     84   line-statements:
     85     - include: imports
     86     - include: decorators
     87     - match: \b(raise)\b
     88       scope: keyword.control.flow.raise.python
     89       push:
     90         - meta_scope: meta.statement.raise.python
     91         - include: line-continuation-or-pop
     92         - match: \b(from)\b
     93           scope: keyword.control.flow.raise.from.python
     94           set:
     95             - meta_scope: meta.statement.raise.python
     96             - include: line-continuation-or-pop
     97             - include: expression-in-a-statement
     98         - include: expression-in-a-statement
     99     - match: \b(assert)\b
    100       scope: keyword.control.flow.assert.python
    101     - match: \b(del)\b
    102       scope: keyword.other.del.python
    103     - match: \b(print)\b(?! *([,.()\]}]))
    104       scope: keyword.other.print.python
    105     - match: \b(exec)\b(?! *($|[,.()\]}]))
    106       scope: keyword.other.exec.python
    107     - match: \b(return)\b
    108       scope: keyword.control.flow.return.python
    109     - match: \b(break)\b
    110       scope: keyword.control.flow.break.python
    111     - match: \b(continue)\b
    112       scope: keyword.control.flow.continue.python
    113     - match: \b(pass)\b
    114       scope: keyword.control.flow.pass.python
    115 
    116   imports:
    117     - match: \b(import)\b
    118       scope: keyword.control.import.python
    119       push:
    120         - meta_scope: meta.statement.import.python
    121         - include: line-continuation-or-pop
    122         - match: ','
    123           scope: punctuation.separator.import-list.python
    124         - match: \.
    125           scope: invalid.illegal.unexpected-relative-import.python
    126         - include: import-alias
    127         - include: qualified-name
    128         - match: (?=\S)
    129           pop: true
    130     - match: \b(from)\b
    131       scope: keyword.control.import.from.python
    132       push:
    133         - meta_scope: meta.statement.import.python
    134         - meta_content_scope: meta.import-source.python
    135         - include: line-continuation-or-pop
    136         - match: \b(import)\b
    137           scope: keyword.control.import.python
    138           set:
    139             - meta_scope: meta.statement.import.python
    140             - include: line-continuation-or-pop
    141             - match: ' *(\()'
    142               captures:
    143                 1: punctuation.section.import-list.begin.python
    144               set:
    145                 - meta_scope: meta.statement.import.python
    146                 - include: comments
    147                 - match: \)
    148                   scope: punctuation.section.import-list.end.python
    149                   pop: true
    150                 - include: import-name-list
    151                 - match: (?=\S)
    152                   pop: true
    153             - match: ''
    154               set:
    155                 - meta_scope: meta.statement.import.python
    156                 - include: line-continuation-or-pop
    157                 - include: import-name-list
    158                 - match: (?=\S)
    159                   pop: true
    160             - match: (?=\S)
    161               pop: true
    162         - include: import-from-name
    163         - match: (?=\S)
    164           pop: true
    165 
    166   import-name-list:
    167     - match: ','
    168       scope: punctuation.separator.import-list.python
    169     - include: import-alias
    170     - include: name
    171     - match: \*
    172       scope: constant.language.import-all.python
    173     - match: \S+
    174       scope: invalid.illegal.name.import.python
    175 
    176   import-alias:
    177     - match: \b(as)\b
    178       scope: keyword.control.import.as.python
    179 
    180   import-from-name:
    181     - match: \.+
    182       scope: meta.import-path.python keyword.control.import.relative.python
    183     - match: (?={{path}})
    184       push:
    185         - meta_scope: meta.import-path.python
    186         - match: '{{illegal_names}}\b'
    187           scope: invalid.illegal.name.python
    188         - match: '{{identifier}}'
    189           scope: meta.import-name.python
    190         - match: \s*(\.) *(?:({{illegal_names}}\b)|({{identifier}}))
    191           captures:
    192             1: punctuation.accessor.dot.python
    193             2: invalid.illegal.name.python
    194             3: meta.import-name.python
    195         - match: \ *(\. *\S+) # matches and consumes the remainder of "abc.123" or "abc.+"
    196           captures:
    197             1: invalid.illegal.name.python
    198           pop: true
    199         - match: ''
    200           pop: true
    201 
    202   block-statements:
    203     # async for ... in ...:
    204     - match: \b(async +)?(for)\b
    205       captures:
    206         1: storage.modifier.async.python
    207         2: keyword.control.loop.for.python
    208       push:
    209         - meta_scope: meta.statement.loop.for.python
    210         - include: line-continuation-or-pop
    211         - match: \bin\b
    212           scope: keyword.control.loop.for.in.python
    213           set:
    214             - meta_content_scope: meta.statement.loop.for.python
    215             - include: line-continuation-or-pop
    216             - match: ':(?!=)'
    217               scope: meta.statement.loop.for.python punctuation.section.block.loop.for.python
    218               pop: true
    219             - include: expression-in-a-statement
    220         - match: ':(?!=)'
    221           scope: invalid.illegal.missing-in.python
    222           pop: true
    223         - include: target-list
    224     # async with ... as ...:
    225     - match: \b(async +)?(with)\b
    226       captures:
    227         1: storage.modifier.async.python
    228         2: keyword.control.flow.with.python
    229       push: with-body
    230     # except ... as ...:
    231     - match: \bexcept\b
    232       scope: keyword.control.exception.catch.python
    233       push:
    234         - meta_scope: meta.statement.exception.catch.python
    235         - include: line-continuation-or-pop
    236         - match: ':(?!=)'
    237           scope: punctuation.section.block.exception.catch.python
    238           pop: true
    239         - match: '\bas\b'
    240           scope: keyword.control.exception.catch.as.python
    241           set:
    242             - meta_content_scope: meta.statement.exception.catch.python
    243             - include: line-continuation-or-pop
    244             - match: ':'
    245               scope: meta.statement.exception.catch.python punctuation.section.block.exception.catch.python
    246               pop: true
    247             - include: name
    248         - include: target-list
    249     - match: \bif\b
    250       scope: keyword.control.conditional.if.python
    251       push:
    252         - meta_scope: meta.statement.conditional.if.python
    253         - include: line-continuation-or-pop
    254         - match: ':(?!=)'
    255           scope: punctuation.section.block.conditional.if.python
    256           pop: true
    257         - include: expression-in-a-statement
    258     - match: \bwhile\b
    259       scope: keyword.control.loop.while.python
    260       push:
    261         - meta_scope: meta.statement.loop.while.python
    262         - include: line-continuation-or-pop
    263         - match: ':(?!=)'
    264           scope: punctuation.section.block.loop.while.python
    265           pop: true
    266         - include: expression-in-a-statement
    267     - match: \b(else)\b(?:\s*(:))?
    268       scope: meta.statement.conditional.else.python
    269       captures:
    270         1: keyword.control.conditional.else.python
    271         2: punctuation.section.block.conditional.else.python
    272     - match: \b(try)\b(?:\s*(:))?
    273       scope: meta.statement.exception.try.python
    274       captures:
    275         1: keyword.control.exception.try.python
    276         2: punctuation.section.block.exception.try.python
    277     - match: \b(finally)\b(?:\s*(:))?
    278       scope: meta.statement.exception.finally.python
    279       captures:
    280         1: keyword.control.exception.finally.python
    281         2: punctuation.section.block.exception.finally.python
    282     - match: \belif\b
    283       scope: keyword.control.conditional.elseif.python
    284       push:
    285         - meta_scope: meta.statement.conditional.elseif.python
    286         - match: ':(?!=)'
    287           scope: punctuation.section.block.conditional.elseif.python
    288           pop: true
    289         - match: $\n?
    290           pop: true
    291         - include: expression-in-a-statement
    292 
    293   with-body:
    294     - meta_scope: meta.statement.with.python
    295     - include: line-continuation-or-pop
    296     - match: \b(as)\b
    297       scope: keyword.control.flow.with.as.python
    298       set: with-as
    299     - match: ':(?!=)'
    300       scope: punctuation.section.block.with.python
    301       pop: true
    302     - match: ','
    303       scope: punctuation.separator.with-resources.python
    304     - include: expression-in-a-statement
    305 
    306   with-as:
    307     - meta_scope: meta.statement.with.python
    308     - include: line-continuation-or-pop
    309     - match: ':'
    310       scope: punctuation.section.block.with.python
    311       pop: true
    312     - match: ','
    313       scope: punctuation.separator.with-resources.python
    314       set: with-body
    315     - include: name
    316     - include: groups
    317     - include: lists
    318 
    319   expressions-common:
    320     - include: comments
    321     - include: constants
    322     - include: numbers
    323     - include: yields
    324     - include: operators
    325     - include: lambda
    326     - match: \b(await)\b
    327       scope: keyword.other.await.python
    328     - include: inline-if
    329     - include: strings
    330     - include: function-calls
    331     - include: item-access
    332     - include: lists
    333     - include: dictionaries-and-sets
    334     - include: tuples
    335     - include: groups
    336     - match: \)
    337       scope: invalid.illegal.stray.brace.round.python
    338     - match: \]
    339       scope: invalid.illegal.stray.brace.square.python
    340     - match: \}
    341       scope: invalid.illegal.stray.brace.curly.python
    342     - include: line-continuation
    343 
    344   # Always include these last and only one at a time!
    345   expression-as-a-statement:
    346     - include: expressions-common
    347     - include: qualified-name
    348 
    349   expression-in-a-statement:
    350     # Differs from expression-as-a-statement in that:
    351     # - invalid-name matches will pop the current context
    352     # - assignment expressions
    353     - include: expressions-common
    354     - include: illegal-names-pop
    355     - include: qualified-name
    356     - include: assignment-expression
    357 
    358   expression-in-a-group:  # Always include this last!
    359     # Differs from expression-in-a-statement in that:
    360     # - accessor matching continues into the next line
    361     - include: expression-in-a-statement
    362     - match: '(\.) *(?={{identifier}})'
    363       captures:
    364         1: punctuation.accessor.dot.python
    365       push:
    366         - include: magic-function-names
    367         - include: magic-variable-names
    368         - include: illegal-names
    369         - include: generic-names
    370         - match: ''
    371           pop: true
    372 
    373   after-expression:
    374     # direct function call
    375     - match: '\s*(\()'
    376       captures:
    377         1: punctuation.section.arguments.begin.python
    378       push:
    379         - meta_scope: meta.function-call.arguments.python
    380         - match: \)
    381           scope: punctuation.section.arguments.end.python
    382           pop: true
    383         - include: arguments
    384     # item access
    385     - match: '\s*(\[)'
    386       captures:
    387         1: meta.item-access.python punctuation.section.brackets.begin.python
    388       push:
    389         - meta_content_scope: meta.item-access.arguments.python
    390         - match: \]
    391           scope: meta.item-access.python punctuation.section.brackets.end.python
    392           pop: true
    393         - include: illegal-assignment-expression
    394         - match: ':'
    395           scope: punctuation.separator.slice.python
    396         - include: expression-in-a-group
    397     # indirect function call following attribute access
    398     - include: function-calls
    399     # arbitrary attribute access
    400     - match: '\s*(\.)'
    401       captures:
    402         1: punctuation.accessor.dot.python
    403       push:
    404         - include: magic-function-names
    405         - include: magic-variable-names
    406         - include: illegal-names
    407         - include: generic-names
    408         - match: ''
    409           pop: true
    410     - match: ''
    411       pop: true
    412 
    413   comments:
    414     - match: "#"
    415       scope: punctuation.definition.comment.python
    416       push:
    417         - meta_scope: comment.line.number-sign.python
    418         - match: \n
    419           pop: true
    420 
    421   constants:
    422     - match: \b(None|True|False|Ellipsis|NotImplemented|__debug__)\b
    423       scope: constant.language.python
    424     - match: \.{3}(?!\w)
    425       scope: constant.language.python
    426 
    427   numbers:
    428     # https://docs.python.org/3/reference/lexical_analysis.html#numeric-literals
    429     # hexadecimal
    430     - match: \b(?i)(0x)\h*(L) # py2
    431       scope: constant.numeric.integer.hexadecimal.python
    432       captures:
    433         1: punctuation.definition.numeric.base.python
    434         2: storage.type.numeric.python
    435     - match: \b(?i)(0x)(_?\h)+
    436       scope: constant.numeric.integer.hexadecimal.python
    437       captures:
    438         1: punctuation.definition.numeric.base.python
    439     # octal
    440     - match: \b(?i)(0o?)(?=o|[0-7])[0-7]*(L) # py2
    441       scope: constant.numeric.integer.octal.python
    442       captures:
    443         1: punctuation.definition.numeric.base.python
    444         2: storage.type.numeric.python
    445     - match: \b(?i)(0)[0-7]+ # py2
    446       scope: constant.numeric.integer.octal.python
    447       captures:
    448         1: punctuation.definition.numeric.base.python
    449     - match: \b(?i)(0o)(_?[0-7])+
    450       scope: constant.numeric.integer.octal.python
    451       captures:
    452         1: punctuation.definition.numeric.base.python
    453     # binary
    454     - match: \b(?i)(0b)[01]*(L) # py2
    455       scope: constant.numeric.integer.binary.python
    456       captures:
    457         1: punctuation.definition.numeric.base.python
    458         2: storage.type.numeric.python
    459     - match: \b(?i)(0b)(_?[01])*
    460       scope: constant.numeric.integer.binary.python
    461       captures:
    462         1: punctuation.definition.numeric.base.python
    463     # complex
    464     - match: |-
    465         (?x:
    466           # 1.j, 1.1j, 1.1e1j, 1.1e-1j, 1.e1j, 1.e-1 | 1e1j, 1e-1j
    467           \b{{digits}} (\.)? {{digits}}? {{exponent}}?
    468           # .1j, .1e1j, .1e-1j
    469           | (\.) {{digits}} {{exponent}}?
    470         )([jJ])
    471       scope: constant.numeric.imaginary.decimal.python
    472       captures:
    473         1: punctuation.separator.decimal.python
    474         2: punctuation.separator.decimal.python
    475         3: storage.type.numeric.python
    476     # floating point
    477     - match: |-
    478         (?x:
    479           # 1., 1.1, 1.1e1, 1.1e-1, 1.e1, 1.e-1 | 1e1, 1e-1
    480           \b{{digits}} (?: (\.) {{digits}}? {{exponent}}? | {{exponent}} )
    481           # .1, .1e1, .1e-1
    482           | (\.) {{digits}} {{exponent}}?
    483         )
    484       scope: constant.numeric.float.decimal.python
    485       captures:
    486         1: punctuation.separator.decimal.python
    487         2: punctuation.separator.decimal.python
    488     # integer
    489     - match: \b(?i)(?:[1-9]\d*|0)(L)\b # py2
    490       scope: constant.numeric.integer.decimal.python
    491       captures:
    492         1: storage.type.numeric.python
    493     - match: \b(?i)([1-9][\d_]*|0)\b
    494       scope: constant.numeric.integer.decimal.python
    495 
    496   modifiers:
    497     - match: \b(?:(global)|(nonlocal))\b
    498       captures:
    499         1: storage.modifier.global.python
    500         2: storage.modifier.nonlocal.python
    501       push:
    502         - include: line-continuation-or-pop
    503         - match: ','
    504           scope: punctuation.separator.storage-list.python
    505         - include: name
    506         - match: \S+
    507           scope: invalid.illegal.name.storage.python
    508 
    509   yields:
    510     - match: \b(yield)(?:\s+(from))?\b
    511       captures:
    512         1: keyword.control.flow.yield.python
    513         2: keyword.control.flow.yield-from.python
    514 
    515   assignment-expression:
    516     - match: :=
    517       scope: keyword.operator.assignment.inline.python
    518 
    519   illegal-assignment-expression:
    520     - match: :=
    521       scope: invalid.illegal.not-allowed-here.python
    522 
    523   assignments:
    524     - include: illegal-assignment-expression
    525     - match: ':'
    526       scope: punctuation.separator.annotation.variable.python
    527     - match: \+=|-=|\*=|/=|//=|%=|@=|&=|\|=|\^=|>>=|<<=|\*\*=
    528       scope: keyword.operator.assignment.augmented.python
    529     - match: '=(?!=)'
    530       scope: keyword.operator.assignment.python
    531 
    532   operators:
    533     - match: <>
    534       scope: invalid.deprecated.operator.python
    535     - match: <\=|>\=|\=\=|<|>|\!\=
    536       scope: keyword.operator.comparison.python
    537     - match: \+|\-|\*|\*\*|/|//|%|<<|>>|&|\||\^|~
    538       scope: keyword.operator.arithmetic.python
    539     - match: \b(and|in|is|not|or)\b
    540       comment: keyword operators that evaluate to True or False
    541       scope: keyword.operator.logical.python
    542     - match: '@'
    543       scope: keyword.operator.matrix.python
    544 
    545   allow-unpack-operators:
    546     # Match unpacking operators, if present
    547     - include: comments
    548     - match: \*{3,}
    549       scope: invalid.illegal.syntax.python
    550       pop: true
    551     - match: \*\*
    552       scope: keyword.operator.unpacking.mapping.python
    553       pop: true
    554     - match: \*
    555       scope: keyword.operator.unpacking.sequence.python
    556       pop: true
    557     - match: (?=\S)
    558       pop: true
    559 
    560   classes:
    561     - match: '^\s*(class)\b'
    562       captures:
    563         1: storage.type.class.python keyword.declaration.class.python
    564       push:
    565         - meta_scope: meta.class.python
    566         - include: line-continuation-or-pop
    567         - match: ':'
    568           scope: punctuation.section.class.begin.python
    569           pop: true
    570         - match: "(?={{identifier}})"
    571           push:
    572             - meta_content_scope: entity.name.class.python
    573             - include: entity-name-class
    574             - match: ''
    575               pop: true
    576         - match: \(
    577           scope: punctuation.section.inheritance.begin.python
    578           set:
    579             - meta_scope: meta.class.inheritance.python
    580             - match: \)
    581               scope: punctuation.section.inheritance.end.python
    582               set:
    583                 - include: line-continuation-or-pop
    584                 - match: ':'
    585                   scope: meta.class.python punctuation.section.class.begin.python
    586                   pop: true
    587                 - match: (?=\S)
    588                   pop: true
    589             - match: ':'
    590               scope: invalid.illegal.no-closing-parens.python
    591               pop: true
    592             - match: ','
    593               scope: punctuation.separator.inheritance.python
    594             - include: illegal-names-pop
    595             - match: ({{identifier}}) *(=)
    596               captures:
    597                 1: variable.parameter.class-inheritance.python
    598                 2: keyword.operator.assignment.python
    599             - match: (?={{path}})
    600               push:
    601                 - meta_scope: entity.other.inherited-class.python
    602                 - match: '{{identifier}}(?: *(\.) *)?'
    603                   captures:
    604                     1: punctuation.accessor.dot.python
    605                 - match: ''
    606                   pop: true
    607             - include: expression-in-a-group
    608 
    609   functions:
    610     - match: '^\s*(?:(async)\s+)?(def)\b'
    611       captures:
    612         1: storage.modifier.async.python
    613         2: storage.type.function.python keyword.declaration.function.python
    614       push:
    615         - meta_scope: meta.function.python
    616         - include: line-continuation-or-pop
    617         - match: ':'
    618           scope: punctuation.section.function.begin.python
    619           pop: true
    620         - match: "(?={{identifier}})"
    621           push:
    622             - meta_content_scope: entity.name.function.python
    623             - include: entity-name-function
    624             - match: ''
    625               pop: true
    626         - match: '(?=\()'
    627           set:
    628             - match: \(
    629               scope: meta.function.parameters.python punctuation.section.parameters.begin.python
    630               set: [function-parameters, allow-unpack-operators]
    631 
    632   function-parameters:
    633     - meta_content_scope: meta.function.parameters.python
    634     - match: \)
    635       scope: punctuation.section.parameters.end.python
    636       set: function-after-parameters
    637     - include: comments
    638     - match: ','
    639       scope: punctuation.separator.parameters.python
    640       push: allow-unpack-operators
    641     - match: /
    642       scope: storage.modifier.positional-args-only.python
    643       push:
    644         - match: (?=[,)])
    645           pop: true
    646         - match: \S
    647           scope: invalid.illegal.expected-comma.python
    648     - match: '(?==)'
    649       set:
    650         - match: '='
    651           scope: keyword.operator.assignment.python
    652           set:
    653             - meta_scope: meta.function.parameters.default-value.python
    654             - match: '(?=[,)])'
    655               set: [function-parameters, allow-unpack-operators]
    656             - include: illegal-assignment-expression
    657             - include: expression-in-a-group
    658     - match: '(?=:)'
    659       set:
    660         - match: ':'
    661           scope: punctuation.separator.annotation.parameter.python
    662           set:
    663             - meta_scope: meta.function.parameters.annotation.python
    664             - match: '(?=[,)=])'
    665               set: function-parameters
    666             - include: illegal-assignment-expression
    667             - include: expression-in-a-group
    668     - include: function-parameters-tuple
    669     - include: illegal-names
    670     - match: '{{identifier}}'
    671       scope: variable.parameter.python
    672     - include: line-continuation
    673 
    674   function-parameters-tuple:
    675     # python 2 style tuple arguments
    676     # removed from python 3 since PEP-3113
    677     - match: \(
    678       scope: punctuation.section.group.begin.python
    679       push:
    680         - meta_scope: meta.group.python
    681         - match: \)
    682           scope: punctuation.section.group.end.python
    683           set: after-expression
    684         - include: comments
    685         - match: ','
    686           scope: punctuation.separator.parameters.python
    687           push: allow-unpack-operators
    688         # default values should follow the argument
    689         - match: '='
    690           push:
    691             - meta_scope: invalid.illegal.default-value.python
    692             - match: '(?=[,)=])'
    693               pop: true
    694         # python 2 does not support type annotations
    695         - match: '(?=:)'
    696           push:
    697             - meta_scope: invalid.illegal.annotation.python
    698             - match: '(?=[,)=])'
    699               pop: true
    700         - include: illegal-names
    701         - match: '{{identifier}}'
    702           scope: variable.parameter.python
    703         - include: line-continuation
    704 
    705   function-after-parameters:
    706     - meta_content_scope: meta.function.python
    707     - match: '(?=->)'
    708       set:
    709         - meta_content_scope: meta.function.annotation.return.python
    710         - match: ->
    711           scope: punctuation.separator.annotation.return.python
    712         - include: illegal-assignment-expression
    713         - match: '(?=:)'
    714           set: function-after-parameters
    715         - include: line-continuation-or-pop
    716         - include: expression-in-a-statement
    717     - match: ':'
    718       scope: meta.function.python punctuation.section.function.begin.python
    719       pop: true
    720     - include: comments
    721     - match: (?=\S)
    722       pop: true
    723 
    724   decorators:
    725     - match: ^\s*(?=@)
    726       push:
    727         # Due to line continuations, we don't know whether this is a "function call" yet
    728         - meta_content_scope: meta.annotation.python
    729         - match: '@'
    730           scope: punctuation.definition.annotation.python
    731         - match: $
    732           pop: true
    733         - include: line-continuation-or-pop
    734         - match: (?=\.?\s*{{path}}\s*\() # now we do
    735           set: [decorator-function-call-wrapper, qualified-name-until-leaf]
    736         - match: (?=\.?\s*{{path}})
    737           push: [decorator-wrapper, qualified-name-until-leaf]
    738         - match: \S
    739           scope: invalid.illegal.character.python
    740           pop: true
    741 
    742   decorator-wrapper:
    743     - match: (\.)\s*
    744       captures:
    745         1: punctuation.accessor.dot.python
    746       set:
    747         - meta_scope: meta.qualified-name.python
    748         - meta_content_scope: variable.annotation.python
    749         - include: dotted-name-specials
    750         - include: generic-names
    751         - match: ''
    752           pop: true
    753     - match: ''
    754       set:
    755         - meta_scope: meta.qualified-name.python variable.annotation.python
    756         - include: name-specials
    757         - include: generic-names
    758         - match: ''
    759           pop: true
    760 
    761   decorator-function-call-wrapper:
    762     - meta_scope: meta.annotation.function.python
    763     - match: \)
    764       scope: punctuation.section.arguments.end.python
    765       set: after-expression
    766     - match: \(
    767       scope: meta.annotation.function.python punctuation.section.arguments.begin.python
    768       push:
    769         - clear_scopes: 1
    770         - meta_content_scope: meta.annotation.arguments.python
    771         - match: (?=\))
    772           pop: true
    773         - include: arguments
    774     - match: (\.)\s*
    775       captures:
    776         1: punctuation.accessor.dot.python
    777       push:
    778         - meta_scope: meta.qualified-name.python
    779         - meta_content_scope: variable.annotation.function.python
    780         - include: dotted-name-specials
    781         - include: generic-names
    782         - match: ''
    783           pop: true
    784     - match: ''
    785       push:
    786         - meta_scope: meta.qualified-name.python variable.annotation.function.python
    787         - include: name-specials
    788         - include: generic-names
    789         - match: ''
    790           pop: true
    791 
    792   item-access:
    793     - match: '(?={{path}}\s*\[)'
    794       push:
    795         - match: \]
    796           scope: meta.item-access.python punctuation.section.brackets.end.python
    797           set: after-expression
    798         - match: '(?={{path}}\s*\[)'
    799           push:
    800             - meta_content_scope: meta.item-access.python
    801             - match: '(?=\s*\[)'
    802               pop: true
    803             - include: qualified-name
    804         - match: \[
    805           scope: meta.item-access.python punctuation.section.brackets.begin.python
    806           push:
    807             - meta_content_scope: meta.item-access.arguments.python
    808             - match: '(?=\])'
    809               pop: true
    810             - match: ':'
    811               scope: punctuation.separator.slice.python
    812             - include: expression-in-a-group
    813 
    814   function-calls:
    815     - match: '(?=(\.\s*)?{{path}}\s*\()'
    816       push: [function-call-wrapper, qualified-name-until-leaf]
    817 
    818   function-call-wrapper:
    819     - meta_scope: meta.function-call.python
    820     - match: (?=\()  # need to remove meta.function-call.python from opening parens
    821       set:
    822         - match: \(
    823           scope: punctuation.section.arguments.begin.python
    824           set:
    825             - meta_scope: meta.function-call.arguments.python
    826             - match: \)
    827               scope: punctuation.section.arguments.end.python
    828               set: after-expression
    829             - include: arguments
    830     - match: (\.)\s*(?={{identifier}})
    831       captures:
    832         1: punctuation.accessor.dot.python
    833       push:
    834         - meta_scope: meta.qualified-name.python
    835         - meta_content_scope: variable.function.python
    836         - include: dotted-name-specials
    837         - include: generic-names
    838         - match: ''
    839           pop: true
    840     - match: (?={{identifier}})
    841       push:
    842         - meta_scope: meta.qualified-name.python variable.function.python
    843         - include: name-specials
    844         - include: generic-names
    845         - match: ''
    846           pop: true
    847 
    848   arguments:
    849     - include: keyword-arguments
    850     - match: ','
    851       scope: punctuation.separator.arguments.python
    852       push: allow-unpack-operators
    853     - include: inline-for
    854     - include: expression-in-a-group
    855 
    856   keyword-arguments:
    857     - match: '(?={{identifier}}\s*=(?!=))'
    858       push:
    859         - include: line-continuation-or-pop
    860         - match: '='
    861           scope: keyword.operator.assignment.python
    862           set:
    863             - include: illegal-assignment-expression
    864             - match: (?=[,):])
    865               pop: true
    866             - include: expression-in-a-group
    867         - include: illegal-names
    868         - match: '{{identifier}}'
    869           scope: variable.parameter.python
    870 
    871   lambda:
    872     - match: \b(lambda)(?=\s|:|$)
    873       scope: storage.type.function.inline.python keyword.declaration.function.inline.python
    874       push: [lambda-parameters, allow-unpack-operators]
    875 
    876   lambda-parameters:
    877     - meta_scope: meta.function.inline.python
    878     - meta_content_scope: meta.function.inline.parameters.python
    879     - include: line-continuation-or-pop
    880     - match: '\:'
    881       scope: punctuation.section.function.begin.python
    882       set:
    883         # clear meta_scope
    884         - match: ''
    885           set:
    886             - meta_scope: meta.function.inline.body.python
    887             - include: illegal-assignment-expression
    888             # We don't know whether we are within a grouped
    889             # or line-statement context at this point.
    890             # If we're in a group, the underlying context will take over
    891             # at the end of the line.
    892             - match: (?=[,):])|$
    893               pop: true
    894             - include: expression-in-a-statement
    895     - match: ','
    896       scope: punctuation.separator.parameters.python
    897       push: allow-unpack-operators
    898     - include: keyword-arguments
    899     - include: function-parameters-tuple
    900     - include: illegal-names
    901     - match: '{{identifier}}'
    902       scope: variable.parameter.python
    903     - match: '\S'
    904       scope: invalid.illegal.expected-parameter.python
    905 
    906   groups:
    907     - match: \(
    908       scope: punctuation.section.group.begin.python
    909       push:
    910         - meta_scope: meta.group.python
    911         - match: \)
    912           scope: punctuation.section.group.end.python
    913           set: after-expression
    914         - match: ','
    915           scope: punctuation.separator.tuple.python
    916         - include: inline-for
    917         - include: expression-in-a-group
    918 
    919   tuples:
    920     # We don't know for certain, whether a parenthesized expression is a tuple,
    921     # so try looking ahead.
    922     - match: (\()\s*(\))
    923       scope: meta.sequence.tuple.empty.python
    924       captures:
    925         1: punctuation.section.sequence.begin.python
    926         2: punctuation.section.sequence.end.python
    927       push: after-expression
    928     - match: \((?={{simple_expression}},|\s*\*{{path}})
    929       scope: punctuation.section.sequence.begin.python
    930       push: inside-tuple
    931     # TODO generator
    932     # - match: \((?:{{simple_expression}}for)
    933 
    934   inside-tuple:
    935     - meta_scope: meta.sequence.tuple.python
    936     - match: \)
    937       scope: punctuation.section.sequence.end.python
    938       set: after-expression
    939     - match: ','
    940       scope: punctuation.separator.sequence.python
    941       push: allow-unpack-operators
    942     - include: inline-for
    943     - include: expression-in-a-group
    944 
    945   lists:
    946     - match: (\[)\s*(\])
    947       scope: meta.sequence.list.empty.python
    948       captures:
    949         1: punctuation.section.sequence.begin.python
    950         2: punctuation.section.sequence.end.python
    951       push: after-expression
    952     - match: \[
    953       scope: punctuation.section.sequence.begin.python
    954       push: [inside-list, allow-unpack-operators]
    955 
    956   inside-list:
    957     - meta_scope: meta.sequence.list.python
    958     - match: \]
    959       scope: punctuation.section.sequence.end.python
    960       set: after-expression
    961     - match: ','
    962       scope: punctuation.separator.sequence.python
    963       push: allow-unpack-operators
    964     - include: inline-for
    965     - include: expression-in-a-group
    966 
    967   dictionaries-and-sets:
    968     # Dictionaries and set literals use the same punctuation,
    969     # so we try looking ahead to determine whether we have a dict or a set.
    970     - match: '(\{)\s*(\})'
    971       scope: meta.mapping.empty.python
    972       captures:
    973         1: punctuation.section.mapping.begin.python
    974         2: punctuation.section.mapping.end.python
    975       push: after-expression
    976     - match: \{(?={{simple_expression}}:|\s*\*\*)
    977       scope: punctuation.section.mapping.begin.python
    978       push: inside-dictionary
    979     - match: \{(?={{simple_expression}}[,}]|\s*\*)
    980       scope: punctuation.section.set.begin.python
    981       push: inside-set
    982     # If the expression is "more complex" or on the next line,
    983     # fall back to default and determine later.
    984     - match: \{
    985       scope: punctuation.section.mapping-or-set.begin.python
    986       push:
    987         - meta_scope: meta.mapping-or-set.python
    988         - match: \}
    989           scope: punctuation.section.mapping-or-set.end.python
    990           set: after-expression
    991         - match: (?={{simple_expression}}:|\s*\*\*)
    992           set: inside-dictionary
    993         - match: (?={{simple_expression}}[,}]|\s*\*)
    994           set: inside-set
    995         - match: ','
    996           scope: punctuation.separator.set.python
    997           set: inside-set
    998         - include: illegal-assignment-expression
    999         - match: ':'
   1000           scope: punctuation.separator.mapping.key-value.python
   1001           set: inside-directory-value
   1002         - include: inline-for
   1003         - include: expression-in-a-group
   1004 
   1005   inside-dictionary:
   1006     - meta_scope: meta.mapping.python
   1007     - match: \}
   1008       scope: punctuation.section.mapping.end.python
   1009       set: after-expression
   1010     - include: illegal-assignment-expression
   1011     - match: ':'
   1012       scope: punctuation.separator.mapping.key-value.python
   1013       set: inside-directory-value
   1014     - match: ','
   1015       scope: invalid.illegal.expected-colon.python
   1016     - match: \*\*
   1017       scope: keyword.operator.unpacking.mapping.python
   1018       push:
   1019         - match: (?=\})
   1020           pop: true
   1021         - match: ','
   1022           scope: punctuation.separator.mapping.python
   1023           pop: true
   1024         - include: expression-in-a-group
   1025     - include: comments
   1026     - match: (?=\S)
   1027       push:
   1028         - clear_scopes: 1
   1029         - meta_scope: meta.mapping.key.python
   1030         - match: \s*(?=\}|,|:)
   1031           pop: true
   1032         - include: expression-in-a-group
   1033 
   1034   inside-directory-value:
   1035     - meta_content_scope: meta.mapping.python
   1036     - match: \}
   1037       scope: punctuation.section.mapping.end.python
   1038       set: after-expression
   1039     - match: (?=,)
   1040       set:
   1041         # clear meta scope from this match, because 'inside-directory' has it in meta_scope
   1042         - match: ','
   1043           scope: punctuation.separator.mapping.python
   1044           set: inside-dictionary
   1045     - match: (?=for\b)
   1046       push:
   1047         - match: (?=\})
   1048           pop: true
   1049         - match: ','
   1050           scope: invalid.illegal.unexpected-comma.python
   1051         - include: inline-for
   1052         - include: expression-in-a-group
   1053     - include: comments
   1054     - match: (?=\S)
   1055       push:
   1056         - clear_scopes: 1
   1057         - meta_content_scope: meta.mapping.value.python
   1058         - match: (?=\s*(\}|,|for\b))
   1059           pop: true
   1060         - include: expression-in-a-group
   1061 
   1062   inside-set:
   1063     - meta_scope: meta.set.python
   1064     - match: \}
   1065       scope: punctuation.section.set.end.python
   1066       set: after-expression
   1067     - include: illegal-assignment-expression
   1068     - match: ':'
   1069       scope: invalid.illegal.colon-inside-set.python
   1070     - match: ','
   1071       scope: punctuation.separator.set.python
   1072     - match: \*
   1073       scope: keyword.operator.unpacking.sequence.python
   1074       push:
   1075         - match: (?=\})
   1076           pop: true
   1077         - match: ','
   1078           scope: punctuation.separator.set.python
   1079           pop: true
   1080         - include: expression-in-a-group
   1081     - include: inline-for
   1082     - include: expression-in-a-group
   1083 
   1084   builtin-exceptions:
   1085     - match: |-
   1086         (?x)\b(
   1087         	(
   1088         		Arithmetic|Assertion|Attribute|BlockingIO|BrokenPipe|Buffer|ChildProcess|
   1089         		Connection(Aborted|Refused|Reset)?|EOF|Environment|FileExists|
   1090         		FileNotFound|FloatingPoint|Interrupted|IO|IsADirectoryError|
   1091         		Import|Indentation|Index|Key|Lookup|Memory|Name|NotADirectory|
   1092         		NotImplemented|OS|Overflow|Permission|ProcessLookup|Reference|
   1093         		Runtime|Standard|Syntax|System|Tab|Timeout|Type|UnboundLocal|
   1094         		Unicode(Encode|Decode|Translate)?|Value|VMS|Windows|ZeroDivision
   1095         	)Error|
   1096         	((Pending)?Deprecation|Runtime|Syntax|User|Future|Import|Unicode|Bytes)?Warning|
   1097         	(Base)?Exception|
   1098         	SystemExit|StopIteration|NotImplemented|KeyboardInterrupt|GeneratorExit
   1099         )\b
   1100       scope: support.type.exception.python
   1101 
   1102   builtin-functions:
   1103     - match: |-
   1104         (?x)\b(
   1105         	__import__|all|abs|any|apply|ascii|bin|breakpoint|callable|chr|classmethod|cmp|coerce|
   1106         	compile|delattr|dir|divmod|enumerate|eval|exec|execfile|filter|format|getattr|
   1107         	globals|hasattr|hash|help|hex|id|input|intern|isinstance|issubclass|iter|
   1108         	len|locals|map|max|min|next|oct|open|ord|pow|print|property|range|
   1109         	raw_input|reduce|reload|repr|reversed|round|setattr|sorted|staticmethod|
   1110         	sum|super|type|unichr|vars|zip
   1111         )\b
   1112       scope: support.function.builtin.python
   1113 
   1114   builtin-types:
   1115     - match: |-
   1116         (?x)\b(
   1117         	basestring|bool|buffer|bytearray|bytes|complex|dict|float|frozenset|int|
   1118         	list|long|memoryview|object|range|set|slice|str|tuple|unicode|xrange
   1119         )\b
   1120       scope: support.type.python
   1121 
   1122   name:
   1123     - match: '(?={{identifier}})'
   1124       push:
   1125         - include: name-specials
   1126         - match: '{{identifier_constant}}'
   1127           scope: variable.other.constant.python
   1128         - include: generic-names
   1129         - match: ''
   1130           pop: true
   1131 
   1132   dotted-name:
   1133     - match: '\s*(\.)\s*(?={{identifier}})'
   1134       captures:
   1135         1: punctuation.accessor.dot.python
   1136       push:
   1137         - include: dotted-name-specials
   1138         - match: '{{identifier_constant}}'
   1139           scope: variable.other.constant.python
   1140         - include: generic-names
   1141         - match: ''
   1142           pop: true
   1143 
   1144   qualified-name:
   1145     - match: '(?={{path}})'
   1146       push:
   1147         - meta_scope: meta.qualified-name.python
   1148         - include: name
   1149         - include: dotted-name
   1150         - match: ''
   1151           pop: true
   1152 
   1153   qualified-name-until-leaf:
   1154     # Push this together with another context to match a qualified name
   1155     # until the last non-special identifier (if any).
   1156     # This allows the leaf to be scoped individually.
   1157     - meta_scope: meta.qualified-name.python
   1158     # If a line continuation follows, this may or may not be the last leaf (most likley not though)
   1159     - match: (?={{identifier}}\s*(\.|\\))
   1160       push:
   1161         - include: name-specials
   1162         - include: generic-names
   1163         - match: ''
   1164           pop: true
   1165     - match: (\.)\s*(?={{identifier}}\s*(\.|\\))
   1166       captures:
   1167         1: punctuation.accessor.dot.python
   1168       push:
   1169         - include: dotted-name-specials
   1170         - include: generic-names
   1171         - match: ''
   1172           pop: true
   1173     - match: \.(?!\s*{{identifier}})  # don't match last dot
   1174       scope: punctuation.accessor.dot.python
   1175     - match: (?=\S|$)
   1176       pop: true
   1177 
   1178   name-specials:
   1179     - include: builtin-functions
   1180     - include: builtin-types
   1181     - include: builtin-exceptions
   1182     - include: illegal-names
   1183     - include: magic-function-names
   1184     - include: magic-variable-names
   1185     - include: language-variables
   1186 
   1187   dotted-name-specials:
   1188     - include: magic-function-names
   1189     - include: magic-variable-names
   1190     - include: illegal-names
   1191 
   1192   entity-name-class:
   1193     - include: illegal-names
   1194     - include: generic-names
   1195 
   1196   entity-name-function:
   1197     - include: magic-function-names
   1198     - include: illegal-names
   1199     - include: generic-names
   1200 
   1201   generic-names:
   1202     - match: '{{identifier}}'
   1203       scope: meta.generic-name.python
   1204 
   1205   illegal-names:
   1206     - match: \b{{illegal_names}}\b
   1207       scope: invalid.illegal.name.python
   1208 
   1209   illegal-names-pop:
   1210     - match: \b{{illegal_names}}\b
   1211       scope: invalid.illegal.name.python
   1212       pop: true
   1213 
   1214   language-variables:
   1215     - match: \b(self|cls)\b
   1216       scope: variable.language.python
   1217     - match: _(?!{{identifier_continue}})
   1218       scope: variable.language.python
   1219 
   1220   line-continuation:
   1221     - match: (\\)(.*)$\n?
   1222       captures:
   1223         1: punctuation.separator.continuation.line.python
   1224         2: invalid.illegal.unexpected-text.python
   1225     # make sure to resume parsing at next line
   1226       push:
   1227         # This prevents strings after a continuation from being a docstring
   1228         - include: strings
   1229         - match: (?=\S|^\s*$|\n)  # '\n' for when we matched a string earlier
   1230           pop: true
   1231 
   1232   line-continuation-or-pop:
   1233     - include: line-continuation
   1234     - match: (?=\s*($|;|#))
   1235       pop: true
   1236 
   1237   magic-function-names:
   1238     # https://docs.python.org/2/reference/datamodel.html
   1239     # https://docs.python.org/3/reference/datamodel.html
   1240     - match: |-
   1241         (?x)\b__(?:
   1242           # unary operators
   1243           invert|neg|pos|abs|
   1244           # binary operators
   1245           add|and|div|divmod|floordiv|lshift|mod|mul|or|pow|rshift|sub|truediv|xor|
   1246           contains|
   1247           # right-hand binary operators
   1248           radd|rand|rdiv|rdivmod|rfloordiv|rlshift|rmod|rmul|ror|rpow|rrshift|rsub|rtruediv|rxor|
   1249           # in-place operator assignments
   1250           iadd|iand|idiv|ifloordiv|ilshift|imod|imul|ior|ipow|irshift|isub|itruediv|ixor|
   1251           # comparisons
   1252           eq|ge|gt|le|lt|ne|
   1253           cmp|rcmp| # py2
   1254           # primary coercion
   1255           bool|str|
   1256           nonzero|unicode| # py2
   1257           # number coercion (converts something to a number)
   1258           bytes|complex|float|index|int|round|
   1259           long| # py2
   1260           # other "coercion"
   1261           format|len|length_hint|hash|repr|reversed|
   1262           coerce|hex|oct| # py2
   1263           fspath|
   1264           # iterator (and 'await')
   1265           iter|next|
   1266           aiter|anext|
   1267           await|
   1268           # attribute and item access
   1269           delattr|delitem|delslice|
   1270           getattr|getattribute|getitem|getslice|
   1271           setattr|setitem|setslice|
   1272           dir|missing|
   1273           # context manager
   1274           enter|exit|
   1275           aenter|aexit|
   1276           # other class magic
   1277           call|del|init|new|init_subclass|
   1278           instancecheck|subclasscheck|
   1279           # pickling
   1280           getnewargs|getnewargs_ex|getstate|setstate|reduce|reduce_ex|
   1281           # descriptors
   1282           delete|get|set|set_name|
   1283           # class-specific
   1284           subclasses|
   1285           # dataclasses (PEP 557)
   1286           post_init|
   1287           # for typing core support (PEP 560)
   1288           class_getitem|mro_entries
   1289         )__\b
   1290       comment: these methods have magic interpretation by python and are generally called indirectly through syntactic constructs
   1291       scope: support.function.magic.python
   1292 
   1293   magic-variable-names:
   1294     # magic variables which a class/module/object may have.
   1295     # https://docs.python.org/3/library/inspect.html#types-and-members
   1296     # https://docs.python.org/3/reference/datamodel.html#object.__slots__
   1297     # https://docs.python.org/3/reference/datamodel.html#preparing-the-class-namespace
   1298     - match: |-
   1299         (?x)\b__(?:
   1300           # generic object
   1301           class|dict|doc|module|name|
   1302           # module-specific / global
   1303           all|file|package|
   1304           # functions & methods
   1305           annotations|closure|code|defaults|func|globals|kwdefaults|self|qualname|
   1306           # classes (attributes)
   1307           bases|prepare|slots|metaclass|mro|
   1308           # Python 2
   1309           members|methods
   1310         )__\b
   1311       scope: support.variable.magic.python
   1312 
   1313   docstrings:
   1314     - match: ^\s*(?=(?i)(ur|ru|u|r)?("""|'''))
   1315       push:
   1316       - match: (?i)(u)?("""|''')
   1317         captures:
   1318           1: storage.type.string.python
   1319           2: punctuation.definition.comment.begin.python
   1320         set:
   1321           - meta_scope: comment.block.documentation.python
   1322           - include: escaped-unicode-char
   1323           - include: escaped-char
   1324           - match: '\2'
   1325             scope: punctuation.definition.comment.end.python
   1326             pop: true
   1327       - match: (?i)(u?ru?)("""|''')
   1328         captures:
   1329           1: storage.type.string.python
   1330           2: punctuation.definition.comment.begin.python
   1331         set:
   1332           - meta_scope: comment.block.documentation.python
   1333           - match: '\2'
   1334             scope: punctuation.definition.comment.end.python
   1335             pop: true
   1336 
   1337   escaped-char:
   1338     - match: '(\\x\h{2})|(\\[0-7]{1,3})|(\\[\\"''abfnrtv])'
   1339       captures:
   1340         1: constant.character.escape.hex.python
   1341         2: constant.character.escape.octal.python
   1342         3: constant.character.escape.python
   1343     - match: \\.  # deprecated in 3.6 and will eventually be a syntax error
   1344       scope: invalid.deprecated.character.escape.python
   1345 
   1346   escaped-unicode-char:
   1347     - match: '(\\U\h{8})|(\\u\h{4})|(\\N\{[a-zA-Z ]+\})'
   1348       captures:
   1349         1: constant.character.escape.unicode.16-bit-hex.python
   1350         2: constant.character.escape.unicode.32-bit-hex.python
   1351         3: constant.character.escape.unicode.name.python
   1352 
   1353   escaped-fstring-escape:
   1354     # special-case the '\{{' sequence because it has higher priority than the deprecated '\{'
   1355     - match: (\\)(\{\{|\}\})
   1356       scope: constant.character.escape.backslash.regexp
   1357       captures:
   1358         1: invalid.deprecated.character.escape.python
   1359         2: constant.character.escape.python
   1360 
   1361   line-continuation-inside-string:
   1362     - match: (\\)$\n?
   1363       captures:
   1364         1: punctuation.separator.continuation.line.python
   1365     - match: \n
   1366       scope: invalid.illegal.unclosed-string.python
   1367       set: after-expression
   1368 
   1369   line-continuation-inside-block-string:
   1370     - match: \\$
   1371       scope: punctuation.separator.continuation.line.python
   1372 
   1373   constant-placeholder:
   1374     - match: |- # printf style
   1375         (?x)
   1376         %
   1377           ( \( ({{identifier}}) \) )? # mapping key
   1378           \#?            # alternate form
   1379           0?             # pad with zeros
   1380           \-?            # left-adjust
   1381           \ ?            # implicit sign
   1382           [+-]?          # sign
   1383           (\d*|\*)       # width
   1384           (\. (\d*|\*))? # precision
   1385           [hlL]?         # length modifier (but ignored)
   1386           [acdeEfFgGiorsuxX%]
   1387       scope: constant.other.placeholder.python
   1388       captures:
   1389         2: variable.other.placeholder.python
   1390     - match: '{{strftime_spec}}'
   1391       scope: constant.other.placeholder.python
   1392     - match: '\{\{|\}\}'
   1393       scope: constant.character.escape.python
   1394     - include: formatting-syntax
   1395 
   1396   formatting-syntax:
   1397     # https://docs.python.org/3.6/library/string.html#formatstrings
   1398     - match: |- # simple form
   1399         (?x)
   1400         (\{)
   1401           (?: [\w.\[\]]+)?             # field_name
   1402           (   ! [ars])?                # conversion
   1403           (   : (?:{{format_spec}}|    # format_spec OR
   1404                    [^}%]*%.[^}]*)      # any format-like string
   1405           )?
   1406         (\})
   1407       scope: constant.other.placeholder.python
   1408       captures:
   1409         1: punctuation.definition.placeholder.begin.python
   1410         2: storage.modifier.conversion.python
   1411         3: constant.other.format-spec.python
   1412         4: punctuation.definition.placeholder.end.python
   1413     - match: \{(?=[^\}"']+\{[^"']*\}) # complex (nested) form
   1414       scope: punctuation.definition.placeholder.begin.python
   1415       push:
   1416         - meta_scope: constant.other.placeholder.python
   1417         - match: \}
   1418           scope: punctuation.definition.placeholder.end.python
   1419           pop: true
   1420         - match: '[\w.\[\]]+'
   1421         - match: '![ars]'
   1422           scope: storage.modifier.conversion.python
   1423         - match: ':'
   1424           push:
   1425             - meta_scope: meta.format-spec.python constant.other.format-spec.python
   1426             - match: (?=\})
   1427               pop: true
   1428             - include: formatting-syntax
   1429 
   1430   f-string-content:
   1431     # https://www.python.org/dev/peps/pep-0498/
   1432     # https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings
   1433     - match: \{\{|\}\}
   1434       scope: constant.character.escape.python
   1435     - match: \{\s*\}
   1436       scope: invalid.illegal.empty-expression.python
   1437     - match: (?=\{)
   1438       push: f-string-replacement
   1439     - match: \}
   1440       scope: invalid.illegal.stray-brace.python
   1441 
   1442   f-string-content-with-regex:
   1443     # Same as f-string-content, but will reset the entire scope stack
   1444     # and has an additional match.
   1445     - match: \\(\{\{|\}\})
   1446       scope: constant.character.escape.backslash.regexp
   1447       captures:
   1448         1: constant.character.escape.python
   1449     - match: \{\{|\}\}
   1450       scope: constant.character.escape.python
   1451     - match: \{\s*\}
   1452       scope: invalid.illegal.empty-expression.python
   1453     - match: (?=\{)
   1454       push: f-string-replacement-reset
   1455     - match: \}
   1456       scope: invalid.illegal.stray-brace.python
   1457 
   1458   f-string-replacement:
   1459     - clear_scopes: 1
   1460     - match: \}
   1461       scope: meta.interpolation.python punctuation.section.interpolation.end.python
   1462       pop: true
   1463     - match: \{
   1464       scope: punctuation.section.interpolation.begin.python
   1465       push:
   1466         - meta_scope: meta.interpolation.python
   1467         - match: (?=\})
   1468           pop: true
   1469         - match: '![ars]'
   1470           scope: storage.modifier.conversion.python
   1471         - match: =
   1472           scope: storage.modifier.debug.python
   1473         - match: ':'
   1474           push:
   1475             - meta_scope: meta.format-spec.python constant.other.format-spec.python
   1476             # Because replacements can also be used *within* the format-spec,
   1477             # basically any character is valid and matching {{format_spec}} is useless.
   1478             # - match: '{{format_spec}}'
   1479             - match: (?=\})
   1480               pop: true
   1481             - include: f-string-content
   1482         - match: ''
   1483           push:
   1484             - meta_content_scope: source.python.embedded
   1485             - match: (?==?(![^=]|:|\}))
   1486               pop: true
   1487             - match: \\
   1488               scope: invalid.illegal.backslash-in-fstring.python
   1489             - include: inline-for
   1490             - include: expression-in-a-group
   1491 
   1492   f-string-replacement-reset:
   1493     # Same as f-string-replacement, but with clear_scopes: true
   1494     - clear_scopes: true
   1495     - meta_scope: source.python meta.string.interpolated.python
   1496     - match: \}
   1497       scope: meta.interpolation.python punctuation.section.interpolation.end.python
   1498       pop: true
   1499     - match: \{
   1500       scope: punctuation.section.interpolation.begin.python
   1501       push:
   1502         - meta_scope: meta.interpolation.python
   1503         - match: (?=\})
   1504           pop: true
   1505         - match: '![ars]'
   1506           scope: storage.modifier.conversion.python
   1507         - match: ':'
   1508           push:
   1509             - meta_scope: meta.format-spec.python constant.other.format-spec.python
   1510             - match: (?=\})
   1511               pop: true
   1512             - include: f-string-content
   1513         - match: ''
   1514           push:
   1515             - meta_content_scope: source.python.embedded
   1516             - match: (?=![^=]|:|\})
   1517               pop: true
   1518             - match: \\
   1519               scope: invalid.illegal.backslash-in-fstring.python
   1520             - include: inline-for
   1521             - include: expression-in-a-group
   1522 
   1523   string-quoted-double-block:
   1524     # Triple-quoted capital R raw string, unicode or not, no syntax embedding
   1525     - match: '([uU]?R)(""")'
   1526       captures:
   1527         1: storage.type.string.python
   1528         2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python
   1529       push:
   1530         - meta_content_scope: meta.string.python string.quoted.double.block.python
   1531         - match: '"""'
   1532           scope: punctuation.definition.string.end.python
   1533           set: after-expression
   1534         - include: escaped-unicode-char
   1535     # Triple-quoted capital R raw string, bytes, no syntax embedding
   1536     - match: '([bB]R|R[bB])(""")'
   1537       captures:
   1538         1: storage.type.string.python
   1539         2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python
   1540       push:
   1541         - meta_content_scope: meta.string.python string.quoted.double.block.python
   1542         - match: '"""'
   1543           scope: punctuation.definition.string.end.python
   1544           set: after-expression
   1545     # Triple-quoted raw string, unicode or not, will detect SQL, otherwise regex
   1546     - match: '([uU]?r)(""")'
   1547       captures:
   1548         1: storage.type.string.python
   1549         2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python
   1550       push:
   1551         - meta_content_scope: meta.string.python string.quoted.double.block.python
   1552         - match: '(?={{sql_indicator}})'
   1553           set:
   1554             - meta_scope: meta.string.python string.quoted.double.block.python
   1555             - match: '"""'
   1556               scope: punctuation.definition.string.end.python
   1557               set: after-expression
   1558             - match: ''
   1559               push: scope:source.sql
   1560               with_prototype:
   1561                 - match: '(?=""")'
   1562                   pop: true
   1563                 - include: escaped-unicode-char
   1564                 - include: constant-placeholder
   1565         - match: '(?=\S)'
   1566           set:
   1567             - meta_scope: meta.string.python string.quoted.double.block.python
   1568             - match: '"""'
   1569               scope: punctuation.definition.string.end.python
   1570               set: after-expression
   1571             - match: ''
   1572               push: scope:source.regexp.python
   1573               with_prototype:
   1574                 - match: '(?=""")'
   1575                   pop: true
   1576                 - include: escaped-unicode-char
   1577     # Triple-quoted raw string, bytes, will use regex
   1578     - match: '([bB]r|r[bB])(""")'
   1579       captures:
   1580         1: storage.type.string.python
   1581         2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python
   1582       push:
   1583         - meta_content_scope: meta.string.python string.quoted.double.block.python
   1584         - match: '"""'
   1585           scope: punctuation.definition.string.end.python
   1586           set: after-expression
   1587         - match: ''
   1588           embed: scope:source.regexp.python
   1589           escape: (?=""")
   1590     # Triple-quoted raw f-string
   1591     - match: ([fF]R|R[fF])(""")
   1592       captures:
   1593         1: storage.type.string.python
   1594         2: meta.string.interpolated.python string.quoted.double.block.python punctuation.definition.string.begin.python
   1595       push:
   1596         - meta_content_scope: meta.string.interpolated.python string.quoted.double.block.python
   1597         - match: '"""'
   1598           scope: punctuation.definition.string.begin.python
   1599           set: after-expression
   1600         - include: f-string-content
   1601     # Triple-quoted raw f-string, treated as regex
   1602     - match: ([fF]r|r[fF])(""")
   1603       captures:
   1604         1: storage.type.string.python
   1605         2: meta.string.interpolated.python string.quoted.double.block.python punctuation.definition.string.begin.python
   1606       push:
   1607         - meta_content_scope: meta.string.interpolated.python string.quoted.double.block.python
   1608         - match: '"""'
   1609           scope: punctuation.definition.string.begin.python
   1610           set: after-expression
   1611         - match: ''
   1612           push: scope:source.regexp.python
   1613           with_prototype:
   1614             - match: '(?=""")'
   1615               pop: true
   1616             - include: f-string-content-with-regex
   1617     # Triple-quoted f-string
   1618     - match: ([fF])(""")
   1619       captures:
   1620         1: storage.type.string.python
   1621         2: meta.string.interpolated.python string.quoted.double.block.python punctuation.definition.string.begin.python
   1622       push:
   1623         - meta_content_scope: meta.string.interpolated.python string.quoted.double.block.python
   1624         - match: '"""'
   1625           scope: punctuation.definition.string.begin.python
   1626           set: after-expression
   1627         - include: line-continuation-inside-block-string
   1628         - include: escaped-fstring-escape
   1629         - include: escaped-unicode-char
   1630         - include: escaped-char
   1631         - include: f-string-content
   1632     # Triple-quoted string, unicode or not, will detect SQL
   1633     - match: '([uU]?)(""")'
   1634       captures:
   1635         1: storage.type.string.python
   1636         2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python
   1637       push:
   1638         - meta_content_scope: meta.string.python string.quoted.double.block.python
   1639         - match: '(?={{sql_indicator}})'
   1640           set:
   1641             - meta_scope: meta.string.python string.quoted.double.block.python
   1642             - match: '"""'
   1643               scope: punctuation.definition.string.end.python
   1644               set: after-expression
   1645             - match: ''
   1646               push: scope:source.sql
   1647               with_prototype:
   1648                 - match: '(?=""")'
   1649                   pop: true
   1650                 - include: line-continuation-inside-block-string
   1651                 - include: escaped-unicode-char
   1652                 - include: escaped-char
   1653                 - include: constant-placeholder
   1654         - match: '(?=\S)'
   1655           set:
   1656             - meta_scope: meta.string.python string.quoted.double.block.python
   1657             - match: '"""'
   1658               scope: punctuation.definition.string.end.python
   1659               set: after-expression
   1660             - include: line-continuation-inside-block-string
   1661             - include: escaped-unicode-char
   1662             - include: escaped-char
   1663             - include: constant-placeholder
   1664     # Triple-quoted string, bytes, no syntax embedding
   1665     - match: '([bB])(""")'
   1666       captures:
   1667         1: storage.type.string.python
   1668         2: meta.string.python string.quoted.double.block.python punctuation.definition.string.begin.python
   1669       push:
   1670         - meta_content_scope: meta.string.python string.quoted.double.block.python
   1671         - match: '"""'
   1672           scope: punctuation.definition.string.end.python
   1673           set: after-expression
   1674         - include: line-continuation-inside-block-string
   1675         - include: escaped-char
   1676         - include: constant-placeholder
   1677 
   1678   string-quoted-double:
   1679     # Single-line capital R raw string, unicode or not, no syntax embedding
   1680     - match: '([uU]?R)(")'
   1681       captures:
   1682         1: storage.type.string.python
   1683         2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
   1684       push:
   1685         - meta_content_scope: meta.string.python string.quoted.double.python
   1686         - match: '"'
   1687           scope: punctuation.definition.string.end.python
   1688           set: after-expression
   1689         - include: line-continuation-inside-string
   1690     # Single-line capital R raw string, bytes, no syntax embedding
   1691     - match: '([bB]R|R[bB])(")'
   1692       captures:
   1693         1: storage.type.string.python
   1694         2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
   1695       push:
   1696         - meta_content_scope: meta.string.python string.quoted.double.python
   1697         - match: '"'
   1698           scope: punctuation.definition.string.end.python
   1699           set: after-expression
   1700         - include: line-continuation-inside-string
   1701     # Single-line raw string, unicode or not, starting with a SQL keyword
   1702     - match: '([uU]?r)(")(?={{sql_indicator}})'
   1703       captures:
   1704         1: storage.type.string.python
   1705         2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
   1706       push:
   1707         - meta_content_scope: meta.string.python string.quoted.double.python
   1708         - match: '"'
   1709           scope: punctuation.definition.string.end.python
   1710           set: after-expression
   1711         - include: line-continuation-inside-string
   1712         - match: ''
   1713           push: scope:source.sql
   1714           with_prototype:
   1715             - match: '(?="|\n)'
   1716               pop: true
   1717             - include: constant-placeholder
   1718             - include: line-continuation-inside-string
   1719     # Single-line raw string, unicode or not, treated as regex
   1720     - match: '([uU]?r)(")'
   1721       captures:
   1722         1: storage.type.string.python
   1723         2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
   1724       push:
   1725         - meta_content_scope: meta.string.python string.quoted.double.python
   1726         - match: '"'
   1727           scope: punctuation.definition.string.end.python
   1728           set: after-expression
   1729         - include: line-continuation-inside-string
   1730         - match: ''
   1731           push: scope:source.regexp.python
   1732           with_prototype:
   1733             - match: '(?="|\n)'
   1734               pop: true
   1735             - include: line-continuation-inside-string
   1736     # Single-line raw string, bytes, treated as regex
   1737     - match: '([bB]r|r[bB])(")'
   1738       captures:
   1739         1: storage.type.string.python
   1740         2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
   1741       push:
   1742         - meta_content_scope: meta.string.python string.quoted.double.python
   1743         - match: '"'
   1744           scope: punctuation.definition.string.end.python
   1745           set: after-expression
   1746         - include: line-continuation-inside-string
   1747         - match: ''
   1748           embed: scope:source.regexp.python
   1749           escape: (?="|\n)
   1750     # Single-line raw f-string
   1751     - match: (R[fF]|[fF]R)(")
   1752       captures:
   1753         1: storage.type.string.python
   1754         2: meta.string.interpolated.python string.quoted.double.python punctuation.definition.string.begin.python
   1755       push:
   1756         - meta_content_scope: meta.string.interpolated.python string.quoted.double.python
   1757         - match: '"'
   1758           scope: punctuation.definition.string.end.python
   1759           set: after-expression
   1760         - include: line-continuation-inside-string
   1761         - include: f-string-content
   1762     # Single-line raw f-string, treated as regex
   1763     - match: (r[fF]|[fF]r)(")
   1764       captures:
   1765         1: storage.type.string.python
   1766         2: meta.string.interpolated.python string.quoted.double.python punctuation.definition.string.begin.python
   1767       push:
   1768         - meta_content_scope: meta.string.interpolated.python string.quoted.double.python
   1769         - match: '"'
   1770           scope: punctuation.definition.string.end.python
   1771           set: after-expression
   1772         - include: line-continuation-inside-string
   1773         - match: ''
   1774           push: scope:source.regexp.python
   1775           with_prototype:
   1776             - match: '(?="|\n)'
   1777               pop: true
   1778             - include: line-continuation-inside-string
   1779             - include: f-string-content-with-regex
   1780     # Single-line f-string
   1781     - match: ([fF])(")
   1782       captures:
   1783         1: storage.type.string.python
   1784         2: meta.string.interpolated.python string.quoted.double.python punctuation.definition.string.begin.python
   1785       push:
   1786         - meta_content_scope: meta.string.interpolated.python string.quoted.double.python
   1787         - match: '"'
   1788           scope: punctuation.definition.string.end.python
   1789           set: after-expression
   1790         - include: escaped-fstring-escape
   1791         - include: escaped-unicode-char
   1792         - include: escaped-char
   1793         - include: line-continuation-inside-string
   1794         - include: f-string-content
   1795     # Single-line string, unicode or not, starting with a SQL keyword
   1796     - match: '([uU]?)(")(?={{sql_indicator}})'
   1797       captures:
   1798         1: storage.type.string.python
   1799         2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
   1800       push:
   1801         - meta_content_scope: meta.string.python string.quoted.double.python
   1802         - match: '"'
   1803           scope: punctuation.definition.string.end.python
   1804           set: after-expression
   1805         - include: line-continuation-inside-string
   1806         - match: ''
   1807           push: scope:source.sql
   1808           with_prototype:
   1809             - match: '(?="|\n)'
   1810               pop: true
   1811             - include: escaped-unicode-char
   1812             - include: escaped-char
   1813             - include: line-continuation-inside-string
   1814             - include: constant-placeholder
   1815     # Single-line string, unicode or not
   1816     - match: '([uU]?)(")'
   1817       captures:
   1818         1: storage.type.string.python
   1819         2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
   1820       push:
   1821         - meta_content_scope: meta.string.python string.quoted.double.python
   1822         - match: '"'
   1823           scope: punctuation.definition.string.end.python
   1824           set: after-expression
   1825         - include: escaped-unicode-char
   1826         - include: escaped-char
   1827         - include: line-continuation-inside-string
   1828         - include: constant-placeholder
   1829     # Single-line string, bytes
   1830     - match: '([bB])(")'
   1831       captures:
   1832         1: storage.type.string.python
   1833         2: meta.string.python string.quoted.double.python punctuation.definition.string.begin.python
   1834       push:
   1835         - meta_content_scope: meta.string.python string.quoted.double.python
   1836         - match: '"'
   1837           scope: punctuation.definition.string.end.python
   1838           set: after-expression
   1839         - include: escaped-char
   1840         - include: line-continuation-inside-string
   1841         - include: constant-placeholder
   1842 
   1843   string-quoted-single-block:
   1844     # Triple-quoted capital R raw string, unicode or not, no syntax embedding
   1845     - match: ([uU]?R)(''')
   1846       captures:
   1847         1: storage.type.string.python
   1848         2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python
   1849       push:
   1850         - meta_content_scope: meta.string.python string.quoted.single.block.python
   1851         - match: "'''"
   1852           scope: punctuation.definition.string.end.python
   1853           set: after-expression
   1854     # Triple-quoted capital R raw string, bytes, no syntax embedding
   1855     - match: ([bB]R|R[bB])(''')
   1856       captures:
   1857         1: storage.type.string.python
   1858         2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python
   1859       push:
   1860         - meta_content_scope: meta.string.python string.quoted.single.block.python
   1861         - match: "'''"
   1862           scope: punctuation.definition.string.end.python
   1863           set: after-expression
   1864     # Triple-quoted raw string, unicode or not, will detect SQL, otherwise regex
   1865     - match: ([uU]?r)(''')
   1866       captures:
   1867         1: storage.type.string.python
   1868         2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python
   1869       push:
   1870         - meta_content_scope: meta.string.python string.quoted.single.block.python
   1871         - match: '(?={{sql_indicator}})'
   1872           set:
   1873             - meta_scope: meta.string.python string.quoted.single.block.python
   1874             - match: "'''"
   1875               scope: punctuation.definition.string.end.python
   1876               set: after-expression
   1877             - match: ''
   1878               push: scope:source.sql
   1879               with_prototype:
   1880                 - match: (?=''')
   1881                   pop: true
   1882                 - include: escaped-unicode-char
   1883                 - include: escaped-char
   1884                 - include: constant-placeholder
   1885         - match: '(?=\S)'
   1886           set:
   1887             - meta_scope: meta.string.python string.quoted.single.block.python
   1888             - match: "'''"
   1889               scope: punctuation.definition.string.end.python
   1890               set: after-expression
   1891             - match: ''
   1892               push: scope:source.regexp.python
   1893               with_prototype:
   1894                 - match: (?=''')
   1895                   pop: true
   1896                 - include: escaped-unicode-char
   1897     # Triple-quoted raw string, bytes, will use regex
   1898     - match: ([bB]r|r[bB])(''')
   1899       captures:
   1900         1: storage.type.string.python
   1901         2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python
   1902       push:
   1903         - meta_content_scope: meta.string.python string.quoted.single.block.python
   1904         - match: "'''"
   1905           scope: punctuation.definition.string.end.python
   1906           set: after-expression
   1907         - match: ''
   1908           embed: scope:source.regexp.python
   1909           escape: (?=''')
   1910     # Triple-quoted raw f-string
   1911     - match: ([fF]R|R[fF])(''')
   1912       captures:
   1913         1: storage.type.string.python
   1914         2: meta.string.interpolated.python string.quoted.single.block.python punctuation.definition.string.begin.python
   1915       push:
   1916         - meta_content_scope: meta.string.interpolated.python string.quoted.single.block.python
   1917         - match: "'''"
   1918           scope: punctuation.definition.string.begin.python
   1919           set: after-expression
   1920         - include: f-string-content
   1921     # Triple-quoted raw f-string, treated as regex
   1922     - match: ([fF]r|r[fF])(''')
   1923       captures:
   1924         1: storage.type.string.python
   1925         2: meta.string.interpolated.python string.quoted.single.block.python punctuation.definition.string.begin.python
   1926       push:
   1927         - meta_content_scope: meta.string.interpolated.python string.quoted.single.block.python
   1928         - match: "'''"
   1929           scope: punctuation.definition.string.begin.python
   1930           set: after-expression
   1931         - match: ''
   1932           push: scope:source.regexp.python
   1933           with_prototype:
   1934             - match: (?=''')
   1935               pop: true
   1936             - include: f-string-content-with-regex
   1937     # Triple-quoted f-string
   1938     - match: ([fF])(''')
   1939       captures:
   1940         1: storage.type.string.python
   1941         2: meta.string.interpolated.python string.quoted.single.block.python punctuation.definition.string.begin.python
   1942       push:
   1943         - meta_content_scope: meta.string.interpolated.python string.quoted.single.block.python
   1944         - match: "'''"
   1945           scope: punctuation.definition.string.begin.python
   1946           set: after-expression
   1947         - include: line-continuation-inside-block-string
   1948         - include: escaped-fstring-escape
   1949         - include: escaped-unicode-char
   1950         - include: escaped-char
   1951         - include: f-string-content
   1952     # Triple-quoted string, unicode or not, will detect SQL
   1953     - match: ([uU]?)(''')
   1954       captures:
   1955         1: storage.type.string.python
   1956         2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python
   1957       push:
   1958         - meta_content_scope: meta.string.python string.quoted.single.block.python
   1959         - match: '(?={{sql_indicator}})'
   1960           set:
   1961             - meta_scope: meta.string.python string.quoted.single.block.python
   1962             - match: "'''"
   1963               scope: punctuation.definition.string.end.python
   1964               set: after-expression
   1965             - match: ''
   1966               push: scope:source.sql
   1967               with_prototype:
   1968                 - match: (?=''')
   1969                   pop: true
   1970                 - include: line-continuation-inside-block-string
   1971                 - include: escaped-unicode-char
   1972                 - include: escaped-char
   1973                 - include: constant-placeholder
   1974         - match: '(?=\S)'
   1975           set:
   1976             - meta_scope: meta.string.python string.quoted.single.block.python
   1977             - match: "'''"
   1978               scope: punctuation.definition.string.end.python
   1979               set: after-expression
   1980             - include: line-continuation-inside-block-string
   1981             - include: escaped-unicode-char
   1982             - include: escaped-char
   1983             - include: constant-placeholder
   1984     # Triple-quoted string, bytes, no syntax embedding
   1985     - match: ([bB])(''')
   1986       captures:
   1987         1: storage.type.string.python
   1988         2: meta.string.python string.quoted.single.block.python punctuation.definition.string.begin.python
   1989       push:
   1990         - meta_content_scope: meta.string.python string.quoted.single.block.python
   1991         - match: "'''"
   1992           scope: punctuation.definition.string.end.python
   1993           set: after-expression
   1994         - include: line-continuation-inside-block-string
   1995         - include: escaped-char
   1996         - include: constant-placeholder
   1997 
   1998   string-quoted-single:
   1999     # Single-line capital R raw string, unicode or not, no syntax embedding
   2000     - match: '([uU]?R)('')'
   2001       captures:
   2002         1: storage.type.string.python
   2003         2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
   2004       push:
   2005         - meta_content_scope: meta.string.python string.quoted.single.python
   2006         - match: "'"
   2007           scope: punctuation.definition.string.end.python
   2008           set: after-expression
   2009         - include: line-continuation-inside-string
   2010     # Single-line capital R raw string, bytes, no syntax embedding
   2011     - match: '([bB]R|R[bB])('')'
   2012       captures:
   2013         1: storage.type.string.python
   2014         2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
   2015       push:
   2016         - meta_content_scope: meta.string.python string.quoted.single.python
   2017         - match: "'"
   2018           scope: punctuation.definition.string.end.python
   2019           set: after-expression
   2020         - include: line-continuation-inside-string
   2021     # Single-line raw string, unicode or not, starting with a SQL keyword
   2022     - match: '([uU]?r)('')(?={{sql_indicator}})'
   2023       captures:
   2024         1: storage.type.string.python
   2025         2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
   2026       push:
   2027         - meta_content_scope: meta.string.python string.quoted.single.python
   2028         - match: "'"
   2029           scope: punctuation.definition.string.end.python
   2030           set: after-expression
   2031         - include: line-continuation-inside-string
   2032         - match: ''
   2033           push: scope:source.sql
   2034           with_prototype:
   2035             - match: '(?=''|\n)'
   2036               pop: true
   2037             - include: line-continuation-inside-string
   2038             - include: constant-placeholder
   2039     # Single-line raw string, unicode or not, treated as regex
   2040     - match: '([uU]?r)('')'
   2041       captures:
   2042         1: storage.type.string.python
   2043         2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
   2044       push:
   2045         - meta_content_scope: meta.string.python string.quoted.single.python
   2046         - match: "'"
   2047           scope: punctuation.definition.string.end.python
   2048           set: after-expression
   2049         - include: line-continuation-inside-string
   2050         - match: ''
   2051           push: scope:source.regexp.python
   2052           with_prototype:
   2053             - match: '(?=''|\n)'
   2054               pop: true
   2055             - include: line-continuation-inside-string
   2056     # Single-line raw string, bytes, treated as regex
   2057     - match: '([bB]r|r[bB])('')'
   2058       captures:
   2059         1: storage.type.string.python
   2060         2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
   2061       push:
   2062         - meta_content_scope: meta.string.python string.quoted.single.python
   2063         - match: "'"
   2064           scope: punctuation.definition.string.end.python
   2065           set: after-expression
   2066         - include: line-continuation-inside-string
   2067         - match: ''
   2068           push: scope:source.regexp.python
   2069           with_prototype:
   2070             - match: '(?=''|\n)'
   2071               pop: true
   2072             - include: line-continuation-inside-string
   2073     # Single-line raw f-string
   2074     - match: ([fF]R|R[fF])(')
   2075       captures:
   2076         1: storage.type.string.python
   2077         2: meta.string.interpolated.python string.quoted.single.python punctuation.definition.string.begin.python
   2078       push:
   2079         - meta_content_scope: meta.string.interpolated.python string.quoted.single.python
   2080         - match: "'"
   2081           scope: punctuation.definition.string.end.python
   2082           set: after-expression
   2083         - include: line-continuation-inside-string
   2084         - include: f-string-content
   2085     # Single-line raw f-string, treated as regex
   2086     - match: ([fF]r|r[fF])(')
   2087       captures:
   2088         1: storage.type.string.python
   2089         2: meta.string.interpolated.python string.quoted.single.python punctuation.definition.string.begin.python
   2090       push:
   2091         - meta_content_scope: meta.string.interpolated.python string.quoted.single.python
   2092         - match: "'"
   2093           scope: punctuation.definition.string.end.python
   2094           set: after-expression
   2095         - include: line-continuation-inside-string
   2096         - match: ''
   2097           push: scope:source.regexp.python
   2098           with_prototype:
   2099             - match: (?='|\n)
   2100               pop: true
   2101             - include: line-continuation-inside-string
   2102             - include: f-string-content-with-regex
   2103     # Single-line f-string
   2104     - match: ([fF])(')
   2105       captures:
   2106         1: storage.type.string.python
   2107         2: meta.string.interpolated.python string.quoted.single.python punctuation.definition.string.begin.python
   2108       push:
   2109         - meta_content_scope: meta.string.interpolated.python string.quoted.single.python
   2110         - match: "'"
   2111           scope: punctuation.definition.string.end.python
   2112           set: after-expression
   2113         - include: escaped-fstring-escape
   2114         - include: escaped-unicode-char
   2115         - include: escaped-char
   2116         - include: line-continuation-inside-string
   2117         - include: f-string-content
   2118     # Single-line string, unicode or not, starting with a SQL keyword
   2119     - match: '([uU]?)('')(?={{sql_indicator}})'
   2120       captures:
   2121         1: storage.type.string.python
   2122         2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
   2123       push:
   2124         - meta_content_scope: meta.string.python string.quoted.single.python
   2125         - match: "'"
   2126           scope: punctuation.definition.string.end.python
   2127           set: after-expression
   2128         - include: line-continuation-inside-string
   2129         - match: ''
   2130           push: scope:source.sql
   2131           with_prototype:
   2132             - match: '(?=''|\n)'
   2133               pop: true
   2134             - include: escaped-unicode-char
   2135             - include: escaped-char
   2136             - include: line-continuation-inside-string
   2137             - include: constant-placeholder
   2138     # Single-line string, unicode or not
   2139     - match: '([uU]?)('')'
   2140       captures:
   2141         1: storage.type.string.python
   2142         2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
   2143       push:
   2144         - meta_content_scope: meta.string.python string.quoted.single.python
   2145         - match: "'"
   2146           scope: punctuation.definition.string.end.python
   2147           set: after-expression
   2148         - include: escaped-unicode-char
   2149         - include: escaped-char
   2150         - include: line-continuation-inside-string
   2151         - include: constant-placeholder
   2152     # Single-line string, bytes
   2153     - match: '([bB])('')'
   2154       captures:
   2155         1: storage.type.string.python
   2156         2: meta.string.python string.quoted.single.python punctuation.definition.string.begin.python
   2157       push:
   2158         - meta_content_scope: meta.string.python string.quoted.single.python
   2159         - match: "'"
   2160           scope: punctuation.definition.string.end.python
   2161           set: after-expression
   2162         - include: escaped-char
   2163         - include: line-continuation-inside-string
   2164         - include: constant-placeholder
   2165 
   2166   strings:
   2167     # block versions must be matched first
   2168     - include: string-quoted-double-block
   2169     - include: string-quoted-double
   2170     - include: string-quoted-single-block
   2171     - include: string-quoted-single
   2172 
   2173   inline-for:
   2174     - match: \b(?:(async)\s+)?(for)\b
   2175       captures:
   2176         1: storage.modifier.async.python
   2177         2: keyword.control.loop.for.generator.python
   2178       push:
   2179         - include: comments
   2180         - meta_scope: meta.expression.generator.python
   2181         - match: \bin\b
   2182           scope: keyword.control.loop.for.in.python
   2183           pop: true
   2184         - match: '(?=[)\]}])'
   2185           scope: invalid.illegal.missing-in.python
   2186           pop: true
   2187         - include: illegal-names-pop
   2188         - include: target-list
   2189 
   2190   inline-if:
   2191     - match: \bif\b
   2192       scope: keyword.control.conditional.if.python
   2193     - match: \belse\b
   2194       scope: keyword.control.conditional.else.python
   2195 
   2196   target-list:
   2197     - match: ','
   2198       scope: punctuation.separator.target-list.python
   2199     - match: \(
   2200       scope: punctuation.section.target-list.begin.python
   2201       push:
   2202         - include: comments
   2203         - match: ','
   2204           scope: punctuation.separator.target-list.python
   2205         - match: \)
   2206           scope: punctuation.section.target-list.end.python
   2207           pop: true
   2208         - include: target-list
   2209         - include: name
   2210     - include: name