private function parseWithMode($raw_metar, $strict)
    {
        // prepare decoding inputs/outputs: (upper case, trim,
        // remove 'end of message', no more than one space)
        $clean_metar = trim(strtoupper($raw_metar));
        $clean_metar = preg_replace('#=$#', '', $clean_metar);
        $clean_metar = preg_replace('#[ ]{2,}#', ' ', $clean_metar).' ';
        $remaining_metar = $clean_metar;
        $decoded_metar = new DecodedMetar($clean_metar);
        $with_cavok = false;

        // call each decoder in the chain and use results to populate decoded metar
        foreach ($this->decoder_chain as $chunk_decoder) {
            try {
                // try to parse a chunk with current chunk decoder
                $decoded = $this->tryParsing($chunk_decoder, $strict, $remaining_metar, $with_cavok);

                // log any excception that would have occur at primary decoding
                if (array_key_exists('exception', $decoded)) {
                    $decoded_metar->addDecodingException($decoded['exception']);
                }

                // map obtained fields (if any) to the final decoded object
                $result = $decoded['result'];
                if ($result != null) {
                    foreach ($result as $key => $value) {
                        if ($value !== null) {
                            $setter_name = 'set'.ucfirst($key);
                            $decoded_metar->$setter_name($value);
                        }
                    }
                }

                // update remaining metar for next round
                $remaining_metar = $decoded['remaining_metar'];
            } catch (ChunkDecoderException $cde) {
                // log error in decoded metar
                $decoded_metar->addDecodingException($cde);

                // abort decoding if strict mode is activated, continue otherwise
                if ($strict) {
                    break;
                }

                // update remaining metar for next round
                $remaining_metar = $cde->getRemainingMetar();
            }

            // hook for report status decoder, abort if nil, but decoded metar is valid though
            if ($chunk_decoder instanceof ReportStatusChunkDecoder) {
                if ($decoded_metar->getStatus() == 'NIL') {
                    break;
                }
            }

            // hook for CAVOK decoder, keep CAVOK information in memory
            if ($chunk_decoder instanceof VisibilityChunkDecoder) {
                $with_cavok = $decoded_metar->getCavok();
            }
        }

        return $decoded_metar;
    }