Pull to refresh

Препроцессоры и метаязыки в программах исправления ошибок

Reading time 5 min
Views 5.7K
Компьютерная лингвистика очень консервативна, несмотря на огромное количество уже созданных программ, решающих весьма сложные задачи предварительной обработки целенаправленных языков (подобные программы редко используются в программах проверки орфографии). Далее на примере общепринятого «сложного» случая корректировки «ться» и «тся» я попытаюсь показать, как «консерватизм» программистов приводит к специфическому классу ошибок.

А. Реформатский, будучи весьма прозорливым лингвистом, писал, что существуют ошибки как результат неумелого преподавания в школе грамматики. Алпатов, человек язвительный, заметил, цитирую: «можно сказать, русская грамматика взяла за основу представления петербургских немцев о русском языке». Учитывая дефекты школьного преподавания и особенности психологии составителей грамматик, ться и тся остаются изгоями в компьютерных программах проверки орфографии.

Видимо, своей мрачной славе эти случаи обязаны также тем, что в грамматиках жестко рекомендуют «проверять» правильность написания вопросами «что делать» и «что делает», исключая иные способы. Конечно, если поступать рекомендованным образом, никакая алгоритмизация и последующая корректировка невозможны. Остается только «анаграмматический подход» (когда на выходе программы мы получаем несколько вариантов «исправленного» слова). Видимо, отсюда попытка разделить С.А. Крыловым программы на пуристские и лаксистские.

«Зацикленность» программистов, работающих в команде с профессиональными лингвистами на разборе предложения очевидно связана с недостаточным пониманием лингвистами принципов программирования и «навязыванием» лингвистических представлений программистам. И здесь уважаемый С. А. Крылов демонстрирует подобное — см пост на известном форуме. Это лингвистический взгляд, но не взгляд программиста, для которого важными остаются вопросы иного плана: возможно ли алгоритмизировать грамматическое правило или алгоритмизация невозможна, следует использовать «словарный» подход для проверки слова.
Правка ошибочного написания возвратных глаголов удивительно легка в 40 % (и более) случаев, если отказаться от «что делает, что делать», а понимать возвратный глагол именно так, как следует, по значению: собственно возвратное; взаимно-возвратное; безобъектно-возвратное; общевозвратное & etc. В этом случае задача исправления слова сводится к а) «препроцессорной» обработке фразы, слова; б) создания простейшего метаязыка, позволяющего использовать некие описания для «правил», и этот метаязык будет похожим на классический потоковый редактор, то есть хорошо известный класс программ.

Итак, пусть «топливом» для «препроцессора» у нас будет массив из семи (или меньше) последних букв слов на тся и ться (для примера берем словарь Зализняка). Если взять большее число букв, то «точность» увеличится, это очевидно.
Полученные данные мы разместим в массиве по принципу «елочка корнями в небо» — это оптимизирует и ускорит поиск, а также избавит от возможных ошибок (см. код).

Если кто-то рискнет повторить мой эксперимент со словарем Зализняка, то результат вряд ли удивит: в подобном массиве будет всего 3548 окончаний (т.е. семь или менее последних букв в слове), когда однозначно пишется ться или тся. Число окончаний, где возможно чередование «ться» / «тся» столь же мало — всего 407. Удивительно, правда? Ведь теперь достаточно «прогнать» через массивы проверяемое слово и мы на корню избавимся от неправильных написаний слов типа «кажетЬся», «придетЬся» и т.д. и пресловутых «анаграмм». (Для второго массива, когда возможны варианты написания, потребуется воспользоваться «метаязыком».)

Так выглядит массив «возможен только один вариант» (конечно, это несколько строк из 3548):

// «Елочка в небо»
Для ться — до разделителя ошибочное написание, после — правильное.
ящатся:: ящаться
яхатся:: яхаться
ятатся:: ятаться
ястся:: ясться
ыстся:: ысться
ызтся:: ызться
ртся:: рться
отся:: оться
зтся:: зться

Для тся — до разделителя ошибочное написание, после — правильное:

ящаються:: ящаются
ящаеться:: ящается
ридеться:: ридется
зеються:: зеются
зееться:: зеется
звяться:: звятся
звяться:: рутся
оються:: оются
оеться:: оется
ються:: ются

//Массив для случаев, когда невозможно определить правильное написание (для тся, но очевидно, что для ться следует лишь вставить мягкий знак)

яшится
ячится
ячатся
ушатся
учится
слятся
рщится
оится
нятся
нутся
ятся
ытся
утся
стся
ится
ется
атся

Для примера — простой код, позволяющий искать совпадения в базах:

string correction_verbs(string str) {
// Здесь нельзя использовать map, так как map автоматически сортирует массив
vector < pair < string, string > >data;
vector < pair < string, string > >::iterator it;
// Классы и функции настолько очевидны, что описывать их бессмысленно.
file_operations file_io; // это просто класс для чтения из файлов в массив
string_utilities str_ut; // это класс, где существует утилита replace_all
string first_str, second_str, separator;
// Получаем пути к файлам с данными и загружаем массив
string verbs = global::file_paths.find("verbs_cfg")->second;
data = file_io.readf_vector_pair(verbs, separator); 

for (it = data.begin(); it != data.end(); ++it) {
// Выводим графему после разделителя (может быть любым) и до разделителя
first_str = it->first; // неправильное написание
second_str = it->second; // правильное
// Поиск совпадений в строке
// Если найдено совпадение, то заменяем ться на тся (или наоборот)
if (str.find(second_str) != string::npos) {
str = str_ut.replace_all(str, second_str, first_str);
// Прекращаем работу функции
break;
}
}
// Очищаем массив
data.clear();
return str;
}


Несмотря на столь очевидное и часто используемое в программирование решение, например, при разборе искусственных языков, представленная на рынке лингвистическая программа Орфо (не самая неудачная, пожалуй, даже совершенная во многом) неспособна решить полноценно задачу ться/тся — у нее нет «препроцессора», вместо «препроцессора» используются все те же пресловутые анаграмматические алгоритмы «вычисления расстояний», с неизбежностью «заставляющие» Орфо предлагать какие-то безумные варианты правок.

Смотрим здесь: online.orfo.ru
Вводим фразу с ошибкой: «придеться исправить ошибку».
На выходе получаем, как и ожидалось, следующий пассаж: приодеться, придется, приметься, продеться, прибиться.
Выводы делайте сами.
(Пожалуй, достойный пример того, как лингвисты «прогнули» программистов, получив на выходе неполноценное и безграмотное решение.)

Посмотрим на работу вышеописанного препроцессора. В переменной str у нас будет слово «придеться». В массиве будут только возвратные глаголы «с однозначным написанием». На выходе мы получаем (программа ищет совпадения по последним буквам, начиная с вершины массива) слово, где ридеться однозначно заменяется на ридется (см базы данных, иных вариантов не существует). Если программа не найдет в массиве совпадений, то функция вернет слово без изменений. Разумеется, далее следует произвести проверку в базе «ться» / «тся», применяя некий набор описаний. Но о «метаязыках» в подобных лингвистических программах я напишу в следующем посте, чтобы сообщение не получилось громоздким.

P.S. Безусловно, «препроцессорная» обработка имеет свои недостатки, но программа «мыслит по-человечески», а на выходе все-таки более вменяемый результат.
Tags:
Hubs:
+18
Comments 10
Comments Comments 10

Articles