Prism.languages.parser = Prism.languages.extend('markup', {
  keyword: {
    pattern: /(^|[^^])(?:\^(?:case|eval|for|if|switch|throw)\b|@(?:BASE|CLASS|GET(?:_DEFAULT)?|OPTIONS|SET_DEFAULT|USE)\b)/,
    lookbehind: true,
  },
  variable: {
    pattern: /(^|[^^])\B\$(?:\w+|(?=[.{]))(?:(?:\.|::?)\w+)*(?:\.|::?)?/,
    lookbehind: true,
    inside: {
      punctuation: /\.|:+/,
    },
  },
  function: {
    pattern: /(^|[^^])\B[@^]\w+(?:(?:\.|::?)\w+)*(?:\.|::?)?/,
    lookbehind: true,
    inside: {
      keyword: {
        pattern: /(^@)(?:GET_|SET_)/,
        lookbehind: true,
      },
      punctuation: /\.|:+/,
    },
  },
  escape: {
    pattern: /\^(?:[$^;@()\[\]{}"':]|#[a-f\d]*)/i,
    alias: 'builtin',
  },
  punctuation: /[\[\](){};]/,
});
Prism.languages.insertBefore('parser', 'keyword', {
  'parser-comment': {
    pattern: /(\s)#.*/,
    lookbehind: true,
    alias: 'comment',
  },
  expression: {
    // Allow for 3 levels of depth
    pattern: /(^|[^^])\((?:[^()]|\((?:[^()]|\((?:[^()])*\))*\))*\)/,
    greedy: true,
    lookbehind: true,
    inside: {
      string: {
        pattern: /(^|[^^])(["'])(?:(?!\2)[^^]|\^[\s\S])*\2/,
        lookbehind: true,
      },
      keyword: Prism.languages.parser.keyword,
      variable: Prism.languages.parser.variable,
      function: Prism.languages.parser.function,
      boolean: /\b(?:true|false)\b/,
      number: /\b(?:0x[a-f\d]+|\d+\.?\d*(?:e[+-]?\d+)?)\b/i,
      escape: Prism.languages.parser.escape,
      operator: /[~+*\/\\%]|!(?:\|\|?|=)?|&&?|\|\|?|==|<[<=]?|>[>=]?|-[fd]?|\b(?:def|eq|ge|gt|in|is|le|lt|ne)\b/,
      punctuation: Prism.languages.parser.punctuation,
    },
  },
});
Prism.languages.insertBefore(
  'inside',
  'punctuation',
  {
    expression: Prism.languages.parser.expression,
    keyword: Prism.languages.parser.keyword,
    variable: Prism.languages.parser.variable,
    function: Prism.languages.parser.function,
    escape: Prism.languages.parser.escape,
    'parser-punctuation': {
      pattern: Prism.languages.parser.punctuation,
      alias: 'punctuation',
    },
  },
  Prism.languages.parser['tag'].inside['attr-value']
);
