         ]
       }
       {
-        'comment': 'things to color after the comma'
-        'begin': ','
-        'beginCaptures':
-          '0':
-            'name': 'punctuation.definition.variable.begin.stata'
-        'end': '(?=\\n)'
-        'patterns': [
-          {
-            'begin': '///'
-            'end': '\\n'
-            'name': 'comment.block.stata'
-          }
-          {
-            'comment': 'color options with parentheses'
-            'begin': '([^\\s\\[\\]]+)(\\()'
-            'beginCaptures':
-              '1':
-                'patterns': [
+        comment: 'things to color after the comma'
+        begin: ','
+        beginCaptures:
+          0: name: 'punctuation.definition.variable.begin.stata'
+        end: '(?=\\n)'
+        patterns: [
+          {
+            begin: '///'
+            end: '\\n'
+            name: 'comment.block.stata'
+          }
+          {
+            comment: 'color options with parentheses'
+            begin: '([^\\s\\[\\]]+)(\\()'
+            beginCaptures:
+              1:
+                patterns: [
                   {include: '#macro-local-identifiers'}
                   {include: '#macro-local'}
                   {include: '#macro-global'}
                 ]
-                'comment': 'these are the names that become macros'
-              '2':
-                'name': 'keyword.operator.parentheses.stata'
-            'end': '\\)'
-            'endCaptures':
-              '0':
-                'name': 'keyword.operator.parentheses.stata'
-            'patterns': [
-              {
-                'comment': 'the first word is often a type'
-                'match': '\\b(integer|intege|integ|inte|int|real|string|strin|stri|str)\\b'
-                'captures':
-                  '0':
-                    'name': 'support.type.stata'
+                comment: 'these are the names that become macros'
+              2: name: 'keyword.operator.parentheses.stata'
+            end: '\\)'
+            endCaptures:
+              0: name: 'keyword.operator.parentheses.stata'
+            patterns: [
+              {
+                comment: 'the first word is often a type'
+                match: '\\b(integer|intege|integ|inte|int|real|string|strin|stri|str)\\b'
+                captures:
+                  0: name: 'support.type.stata'
               }
               {include: '#constants'}
               {include: '#operators'}

      }
    ]
  'macro-global-escaped':
    'patterns': [
      {
        'begin': '(\\\\\\$)(\\\\\\{)?'
        'beginCaptures':
          '0':
            'name': 'punctuation.definition.string.begin.stata'
        'end': '(\\\\\\})|(?=\\"|\\s|\\n|/|,)'
        'endCaptures':
          '1':
            'name': 'punctuation.definition.string.end.stata'
        'patterns': [
          {include: '#macro-local'}
          {include: '#macro-global'}
          {
            'match': '[\\w&&[^0-9_]]\\w{0,31}|_\\w{1,31}'
            'name': 'entity.name.type.class.stata'
          }
        ]
      }
    ]
  'macro-global':
    'patterns': [
      {
        'begin': '(\\$)(\\{)'
        'beginCaptures':
          '0':
            'name': 'punctuation.definition.string.begin.stata'
        'end': '\\}'
        'endCaptures':
          '0':
            'name': 'punctuation.definition.string.end.stata'
        'patterns': [
          {include: '#macro-local'}
          {include: '#macro-global'}
          {
            'match': '[\\w&&[^0-9_]]\\w{0,31}|_\\w{1,31}'
            'name': 'entity.name.type.class.stata'
          }
          {
            'match': '.'
            'name': 'comment.line.stata'
          }
        ]
      }
      {
        'begin': '\\$'
        'beginCaptures':
          '0':
            'name': 'punctuation.definition.string.begin.stata'
        'end': '(?!\\w)'
        'endCaptures':
          '1':
            'name': 'punctuation.definition.string.end.stata'
        'patterns': [
          {include: '#macro-local'}
          {include: '#macro-global'}
          {
            'match': '[\\w&&[^0-9_]]\\w{0,31}|_\\w{1,31}'
            'name': 'entity.name.type.class.stata'
          }
        ]
      }
    ]
  'constants':
    'patterns': [
      {include: '#factorvariables'}
      {
        'match': '\\b(?i:(\\d+\\.\\d*(e[\\-\\+]?\\d+)?))(?=[^a-zA-Z_])'
        'name': 'constant.numeric.float.stata'
      }
      {
        'match': '(?<=[^0-9a-zA-Z_])(?i:(\\.\\d+(e[\\-\\+]?\\d+)?))'
        'name': 'constant.numeric.float.stata'
      }
      {
        'match': '\\b(?i:(\\d+e[\\-\\+]?\\d+))'
        'name': 'constant.numeric.float.stata'
      }
      {
        'match': '\\b(\\d+)\\b'
        'name': 'constant.numeric.integer.decimal.stata'
      }
      {
        'match': '(?<![\\w])(\\.(?![\\./]))(?![\\w])'
        'name': 'constant.language.missing.stata'
      }
      {
        'match': '\\b_all\\b'
        'name': 'constant.language.allvars.stata'
      }
    ]
  'factorvariables':
    'patterns': [
      {
        'match': '\\b(i|c|o)\\.(?=[\\w&&[^0-9]]|\\([\\w&&[^0-9]])'
        'name': 'constant.language.factorvars.stata'
      }
      {
        'match': '\\b(i?b)((\\d+)|n)\\.(?=[\\w&&[^0-9]]|\\([\\w&&[^0-9]])'
        'captures':
          '0':
            'name': 'constant.language.factorvars.stata'
          '3':
            'patterns': [
              {include: '#constants'}
            ]
      }
      {
        'match': '\\b(i?b)(\\()(#\\d+|first|last|freq)(\\))\\.(?=[\\w&&[^0-9]]|\\([\\w&&[^0-9]])'
        'captures':
          '0':
            'name': 'constant.language.factorvars.stata'
          '2':
            'name': 'keyword.operator.parentheses.stata'
          '3':
            'patterns': [
              {include: '#constants'}
              {include: '#operators'}
            ]
          '4':
            'name': 'keyword.operator.parentheses.stata'
      }
      {
        'match': '\\b(i?o?)(\\d+)\\.(?=[\\w&&[^0-9]]|\\([\\w&&[^0-9]])'
        'captures':
          '0':
            'name': 'constant.language.factorvars.stata'
          '2':
            'patterns': [
              {include: '#constants'}
            ]
      }
      {
        'match': '\\b(i?o?)(\\()(.*?)(\\))(\\.)(?=[\\w&&[^0-9]]|\\([\\w&&[^0-9]])'
        'captures':
          '1':
            'name': 'constant.language.factorvars.stata'
          '2':
            'name': 'keyword.operator.parentheses.stata'
          '3':
            'patterns': [
              {include: '$self'}
            ]
          '4':
            'name': 'keyword.operator.parentheses.stata'
          '5':
            'name': 'constant.language.factorvars.stata'
      }
    ]
  'operators':
    'patterns': [
      {
        'match': '\\+\\+|\\-\\-|\\+|\\-|\\*|\\^'
        'name': 'keyword.operator.arithmetic.stata'
        'comment': '++ and -- must come first to support ligatures'
      }
      {
        'comment': 'match division operator but not path separator'
        'match': '(?<![\\w.&&[^0-9]])/(?![\\w.&&[^0-9]]|$)'
        'name': 'keyword.operator.arithmetic.stata'
      }
      {
        'comment': 'match division operator but not path separator'
        'match': '(?<![\\w.&&[^0-9]])\\\\(?![\\w.&&[^0-9]]|$)'
        'name': 'keyword.operator.matrix.addrow.stata'
      }
      {
        'match': '\\|\\|'
        'name': 'keyword.operator.graphcombine.stata'
      }
      {
        'match': '\\&|\\|'
        'name': 'keyword.operator.logical.stata'
      }
      {
        'match': '(?:<=|>=|:=|==|!=|~=|<|>|=|!!|!)' # !! is for xshell
        'name': 'keyword.operator.comparison.stata'
      }
      {
        'match': '\\(|\\)'
        'name': 'keyword.operator.parentheses.stata'
      }
      {
        'match': '(##|#)'
        'name': 'keyword.operator.factor-variables.stata'
      }
      {
        'match': '%'
        'name': 'keyword.operator.format.stata'
      }
      {
        'match': ':'
        'name': 'punctuation.separator.key-value'
      }
      {
        'match': '\\['
        'name': 'punctuation.definition.parameters.begin.stata'
      }
      {
        'match': '\\]'
        'name': 'punctuation.definition.parameters.end.stata'
      }
      {
        'match': ','
        'name': 'punctuation.definition.variable.begin.stata'
      }
      {
        'match': ';'
        'name': 'keyword.operator.delimiter.stata'
      }
    ]
  'string-compound':
    'patterns': [
      {
        'begin': '`"'
        'beginCaptures':
          '0':
            'name': 'punctuation.definition.string.begin.stata'
        'end': '"\'|(?=\n)'
        'endCaptures':
          '0':
            'name': 'punctuation.definition.string.end.stata'
        'name': 'string.quoted.double.compound.stata'
        'patterns': [
          {
            'match': '"'
            'name': 'string.quoted.double.compound.stata'
            'comment': 'This must come before #string-regular and #string-compound to accurately color `"""\' in strings'
          }
          {
            'match': '```(?=[^\']*")'
            'name': 'meta.markdown.code.block.stata'
            'comment': 'color "```" as regular text, allowing for words after ```'
            'comment': 'see https://github.com/kylebarron/language-stata/issues/53'
          }
          {include: '#string-regular'}
          {include: '#string-compound'}

      }
    ]
  'string-regular':
    patterns: [
      {
        begin: '(?<!`)"'
        beginCaptures:
          0: name: 'punctuation.definition.string.begin.stata'
        end: '(")(\')?|(?=\n)'
        endCaptures:
          1: name: 'punctuation.definition.string.end.stata'
          2: name: 'invalid.illegal.punctuation.stata'
        name: 'string.quoted.double.stata'
        patterns: [
          {
            match: '```(?=[^\']*")'
            name: 'meta.markdown.code.block.stata'
            comment: 'color "```" as regular text, allowing for words after ```'
            comment: 'see https://github.com/kylebarron/language-stata/issues/53'
          }
          {include: '#macro-local-escaped'}
          {include: '#macro-global-escaped'}
