Sublime Forum

[Syntax Is there a possibility to pop the current context only for specific capture group?

#1

Hi everyone, I wonder if I can do the thing said in the topic?
The example is:

from "file" import abc

That’s not Python, that’s my own language.
So, what I need is:

  1. Consider ‘from’ as a keyword only if it is followed by ‘import’ at some point (at least at the same line for simplicity)
  2. After ‘from’ there goes an expression – that’s why we need to pop out the keyword.control.import context.
  3. After the expression there goes an ‘import’ keyword. It is the standard keyword.
  4. After ‘import’ there goes another expression which shouldn’t be in this context too.

How my current context looks:

import_stmt:
    - match: '\bimport\b'
      scope: keyword.control.import
    - match: '(\bfrom\b)\s*(.*?)\s*(\bimport\b)'
      captures:
        1: keyword.control.import
        2: ???
        3: keyword.control.import

I don’t know how to put a second capture out of current context (that is to highlight it separately, if there’s an indentifier between ‘from’ and ‘import’, highlight it as an identifier anywhere else in the code; if there’s a string, highlight if as a string).

Is it even possible? If not, can you please enable the option to make the element in the ‘captures’ array be possibly of the type ‘match’ as well as ordinary strings?

Then I would fix it something like that:

import_stmt:
    - match: '\bimport\b'
      scope: keyword.control.import
    - match: '(\bfrom\b)\s*(.*?)\s*(\bimport\b)'
      captures:
        1: keyword.control.import
        2:
            - pop: true # or idk something like that to pop off the current context and highlight it separately???
        3: keyword.control.import

Thanks in advance for any helpful advice!

0 Likes

#2

No, this is not possible. You can do everything else though. I don’t really understand your problem with the different color and capture, however.

0 Likes

#3

sounds like using a regex lookahead could help you to identify when to scope from as a keyword

0 Likes

#4

What you want to do is not possible in general, although it may be possible in some special cases.

Suppose contrarily that instead of an expression, from might be followed by a single word. You can match this using a lookahead and multiple contexts:

contexts:
  import-simple:
    - match: \bimport\b
      scope: keyword.control.import

  import-statement:
    - include: import-simple
    - match: \bfrom\b(?=\s*\b\w+\b\s*\bimport\b)
      scope: keyword.control.import
      push:
        - import-simple
        - expression # You must supply this yourself

However, I presume that an “expression” in your language may be complex, possibly including other expressions within itself. Such an expression cannot be matched by a regexp lookahead.

Note that your example will match from "import". I doubt that this is correct.

You say that this is your own language. If so, I would reserve from as a keyword so that it always indicates an export statement. That will avoid all of these difficulties.

The nondeterministic parsing proposal would solve this problem, but even with that capability I would recommend reserving from if for no other reason than that no other text editor will be able to highlight your language anyway.

0 Likes