public IElementType captureHereDoc(boolean afterEmptyCloser){
  popState();
  final PerlHeredocQueueElement heredocQueueElement=heredocQueue.remove(0);
  final String heredocMarker=heredocQueueElement.getMarker();
  final int oldState=heredocQueueElement.getState();
  IElementType tokenType=HEREDOC;
  if (oldState == LEX_HEREDOC_WAITING_QQ) {
    tokenType=HEREDOC_QQ;
  }
 else   if (oldState == LEX_HEREDOC_WAITING_QX) {
    tokenType=HEREDOC_QX;
  }
  CharSequence buffer=getBuffer();
  int tokenStart=getTokenEnd();
  if (!afterEmptyCloser) {
    pushPreparsedToken(tokenStart++,tokenStart,TokenType.NEW_LINE_INDENT);
  }
  int bufferEnd=getBufferEnd();
  int currentPosition=tokenStart;
  int linePos=currentPosition;
  while (true) {
    while (linePos < bufferEnd && buffer.charAt(linePos) != '\n' && buffer.charAt(linePos) != '\r') {
      linePos++;
    }
    int lineContentsEnd=linePos;
    if (linePos < bufferEnd && buffer.charAt(linePos) == '\r') {
      linePos++;
    }
    if (linePos < bufferEnd && buffer.charAt(linePos) == '\n') {
      linePos++;
    }
    if (heredocMarker.isEmpty() && lineContentsEnd == currentPosition && linePos > lineContentsEnd) {
      if (currentPosition > tokenStart) {
        pushPreparsedToken(tokenStart,currentPosition,tokenType);
      }
      pushPreparsedToken(currentPosition,lineContentsEnd + 1,HEREDOC_END);
      if (!heredocQueue.isEmpty() && bufferEnd > lineContentsEnd + 1) {
        setTokenEnd(lineContentsEnd + 1);
        return captureHereDoc(true);
      }
 else {
        return getPreParsedToken();
      }
    }
 else     if (StringUtil.equals(heredocMarker,buffer.subSequence(currentPosition,lineContentsEnd))) {
      if (currentPosition > tokenStart) {
        pushPreparsedToken(tokenStart,currentPosition,tokenType);
      }
      pushPreparsedToken(currentPosition,lineContentsEnd,HEREDOC_END);
      return getPreParsedToken();
    }
 else     if (linePos == bufferEnd) {
      if (linePos > tokenStart) {
        pushPreparsedToken(tokenStart,linePos,tokenType);
      }
      return getPreParsedToken();
    }
    currentPosition=linePos;
  }
}

public IElementType captureHereDoc ( boolean afterEmptyCloser ) { popState ( ) ; final PerlHeredocQueueElement heredocQueueElement = heredocQueue . remove ( 0 ) ; final String heredocMarker = heredocQueueElement . getMarker ( ) ; final int oldState = heredocQueueElement . getState ( ) ; IElementType tokenType = HEREDOC ; if ( oldState == LEX_HEREDOC_WAITING_QQ ) { tokenType = HEREDOC_QQ ; } else if ( oldState == LEX_HEREDOC_WAITING_QX ) { tokenType = HEREDOC_QX ; } CharSequence buffer = getBuffer ( ) ; int tokenStart = getTokenEnd ( ) ; if ( ! afterEmptyCloser ) { pushPreparsedToken ( tokenStart ++ , tokenStart , TokenType . NEW_LINE_INDENT ) ; } int bufferEnd = getBufferEnd ( ) ; int currentPosition = tokenStart ; int linePos = currentPosition ; while ( true ) { while ( linePos < bufferEnd && buffer . charAt ( linePos ) != '\n' && buffer . charAt ( linePos ) != '\r' ) { linePos ++ ; } int lineContentsEnd = linePos ; if ( linePos < bufferEnd && buffer . charAt ( linePos ) == '\r' ) { linePos ++ ; } if ( linePos < bufferEnd && buffer . charAt ( linePos ) == '\n' ) { linePos ++ ; } if ( heredocMarker . isEmpty ( ) && lineContentsEnd == currentPosition && linePos > lineContentsEnd ) { if ( currentPosition > tokenStart ) { pushPreparsedToken ( tokenStart , currentPosition , tokenType ) ; } pushPreparsedToken ( currentPosition , lineContentsEnd + 1 , HEREDOC_END ) ; if ( ! heredocQueue . isEmpty ( ) && bufferEnd > lineContentsEnd + 1 ) { setTokenEnd ( lineContentsEnd + 1 ) ; return captureHereDoc ( true ) ; } else { return getPreParsedToken ( ) ; } } else if ( StringUtil . equals ( heredocMarker , buffer . subSequence ( currentPosition , lineContentsEnd ) ) ) { if ( currentPosition > tokenStart ) { pushPreparsedToken ( tokenStart , currentPosition , tokenType ) ; } pushPreparsedToken ( currentPosition , lineContentsEnd , HEREDOC_END ) ; return getPreParsedToken ( ) ; } else if ( linePos == bufferEnd ) { if ( linePos > tokenStart ) { pushPreparsedToken ( tokenStart , linePos , tokenType ) ; } return getPreParsedToken ( ) ; } currentPosition = linePos ; } }
captures heredoc document and returns appropriate token type
