Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2008.03.30;
Скачать: [xml.tar.bz2];

Вниз

Как лучше парсить строчки в кавычках?   Найти похожие ветки 

 
Like   (2008-02-16 07:58) [0]

Допустим хочу пропарсить код программы, найти все зарезервированные слова, но строчки мешают, потому, что в них тоже могут встречаться эти самые слова.

Как бы их на что-нибудь заменить, пропарсить текст, а потом поменть всё обратно?

Можно было бы заменть символы на такие "#123", но как потом отличишь, где раньше были строчки записаны, а тде такие?

В общем как это лучше сделать? Или может где есть уже готовый код или функция?


 
korstin ©   (2008-02-16 08:02) [1]

Используйте регулярные выражения. Один раз выучив их "язык" подобные проблемы решаются на раз.


 
БарЛог ©   (2008-02-16 09:59) [2]

korstin ©   (16.02.08 08:02) [1]
+1


 
Бегущий человек ©   (2008-02-16 14:51) [3]

Завести таблицу с двумя полями: в одно поле заносить строку, в другое - позиция идентификатора в тексте.


 
kaif ©   (2008-02-16 15:38) [4]

В строках, помеченных как комментарии тоже могут встречаться подобные слова. Так что проблема шире, чем ты думаешь.


 
Mystic ©   (2008-02-16 15:59) [5]

Решений несколько, в зависимости от того, какими инструментами пользоваться.

1. Писать все руками. Написать примитивную функцию
function GetLexem(): string;
которая бы возвращала идентификаторы, символы, строки и комментарии. Что конкретно сейчас находится в данной позиции можно определить в большинстве случаев по первому символу, в крайнем случае по двум-трем. В общем случае задача решаема примерно так:

 repeat
   Ch := GetChar();
 until Ch > " ";
 case Ch of
   "A".."Z","a".."z","_": Result := ReadIdentifier(Ch);
   """": Result := ReadString();
   "{": Result := ReadComment("{");
   "(": if PreviewChar() == "*" then
        begin
          GetChar();
          Result := ReadComment("(*");
        end;  
   else Result := Ch;

   
2. Использовать регулярные выражения. Это средний путь между 1 и 3 и лично мне он в данном случае не нравится. Конечно, можно использовать регулярное выражение по методу LEX, выдергивая по одной лексеме, но в этом случае LEX явно удобнее. Во-вторых для разбора многострочных строк (""" в питоне) и комментариев библиотека регулярных выражений должна поддерживать минималистическую операцию * (либо весьма нетривиальный синтаксис регулярного выражения). Да и многострочностью надо что-то решать... На раз решить не получится.

3. Если такие задачи возникают достаточно часто, то рекомендую обратить внимание на связку LEX + YACC. Лексический анализ (разбиение входа на лексемы) делается просто и быстро. При желании так же просто использовать синтаксический анализ.


 
korstin ©   (2008-02-17 05:24) [6]

[5] В описании трех методов было бы еще неплохо указать соотношение в скорости разбора


 
Like   (2008-02-17 06:59) [7]


> kaif ©   (16.02.08 15:38) [4]
>
> В строках, помеченных как комментарии тоже могут встречаться
> подобные слова. Так что проблема шире, чем ты думаешь.


Их то можно и заранее почикать.

В общем у меня другая складывается идея. Заменить все строчки на #001 #002 и т. д. и создать массив замен. Где первая строка - это то, что заменено на #001, вторая - на #002 и т. д. Только вот проблема, что делать с символом #, который время от времени встречается в паскалевском коде?

Есть ли какой-нибудь такой символ, который точно никогда там не встречается?


 
Семеныч   (2008-02-17 12:38) [8]

> Like   (16.02.08 07:58)  

> хочу пропарсить код программы

То есть, Вы пишете парсер. А разве парсер не знает своего текущего состояния? Знает. Значит, надо ввести в его синтаксис лексемы "строка" и "комментарий", которые он будет пропускать, ничего не делая.


 
Бегущий человек ©   (2008-02-17 16:42) [9]

>Like   (17.02.08 06:59) [7]
Символ ~(tilde)


 
Like   (2008-02-18 06:19) [10]


> Бегущий человек ©   (17.02.08 16:42) [9]
>
> >Like   (17.02.08 06:59) [7]
> Символ ~(tilde)
>


Абсолютно точно? А то вдруг где-нибудь там вылезет.


> Семеныч   (17.02.08 12:38) [8]
>
> > Like   (16.02.08 07:58)  
>
> > хочу пропарсить код программы
>
> То есть, Вы пишете парсер. А разве парсер не знает своего
> текущего состояния? Знает. Значит, надо ввести в его синтаксис
> лексемы "строка" и "комментарий", которые он будет пропускать,
>  ничего не делая.


Как выглядят лексемы? Я хочу заменить строчки на ~1<пробел> ~2<пробел> и т. д. Тогда можно будет легко всё позаменять. Сначала комменатрии, потом строчки, и т. д. Пока не останется всего одна запись, что-нибудь типа: ~10000<пробел>

Получится?


 
Vladix   (2008-02-18 08:58) [11]

В Delphi есть такой класс, как TParser, он собственно и занимается разбором того, что мы в редакторе Delphi пишем (к раскраске служебных слов в редакторе он имеет хоть и косвенное, но очень сильное отношение). Советую присмотреться к этому классу повнимательнее, а не изобретать велосипед ))))


 
Семеныч   (2008-02-18 10:29) [12]

Like   (18.02.08 06:19) [10]

> Я хочу заменить строчки

Если Вы это сделаете, то не называйте получившуюся программу парсером. Потому что это будет что угодно, но только не парсер.

> Как выглядят лексемы?

Примерно так:

<comment> ::= // <anychain> CRLF
 /* anychain */
 { anychain }
<string> ::= " <anychain> "


Вообще, если есть желание "заменить" и возникает вопрос "как выглядят лексемы", то начинать писать парсер надо с изучения хотя бы основ синтаксического анализа. Например, с этой статьи:
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=10


 
Mystic ©   (2008-02-18 11:07) [13]

> [5] В описании трех методов было бы еще неплохо указать
> соотношение в скорости разбора


А что тут сравнивать?

Написать все руками (1) будет самым производительным решением. Потому как даже если предположить, что производительнее (2) или (3), никто не помешает нам написать то же самое руками.

Если рассматривать ту схему, что я привел, то ее производительность зависит от рассматриваемого языка. Для таких языков, как Pascal, она будет сравнима с оптимальной, так как при разработке языка большое внимание было уделено простоте именно ручного разбора. Если брать другие языки, то производительность предложенной схемы очень  зависит от того, насколько лексемы пересекаются между собой. Если взять лексемы " и """, то для того, чтобы на первой кавычке определить, что это за лексема надо в общем случае заглянуть вперед на два символа. Иногда написания ручного лексического анализатора единственный путь, например когда язык сам позволяет определять новые типы лексем. Например, в некоторых реализациях пролога мы можем определить собственный оператор, его приоритет и ассоциативность.

Решение (3) производительнее той схемы, что привел я. Общий механизм примерно такой: например, у нас есть три лексемы [a-zA-Z_][a-zA-Z0-9_]*, :=, ;. Тогда LEX строит конечный автомат для разбора регулярного выражения
^([a-zA-Z_][a-zA-Z0-9_]*|:=|;).
Но тут у нас есть возможность заглянуть внутрь созданного конечного автомата, поэтому нам не составляет труда узнать, какой из вариантов альтернатив реализовался. Кроме того при совпадении выражений, выигрывает более длинное выражение, а затем более раннее, там что написав вначале лексемы if, then, а в конце [a-zA-Z_][a-zA-Z0-9_]* мы на моментально можем получить различие в ключевых словах и идентификаторах.

Решение (2) сложно оценить по производительности. Во-первых, в свое время существовало по крайней мере три алгоритма для разбора регулярных выражений (построение конечного автомата, параллельное движение по шаблону и строке, смешанный вариант). Во-вторых, надо еще придумать схему лексического анализа с использованием библиотеки регулярных выражений. Основной минус я уже называл: наиболее производительно было бы использовать одно регулярное выражение, но его во-первых, сложно строить, во-вторых для полученной лексемы надо заново проводить анализ того, что это за лексема. Использование же нескольких регулярных выражений все равно создает дополнительные проблемы: надо удалять из строки прочитанную лексему и т. п.


 
Running man   (2008-02-18 15:30) [14]

>Like   (18.02.08 06:19) [10]
Нигде. Попробуйте в Delphi приткнуть - получите сообщение  Illegal character



Страницы: 1 вся ветка

Форум: "Прочее";
Текущий архив: 2008.03.30;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.041 c
6-1183968995
Рацелий
2007-07-09 12:16
2008.03.30
Проблемы с геттерами


3-1193909601
Ega23
2007-11-01 12:33
2008.03.30
Помогите с запросом, уже всю баку сломал


15-1202559091
md10
2008-02-09 15:11
2008.03.30
какую СУБД выбрать выбрать


15-1202826005
arreke
2008-02-12 17:20
2008.03.30
AnimationEffect


15-1203214944
Tirael
2008-02-17 05:22
2008.03.30
вирус чтоли...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский