_annotatedText (iterator) {
    const schema = this._getSchema()
    const state = this.state
    const context = last(state.stack)
    /* istanbul ignore next */
    if (!context) {
      throw new Error('Illegal state: context is null.')
    }
    while (iterator.hasNext()) {
      var el = iterator.next()
      var text = ''
      /* istanbul ignore else */
      // Plain text nodes...
      if (el.isTextNode()) {
        text = this._prepareText(el.textContent)
        if (text.length) {
          // Note: text is not merged into the reentrant state
          // so that we are able to return for this reentrant call
          context.text = context.text.concat(text)
          context.offset += text.length
        }
      } else if (el.isCommentNode()) {
        // skip comment nodes
        continue
      } else if (el.isElementNode()) {
        const annoConverter = this._getConverterForElement(el, 'inline')
        // if no inline converter is found we just traverse deeper
        if (!annoConverter) {
          /* istanbul ignore next */
          if (!this.IGNORE_DEFAULT_WARNINGS) {
            console.warn('Unsupported inline element. We will not create an annotation for it, but process its children to extract annotated text.', el.outerHTML)
          }
          // this descends into children elements without introducing a new stack frame
          // and without creating an element.
          const iterator = this.getChildNodeIterator(el)
          this._annotatedText(iterator)
          continue
        }
        // reentrant: we delegate the conversion to the inline node class
        // it will either call us back (this.annotatedText) or give us a finished
        // node instantly (self-managed)
        var startOffset = context.offset
        const annoType = annoConverter.type
        const AnnoClass = schema.getNodeClass(annoType)
        if (!AnnoClass) {
          throw new Error(`No Node class registered for type ${annoType}.`)
        }
        let annoData = this._createNodeData(el, annoType)
        // push a new context so we can deal with reentrant calls
        const stackFrame = {
          path: context.path,
          offset: startOffset,
          text: '',
          annos: []
        }
        state.stack.push(stackFrame)
        // with custom import
        if (annoConverter.import) {
          state.pushContext(el.tagName, annoConverter)
          annoData = annoConverter.import(el, annoData, this) || annoData
          state.popContext()
        }
        // As opposed to earlier implementations we do not rely on
        // let the content be converted by custom implementations
        // as they do not own the content
        // TODO: we should make sure to throw when the user tries to
        if (AnnoClass.isInlineNode()) {
          this._customText(INVISIBLE_CHARACTER)
          // TODO: check if this is correct; after reading an inline,
          // we need to reset the lastChar, so that the next whitespace
          // does not get skipped
          state.lastChar = ''
        } else {
          // We call this to descent into the element
          // which could be 'forgotten' otherwise.
          // TODO: what if the converter has processed the element already?
          const iterator = this.getChildNodeIterator(el)
          this._annotatedText(iterator)
        }
        // ... and transfer the result into the current context
        state.stack.pop()
        context.offset = stackFrame.offset
        context.text = context.text.concat(stackFrame.text)
        // in the mean time the offset will probably have changed to reentrant calls
        const endOffset = context.offset
        annoData.start = {
          path: context.path.slice(0),
          offset: startOffset
        }
        annoData.end = {
          offset: endOffset
        }
        // merge annos into parent stack frame
        const parentFrame = last(state.stack)
        parentFrame.annos = parentFrame.annos.concat(stackFrame.annos, annoData)
      } else {
        console.warn('Unknown element type. Taking plain text.', el.outerHTML)
        text = this._prepareText(el.textContent)
        context.text = context.text.concat(text)
        context.offset += text.length
      }
    }
    // return the plain text collected during this reentrant call
    return context.text
  }
Internal function for parsing annotated text