IPB
ЛогинПароль:

> ВНИМАНИЕ!

Прежде чем задать вопрос, смотрите FAQ.
Рекомендуем загрузить DRKB.

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

 
 Ответить  Открыть новую тему 
> Разбиение текста на блоки, (разделено)
сообщение
Сообщение #1





Группа: Пользователи
Сообщений: 9
Пол: Женский
Реальное имя: Настя

Репутация: -  0  +


Здрасте, я здесь новичок, так что не судите строго за вопросы.
У меня проблема связана с парсеровщиком. Нужно разбить текст на блоки (хотябы) и добавить эти блоки в таблицу (на сервере). На входе - текст вроде:
BEGIN bla-bla-bla
bla-bla-bla
END BEGIN;
Далее могут идти похожие блоки, но вместо BEGIN другие определенные слова.
Если есть какие-нибудь советы по такой разбивке, подскажите, буду очень благодарна.


PS В грамматиках я не очень, так что... unsure.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Бывалый
***

Группа: Пользователи
Сообщений: 206
Пол: Мужской

Репутация: -  3  +


Поскольку задача сформулирована очень обще, ответить толком трудновато. Если в общем случае текст имеет структуру вида
{ * } { * } { * }
где * - произвольный текст, а {} - пары некоторых ограничителей, и при этом между блоками нет никакого левого мусора, то задача упрощается. Если на самом деле все гораздо запутаннее, то...
Упрощенную задачу можно решать так:
Считываем из входного потока произвольный открывающий разделитель. Если это не он, то выдаем ошибку. А если он, то запоминаем его и читаем из входного потока текст, накапливая его в буфер. Как только мы натыкаемся на что-то, что не есть текст, смотрим: это что? ожидаемый закрывающий разделитель? Или какое-то левое служебное слово? Если левое, выдаем ошибку. Если это правильный разделитель, то кидаем содержимое буфера на сервер и возвращаемся в начало цикла, чтобы прочесть очередной произвольный открывающий разделитель. Вот пока и все. Немного сумбурно...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3





Группа: Пользователи
Сообщений: 9
Пол: Женский
Реальное имя: Настя

Репутация: -  0  +


Нет, мусора между блоками нет (в идеале). Проблема в том, что вместо ограничителя (char) стоит слово (string). Как проверить начинается ли строка с "зарезервированного" слова и заканчивается ли она "зарезервированным" словом - что в совокупности составляет блок, который мне нужен.

Ну например текст:

SING abc IS "Алфавит"
HEAD ('Упорядоченная последовательность символов')
END SING;

LOG adsdd IS "Измененный алфавит"
HEAD ('Последовательность символов')
END LOG;

Мне извесно, что этот текст (строка) содержит блоки, которые должны начинаться со слова SING или LOG и заканчиваться END SING; или END LOG; соответственно. Так вот, мне нужно взять по отдельности каждый блок и одновременно проверить их на правильность, т е чтобы на выходе не было результата вроде:

LOG adsdd IS "Измененный алфавит"
HEAD ('Упорядоченная последовательность символов')
END SING;


???

Сообщение отредактировано: Saraby -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


code warrior
****

Группа: Пользователи
Сообщений: 484
Пол: Мужской
Реальное имя: Славен

Репутация: -  8  +


Могу дать парсер строки, который способен разбивать строку на токены - числа, операторы, идентификаторы и терминальные символы, которые ты сам можешь указать (строковые константы не поддерживаются). Кроме того, парсер чувствителен к регистру (так и не добавил опции отключения сей протеворечивой функции)

Всё написано мною на делфи, протестено. cool.gif

А возможно использовать другой тип входных файлов? Например использовать XML формат.
И сбросить парсинг XML на DOM-инспектора. Это скорее всего лучший вариант. blum.gif

Вот пример использования парсера:

procedure TForm1.OnLexem(Sender: TLexParser; const Lexem: TLexem);
var S: string;
begin
// Lexem.Rec - это поле заполнено, в случае, если лексема является
// идентификатором или ключевым словом
// в других случаях придётся вытаскивать лексему используя Copy

S:=Copy(Line, Lexem.Pos, Lexem.Length); //вытаскиваем лексему
Memo1.Lines.Add(Format('%s %s',[S, LEXEMKIND[Lexem.Kind]]));
end;

procedure TForm1.Button1Click(Sender: TObject);
var Parser: TLexParser;
begin
Memo1.Clear;
//в конструкторе можно указать класс хэш-записи
// это нужно я не знаю для чего (на всякий случай эту опцию сохранил)
Parser:=TLexParser.Create;

Parser.EmitSpace:=false; //отключаем "узнавание" пробелов и табов
//(он их будет пропускать)
Parser.EmitEOL:=false; //отключам маркер конца строки

//ограничение на идентификаторы:
// использовать можно тока символы (и цыфры) или
// только знаки и скобки

Parser.AddWord('begin', wtKeyword); // добавляем "ключевое слово"
Parser.AddWord('end',wtKeyword);

Parser.AddWord('+', wtOperator); //добавляем оператор "плюс"
Parser.AddWord('and',wtOperator);

Line:=Edit1.Text;

Parser.ProcessLine(PChar(Line),Length(Line), OnLexem);

// есть перегруженная версия ProcessLine которая
// возвращает массив лексем

Parser.Free;
end;


Прикрепленные файлы
Прикрепленный файл  LexemParser.pas ( 33.22 килобайт ) Кол-во скачиваний: 398


--------------------
ИзВ ин ИтЕ зА нЕ рОв НЫй П оч ЕРк
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5





Группа: Пользователи
Сообщений: 9
Пол: Женский
Реальное имя: Настя

Репутация: -  0  +


спасиб, тока разобраться - не меньше, чем 0,5 литра надо. У меня еще вопрос - как реализовать проверку текста с помощью case..end - есть текст, мы бежим циклом по каждому символу и в конструкции case делаем определенные действия в зависимости от того, символ это алфавитный или цифра, или еще какая нибудь закорючка. Если будет пример такого кусочка кода - то отдельное тому спасибо.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Бывалый
***

Группа: Пользователи
Сообщений: 206
Пол: Мужской

Репутация: -  3  +


Типа так? (TP 6.0)
Program Example;

Var
f: file of char;
c: char;

Begin
Assign(f,'input.txt');
Reset(f);

While not EoF(f) do
begin
Read(f,c);

case c of
'0'..'9':
begin
{ It is a digit }
end;
'A'..'Z','a'..'z':
begin
{ It is a Latin letter }
end;
'$':
begin
{ It is an US Dollar }
end;
else begin
{ Any other Character }
end;
end;
end;

Close(f);
End.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7





Группа: Пользователи
Сообщений: 9
Пол: Женский
Реальное имя: Настя

Репутация: -  0  +


Спасибо тебе большое, именно это мне и надо было! good.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Бывалый
***

Группа: Пользователи
Сообщений: 206
Пол: Мужской

Репутация: -  3  +


Пожалуйста! smile.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9





Группа: Пользователи
Сообщений: 9
Пол: Женский
Реальное имя: Настя

Репутация: -  0  +


Цитата(Бродяжник @ 25.04.2006 14:35) *

Пожалуйста! smile.gif

А ета все можно только если текст находится в файле?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Бывалый
***

Группа: Пользователи
Сообщений: 206
Пол: Мужской

Репутация: -  3  +


А где он находится?
"Скажи, и я скажу..."
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11





Группа: Пользователи
Сообщений: 9
Пол: Женский
Реальное имя: Настя

Репутация: -  0  +


Цитата(Бродяжник @ 25.04.2006 15:30) *

А где он находится?
"Скажи, и я скажу..."

пусть ета просто строка s : string;
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гость






For i := 1 to Length(s) Do
Case s[i] Of
... { То же самое, что приводил Бродяжник }
End;
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13





Группа: Пользователи
Сообщений: 9
Пол: Женский
Реальное имя: Настя

Репутация: -  0  +


Спасибо, пока пищи для размышления много и свою первоначальную задачу я может быть решу, но конечно хотелось бы знать, если кто-то подобным занимался, есть ли более удобный, простой или "эргономичный" способ решения такого рода задач - я имею ввиду парсинг строк какого-либо кода?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14





Группа: Пользователи
Сообщений: 9
Пол: Женский
Реальное имя: Настя

Репутация: -  0  +


Цитата
Function StrOneSpace(s: String): String;
Функция удаляет из строки все лишние пробелы таким образом, что между остальными символами всегда остается только один пробел.


вот эта цитата из паскалевского фака по строкам, туда я вопрос задавать не решаюсь, но не задавать его тоже глупо! Поэтому вопрос такой: а если в строке есть символы #13 и их надо заменить на один пробел, причем неизвесно сколько #13 символов между словами, т.е. bla#13#32#32#13bla - короче надо заменить всю лабуду между словами bla bla на один пробел. Это как делается?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Гость






Ты об этом:
type
CharSet = set of char;

function OneDelim(s: string; delim: CharSet): string;
var i, k: byte;
begin

i := 1;
while i <= length(s) do begin
if s[ i ] in delim then begin
k := 0;
while s[i + k] in delim do inc(k);
delete(s, i, k);
insert(#32, s, i);
end;
inc(i);
end;
OneDelim := s;
end;


const
s: string = 'bla'#13#13#32#13#32'bla';
begin
writeln(s);
s := OneDelim(s, [#13, #32]);
writeln(s);
end.
?

Я только одного не пойму: если тема в разделе Дельфи, почему тебя вообще интересует Паскалевский FAQ? В Дельфях есть столько своих функций для работы со строками, что Паскалю и не снилось!!! Почему ты их не используешь?

Или тему перенести в "Паскаль", чтобы избежать путаницы в дальнейшем?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16





Группа: Пользователи
Сообщений: 9
Пол: Женский
Реальное имя: Настя

Репутация: -  0  +


Цитата(volvo @ 27.04.2006 17:11) *

Я только одного не пойму: если тема в разделе Дельфи, почему тебя вообще интересует Паскалевский FAQ? В Дельфях есть столько своих функций для работы со строками, что Паскалю и не снилось!!! Почему ты их не используешь?

Или тему перенести в "Паскаль", чтобы избежать путаницы в дальнейшем?

Да, я об этом, а тему переносить не надо, я просто, видимо, не все дельфовские функции знаю, а тут FAQ про паскалевские строки подвернулся, вот я и решила задать вопрос...sorry 10.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #17


code warrior
****

Группа: Пользователи
Сообщений: 484
Пол: Мужской
Реальное имя: Славен

Репутация: -  8  +


Цитата(Saraby @ 28.04.2006 14:53) *

я просто, видимо, не все дельфовские функции знаю

Набери в дельфийской справке String handling routines - он тебе полный список доступных функций расскажет.


--------------------
ИзВ ин ИтЕ зА нЕ рОв НЫй П оч ЕРк
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 23.09.2020 23:46
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name