Re[4]: Регулярное выражение для CS
От: regexp  
Дата: 22.11.09 22:40
Оценка:
Здравствуйте, Петрухин Эдуард, Вы писали:

ПЭ>Я тебя уверяю — регулярные выражения тебе не помогут, только зря потратишь время. Для примера: ты в исходном посте упомянул о вложенных классах. Это называется «самовложением». Самовложение — характерный признак контекстно-свободных грамматик (если бы отсутствовали самовложения, грамматика была бы автоматной). Никаким регулярным выражением самовложения тебе не одолеть.


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

Для "математика" это может звучать дико, как любой случай коверканья задачи под инструмент, но я оценил количество работы с парсером и сразу решил, что сделаю как можно более работоспособный регэксп, но не больше.
Re[2]: Регулярное выражение для CS
От: regexp  
Дата: 22.11.09 22:45
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>Никто не находил хороший регэксп для парсинга C#?


А>>Конкретно интересует разбор кода одного-единственного класса на методы, но со всеми потрохами, в т.ч. вложенными классами. Написал свой, но не уверен в качестве, лучше всего бы какой-нибудь активно используемый.


А>Мое любимое регулярное выражение на этот случай — такое. Код компилируется, результурующая сборка поднимается через reflection и исследуется.


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

Ладно, не в этом дело. Задача (выделенная болдом) через отражение не решается.
Re[3]: Регулярное выражение для CS
От: regexp  
Дата: 22.11.09 22:52
Оценка:
Здравствуйте, Niemand, Вы писали:

N>подобную фичу сделал пару недель назад на своем проекте, могу вот поделиться (чуть подредактировал):


N>
N>        public static SomeDataClass[] CompileContext(string filename)
N>        {
N>            try
N>            {
N>                // устанавливаем в режим c# 3.0, BCL 3.5, чтобы кушало лябмды и другое
N>                CSharpCodeProvider codeProvider = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion",
N>"v3.5" } });

N>                var result = codeProvider.CompileAssemblyFromFile(new CompilerParameters(new[] { 
N>                // какие либы здесь надо, а какие не надо - это индивидуйно, меняйте под себя
N>                "System.dll",
N>                "System.Data.dll",
N>                "System.Core.dll",
N>                "System.Web.Services.dll"}, Guid.NewGuid() + ".dll"), // конечно тут надо написать Path.GetTempFile()+".dll", но в моей задаче сойдет и так
N>                    filename);

N>                var assembly = result.CompiledAssembly; // получаем сборку (или исключение)

N>                var contextType = assembly.GetTypes().FirstOrDefault(t => t.BaseType == typeof(SomeMyBaseType)); 
N>                // если класс всего один можно заменить на 
N>                // var contextType = assembly.GetTypes().FirstOrDefault(); 

N>                // дальше вытягиваем список методов (у меня там идет другая логика, потому скопипастил с http://www.csharp-examples.net/get-method-names/ )
N>                MethodInfo[] methodInfos = typeof(MyClass).GetMethods(); // и добавляем .Select(m=>m.Name).ToList() или как-то так если надо только имена методов

N>                // ... ну и так дальше
N>


Извините, это поделка. Я выше приводил пример регэкспа — вот он как раз был написан по аналогичному случаю: для поиска в исходном коде референсов (заданных через атрибуты). Собственно, в плюсах есть аналог — прагма lib (ЕМНИП).

Однако, не в этом дело. Дело в том, что мне нужно

>Конкретно интересует разбор кода одного-единственного класса на методы


Предлагаю на этом закрыть тему отражения.
Re[3]: Регулярное выражение для CS
От: regexp  
Дата: 22.11.09 22:54
Оценка:
Здравствуйте, _DAle_, Вы писали:

_DA>Строго говоря, "регулярные выражения" в том виде, в котором они реализованы в большинстве языков/библиотек, выходят за рамки автоматных грамматик, но эта тема не для "Коллеги, улыбнитесь"


Спьяну ее сюда засунули, что ли? Весельчаки
Re[3]: Регулярное выражение для CS
От: Mr.Cat  
Дата: 22.11.09 23:03
Оценка:
Здравствуйте, regexp, Вы писали:
R>Парсер-шмарсер... Хотелось бы взять одно готовое выражение, отформатировать его (string.Format()) согласно прилагающейся инструкции и получить искомое.
Ты задачу штоле поподробнее опиши.
Но скорее всего регулярные выражения не самый удачный вариант — быстро накатаешь половину рабочей программы — потом напорешься на несколько хитрых частных случаев и будешь их до посинения отлаживать.
Re[4]: Регулярное выражение для CS
От: Кодт Россия  
Дата: 22.11.09 23:03
Оценка:
Здравствуйте, regexp, Вы писали:

_DA>>Строго говоря, "регулярные выражения" в том виде, в котором они реализованы в большинстве языков/библиотек, выходят за рамки автоматных грамматик, но эта тема не для "Коллеги, улыбнитесь"


R>Спьяну ее сюда засунули, что ли? Весельчаки


Исключительно от радости за невинность коллеги.
Однако, исправляю.
Перекуём баги на фичи!
Re[2]: Регулярное выражение для CS
От: Кодт Россия  
Дата: 22.11.09 23:06
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Ну, вот такой регэксп успешно ищет все атрибуты:

А также всё, что похоже на атрибуты, но закомментировано. А также — всё, что находится внутри методов и является не атрибутами, а вызовами оператора []... и так далее, и тому подобное.
Перекуём баги на фичи!
Re[3]: Регулярное выражение для CS
От: Кодт Россия  
Дата: 22.11.09 23:13
Оценка:
Здравствуйте, _DAle_, Вы писали:

_DA>Строго говоря, "регулярные выражения" в том виде, в котором они реализованы в большинстве языков/библиотек, выходят за рамки автоматных грамматик, но эта тема не для "Коллеги, улыбнитесь"


Вот, кстати, давно хотел выяснить: регекспы с расширениями (perl-compatible) дотягивают до КС-грамматики, или образуют какой-то промежуточный класс грамматик между КС и регулярными (автоматными)?
И если дотягивают — как можно построить регексп из, например, БНФ?
У меня есть подозрение, что в любом случае размер регекспа очень нелинейно (вплоть до экспоненты) зависит от размера БНФ.
Поэтому, даже если автор и родит регексп, он либо не влезет в память, либо наглухо загрузит интерпретатор.
Перекуём баги на фичи!
Re[3]: Регулярное выражение для CS
От: regexp  
Дата: 22.11.09 23:18
Оценка:
Здравствуйте, Кодт, Вы писали:

К>но закомментировано.


Уже было.

>А также — всё, что находится внутри методов и является не атрибутами, а вызовами оператора []...


Это предусмотренный случай ССЗБ. Ничто, конечно, не мешает передать атрибут в индексер, но он не для этого предназначен.

>и так далее, и тому подобное.


А именно?
Re[4]: Регулярное выражение для CS
От: regexp  
Дата: 22.11.09 23:23
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>Здравствуйте, regexp, Вы писали:

R>>Парсер-шмарсер... Хотелось бы взять одно готовое выражение, отформатировать его (string.Format()) согласно прилагающейся инструкции и получить искомое.
MC>Ты задачу штоле поподробнее опиши.

Да ерунда, обычный редактор:

[+] [foo]
[-] void bar(object o)
|   {
|        int i = 0;
|   }


С некоторой спецификой, правда, не имеющей отношения к теме.

MC>Но скорее всего регулярные выражения не самый удачный вариант — быстро накатаешь половину рабочей программы — потом напорешься на несколько хитрых частных случаев и будешь их до посинения отлаживать.
Re[4]: Регулярное выражение для CS
От: _DAle_ Беларусь  
Дата: 23.11.09 06:47
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, _DAle_, Вы писали:


_DA>>Строго говоря, "регулярные выражения" в том виде, в котором они реализованы в большинстве языков/библиотек, выходят за рамки автоматных грамматик, но эта тема не для "Коллеги, улыбнитесь"


К>Вот, кстати, давно хотел выяснить: регекспы с расширениями (perl-compatible) дотягивают до КС-грамматики, или образуют какой-то промежуточный класс грамматик между КС и регулярными (автоматными)?


Немножко про это есть в википедии http://en.wikipedia.org/wiki/Regular_expression#Patterns_for_non-regular_languages

К>И если дотягивают — как можно построить регексп из, например, БНФ?

К>У меня есть подозрение, что в любом случае размер регекспа очень нелинейно (вплоть до экспоненты) зависит от размера БНФ.
К>Поэтому, даже если автор и родит регексп, он либо не влезет в память, либо наглухо загрузит интерпретатор.
Re[5]: Регулярное выражение для CS
От: midcyber
Дата: 23.11.09 08:31
Оценка:
Здравствуйте, regexp, Вы писали:

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


Начать работать с парсерами легко! На примере C# версии 2.0:

1. Скачиваешь Coco/R
Тебе понадобятся файлы Coco.exe, Scanner.frame, Parser.frame, CSharp2.ATG, CS2Parser.cs

2. Редактируешь файл CSharp2.ATG (сделай копию на всякий случай) — это описание грамматики
Первая треть файла — между COMPILER CS2 и CHARACTERS (SCANNER DESCRIPTION) — обычный C# код, можешь заводить там свои переменные, списки и методы.
Вторая часть — между CHARACTERS и PRODUCTIONS — описание терминалов — меняй, только если у тебя язык отличается от C#
Третья часть — после PRODUCTIONS — собственно грамматика. Свой C# код надо писать в блоках (. .), после соответствующих частей правил разбора.

Для нашего примера:
Описание StructMemberDeclaration<Modifiers m> дополняешь (мои правки выделены курсивом):
StructMemberDeclaration<Modifiers m> (. TypeKind type; Operator op; string memberName; .)
...
VariableDeclarators ";"
| /* Property | Indexer | Method */
MemberName<out memberName>    (. Console.WriteLine(memberName); .)

Тут мы указываем парсеру при каждой встрече элемента MemberName сохранять (out) его имя в переменную memberName (объявлена в самом начале правила) и выводить ее в консоль

Меняешь описание MemberName на такое:
MemberName<out string name>
= ident    (. name = t.val; .)
[ "::" ident (. name += "::"+t.val; .) ]
  [ IF (la.kind == _lt && IsPartOfMemberName()) TypeArgumentList ]
  { IF (la.kind == _dot && Peek(1).kind == _ident)
    "." ident (. name += "."+t.val; .)
    [ IF (la.kind == _lt && IsPartOfMemberName()) TypeArgumentList ]
  }
.

Тут мы просим MemberName накопить в строку то, что нашел парсер (t.val — это текущий найденный парсером токен,
то есть для строки "Buffer.Close" будут последовательно найдены "Buffer", ".", "Close", соответственно сработают первая и последняя части правил)

3. Генерируешь исходники сканера/парсера (я делал в командной строке):
coco.exe CSharp2.ATG

(должно быть сообщение parser + scanner generated, 0 errors detected)
4. Собираешь все это вместе (как вызывать парсер из своего кода, смотри в CS2Parser.cs)
csc.exe CS2Parser.cs Scanner.cs Parser.cs

5. Проверяешь
CS2Parser.exe somesourcefile.cs

Должна получиться распечатка имен методов.

Когда разберешься, можешь переходить к сигнатурам (TypeArgumentList), конструкторам и тому подобному, потом к квалифицированным именам.
Для последнего придется написать в первой части файла какой-то простенький стек, который хранит имя класса на текущей глубине разбора.
Re[5]: Регулярное выражение для CS
От: Mr.Cat  
Дата: 23.11.09 10:20
Оценка: +1
Здравствуйте, regexp, Вы писали:
R>Да ерунда, обычный редактор:
R>
R>[+] [foo]
R>[-] void bar(object o)
R>|   {
R>|        int i = 0;
R>|   }
R>

Ну если нужны только подсветка, фолдинг и прочие нехитрые вещи — тогда погляди, как это сделано в vim или notepad++. Думаю, в итоге там все сводится к прогону разными регулярными выражениями с разными приоритетами: сперва комментарии выявляются (и внутри них больше ничего не подсвечивается), потом строки и т.п.
Re[5]: Регулярное выражение для CS
От: Кодт Россия  
Дата: 23.11.09 11:38
Оценка:
Здравствуйте, _DAle_, Вы писали:

К>>Вот, кстати, давно хотел выяснить: регекспы с расширениями (perl-compatible) дотягивают до КС-грамматики, или образуют какой-то промежуточный класс грамматик между КС и регулярными (автоматными)?


_DA>Немножко про это есть в википедии http://en.wikipedia.org/wiki/Regular_expression#Patterns_for_non-regular_languages


Как-то уж очень немножко
Я так понял, регекспы с обратными отсылками описывают контекстно-зависимые грамматики (наверно, не всевозможные, а некое подмножество?)
Например,
/ alfa (beta) gamma \1 delta /

Соответствуют правила вывода
Regex -> Use beta
Use X -> alfa X gamma X delta


Кстати, неутешительно для топикстартера: сопоставление регекспа с бэкреференсами — NP-полная задача, т.е. парсер выжрет время-память.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[6]: Регулярное выражение для CS
От: _DAle_ Беларусь  
Дата: 23.11.09 23:07
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, _DAle_, Вы писали:


К>>>Вот, кстати, давно хотел выяснить: регекспы с расширениями (perl-compatible) дотягивают до КС-грамматики, или образуют какой-то промежуточный класс грамматик между КС и регулярными (автоматными)?


_DA>>Немножко про это есть в википедии http://en.wikipedia.org/wiki/Regular_expression#Patterns_for_non-regular_languages


К>Как-то уж очень немножко

К>Я так понял, регекспы с обратными отсылками описывают контекстно-зависимые грамматики (наверно, не всевозможные, а некое подмножество?)

Я тут сразу рванул писать, что Back references не спасают даже от классического контекстно-свободного языка AnBn (ну в смысле ab, aabb, aaabbb, ...). Но потом, погуглив и поспрашивав в IRC, нашел, что, например, в perl 5.10 можно сейчас вроде бы написать /^(a(?1)?b)$/, и таким образом используя рекурсию победить эту проблему. Но с другой стороны контекстно-зависимый AnBnCn уже так с помощью backreferences и recursion не воспроизведешь.

В общем, вроде бы получается так..
Множество языков, которые описывают regexp c Back references, пересекается с контекстно-свободными языками.
Множество языков, которые описывают regexp с Back references и recursion, содержат в себе все контекстно-свободные, и сами содержатся в множестве контекстно-зависимых.
Это все может оказаться неправдой, но похоже на нее
Re[7]: Регулярное выражение для CS
От: Кодт Россия  
Дата: 24.11.09 10:09
Оценка:
Здравствуйте, _DAle_, Вы писали:

_DA>Я тут сразу рванул писать, что Back references не спасают даже от классического контекстно-свободного языка AnBn (ну в смысле ab, aabb, aaabbb, ...). Но потом, погуглив и поспрашивав в IRC, нашел, что, например, в perl 5.10 можно сейчас вроде бы написать /^(a(?1)?b)$/, и таким образом используя рекурсию победить эту проблему. Но с другой стороны контекстно-зависимый AnBnCn уже так с помощью backreferences и recursion не воспроизведешь.


_DA>Множество языков, которые описывают regexp c Back references, пересекается с контекстно-свободными языками.


А не с КЗ? /([A-Z]+)_(?1)_(?1)/ как представить в КС?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[8]: Регулярное выражение для CS
От: _DAle_ Беларусь  
Дата: 24.11.09 10:16
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, _DAle_, Вы писали:


_DA>>Я тут сразу рванул писать, что Back references не спасают даже от классического контекстно-свободного языка AnBn (ну в смысле ab, aabb, aaabbb, ...). Но потом, погуглив и поспрашивав в IRC, нашел, что, например, в perl 5.10 можно сейчас вроде бы написать /^(a(?1)?b)$/, и таким образом используя рекурсию победить эту проблему. Но с другой стороны контекстно-зависимый AnBnCn уже так с помощью backreferences и recursion не воспроизведешь.


_DA>>Множество языков, которые описывают regexp c Back references, пересекается с контекстно-свободными языками.


К>А не с КЗ? /([A-Z]+)_(?1)_(?1)/ как представить в КС?


Под пересекается я имел ввиду, что ни одно из множеств не содержит другое.
Re[6]: Регулярное выражение для CS
От: Au1  
Дата: 24.11.09 12:14
Оценка: -1
Здравствуйте, Mr.Cat, Вы писали:


MC>Ну если нужны только подсветка, фолдинг и прочие нехитрые вещи — тогда погляди, как это сделано в vim или notepad++. Думаю, в итоге там все сводится к прогону разными регулярными выражениями с разными приоритетами: сперва комментарии выявляются (и внутри них больше ничего не подсвечивается), потом строки и т.п.



Не прокатит по причине возможной вложенности одного в другое. Например:

/* ......... " ..../*...*/.... " ....... */..........."
и
".........../*...*/...".....".....*/........"

как ни парси регекспами, контрпример можно будет построить в общем случае.
Re[7]: Регулярное выражение для CS
От: Mr.Cat  
Дата: 25.11.09 11:11
Оценка:
Здравствуйте, Au1, Вы писали:
Au1>Не прокатит по причине возможной вложенности одного в другое. Например:
Au1>/* ......... " ..../*...*/.... " ....... */..........."
Au1>и
Au1>".........../*...*/...".....".....*/........"
В чем конкретно ты тут видишь проблему? Как, на твой взгляд, это распарсится регекспами? И как оно, на твой взгляд, должно распарситься? Я проблемы не вижу. Вот как парсит тутошний регексповый форматтер.
/* ......... " ..../*...*/.... " ....... */..........."

".........../*...*/...".....".....*/........"

VS парсит точно так же.

Au1>как ни парси регекспами, контрпример можно будет построить в общем случае.

Если речь идет о подсветке и фолдинге редакторе, то 100% корректной работы не нужно. Достаточно покрытия определенного процента ситуаций, я считаю.
Re[8]: Регулярное выражение для CS
От: Au1  
Дата: 25.11.09 12:41
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>
MC>/* ......... " ..../*...*/.... " ....... */..........."
MC>

MC>
MC>".........../*...*/...".....".....*/........"
MC>

MC>VS парсит точно так же.

Au1>>как ни парси регекспами, контрпример можно будет построить в общем случае.

MC>Если речь идет о подсветке и фолдинге редакторе, то 100% корректной работы не нужно. Достаточно покрытия определенного процента ситуаций, я считаю.

Возможно, пример не очень удачный. Давай попробую так:

MC>
MC>/* ......... " ..../*...*/.... " ....... */..........."
MC>

MC>
MC>".../* ......... " ..../*...*/.... " ....... */..........."
MC>

MC>
MC>"...".../* ......... " ..../*...*/.... " ....... */..........."
MC>

MC>
MC>"..."...".../* ......... " ..../*...*/.... " ....... */..........."
MC>


Если не трудно, приведи кусок местного кода, который различает эти ситуации. А именно, умеет понимать разницу между первыми тремя ситуациями. Может я не умею готовить регекспы, но с ходу не могу придумать, как различить эти ситуации. Зато умею это делать без регекспов — проходом по коду и запоминанием уровня вложенности и типа парной конструкции для каждого символа.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.