heredoc (RubyLexer)

    # File lib/ruby_lexer.rb, line 87
      def heredoc here # 63 lines
        _, eos, func, last_line = here

        indent  = (func & STR_FUNC_INDENT) != 0
        expand  = (func & STR_FUNC_EXPAND) != 0
        eos_re  = indent ? /[ \t]*#{eos}(\r?\n|\z)/ : /#{eos}(\r?\n|\z)/
        err_msg = "can't match #{eos_re.inspect} anywhere in "

        rb_compile_error err_msg if
          src.eos?

        if src.beginning_of_line? && src.scan(eos_re) then
          src.unread_many last_line # TODO: figure out how to remove this
          self.yacc_value = eos
          return :tSTRING_END
        end

        self.string_buffer = []

        if expand then
          case
          when src.scan(/#[$@]/) then
            src.pos -= 1 # FIX omg stupid
            self.yacc_value = src.matched
            return :tSTRING_DVAR
          when src.scan(/#[{]/) then
            self.yacc_value = src.matched
            return :tSTRING_DBEG
          when src.scan(/#/) then
            string_buffer << '#'
          end

          until src.scan(eos_re) do
            c = tokadd_string func, "\n", nil

            rb_compile_error err_msg if
              c == RubyLexer::EOF

            if c != "\n" then
              self.yacc_value = string_buffer.join.delete("\r")
              return :tSTRING_CONTENT
            else
              string_buffer << src.scan(/\n/)
            end

            rb_compile_error err_msg if
              src.eos?
          end

          # tack on a NL after the heredoc token - FIX NL should not be needed
          src.unread_many(eos + "\n") # TODO: remove this... stupid stupid stupid
        else
          until src.check(eos_re) do
            string_buffer << src.scan(/.*(\n|\z)/)
            rb_compile_error err_msg if
              src.eos?
          end
        end

        self.lex_strterm = [:heredoc, eos, func, last_line]
        self.yacc_value = string_buffer.join.delete("\r")

        return :tSTRING_CONTENT
      end