Кто чем пользуется для реализации парсеров для .net? Почему выбрали именно это, какие плюсы, минусы, подводные камни?
Грамматика простая, поэтому важно удобство. Расширяемость (рекламируют у пакратов такую возможность же) — плюс, но пока я все равно не знаю, как ее заиспользовать. Пока склоняюсь к Irony, потому как ее рекламировал Кирилл Осенков.
Гуглить умею.
Спасибо.
Здравствуйте, Mr.Cat, Вы писали:
MC>Кто чем пользуется для реализации парсеров для .net? Почему выбрали именно это, какие плюсы, минусы, подводные камни?
Когда-то давно в 2006-м году понадобилось для очень простого DSL-я, решил использовать Coco/R. Выбор в общем-то был только между ним и ANTLR, выбрал Coco/R потому что показался проще. Плюс в простоте, пожалуй — написал грамматику, получил файлы сканнера и парсера. Минус — я немного менял шаблон парсера, учитывая мою специфику, потому что версия по умолчанию получилась довольно медлительной. Ну, и в плане удобства это просто суровый рабочий инструмент без IDE — написал грамматику, запустил, получил классы. Подводный камень — годится только для LL(k) грамматик, у меня была LL(1).
Здравствуйте, Mr.Cat, Вы писали:
MC>Кто чем пользуется для реализации парсеров для .net? Почему выбрали именно это, какие плюсы, минусы, подводные камни? MC>Грамматика простая, поэтому важно удобство. Расширяемость (рекламируют у пакратов такую возможность же) — плюс, но пока я все равно не знаю, как ее заиспользовать. Пока склоняюсь к Irony, потому как ее рекламировал Кирилл Осенков.
А мне так и непонятно, в чем фишка Irony. По-моему проще в виде EBNF все описать.
Если опыта с генерилками не было, то я бы выбирал то, что удобнее + то, что более или менее широко используется. По Coco/R ИМХО тут многие подскажут.
Здравствуйте, VladD2, Вы писали: VD>А объем? И вообще грамматика уже есть (т.е. есть спецификация языка) или речь идет о разработке своего языка?
Речь идет об s-выражениях сперва, а дальше как получится. Т.е. по идее грамматика небольшая.
Здравствуйте, Mr.Cat, Вы писали:
VD>>А объем? И вообще грамматика уже есть (т.е. есть спецификация языка) или речь идет о разработке своего языка? MC>Речь идет об s-выражениях сперва,
А зачем для этого вообще какой-то парсер? Парсер S-выражений пришется за час вручную.
MC>а дальше как получится.
Не понял.
MC>Т.е. по идее грамматика небольшая.
Тогда все равно. Для сложной грамматики я бы посоветовал ANTLR. А так подойдет любой LL-построитель парсеров. LR лучше не брать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Воронков Василий, Вы писали: ВВ>А мне так и непонятно, в чем фишка Irony. По-моему проще в виде EBNF все описать. ВВ>Если опыта с генерилками не было, то я бы выбирал то, что удобнее + то, что более или менее широко используется. По Coco/R ИМХО тут многие подскажут.
Из генерилок юзал antlr, из негенерилок — parsec. Сейчас интересуюсь общественным мнением.
Тут, я смотрю, в почете все-таки генераторы: antlr, coco/r — мне них не нравится то, что они как-то плохо, на мой взгляд, уживаются с visual studio. Т.е. чего бы мне хотелось в идеале — чтобы в проект было добавлено (и в сурс-контроле лежало) только описание грамматики, а код генерился бы при сборке, тогда как солюшены в vs ориентированы на добавление в них исходников именно на шарпе (vb, f#, нужное подчеркнуть).
Здравствуйте, Mr.Cat, Вы писали:
ВВ>>А мне так и непонятно, в чем фишка Irony. По-моему проще в виде EBNF все описать. ВВ>>Если опыта с генерилками не было, то я бы выбирал то, что удобнее + то, что более или менее широко используется. По Coco/R ИМХО тут многие подскажут. MC>Из генерилок юзал antlr, из негенерилок — parsec. Сейчас интересуюсь общественным мнением. MC>Тут, я смотрю, в почете все-таки генераторы: antlr, coco/r — мне них не нравится то, что они как-то плохо, на мой взгляд, уживаются с visual studio. Т.е. чего бы мне хотелось в идеале — чтобы в проект было добавлено (и в сурс-контроле лежало) только описание грамматики, а код генерился бы при сборке, тогда как солюшены в vs ориентированы на добавление в них исходников именно на шарпе (vb, f#, нужное подчеркнуть).
При желании можно сделать и так. Для таких вещей в студии есть custom build actions. Написать собственный build action для файлов *.atg задача не очень трудоемкая в принципе. В итоге уровень юзабилити будет примерно тот же, что и с типизированными датасетами какими-нибудь или файлами ресурсов.
Здравствуйте, VladD2, Вы писали:
VD>>>А зачем для этого вообще какой-то парсер? Парсер S-выражений пришется за час вручную. MC>>Я ленивый VD>Дорогая лень. Написать парсер S-выражений проще чем наладить работу большинства генераторов парсеров.
Да, но когда работа уже налажена, то с генератором все же проще. Так что вполне нормальная инвестиция времени для будущих задач, если еще что-нибудь парсить придется.
Здравствуйте, Воронков Василий, Вы писали: ВВ>При желании можно сделать и так. Для таких вещей в студии есть custom build actions.
И в билд-экшене вызывать какой-нить хитрый мейк, который скомпилит и файл проекта поправит? Ну если часто не менять грамматику — то более-менее по идее. А если msbuild попробовать, он ведь какой-то кастомизируемый, как он там с солюшенами взаимодействует?
Здравствуйте, Mr.Cat, Вы писали:
MC>Здравствуйте, Воронков Василий, Вы писали: ВВ>>При желании можно сделать и так. Для таких вещей в студии есть custom build actions. MC>И в билд-экшене вызывать какой-нить хитрый мейк, который скомпилит и файл проекта поправит? Ну если часто не менять грамматику — то более-менее по идее. А если msbuild попробовать, он ведь какой-то кастомизируемый, как он там с солюшенами взаимодействует?
Гм, не совсем. Мейк тут вообще ну нужен. И частое изменение грамматика здесь, мне кажется, не причем. CoCo/R все же довольно быстро работает.
Я имею в виду ту модель, которую предлагает сама студия. Вот ты создал файл с ресурсами. У него есть билд-акшин, который включен по умолчанию. Даже в проекте видно, что есть определение ресурса, а под ним, под "плюсиком", прячется автоматически генерируемый файл с кодом. Поменял ресурс — файл с кодом автоматически перегенерился. И никаких изменений в проект делать не нужно.
Здесь будет аналогично. У тебя есть EBNF-описание. Под ним прячется сгенерированный код. Поменял — и тут же в дизайн-тайме код перегенерился. И все.
Надо будет правда немножко подправить Кокор, правда совсем чуть-чуть:
— Сделать так, чтобы он генерил все в один файл, а не два (Parser+Scanner)
— Избавиться от шаблонов парсера и сканнера (parser.frame, scanner.frame). Они по большому счету не нужны.
— Поменять сами шаблоны (названия классов и пр-ва имен должны формироваться на основе .atg-файла, классы должны быть partial, репорты об ошибках — через partial-методы).
В общем и целом работы на пару часов от силы. В итоге получится как раз "родное" с т.з. идеологии студии решение.
Здравствуйте, Воронков Василий, Вы писали: ВВ>Я имею в виду ту модель, которую предлагает сама студия. Вот ты создал файл с ресурсами. У него есть билд-акшин, который включен по умолчанию. Даже в проекте видно, что есть определение ресурса, а под ним, под "плюсиком", прячется автоматически генерируемый файл с кодом. Поменял ресурс — файл с кодом автоматически перегенерился. И никаких изменений в проект делать не нужно. ВВ>Здесь будет аналогично. У тебя есть EBNF-описание. Под ним прячется сгенерированный код. Поменял — и тут же в дизайн-тайме код перегенерился. И все. ВВ>Надо будет правда немножко подправить Кокор, правда совсем чуть-чуть: ВВ>- Сделать так, чтобы он генерил все в один файл, а не два (Parser+Scanner) ВВ>- Избавиться от шаблонов парсера и сканнера (parser.frame, scanner.frame). Они по большому счету не нужны. ВВ>- Поменять сами шаблоны (названия классов и пр-ва имен должны формироваться на основе .atg-файла, классы должны быть partial, репорты об ошибках — через partial-методы). ВВ>В общем и целом работы на пару часов от силы. В итоге получится как раз "родное" с т.з. идеологии студии решение.
О, по идее, мне этого и хочется. Где можно поподробнее почитать про такое управление генерацией кода в студии?
Здравствуйте, AndrewVK, Вы писали:
ВВ>>А каких, например? AVK>Строгая типизация
Тут неясно. А в чем проблемы с типизацией у Кокора? Или ты имеешь в виду отсутствие всяких интеллисенсов при редактировании atg?
Но с другой стороны DSL, предлагаемый Кокором, более подходит для описания грамматики, чем перегруженные операторы в шарпе ИМХО.
AVK>и отсутствие неудобоваримой мешанины из описания грамматики и семантического кода.
А он же сам AST генерит? Последнее, я так понимаю, прямо следствие того, что AST писать руками не надо.
Вообще мешанина, конечно, минус Кокора. Но мне казалось, что под вкусностями понимаются какие-то дополнительные фишки Irony.
Здравствуйте, Mr.Cat, Вы писали:
MC>Тут, я смотрю, в почете все-таки генераторы: antlr, coco/r — мне них не нравится то, что они как-то плохо, на мой взгляд, уживаются с visual studio. Т.е. чего бы мне хотелось в идеале — чтобы в проект было добавлено (и в сурс-контроле лежало) только описание грамматики, а код генерился бы при сборке, тогда как солюшены в vs ориентированы на добавление в них исходников именно на шарпе (vb, f#, нужное подчеркнуть).
Тут посоветовали уже написать Custom Build Action. Наверное, это самое правильное решение, мы на проекте использовали менее правильное, но и менее трудоёмкое — просто добавили в проект pre-build event, который вызывает Coco.exe и перед каждой сборкой проекта генерит .cs файлы сканнера/парсера. Сами .cs файлы включены в .csproj, но в VSS не зачекинены.
Решение простое, но, как и любое решение с кодогенерацией, не нравится мне тем, что кто-то случайно может зачекинить сгенерированные файлы в VSS, а им там и правда не место. С другой стороны, и Custom Build Action от этого не спасёт.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Да, но когда работа уже налажена, то с генератором все же проще. Так что вполне нормальная инвестиция времени для будущих задач, если еще что-нибудь парсить придется.
А уверен, что придется? Обычно те кто парсит S-выражения больше ничего не парсят.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mr.Cat, Вы писали:
MC>Тут, я смотрю, в почете все-таки генераторы: antlr, coco/r — мне них не нравится то, что они как-то плохо, на мой взгляд, уживаются с visual studio. Т.е. чего бы мне хотелось в идеале — чтобы в проект было добавлено (и в сурс-контроле лежало) только описание грамматики, а код генерился бы при сборке, тогда как солюшены в vs ориентированы на добавление в них исходников именно на шарпе (vb, f#, нужное подчеркнуть).
Скачай проект R#, погляди как там сделана интеграция со студией (там использовался CocoR).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mr.Cat, Вы писали:
MC>О, по идее, мне этого и хочется. Где можно поподробнее почитать про такое управление генерацией кода в студии?
На фиг она тебе не упала. Тебе достаточно иметь castom action который можно добавить в любой проект. Ну, а генерируемые файлы добавляются один раз вручную.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
ВВ>>Да, но когда работа уже налажена, то с генератором все же проще. Так что вполне нормальная инвестиция времени для будущих задач, если еще что-нибудь парсить придется.
VD>А уверен, что придется? Обычно те кто парсит S-выражения больше ничего не парсят.
Не знаю, может, просто текущая задача по работе такая или язык запросов с подобной нотаций. У запросов к AD, например, синтаксис запросов — почти S-выражения.
А вообще "парсить парсит S-выражения" понятия весьма расплывчатое. А при рукопашной реализации парсера больше возни будет ИМХО не со "скобочками", а с токенизацией. Парсить те же float-ы по стандарту и проч. Так что за час можно и не управиться.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Не знаю, может, просто текущая задача по работе такая или язык запросов с подобной нотаций. У запросов к AD, например, синтаксис запросов — почти S-выражения.
Ни у каких запросов синтаксис не может быть "почти S-выражения". Это можно (с огромной натяжкой) сказать про XML, разве что.
ВВ>А вообще "парсить парсит S-выражения" понятия весьма расплывчатое. А при рукопашной реализации парсера больше возни будет ИМХО не со "скобочками", а с токенизацией. Парсить те же float-ы по стандарту и проч. Так что за час можно и не управиться.
Токены можно с успехом выделить регекспами. Далее парсинг превращается в часовое занятие.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Mr.Cat, Вы писали:
MC>Здравствуйте, Воронков Василий, Вы писали: ВВ>>Я имею в виду ту модель, которую предлагает сама студия. Вот ты создал файл с ресурсами. У него есть билд-акшин, который включен по умолчанию. Даже в проекте видно, что есть определение ресурса, а под ним, под "плюсиком", прячется автоматически генерируемый файл с кодом. Поменял ресурс — файл с кодом автоматически перегенерился. И никаких изменений в проект делать не нужно. ВВ>>Здесь будет аналогично. У тебя есть EBNF-описание. Под ним прячется сгенерированный код. Поменял — и тут же в дизайн-тайме код перегенерился. И все. ВВ>>Надо будет правда немножко подправить Кокор, правда совсем чуть-чуть: ВВ>>- Сделать так, чтобы он генерил все в один файл, а не два (Parser+Scanner) ВВ>>- Избавиться от шаблонов парсера и сканнера (parser.frame, scanner.frame). Они по большому счету не нужны. ВВ>>- Поменять сами шаблоны (названия классов и пр-ва имен должны формироваться на основе .atg-файла, классы должны быть partial, репорты об ошибках — через partial-методы). ВВ>>В общем и целом работы на пару часов от силы. В итоге получится как раз "родное" с т.з. идеологии студии решение.
MC>О, по идее, мне этого и хочется. Где можно поподробнее почитать про такое управление генерацией кода в студии?
Здравствуйте, Mr.Cat, Вы писали:
MC>Кто чем пользуется для реализации парсеров для .net? Почему выбрали именно это, какие плюсы, минусы, подводные камни? MC>Грамматика простая, поэтому важно удобство. Расширяемость (рекламируют у пакратов такую возможность же) — плюс, но пока я все равно не знаю, как ее заиспользовать. Пока склоняюсь к Irony, потому как ее рекламировал Кирилл Осенков.
Вот, кстати, хорошая причина по рекламировать наш новый макрос PEG-парсер (исходники доступны здесь).
Описание парсера объявляется прямо внутри проекта в мета-тарибуте, в виде PEG. Вот пример калькулятора реализованного на базе данного макроса: CalcParser.n
using Nemerle.Peg;
using Nemerle;
using System.Collections.Generic;
namespace Parsers
{
[PegGrammar(start,
grammar
{
any = ['\u0000'..'\uFFFF'];
digit = ['0'..'9']+;
spaces = ' '*;
num : int = digit spaces;
unaryMinus : int = '-' spaces simplExpr;
parenthesesExpr : int = '(' spaces sumOrSub ')' spaces;
simplExpr : int = num / parenthesesExpr / unaryMinus;
mulOrDiv : int = simplExpr (('*' / '/') spaces simplExpr)*;
sumOrSub : int = mulOrDiv (('+' / '-') spaces mulOrDiv )*;
start : int = spaces sumOrSub !any;
})]
public class CalcParser : ParserBase[int]
{
//Requred for parser -------------------------------------------------------------------------------------------- private num(digit : NToken, _ : NToken) : int
{
int.Parse(digit.GetText())
}
private unaryMinus(_ : NToken, _ : NToken, simpleExpr : VToken[int]) : int
{
-simpleExpr.Value
}
private parenthesesExpr(_ : NToken, _ : NToken, simpleExpr : VToken[int], _ : NToken, _ : NToken) : int
{
simpleExpr.Value
}
// TODO: autogenerate this blockprivate simplExpr(simpleExpr : VToken[int]) : int
{
simpleExpr.Value
}
// TODO: end todoprivate start(_ : NToken, simpleExpr : VToken[int], _ : NToken) : int
{
simpleExpr.Value
}
private mulOrDiv(simpleExpr : VToken[int], lst : List[NToken * NToken * VToken[int]]) : int
{
DoOpHelper(simpleExpr, lst)
}
private sumOrSub(simpleExpr : VToken[int], lst : List[NToken * NToken * VToken[int]]) : int
{
DoOpHelper(simpleExpr, lst)
}
//End requred for parser -------------------------------------------------------------------------------------------- public this(text : string)
{
base(text);
}
private DoOpHelper(simpleExpr : VToken[int], lst : List[NToken * NToken * VToken[int]]) : int
{
def doOp(x : int, y : int, op : string) : int
{
match (op)
{
| ("*") => x * y
| ("/") => x / y
| ("+") => x + y
| ("-") => x - y
| _ => assert(false);
}
}
mutable r = simpleExpr.Value;
foreach ((opTok, _, secondTok) in lst)
r = doOp(r, secondTok.Value, opTok.GetText());
r
}
}
}