code: function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) {
    let flattenSpans = mode.flattenSpans
    if (flattenSpans == null) flattenSpans = cm.options.flattenSpans
    let curStart = 0, curStyle = null
    let stream = new StringStream(text, cm.options.tabSize, context), style
    let inner = cm.options.addModeClass && [null]
    if (text == "") extractLineClasses(callBlankLine(mode, context.state), lineClasses)
    while (!stream.eol()) {
      if (stream.pos > cm.options.maxHighlightLength) {
        flattenSpans = false
        if (forceToEnd) processLine(cm, text, context, stream.pos)
        stream.pos = text.length
        style = null
      } else {
        style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses)
      }
      if (inner) {
        let mName = inner[0].name
        if (mName) style = "m-" + (style ? mName + " " + style : mName)
      }
      if (!flattenSpans || curStyle != style) {
        while (curStart < stream.start) {
          curStart = Math.min(stream.start, curStart + 5000)
          f(curStart, curStyle)
        }
        curStyle = style
      }
      stream.start = stream.pos
    }
    while (curStart < stream.pos) {
      // Webkit seems to refuse to render text nodes longer than 57444
      // characters, and returns inaccurate measurements in nodes
      // starting around 5000 chars.
      let pos = Math.min(stream.pos, curStart + 5000)
      f(pos, curStyle)
      curStart = pos
    }
  }
docs: Run the given mode's parser over a line, calling f for each token.