   ^ \d*\.?\d+ (?:e[+-]?\d+)?  # decimal
 ///i
 
-HEREDOC    = /// ^ ("""|''') ([\s\S]*?) (?:\n[^\n\S]*)? \1 ///
+HEREDOC    = /// ^ ("""|''') (( [\s\S]*? ([^\\]|\\\\) )?) \1 ///
 
 OPERATOR   = /// ^ (
   ?: [-=]>             # function

      when "'"
        return 0 unless match = SIMPLESTR.exec @chunk
        string = match[0]
        @token 'STRING', @removeNewlines(string), 0, string.length
      when '"'
        return 0 unless string = @balancedString @chunk, '"'
        if 0 < string.indexOf '#{', 1
          @interpolateString string[1...-1], strOffset: 1, lexedLength: string.length
        else
          @token 'STRING', @removeNewlines(string), 0, string.length
      else
        return 0
    if octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test string

    if heredoc
      str.replace MULTILINER, '\\n'
    else
      # Trim leading and trailing whitespace, string includes quotes
      str.replace(/^(.)\s*\n\s*/, '$1')
         .replace(/\s*\n\s*(.)$/, '$1')
         .replace(/\s*\n\s*/g, ' ')

  # Constructs a string token by escaping quotes and newlines.
  makeString: (body, quote, heredoc) ->
