Re: An Introduction to Nitra
От: 0x7be СССР  
Дата: 14.11.13 19:25
Оценка:
Здравствуйте, SergeyT., Вы писали:

ST>А чего молчите-то? JetBrains Company Blog — An Introduction to Nitra

Я правильно понимаю, что смогу при помощи этого забабахать свой c# с монадами и операторами и компилировать его в IL?
Re[2]: An Introduction to Nitra
От: WolfHound  
Дата: 14.11.13 19:33
Оценка:
Здравствуйте, 0x7be, Вы писали:

0>Я правильно понимаю, что смогу при помощи этого забабахать свой c# с монадами и операторами и компилировать его в IL?

Со временем да.
Более того грамматика, типизатор и кодогенератор для C# будут идти в поставке.
Тебе придётся только маленькие кусочки дописать.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[7]: An Introduction to Nitra
От: jazzer Россия Skype: enerjazzer
Дата: 15.11.13 02:46
Оценка:
Здравствуйте, VladD2, Вы писали:

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


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


VD>Ты тут путаешь теплое с мягким. Я даже не говорю о сложности сравнения DSL-ей получающихся в С++ и созданных с помощью Nitra, потому как когда я говорю о генерации С-кода, то я говорю о коде парсера, а не о коде который может породить DSL.


Коде парсера DSL? Т.е. у него будет просто API из одной функции типа nitra_parse_result* parseDSL(const char* dsl_text)? Или как? И, главное, что потом? Как взаимодействовать с объектами в основной плюсовой программе?

Например, в Boost.Spirit считывание разделенных чем-нть (в данном случае — запятой) в какой-нть контейнер (в данном случае — вектор даблов) делается так (сам парсер — double_%','):
std::vector<double> store;
spirit::phrase_parse(str.begin(), str.end(), double_%',', space, store);

более того, я даже могу написать auto_%',' — и он вычислит тип парсера, исходя из типа элемента контейнера store.

Допустим, я решаю отказаться от Boost.Spirit в пользу нитры и писать парсер там на красивом DSL-е. Какой интерфейс я получу в результате в С++?

VD>Сейчас у нас схема такая:

VD>1. Nitra.exe или компилятор/интеграция Nemerle парсит файл грамматики и генерирует дотнет-сборку (MSIL) парсера. Делается это средствами метапрограммирования Nemerle (хотя это скрыто от пользователя).
VD>2. Программа на дотнете запускает парсер путем вызова некоторых API-функций.
VD>3. Загруженный на этапе 2 парсер парсит то что ему скормят и выдает некую структуру данных ParseResult. Она на низком уровне описывает результат парсинга.
VD>4. Программа на дотнете передает ParseResult в другие API-функции чтобы получить некоторые сервисы (например, объектный AST или для произведения вычислений).

VD>Так вот мы можем генерировать не дотнет-сборку, а нативную DLL или даже ее исходный код. Это позволит на этапах 2-4 пользоваться не только .Net API, но и любым другим (Java или нативным).


Дело в том, что сборка в .Net и сишная DLL в С++ — это огромная разница в возможностях взаимодействия. В .Net она встроится в систему типов, при ошибке выкинет нормальное .Net-исключение, т.е. интегрируется с любым .Net-языком на достаточно высоком уровне. В С++ придется написать гору кода, чтоб предоставить нормальный интерфейс к этой DLL.

VD>Для каждой поддерживаемой платформы придется создать рантайм, но все рантаймы будут работать с единой структурой данных (ParseResult).

VD>Это возможно, так как ParseResult — это очень низкоуровневая структура. По сути там только два куска динамически занимаемой памяти и эта память может быть занята средствами ОС. Кое какие сложности возникнут с представлением информации получаемой при восстановлении после ошибок, но ее тоже можно представить в виде простых сишных структур, а память для них выделять из пула (который можно будет освободить одним махом).

VD>В наших алгоритмах почти не нужна динамическая память. Именно по этому их будет относительно легко перенести на С.

VD>В природе нет никакого плюсового компилятора. Их множество. Все известные мне умеют компилировать С. Оптимизации при этом будут те же, за исключением число С++-ных оптимизаций которые на просто не нужны.
VD>С же банально более переносимый язык.

Да вопросов нет, что Си — самый переносимый и доступен из С++ напрямую. Вопрос в удобстве. Си ни разу не удобен для плюсовика.

J>>Плюс, я так понимаю, то, что сгенерено Нитрой, будет в результате доступно в виде отдельной сишной библиотеки, так?


VD>В принцие, да. Только скорее ее нужно назвать "нативно". С — это только один из вариантов реализации. Но это библиотека содержащая внутри код парсера, а результат компиляции DSL-я. Это нужно отчетливо понимать.


Ну так интерфейс у него по-прежнему будет сишный для моей сиплюсовой программы, так ведь?

J>>Со стандартными сишными проблемами с управлением памятью, передачей параметров только по указателю, отсутствием исключений и прочим...


VD>Проблемы управления память будет нашими проблемами. Мы не предлагаем использовать такие ДЛЛ-и самостоятельно. Они слишком низкоуровенвые для этого.


А как их тогда использовать? Не понимаю.

VD>Плюс в них есть не все что нужно. Кроме генерируемой части у парсеров есть и рукописная. Она находится в рантайме. Некоторые вещи просто нельзя будет написать на С, так как они зависят от платформы. Например, материализация AST должна порождать AST в виде объектов целевой платформы, а не структур С. Хотя если использовать наши AST-методы можно обойтись без материализации AST-а для конкретной платформы.


Да, я о платформе (асме) и не веду пока речь даже. Меня интересует высокоуровневая интеграция с С++.

J>>Не очень понятно, как интерфейситься с теми же плюсами — сишный уровень все-таки очень ограниченнный.


VD>Для плюсов можно создать рантайм который будет прозрачно представлять данные для С++-программиста. Учитывая совместимость С++ и С это будет даже проще реализовать.


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

VD>Что касается управления памятью, то парсеры используют столь низкоуровневые структуры данных, что это для них не проблема. Куда большей проблемой является кросплатформная реализация АСТ-методов. Во-первых, они пишутся на некотором языке. А во-вторых, оперируют частями грамматики как объектами и могут использовать такие фишки (которые будут предоставляться Nitra) как квази-цитирование. Конечно можно использовать в них язык целевой платформы, но он будет по определению ограничен своими возможностями. Например, в С++ будет невозможно использовать сопоставление с образцом для распознавания сложных сочетаний конструкций в коде. Ну, и опят же управление памятью начинает играть роль.


Ну и как оно все будет работать со сложными конструкциями в С++ коде?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[8]: An Introduction to Nitra
От: WolfHound  
Дата: 15.11.13 10:53
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Допустим, я решаю отказаться от Boost.Spirit в пользу нитры и писать парсер там на красивом DSL-е. Какой интерфейс я получу в результате в С++?

Красивый.
О проектировании интерфейса для С++ мы сейчас даже не думаем.
Сейчас есть масса более приоритетных задач.

J>Дело в том, что сборка в .Net и сишная DLL в С++ — это огромная разница в возможностях взаимодействия. В .Net она встроится в систему типов, при ошибке выкинет нормальное .Net-исключение, т.е. интегрируется с любым .Net-языком на достаточно высоком уровне. В С++ придется написать гору кода, чтоб предоставить нормальный интерфейс к этой DLL.

Не придётся. Всё что нужно сгенерируем. Ваще не проблема.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: An Introduction to Nitra
От: catbert  
Дата: 15.11.13 11:00
Оценка:
Не знаю куда баги писать, но на звездочки в ошибочных инпутах эта штука как-то болезненно реагирует.
Re[2]: An Introduction to Nitra
От: WolfHound  
Дата: 15.11.13 11:05
Оценка: 3 (1)
Здравствуйте, catbert, Вы писали:

C>Не знаю куда баги писать,

Попробуй сюда.
http://youtrack.jetbrains.com/issues/NTR
Должен быть уже открыт.

C>но на звездочки в ошибочных инпутах эта штука как-то болезненно реагирует.

На ошибочные тексты оно сейчас вообще болезненно реагирует.
Сейчас только этим и занимаемся.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: An Introduction to Nitra
От: Аноним  
Дата: 15.11.13 11:22
Оценка:
Здравствуйте, WolfHound, Вы писали:

Что то Влада нет в скайпе....
Re[8]: An Introduction to Nitra
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.11.13 12:48
Оценка: 12 (1)
Здравствуйте, jazzer, Вы писали:

VD>>Ты тут путаешь теплое с мягким. Я даже не говорю о сложности сравнения DSL-ей получающихся в С++ и созданных с помощью Nitra, потому как когда я говорю о генерации С-кода, то я говорю о коде парсера, а не о коде который может породить DSL.


J>Коде парсера DSL?


Да. Мы создаем tool для разработки языков который можно будет использовать и по частям. Пока готова только первая часть — динамически расширяемый парсер.

J>Т.е. у него будет просто API из одной функции типа nitra_parse_result* parseDSL(const char* dsl_text)? Или как?


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

J>И, главное, что потом? Как взаимодействовать с объектами в основной плюсовой программе?


Пожалуй проще "заглянуть под капот", чтобы было понятнее. В этом nitra_parse_result лежит несколько простых переменных (целые, булевы и т.п.) и пара целочисленных массивов. В одном массиве лежит лог парсинга закодированный определенным образом. Во втором информация о мемоизации (ссылки во первый массив). Таким образом AST закодирован этими двумя массивами.

Мы можем посторить эти массив на любом языке./платформе Например на дотнете (как сейчас) или на С/нэитив коде (гипотетически). Этот код (код парсинга) частично универсальный (такого кода очень не много), а частично генерируется по грамматике (вот его много, но он генерируется, а генератор всегда можно поменять).

Далее есть алгоритм обхода этих массивов. Этот алгоритм универсален и его можно перенести на любой язык. На С++ можно написать базовый класс у наследников которого будут вызваться переопределенные методы. Получается нечто вроде SAX-модели для ХМЛ-я в Яве.

Кроме того к грамматике еще имеется так называемая "рефлексия". Это метаданные описанные в виде статических структур данных (для каждого правила). Их можно читать как во время исполнения, так и во время компиляции. Это позволяет написать на любом языке генераторы или интепретаторы. Например, не сложно написать материализатор AST для С++.

Еще один вариант (несколько более сложный, но самый интересный) — генерация С++ (или любого другого языка) по нашим AST-методам. AST-методы — это DSL который позволяет объявить методы прямо внутри правил и оперировать, внутри этих методов, частями грамматики как полями объектов.

Если это сделать, то на С++ можно будет просто взывать AST-метод и получить нужно значение. А С++-код его получающий будет скомпилирован по коду AST-метода.

Прикинь полноценные лямбды и паттерн-матчинг в С++?

J>Допустим, я решаю отказаться от Boost.Spirit в пользу нитры и писать парсер там на красивом DSL-е. Какой интерфейс я получу в результате в С++?


Я вше как раз описал три возможных варианта, по мере сложности их реализации.

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

J>Дело в том, что сборка в .Net и сишная DLL в С++ — это огромная разница в возможностях взаимодействия.


Взаимодействовать с ней ты будешь через API. Главное, что данные представляются так, что ни на одном языке/платформе с ними проблем не будет (это просто массивы целых чисел).

J>В .Net она встроится в систему типов, при ошибке выкинет нормальное .Net-исключение, т.е. интегрируется с любым .Net-языком на достаточно высоком уровне. В С++ придется написать гору кода, чтоб предоставить нормальный интерфейс к этой DLL.


Если в парсере вылетает исключение — это ошибка и ее нужно чинить. По делу исключений быть не может. Мы их не генерируем и не используем. У на эдакий олскульный С-ишный код (для производительности).


J>Да вопросов нет, что Си — самый переносимый и доступен из С++ напрямую. Вопрос в удобстве. Си ни разу не удобен для плюсовика.


Удобство обеспечивается API и генерацией специализированного для С++ кода. Мы в Nemerle и C# не колупаемся с массивами? Вот, например, код строчного калькулятора написанный на C# с использованием Nitra:
using N2;
using System;
 
class Program
{
  static void Main()
  {
    var parserHost = new ParserHost();
    for(;;)
    {
      Console.Write("input>");
      var input = Console.ReadLine();
 
      // выходим, если пользователь ввел пустую строку
      if (string.IsNullOrWhiteSpace(input))
        return;
 
      // Парсим строку с помощью стартового правила
      var parseResult = Calc.Start(SourceSnapshot(input), parserHost);
      // Создаем материализованный AST
      var ast = CalcAstWalkers.Start(parseResult);
 
      Console.WriteLine("Pretty print: " + ast);
 
      // Выводим сообщения об ошибках, если таковые имеются
      foreach(var error in parseResult.GetErrors())
      {
        var lineCol = error.Location.StartLineColumn;
        Console.WriteLine("(" + lineCol.Line + "," + lineCol.Column + "): " + error.Message);
      }
 
      // Вычисляем результат выражения путем вызова
      // AST-метода и выводим значение на консоль.
      Console.WriteLine("Result: " + ast.Value());
    }
  }
}


А вот грамматика с AST-методами:

using N2.Runtime;
using System;
 
syntax module Calc
{
  // синтаксические модули из стандартной библиотеки
  using PrettyPrint;
  using TokenNames;
  using StandardSpanClasses;
  using Whitespaces;
 
 
  [StartRule]
  syntax Start = Expr !Any
  {
    Value() : double = Expr.Value();
  }
 
  syntax Expr
  {
    Value() : double;
    missing Value = double.NaN;
 
     | [SpanClass(Number)] Number
      {
        regex Digit = ['0'..'9'];
        regex Number = Digit+ ('.' Digit+)?;
 
        override Value = double.Parse(GetText(Number));
      }
 
    | ParenthesesParentheses = '(' Expr ')'
      {
        override Value = Expr.Value();
      }
    | Add         = Expr '+' Expr precedence 10
      {
        override Value = Expr1.Value() + Expr2.Value();
      }
    | Sub         = Expr '-' Expr precedence 10
      {
        override Value = Expr1.Value() - Expr2.Value();
      }
    | Mul         = Expr '*' Expr precedence 20
      {
        override Value = Expr1.Value() * Expr2.Value();
      }
    | Div         = Expr '/' Expr precedence 20
      {
        override Value = Expr1.Value() / Expr2.Value();
      }
    | Pow      = Expr '^' Expr precedence 30 right-associative
            {
        override Value =
          Math.Pow(Expr1.Value(), Expr2.Value());
      }
    | Neg         = '-' Expr            precedence 100
      {
        override Value = -Expr.Value();
      }
  }
}


Консольный выхлоп:
input>2 +    3*4
Pretty print: 2+3*4
Result: 14
input>2+
Pretty print: 2+
(1,3): Expected: Expr.
Result: NaN
input>$3
Pretty print: 3
(1,1): Unexpected token
Result: 3
input>


J>Ну так интерфейс у него по-прежнему будет сишный для моей сиплюсовой программы, так ведь?


Нет. Не так. Интерфейс можно сделать специализированным для конкретного языка.

J>А как их тогда использовать? Не понимаю.


Я уже несколько раз говорил — через API и генерированный специально для конкретного языка код.

J>Да, я о платформе (асме) и не веду пока речь даже. Меня интересует высокоуровневая интеграция с С++.


Под алатфоромой я скорее .Net/Java/native имею в виду.

J>Вот с этого места поподробнее хотелось мы. Потому что пока я не вижу, как будет выглядеть эта прозрачность.


Вот для дотнета мы предоставляет разного рода базовые классы обходчиков, атериализованный AST (классы/объекты дотнета) и AST-методы — DSL скрывающий от пользователя детали реализации и позволяющий писать методы производящие вычисления как бы над грамматикой.

Тоже самое можно сделать и для С++. Проще всего сделать обходчик дергающий методы. Чуть сложнее наладить генерацию AST-а для С++. Значительно сложнее генерировать по AST-методам С++-код. Но все вполне реально. Было бы желание, время и необходимость.

J>Ну и как оно все будет работать со сложными конструкциями в С++ коде?


Это вопрос преобразования данных. В парсингде речь всегда идет о разборе отрезков строк.

ЗЫ

Ты еще забываешь, что сравнивать Nita и Boost.Spirit не вполне корректно.

Мы, в отличии от Boost.Spirit-а, предоставляем кучу гарантированно качественных севрисов:
1. Сам парсер быстр и имеет вычислительную сложность порядка O(n) (при отсутствии ошибок в разбираемом коде).
2. Алгоритм разбирает все однозначные контекстно-свободные грамматики и многие неоднозначные.
3. Предоставляется автоматическая поддержка в IDE (подсветка, фолдинг, диагностика ошибок).
4. В будущем это будет законченное решение предоставляющее полный набор IDE-сервисов и позволяющее создавать автономные компилятора. Тут тебе будет и связывание имен, и вывод типов, и сменяемые бэкэнды.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: An Introduction to Nitra
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.11.13 12:49
Оценка:
Здравствуйте, catbert, Вы писали:

C>Не знаю куда баги писать, но на звездочки в ошибочных инпутах эта штука как-то болезненно реагирует.


С ошибками погоди. Мы тут уже некоторые правим. Доправим, тогда еще раз проверишь. Скорее всего проблемы уйдут.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: An Introduction to Nitra
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.11.13 12:51
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Что то Влада нет в скайпе....


Мой старый скайп протух. Пользуйтесь новым скайповским экаунтом — vc.rsdn.ru
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: An Introduction to Nitra
От: Аноним  
Дата: 16.11.13 18:58
Оценка:
Есть проект в котором нужно парсить C# и Delphi файлы, как раз бы нитра и пригодился, для шарпа использую Roslyn, а для дельфи регексы.
А планируется ли какая-та тулза для конвертации синтакса из других известных парсеров в синтакс нитры?
Re[3]: An Introduction to Nitra
От: catbert  
Дата: 17.11.13 10:13
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>С ошибками погоди. Мы тут уже некоторые правим. Доправим, тогда еще раз проверишь. Скорее всего проблемы уйдут.


Да я не жалуюсь, просто для информации.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.