Re[7]: Реализация парсеров
От: Воронков Василий Россия  
Дата: 01.03.10 10:54
Оценка: 14 (1)
Здравствуйте, Mr.Cat, Вы писали:

MC>О, по идее, мне этого и хочется. Где можно поподробнее почитать про такое управление генерацией кода в студии?


Например, тут: http://aviadezra.blogspot.com/2008/11/developing-custom-tool-for-visual.html
Официальное название: Visual Studio Custom Build Tool.
Вообще в гугле много информации и готовых примеров.
Re[3]: Реализация парсеров
От: Oyster Украина https://github.com/devoyster
Дата: 01.03.10 16:04
Оценка:
Здравствуйте, 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 от этого не спасёт.
... << RSDN@Home 1.2.0 alpha 4 rev. 1419>>
Re[9]: Реализация парсеров
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.03.10 17:50
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Да, но когда работа уже налажена, то с генератором все же проще. Так что вполне нормальная инвестиция времени для будущих задач, если еще что-нибудь парсить придется.


А уверен, что придется? Обычно те кто парсит S-выражения больше ничего не парсят.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Реализация парсеров
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.03.10 17:53
Оценка: 7 (1)
Здравствуйте, Mr.Cat, Вы писали:

MC>Тут, я смотрю, в почете все-таки генераторы: antlr, coco/r — мне них не нравится то, что они как-то плохо, на мой взгляд, уживаются с visual studio. Т.е. чего бы мне хотелось в идеале — чтобы в проект было добавлено (и в сурс-контроле лежало) только описание грамматики, а код генерился бы при сборке, тогда как солюшены в vs ориентированы на добавление в них исходников именно на шарпе (vb, f#, нужное подчеркнуть).


Скачай проект R#, погляди как там сделана интеграция со студией (там использовался CocoR).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Реализация парсеров
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.03.10 17:55
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

MC>О, по идее, мне этого и хочется. Где можно поподробнее почитать про такое управление генерацией кода в студии?


На фиг она тебе не упала. Тебе достаточно иметь castom action который можно добавить в любой проект. Ну, а генерируемые файлы добавляются один раз вручную.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Реализация парсеров
От: Воронков Василий Россия  
Дата: 01.03.10 17:57
Оценка:
Здравствуйте, VladD2, Вы писали:

ВВ>>Да, но когда работа уже налажена, то с генератором все же проще. Так что вполне нормальная инвестиция времени для будущих задач, если еще что-нибудь парсить придется.


VD>А уверен, что придется? Обычно те кто парсит S-выражения больше ничего не парсят.


Не знаю, может, просто текущая задача по работе такая или язык запросов с подобной нотаций. У запросов к AD, например, синтаксис запросов — почти S-выражения.
А вообще "парсить парсит S-выражения" понятия весьма расплывчатое. А при рукопашной реализации парсера больше возни будет ИМХО не со "скобочками", а с токенизацией. Парсить те же float-ы по стандарту и проч. Так что за час можно и не управиться.
Re[11]: Реализация парсеров
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.03.10 18:22
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Не знаю, может, просто текущая задача по работе такая или язык запросов с подобной нотаций. У запросов к AD, например, синтаксис запросов — почти S-выражения.


Ни у каких запросов синтаксис не может быть "почти S-выражения". Это можно (с огромной натяжкой) сказать про XML, разве что.

ВВ>А вообще "парсить парсит S-выражения" понятия весьма расплывчатое. А при рукопашной реализации парсера больше возни будет ИМХО не со "скобочками", а с токенизацией. Парсить те же float-ы по стандарту и проч. Так что за час можно и не управиться.


Токены можно с успехом выделить регекспами. Далее парсинг превращается в часовое занятие.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Реализация парсеров
От: Mr.Cat  
Дата: 02.03.10 14:05
Оценка:
Здравствуйте, AndrewVK, Вы писали:
AVK>Впрочем, если Irony достаточно зрелый, он может дать много вкусностей.
Например, каких?
Re[5]: Реализация парсеров
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 02.03.10 14:41
Оценка:
Здравствуйте, Mr.Cat, Вы писали:

AVK>>Впрочем, если Irony достаточно зрелый, он может дать много вкусностей.

MC>Например, каких?

Ты предыдущий ответ не читал?
... << RSDN@Home 1.2.0 alpha 4 rev. 1464 on Windows 7 6.1.7600.0>>
AVK Blog
Re[6]: Реализация парсеров
От: Mr.Cat  
Дата: 02.03.10 14:54
Оценка:
Здравствуйте, AndrewVK, Вы писали:
AVK>Ты предыдущий ответ не читал?
http://rsdn.ru/forum/dotnet/3721230.aspx
Автор: AndrewVK
Дата: 01.03.10
?
Re[7]: Реализация парсеров
От: Аноним  
Дата: 22.03.10 08:13
Оценка: 24 (2)
Здравствуйте, Mr.Cat, Вы писали:

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

ВВ>>Я имею в виду ту модель, которую предлагает сама студия. Вот ты создал файл с ресурсами. У него есть билд-акшин, который включен по умолчанию. Даже в проекте видно, что есть определение ресурса, а под ним, под "плюсиком", прячется автоматически генерируемый файл с кодом. Поменял ресурс — файл с кодом автоматически перегенерился. И никаких изменений в проект делать не нужно.
ВВ>>Здесь будет аналогично. У тебя есть EBNF-описание. Под ним прячется сгенерированный код. Поменял — и тут же в дизайн-тайме код перегенерился. И все.
ВВ>>Надо будет правда немножко подправить Кокор, правда совсем чуть-чуть:
ВВ>>- Сделать так, чтобы он генерил все в один файл, а не два (Parser+Scanner)
ВВ>>- Избавиться от шаблонов парсера и сканнера (parser.frame, scanner.frame). Они по большому счету не нужны.
ВВ>>- Поменять сами шаблоны (названия классов и пр-ва имен должны формироваться на основе .atg-файла, классы должны быть partial, репорты об ошибках — через partial-методы).
ВВ>>В общем и целом работы на пару часов от силы. В итоге получится как раз "родное" с т.з. идеологии студии решение.

MC>О, по идее, мне этого и хочется. Где можно поподробнее почитать про такое управление генерацией кода в студии?


Уже сделано:
http://www.codeproject.com/KB/cs/vsCoco.aspx
Re: Реализация парсеров
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.03.10 22:45
Оценка: 7 (1)
Здравствуйте, 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 block
    private simplExpr(simpleExpr : VToken[int]) : int
    {
      simpleExpr.Value
    }
    // TODO: end todo
    
    private 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  
    }
  }
}


А так выглядит использование:

Main.n
def calc = CalcParser(text);  
def pos  = calc.ParsedSymbolsCount;
def res  = calc.Result;
        
WriteLine($"result is: $res");
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.