protected function parseStatements( $string )
    {
        $lines = explode( "\n", $string );
        $statements = array();
        $statement = null;

        foreach ( $lines as $line )
        {
            // Skip empty lines
            if ( trim( $line ) === '' )
            {
                continue;
            }

            // Check for line length
            $line = rtrim( $line );
            $echodLine = '"' . substr( $line, 0, 30 ) . '..."';
            if ( strlen( $line ) > 79 )
            {
                throw new arbitCommitParserException( "Too long line: $echodLine" );
            }

            if ( preg_match( '(^-\\x20
              (?# Type of statement )
                (?P<type>Refs|Fixed|Closed|Implemented|Documented|Tested)
              (?# Match optional bug number )
                (?:\\x20\\#(?P<bug>[1-9]+[0-9]*))?
              (?# Match required text line )
                (?::\\x20(?P<text>[\x20-\x7E]+))?
            $)x', $line, $match ) )
            {
                // Check if required text has been included in message
                if ( !isset( $match['text'] ) || empty( $match['text'] ) )
                {
                    throw new arbitCommitParserException(
                        "Textual description missing in line $echodLine"
                    );
                }

                // Check if bug number has been set for statements requiring a
                // bug number
                if ( in_array( $match['type'], array(
                        'Refs',
                        'Fixed',
                        'Closed',
                     ) ) )
                {
                    if ( !isset( $match['bug'] ) || empty( $match['bug'] ) )
                    {
                        throw new arbitCommitParserException(
                            "Missing bug number in line: $echodLine"
                        );
                    }
                }

                // Ensure no bug number has been provided for statements which
                // may not be used together with a bug number
                if ( in_array( $match['type'], array(
                        'Tested',
                     ) ) )
                {
                    if ( isset( $match['bug'] ) && !empty( $match['bug'] ) )
                    {
                        throw new arbitCommitParserException(
                            "Superflous bug number in line: $echodLine"
                        );
                    }

                    // Force bug to null, so we can use this variable later
                    $match['bug'] = null;
                }

                // Append prior statement to statement array
                if ( $statement !== null )
                {
                    $statements[] = $statement;
                }

                // Create new statement from data
                $statement = array(
                    'type' => str_replace( 'Closed', 'Fixed', $match['type'] ),
                    'bug'  => $match['bug'],
                    'text' => $match['text'],
                );
            }
            elseif ( preg_match( '(^  (?P<text>[\x20-\x7E]+)$)', $line, $match ) )
            {
                if ( $statement == null )
                {
                    // Each additional comment line has to be preceeded by a
                    // statement
                    throw new arbitCommitParserException(
                        "No statement precedes text line: $echodLine"
                    );
                }

                $statement['text'] .= ' ' . $match['text'];
            }
            else
            {
                throw new arbitCommitParserException(
                    "Invalid commit message: $echodLine"
                );
            }
        }

        return $statements;
    }