Sublime Forum

Syntax files: captures for variables

#1

The variables feature of syntax files is very useful, but it could be improved by allowing captures on the variables.

Here is an incomplete example:

  char_selector: | # incomplete
    (?xi)
    (?:
      \(
        \s*
        (?:
          LEN \s* = \s* {{type_param_value}} \s* , \s* KIND \s* = \s* {{int_constant_expr}}
        |
          {{type_param_value}} \s* ,  \s* (?:KIND \s* =)?  \s* {{int_constant_expr}}
        |
          KIND \s* = \s* {{int_constant_expr}}  \s* (?: , \s* LEN \s* = \s* {{type_param_value}})?
        |
          (?:LEN \s* = \s* )? {{type_param_value}}
        )
        \s*
      \)
    |
      \s* \* \s* {{char_length}} \s* ,? \s*
    )
  intrinsic_type_spec: |
    (?xi)
    (?:
      \bCHARACTER\b \s* {{char_selector}}
    |
      \b(?:COMPLEX|INTEGER|LOGICAL|REAL)\b (?:\s* {{kind_selector}})?
    |
      \b DOUBLE \s+ (?:COMPLEX|PRECISION) \b
    )
  derived_type_spec: | # missing type_param_spec_list
    (?xi)
    (?:
      {{ident}}
    )
  declaration_type_spec_part1: |
    (?xi)
    (?:
      {{intrinsic_type_spec}}
    |
      type \s* \( \s* {{intrinsic_type_spec}} \s* \)
    |
      type \s* \( \s* {{derived_type_spec}} \s* \)
    |
      class \s* \( \s* {{derived_type_spec}} \s* \)
    |
      class \s* \( \s* \* \s* \)
    )
  declaration_type_spec: | # TODO not used yet
    (?xi)
    (?:
      {{declaration_type_spec_part1}}
      (
        \s* :: \s*
      |
        \s* , {{attr_spec_list}} \s* :: \s*
      )?
      {{entity_decl_list}}
    )

contexts:
  main:
    # function/subroutine definition with parameter list
    - match: |
        (?xi)
        (?:^
          \s*
          ((?:{{modifier}}\s+)*)
          ({{declaration_type_spec_part1}}\s+)?
          \b (FUNCTION|SUBROUTINE) \b
          \s+ ({{ident}})
          \s* (\(|&) # match opening bracket
        )
      scope: meta.subroutine-declaration.fortran
      captures:
        1: keyword.modifier.fortran
        2: storage.type.fortran
        3: keyword.program-unit.fortran
        4: entity.name.function.fortran
      push: subroutine_parameter_list

It would be nice to be able to turn all of those unmatched groups into matched groups and apply scopes to them. However, keeping track of so many nested groups makes it difficult to apply the correct scopes when using these variables in the contexts section. Ideally one would be able to specify scopes for each group captured directly in the variable regular expression, without capturing groups from within referenced variables. Then when variables are used in the contexts section, only the groups defined in that regex would be numbered, and all of the captures from the variable regular expression would be applied without modifying the top-level group indexing.

This would even cut down on repetition for simpler cases. If you could define {{ident}} to always have the appropriate scope there would be no need to capture identifier and apply the correct scope everywhere it is used in the contexts section.

2 Likes