lib/core.js
function compileLanguage(language) {
  compileMode(language)

  // Compile a language mode, optionally with a parent.
  function compileMode(mode, parent) {
    var compiledKeywords = {}
    var terminators

    if (mode.compiled) {
      return
    }

    mode.compiled = true

    mode.keywords = mode.keywords || mode.beginKeywords

    if (mode.keywords) {
      if (typeof mode.keywords === 'string') {
        flatten('keyword', mode.keywords)
      } else {
        Object.keys(mode.keywords).forEach(function(className) {
          flatten(className, mode.keywords[className])
        })
      }

      mode.keywords = compiledKeywords
    }

    mode.lexemesRe = langRe(mode.lexemes || /\w+/, true)

    if (parent) {
      if (mode.beginKeywords) {
        mode.begin =
          '\\b(' + mode.beginKeywords.split(space).join(verticalBar) + ')\\b'
      }

      if (!mode.begin) {
        mode.begin = /\B|\b/
      }

      mode.beginRe = langRe(mode.begin)

      if (!mode.end && !mode.endsWithParent) {
        mode.end = /\B|\b/
      }

      if (mode.end) {
        mode.endRe = langRe(mode.end)
      }

      mode.terminatorEnd = source(mode.end) || ''

      if (mode.endsWithParent && parent.terminatorEnd) {
        mode.terminatorEnd +=
          (mode.end ? verticalBar : '') + parent.terminatorEnd
      }
    }

    if (mode.illegal) {
      mode.illegalRe = langRe(mode.illegal)
    }

    if (mode.relevance === undefined) {
      mode.relevance = 1
    }

    if (!mode.contains) {
      mode.contains = []
    }

    mode.contains = concat.apply(
      [],
      mode.contains.map(function(c) {
        return expandMode(c === 'self' ? mode : c)
      })
    )

    mode.contains.forEach(function(c) {
      compileMode(c, mode)
    })

    if (mode.starts) {
      compileMode(mode.starts, parent)
    }

    terminators = mode.contains
      .map(map)
      .concat([mode.terminatorEnd, mode.illegal])
      .map(source)
      .filter(Boolean)

    mode.terminators =
      terminators.length === 0
        ? {exec: execNoop}
        : langRe(terminators.join(verticalBar), true)

    function map(c) {
      return c.beginKeywords ? '\\.?(' + c.begin + ')\\.?' : c.begin
    }

    // Flatten a classname.
    function flatten(className, value) {
      var pairs
      var pair
      var index
      var length

      if (language[keyInsensitive]) {
        value = value.toLowerCase()
      }

      pairs = value.split(space)
      length = pairs.length
      index = -1

      while (++index < length) {
        pair = pairs[index].split(verticalBar)

        compiledKeywords[pair[0]] = [className, pair[1] ? Number(pair[1]) : 1]
      }
    }
  }

  // Create a regex for `value`.
  function langRe(value, global) {
    return new RegExp(
      source(value),
      'm' + (language[keyInsensitive] ? 'i' : '') + (global ? 'g' : '')
    )
  }

  // Get the source of an expression or string.
  function source(re) {
    return (re && re.source) || re
  }
}
function compileLanguage(language) {
  compileMode(language)

  // Compile a language mode, optionally with a parent.
  function compileMode(mode, parent) {
    var compiledKeywords = {}
    var terminators

    if (mode.compiled) {
      return
    }

    mode.compiled = true

    mode.keywords = mode.keywords || mode.beginKeywords

    if (mode.keywords) {
      if (typeof mode.keywords === 'string') {
        flatten('keyword', mode.keywords)
      } else {
        Object.keys(mode.keywords).forEach(function(className) {
          flatten(className, mode.keywords[className])
        })
      }

      mode.keywords = compiledKeywords
    }

    mode.lexemesRe = langRe(mode.lexemes || /\w+/, true)

    if (parent) {
      if (mode.beginKeywords) {
        mode.begin =
          '\\b(' + mode.beginKeywords.split(space).join(verticalBar) + ')\\b'
      }

      if (!mode.begin) {
        mode.begin = /\B|\b/
      }

      mode.beginRe = langRe(mode.begin)

      if (!mode.end && !mode.endsWithParent) {
        mode.end = /\B|\b/
      }

      if (mode.end) {
        mode.endRe = langRe(mode.end)
      }

      mode.terminatorEnd = source(mode.end) || ''

      if (mode.endsWithParent && parent.terminatorEnd) {
        mode.terminatorEnd +=
          (mode.end ? verticalBar : '') + parent.terminatorEnd
      }
    }

    if (mode.illegal) {
      mode.illegalRe = langRe(mode.illegal)
    }

    if (mode.relevance === undefined) {
      mode.relevance = 1
    }

    if (!mode.contains) {
      mode.contains = []
    }

    mode.contains = concat.apply(
      [],
      mode.contains.map(function(c) {
        return expandMode(c === 'self' ? mode : c)
      })
    )

    mode.contains.forEach(function(c) {
      compileMode(c, mode)
    })

    if (mode.starts) {
      compileMode(mode.starts, parent)
    }

    terminators = mode.contains
      .map(map)
      .concat([mode.terminatorEnd, mode.illegal])
      .map(source)
      .filter(Boolean)

    mode.terminators =
      terminators.length === 0
        ? {exec: execNoop}
        : langRe(terminators.join(verticalBar), true)

    function map(c) {
      return c.beginKeywords ? '\\.?(' + c.begin + ')\\.?' : c.begin
    }

    // Flatten a classname.
    function flatten(className, value) {
      var pairs
      var pair
      var index
      var length

      if (language[keyInsensitive]) {
        value = value.toLowerCase()
      }

      pairs = value.split(space)
      length = pairs.length
      index = -1

      while (++index < length) {
        pair = pairs[index].split(verticalBar)

        compiledKeywords[pair[0]] = [className, pair[1] ? Number(pair[1]) : 1]
      }
    }
  }

  // Create a regex for `value`.
  function langRe(value, global) {
    return new RegExp(
      source(value),
      'm' + (language[keyInsensitive] ? 'i' : '') + (global ? 'g' : '')
    )
  }

  // Get the source of an expression or string.
  function source(re) {
    return (re && re.source) || re
  }
}
function compileLanguage ( language ) { compileMode ( language ) // Compile a language mode, optionally with a parent. function compileMode ( mode , parent ) { var compiledKeywords = { } var terminators if ( mode . compiled ) { return } mode . compiled = true mode . keywords = mode . keywords || mode . beginKeywords if ( mode . keywords ) { if ( typeof mode . keywords === 'string' ) { flatten ( 'keyword' , mode . keywords ) } else { Object . keys ( mode . keywords ) . forEach ( function ( className ) { flatten ( className , mode . keywords [ className ] ) } ) } mode . keywords = compiledKeywords } mode . lexemesRe = langRe ( mode . lexemes || / \w+ / , true ) if ( parent ) { if ( mode . beginKeywords ) { mode . begin = '\\b(' + mode . beginKeywords . split ( space ) . join ( verticalBar ) + ')\\b' } if ( ! mode . begin ) { mode . begin = / \B|\b / } mode . beginRe = langRe ( mode . begin ) if ( ! mode . end && ! mode . endsWithParent ) { mode . end = / \B|\b / } if ( mode . end ) { mode . endRe = langRe ( mode . end ) } mode . terminatorEnd = source ( mode . end ) || '' if ( mode . endsWithParent && parent . terminatorEnd ) { mode . terminatorEnd += ( mode . end ? verticalBar : '' ) + parent . terminatorEnd } } if ( mode . illegal ) { mode . illegalRe = langRe ( mode . illegal ) } if ( mode . relevance === undefined ) { mode . relevance = 1 } if ( ! mode . contains ) { mode . contains = [ ] } mode . contains = concat . apply ( [ ] , mode . contains . map ( function ( c ) { return expandMode ( c === 'self' ? mode : c ) } ) ) mode . contains . forEach ( function ( c ) { compileMode ( c , mode ) } ) if ( mode . starts ) { compileMode ( mode . starts , parent ) } terminators = mode . contains . map ( map ) . concat ( [ mode . terminatorEnd , mode . illegal ] ) . map ( source ) . filter ( Boolean ) mode . terminators = terminators . length === 0 ? { exec : execNoop } : langRe ( terminators . join ( verticalBar ) , true ) function map ( c ) { return c . beginKeywords ? '\\.?(' + c . begin + ')\\.?' : c . begin } // Flatten a classname. function flatten ( className , value ) { var pairs var pair var index var length if ( language [ keyInsensitive ] ) { value = value . toLowerCase ( ) } pairs = value . split ( space ) length = pairs . length index = - 1 while ( ++ index < length ) { pair = pairs [ index ] . split ( verticalBar ) compiledKeywords [ pair [ 0 ] ] = [ className , pair [ 1 ] ? Number ( pair [ 1 ] ) : 1 ] } } } // Create a regex for `value`. function langRe ( value , global ) { return new RegExp ( source ( value ) , 'm' + ( language [ keyInsensitive ] ? 'i' : '' ) + ( global ? 'g' : '' ) ) } // Get the source of an expression or string. function source ( re ) { return ( re && re . source ) || re } }
Compile a language.
Compile a language .