Sublime Forum

Syntax definition for nested matches

#1

I’ve had difficulty finding help with adding something simple to a custom syntax I created…
I just need to match text in square brackets but the square brackets can be nested eg…
[a[b]c]
My current definition highlights the “[a[b]” but does not highlight the “c]” as the “]” after the b is being picked up as the end of the sequence - not taking into account that there were 2 opening brackets.

This is the syntax I have currently…

  • match: [
    push: preprocessor
    preprocessor:
    • meta_scope: storage.type.qpscl
    • match: \.
    • match: ]
      pop: true

Is anyone able to suggest the best way to cope with the nested brackets?

0 Likes

#2

you should just be able to include the context that has the match: [ rule from inside the preprocessor rule:

  main:
    - match: \[
      push: preprocessor
  preprocessor:
    - meta_scope: storage.type.qpscl
    - match: \.
    - match: \]
      pop: true
    - include: main
1 Like

#3

The general root of your problem is that only the rules from the context currently at the top of the context stack are used.

In your example here, the context that contains - match: [ pushes the preprocessor context onto the top of the stack. Once that happens the only rules that can match are the \. and the ] to leave.

So, given the input [a [b] c], once the first [ is seen, you’re inside preprocessor where there’s no rule that says that a [ should enter a new nested level; instead that character is consumed by the \. rule, the ] is seen to pop back to the prior context, and now the remainder of the input c] is just highlighted by whatever rules exist in the outer context.

Try something like this:

contexts:
  main:
    - include: enter-preprocessor

  enter-preprocessor:
    - match: '\['
      push: preprocessor

  preprocessor:
    - meta_scope: storage.type.qpscl
    - include: enter-preprocessor
    - match: ']'
      pop: true

Now from the main level if there’s a [ seen, it pushes into the preprocessor context, which also contains the rule that says that a [ should push into a new instance of preprocessor, allowing the nested parsing you want.

If you check the scopes, you can see that the first [ scopes as source.qpscl storage.type.qpscl whereas the second [ scopes as source.qpscl storage.type.qpscl storage.type.qpscl (i.e. there are two storage scopes now because it’s nesting on itself).

You may be tempted to put that include directly inside of preprocessor and skip the extra context, but that will generate an error. When syntaxes are compiled, the include statements inject the content of the given context directly into the current one as new instances of the same rule. A context that includes itself will trigger an error about infinite recursion since it doesn’t know when to stop.

0 Likes

#4

Thanks very much, that’s a nice approach - very useful to know about!

0 Likes

#5

Thanks so much for explaining so thoroughly. This works perfectly.
I had tried a number of other things (reading the docs/other posts) but after a couple of hours of them failing, I thought I’d seek assistance - and keep the problem simple.

0 Likes