Форум программистов, компьютерный форум, киберфорум
antikiler_
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

DELPHI. Класс Tparser. Часть I. Русские буквы и слова.

Запись от antikiler_ размещена 06.11.2012 в 17:33
Показов 16286 Комментарии 4
Метки delphi

Как известно, в Дельфи имеется служебный недокументированный класс TParser - лексический анализатор. Основное его предназначение это разбор *.dfm файлов Дельфи. Но он, так же может работать с любым текстом, при этом он разбирает его на свои лексемы - слова, числа(простые, вещественные), знаки препинания,служебные символы. Вот как он это делает

Нажмите на изображение для увеличения
Название: dfm.PNG
Просмотров: 1210
Размер:	82.9 Кб
ID:	1459
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
procedure TForm12.Button1Click(Sender: TObject);
var
  Stream: TmemoryStream;
  Parser: TParser;
  FBuffer: TBytes;
begin
   memo1.Lines.LoadFromFile('D:\Диск с\дельфи\Projects\lessons1\unit10.dfm');
  Stream := TMemoryStream.Create;
  Stream.WriteBuffer(AnsiString(Memo1.Text)[1], Length(Memo1.Text));
   Parser := TParser.Create(Stream);
  with Parser do
    try
      while Parser.Token <> toEof do
        begin
           if token = toWString then
                Memo2.Lines.Add(Parser.TokenWideString)
          else
           Memo2.Lines.Add(Parser.TokenString);
          NextToken;
        end;
    finally
      Stream.Free;
      Parser.Free;
    end; 
end;
Все бы хорошо, но есть маленький ньюанс (как оказалось - он там не один)). Русские слова он все разбирает по буквам. Он считает их как-бы "техническим" символами, если точнее он относит их к категории ctOther


Нажмите на изображение для увеличения
Название: rus.PNG
Просмотров: 992
Размер:	55.2 Кб
ID:	1460

но если символ показан в кодировке Unicod'a то все ок.

Нажмите на изображение для увеличения
Название: unicod.PNG
Просмотров: 912
Размер:	64.2 Кб
ID:	1461

Есть несколько решений как заставить TParser разбирать русские слова. Например можно склеивать их при разборе
Delphi
1
2
3
4
5
6
7
8
............. 
while Parser.token in ['А'..'я'] do
         begin
           s:=s + TokenString;
           NextToken;
         end;
  Memo2.Lines.Add(s);
..............
Недостаток такого метода, склеивает все слова в одно большое слово, если нет каких либо знаков препинания между словами. Пробел,символ #13 , символ #10 , являются внутренними разделителями и вытащить их через TParser - проблематично. Решить и это можно, но все как-то через...заднее место... Во общем, на мой взгляд, самое простое решение этой загвоздки - это добавить распознавание русских букв не как ctOther, а как и английские-ctLetterStart
Все делалось в Дельфи 2010.
  • Некорректное решение
И так, класс TParser находится в модуле Classes.pas, в каталоге Program Files (x86)\Embarcadero\RAD Studio\7.0\source\Win32\rtl\common. Делаем его копию(на всякий случай). Открываем его и переходим на строку 9576.
Нас интересует эти две строки
Delphi
1
2
 case Char(FBuffer[ABufPos - 1]) of
    'A'..'Z', 'a'..'z', '_': Result := ctLetterStart;
Заменяем на
Delphi
1
2
 case  Ansichar(FBuffer[ABufPos - 1]) of
    'A'..'Z', 'a'..'z', '_','А'..'Я', 'а'..'я','ё','Ё': Result := ctLetterStart;
Компилируем и сохраняем. Все, теперь наш Tparser работает с русскими словами

Нажмите на изображение для увеличения
Название: final.PNG
Просмотров: 809
Размер:	58.7 Кб
ID:	1458

Но это, ещё не все. TParser пока не может понять слова через дефис.

Нажмите на изображение для увеличения
Название: defis.PNG
Просмотров: 717
Размер:	62.2 Кб
ID:	1467

Если Вам такое не подходит, продолжаем "мучить" Classes.pas. Переходим на строку 9693. И изменяем строку
Delphi
1
while CharType(Q) in [ctLetterStart, ctLetterNumber, ctNumber] do
так
Delphi
1
while CharType(Q) in [ctLetterStart, ctLetterNumber, ctNumber,ctDash] do
Компилируем и сохраняем. Теперь наш Tparser работает с словами через дефис. Это кстати относится и к английским словам.

Нажмите на изображение для увеличения
Название: defis2PNG.PNG
Просмотров: 681
Размер:	55.6 Кб
ID:	1468

Вот и все. При данном изменении(напрямую), пока не наблюдалось каких-либо ошибок компилятора.
Способ, конечно не совсем правильный. Но делать класс от Tparser, и замещать его методы не получится, т.к. нам необходимо доступ к полям и методам в секции private, а это возможно только если дочерний класс находится в том же модуле, что и родительский класс. Можно скопировать полностью Tparser в другой модуль, изменить все необходимое, и пользоваться ним, что будет конечно гораздо правильнее.

Полезные ссылки:
Как работать с Tparser
Интерпретатор на коленке на основе TParser
Использование TParser
Недокументированный TParser
Простое использование TParser
Cинтаксический анализатор арифметических выражений на основе Tparser - а вот к этой статье Я вернусь во торой части, т.к. есть ошибки
Метки delphi
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 4
Комментарии
  1. Старый комментарий
    Аватар для snake32
    О! Как во время! Мне как раз парсер слов нужен для переноса на след строку если не помещается.
    Спасибо!
    Запись от snake32 размещена 06.11.2012 в 17:40 snake32 вне форума
  2. Старый комментарий
    Рад помочь .
    Запись от antikiler_ размещена 06.11.2012 в 17:50 antikiler_ вне форума
  3. Старый комментарий
    Аватар для Alex_pac
    Заменяем на

    case Ansichar(FBuffer[ABufPos - 1]) of
    'A'..'Z', 'a'..'z', '_','А'..'Я', 'а'..'я','ё','Ё': Result := ctLetterStart;
    Унаследоваться никак нельзя? обязательно исходники править?

    Однако сам по себе TParser использовать несколько неудобно ибо он для этого не предназначен. Лучше использовать регулярные выражения.
    Запись от Alex_pac размещена 10.11.2012 в 05:18 Alex_pac вне форума
  4. Старый комментарий
    Унаследоваться никак нельзя? обязательно исходники править?
    Все его методы объявленны как статические. А необходимая нам метод для правки
    Delphi
    1
    
    function CharType(var ABufPos: Integer): TCharType;
    находится в секции private,который в свою очередь использует поля из той же секции.
    Однако сам по себе TParser использовать несколько неудобно ибо он для этого не предназначен.
    Так и есть. Например слово может состоять из букв и цифр(!), но начинаться на букву или символ подчеркивания ( _ ), во общем как и индетификатор в дельфи.. Но при необходимой сноровки - это можно обойти...
    Лучше использовать регулярные выражения.
    Думаю, что все зависит от поставленной задачи и оптимальных методов ее достижения(чем проще - тем лучше, плюс -чем удобней)...
    Запись от antikiler_ размещена 12.11.2012 в 17:10 antikiler_ вне форума
 
Новые блоги и статьи
сукцессия 37. Внедрил дипсик в свой оркестр из ИИ. У него закончилось пространство чата, потому опубликую выводы из его работы здесь
anaschu 21.07.2026
==================================================================== КОНТЕКСТ: Моделирование микоризной сукцессии (AM → ECM) ==================================================================== . . .
сукцессия 36. Делаю прогоны модели около порога бифуркации (превращения эндо микоризы в экто микоризу)
anaschu 21.07.2026
СУКЦЕССИЯ МИКОРИЗ: КАК МАТЕМАТИКА ОБЪЯСНЯЕТ ПОДЗЕМНУЮ ВОЙНУ Мы привыкли думать, что лес — это деревья. А грибы — это то, что мы собираем в корзинку осенью. Но если заглянуть под землю, окажется,. . .
ИИ и человечность
kumehtar 21.07.2026
Забавно, что общаясь с ИИ, я замечаю, насколько он высказывается умно, и насколько верит в людей. Он умеет прощать. Он знает как отвечать не обесценивая опыт других людей, даже если сам не верит. Он. . .
Нейтральные знания ..., ... чистая наука. Пока что-то проходит модерацию на Хабре, стоит развить мысль ...
Hrethgir 20.07.2026
К таким радикальным взглядам я конечно в той публикации не приходил, но чтобы скоротать вечер, решил углубиться немного. 1. Почему показания термометра заряжены целью? Цель заложена в самом. . .
Установка нескольких штампов электронной подписи в строго определенных местах файла docx
ВладимирСамохин 19.07.2026
(В!) Работа с Электронной подписью - это неотъемлемая часть современного документооборота. Но что делать, если нужно поставить несколько штампов электронной подписи в строго определенных местах. . .
сукцессия 35. Научная статья о проделанной работе
anaschu 19.07.2026
Написал в формате латекс и пдф
Вангую, что это не пройдёт модерацию, и на неделе я запущу свой сервер.
Hrethgir 19.07.2026
Эта публикация сейчас в песочнице и ждёт приглашения. https:/ / habr. com/ ru/ sandbox/ 295048/ По ссылке 403. Не очень информативно такую ссылку постить. Запись от Usaga размещена Сегодня в 06:46 . . .
сукцессия 33. открытые вопросы от клауде
anaschu 19.07.2026
"Что накопилось за эту часть А — тринадцать правок, из которых шесть пришли из ваших вопросов и каждая оказалась реальной ошибкой, а не калибровкой: односторонний симбиоз, отсутствующий листопад,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru