<?php
header("Content-Type: text/plain");
mb_internal_encoding('utf-8');

// Текст: 
$text = <<<EOF
нет пробела после запятой,точки с запятой;восклицательного знака!вопросительного знака?двоеточия:
«жы» или «шы» написано с буквой ы,
в тексте есть слово «координально» или «сдесь», «зделал», «зделаю», «зделан»
в тексте есть слова а или но без запятой перед ними.
EOF
;

// Массив патернов поиска и описаний и исправлений ошибок
$regexpArray = array(
        array('regexp' => '/(\\S+)(,|;|!|[?]|:)(\\S+)/u', 'explain' => 'нет обязательного пробела после «.,!?;:»', 'replace' => '$1$2 $3'),
        array('regexp' => '/(\\S*)([ ]*)(\\S*)(ж|ш)ы(\\S*)([ ]*)(\\S*)/u', 'explain' => '«жи» или «ши» написано с буквой ы', 'replace' => '$1$2$3$4и$5$6$7'),
        array('regexp' => '/(координально)/u', 'explain' => 'орфографические ошибки в словах', 'replace' => 'кардинально'),
        array('regexp' => '/(сдесь)/u', 'explain' => 'орфографическая ошибка №1 в слове', 'replace' => 'здесь'),
        array('regexp' => '/(здела)(\\w+)/u', 'explain' => 'орфографическая ошибка №2 в слове', 'replace' => 'сдела'),
        array('regexp' => '/(\\S*)([^,])([ ])(но|а)(\\s)/u', 'explain' => 'союзы А или НО без запятой перед ними', 'replace' => '$1$2,$3$4$5')
        );

// Выводим кусок текста с ошибкой  
foreach ($regexpArray as $key => $value) {       
    
    if (preg_match_all($regexpArray[$key]['regexp'], $text, $result, PREG_SET_ORDER)) {
            
        echo "\nОшибка: {$regexpArray[$key]['explain']}\n";
            
        foreach ($result as $e) {
            echo "*{$e[0]}*\n";               
        }
    }    
}

// Исправляем ошибки в тексте
foreach ($regexpArray as $key => $value) {
    $text = preg_replace ($regexpArray[$key]['regexp'], $regexpArray[$key]['replace'], $text);
}
echo "\nИсправленный текст:\n{$text}";
?>
