Информация об изменениях

Сообщение Re[15]: Опциональные типы от 24.02.2017 18:12

Изменено 24.02.2017 18:25 vdimas

Re[15]: Опциональные типы
Здравствуйте, fddima, Вы писали:

V>>Подсказка №1: GRL/LALR существуют во всех компиляторах языков, где требуется перемалывать БОЛЬШИЕ объемы

F> Если ты тонко намекаешь на C++ — то мэйнстрим gcc/clang — это рукописные recursive-descent.

Не совсем. Исторически GCC — это LALR-парсер. Но LALR имеет известные проблемы (не буду тут расписывать, бо они на всех углах расписаны).
Поэтому часто используют LALR + некое ручное допиливание неоднозначных мест.

Более того, есть такой трюк — декомпозиция грамматик. Вот был пример ПЕГ — это и есть, собсно, принцип такой декомпозии.

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

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

А вот это уже тело ф-ий удобней разбирать восходящими грамматиками — особенно что касается вложенных вызовов или математических выражений или совместной работе одного и другого. Что и происходит в реальности. Там тот же самый *LR. Потому что нисходящий разбор страдает склонностями к зацикливаниям на неоднозначных участках кода by design или к тяжеловесным откатам — и это тоже на всех углах обсосано, не буду повторяться.


F>Предполагаю что c# рослин тоже.


C# рассматривать нелепо:
— грамматика сильно однозначная;
— объем перемалываемых исходников смешон; для сравнения, в современной С++ программе из каждого CPP-фала может быть подключено до половины Буста (утрирую, но оно близко к такому положению дел).


F>Только GLR нафиг никому не впился:

F> — сложно восстанавливаться после ошибок;

Наоборот, если речь о неоднозначных участках кода.
При рекурсивном спуске проще генерить ошибку только о простых ситуациях, типа, тут идёт объявление класса, а после имени класса написано, скажем, const — и генерим ошибку "это не ожидается здесь". ))


F> — сложно сообразить вменяемый еррор репортинг;


Еще раз, медленно — ровно наоборот.

LR-разбор в состоянии подсказать множество верных ожидаемых символов. В реальности там выбор из 1-2-х вариантов максимум, потому что в С++ неоднозначность происходит в выборе м/у идентификатором типа или переменой, вот и вся неоднозначность, которой "болеет" С++.

Т.е. типа такого:
id1 id2(id3);

В этом месте id1 — всегда идентификатор типа, а вот чем является id2 зависит от id3.

Если id3 — это значение (переменная/константа/перечисление), то id2 — это идентификатор переменной, а всё выражение означает объявление переменной типа id1 и вызов соотв. конструктора этого типа. А если id3 — это имя типа, то всё выражение означает объявление сигнатуры некоей ф-ии id2.

С другой стороны, подобную неоднозначность НЕ обязательно сваливать на парсер и её не сваливают — для такой конструкции заводится отдельный "недоопределённый" нетерминал и его ресолвят до однозначного через таблицу идентификаторов ручками. Т.е. на скорости работы именно парсера по алгоритму *LR это не сказывается (если убрать ресолвинг). Это конкретные заморочки конкретно С++, которые верны для ЛЮБОГО алгоритма парсинга.


F> — сложно саппортить.


Сложно изменять мелкими шажками, ты хотел сказать.
Т.е. сложно экспериментировать на коленке, верно?
Но к лексерам это точно так же относится, однако же лексеры часто всё-равно идут автогенерённые.

Тут принцип простой — если нужен наколенный вариант для экспериментов, то ОК, пусть будет рукопашный код c предпросмотром (обязательно с предпросмотром, увы).

Собсно, команда GCC пишет о своём переходе на рукописный вариант:

the main benefits are facilitating of future enhancements


Но пишет так же о рисках:

Code may be wrongly accepted which should be rejected, or wrongly rejected which should be accepted.

Кароч, тут можно было бы вести две ветки: на одной наколенно экспериментировать с новыми фичами языка, а на другой уже иметь автоматизированную и оптимизированную генерацию парсера по текущей "наэкспериментированной" версии грамматики. Тогда будет убран человеческий фактор, являющийся основой описанных рисков.

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

Каждый метод имеет свои плюсы и минусы. Когда в виде явной таблицы, то парсер может настраиваться в рантайм, для некоторых предметных областей это важно (я работал именно с такими). Когда не нужно настраивать грамматики в рантайм, то эффективней может оказаться на goto.

Вот у Вольфхаунда, в последний раз, когда я смотрел на генерируемый им код (давно это было) — шла техника на goto. Как сейчас — не знаю. Давно не интересовался, т.к. он не исполнил данное 8 лет назад обещание сделать генерацию парсера на произвольные технологии, в том числе нейтивные.
Это много и долго.
В итоге, он уже скоро 10 лет занимается этой темой, а полезность выхлопа (востребованность результата) приближается к 0-лю.
Поэтому, он там может надуваться сколько ему вздумается, но нужен пригодный для потребления результат.


F> Любой табличный метод который невозможно нормально отдебажить — в длинной перспективе обречены на провал — никто просто не хочет с этим возиться.


Дебажить надо исходную грамматику, а не автоегенерённый парсер.
Тут опять декомпозиция: отдельно отлаживается грамматика и отдельно генератор.


F>Именно поэтому ни один нормальный фронтэнд не использует *L*.


"ни один нормальный фронтэнд"

Как раз наоборот.
Все "нормальные фронтенды" (С) для С++ используют *LR парсеры от EDG:
— MSVC;
— Intel compiler;
— Comeau;

Плюс всевозможные встраиваемые диалекты С/С++, включая многочисленные диалекты шейдеров (С-подобные языки):
— Analog Devices;
— ARM;
— AT&T;
— Axivion;
— Fujitsu Siemens Computers;
— Hewlett-Packard;
— Parasoft;
— и т.д. до бесконечности.

Вот что такое на сегодня мейнстрим.
Остальное рядом с ними тормозит как программист после бессонной ночи. ))

А конкретно GCC — это бесконечное экспериментаторство и баги на багах. Блин, уже 2017-й год, а у них до сих пор работоспособность (т.е. семантика) программы зависит от ключей оптимизации. У меня не всегда на -O3 программы продолжают работать.
Это как вообще? ))


F>При этом местами могут применяться всякие выверты и оптимизации основанные на автоматах.


Не важно. Промышленного кач-ва у GCC нет.

Для критичных вещей с серьезной оптимизацией под линухами используют icc (Intel compiler), который имеет режим совместимости бинарного кода библиотек с GCC. Потому что, повторюсь, уровень оптимизации -O3 до сих пор является де-факто не работающим в GCC. А если мы компиляем в продакшн на GCC, то только на -O2, как и весь остальной мир, ес-но.


F> Мне тут сказать вам только обоим — фейспалм. Нитра — хороша — но это не парсер. Это язык сам в себе. Спасибо, но это не то что нужно. (Хотя мне очень нравится инструмент). Проблема тока что авторы почему-то решили что бутстрап нужен только им — поэтому и имеют что имеют.


Проблема в том, что тот же EDG генерит парсеры под несколько технологий, а Нитра — только под дотнет. Никаких других проблем там нет.
В принципе, подход неплох, но целеполагание было ошибочным, ведь рынок парсеров именно под дотнет, считай, нулевой — там же монополия.


F>А так — хваставство у обоих. Правда у WH — есть на что ссылаться.


Я только что сослался много на чего — на весь коммерческий мейнстрим, собсно. Т.е. на вообще весь.
Данную мою инфу ты можешь проверить прямо сейчас.


F>У тебя нет.


Т.е., если у меня нет генератора парсера, а есть только его рукописная реализация, то я не могу обсуждать преимуществ алгоритмов разбора с Великим и Ужасным Волфхаундом? Т.е. только потому, что у него есть генератор под дотнет? ))

Кароч, это детсад, но.
Я могу интересующимся в личку выслать ключевые слова, по которым можно найти использование моей разработки. Работа была сделана на заказ когда-то и под NDA, в сфере EDI с этим строго. Заказчик из Штатов, это был госзаказ. Одна из систем ГОСУДАРСТВЕННОЙ СЕРТИФИКАЦИИ участников электронного документооборота уже много лет юзает моё поделие. А кто широко юзает поделие нашего Великого и Ужасного, ы? ))

===========
В общем, не люблю переходить на пенисометрию, но Великий и Ужасный задалбывает именно этим и сходу.

Рассуждать просто о технологиях с честной аргументацией, т.е. в отрыве от неких "личных достижений" — у него это как разрыв шаблона каждый раз.
С т.з. технаря — некрасивые замашки. Инфатильность.
Re[15]: Опциональные типы
Здравствуйте, fddima, Вы писали:

V>>Подсказка №1: GRL/LALR существуют во всех компиляторах языков, где требуется перемалывать БОЛЬШИЕ объемы

F> Если ты тонко намекаешь на C++ — то мэйнстрим gcc/clang — это рукописные recursive-descent.

Исторически GCC юзал LALR-парсер. Но LALR имеет известные проблемы (не буду тут расписывать, бо они на всех углах расписаны).
Поэтому часто используют LALR + некое ручное допиливание неоднозначных мест.

Более того, есть такой трюк — декомпозиция грамматик. Вот был пример ПЕГ — это и есть, собсно, принцип такой декомпозии.

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

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

А вот это уже тело ф-ий удобней разбирать восходящими грамматиками — особенно что касается вложенных вызовов или математических выражений или совместной работе одного и другого. Что и происходит в реальности. Там тот же самый *LR. Потому что нисходящий разбор страдает склонностями к зацикливаниям на неоднозначных участках кода by design или к тяжеловесным откатам — и это тоже на всех углах обсосано, не буду повторяться.


F>Предполагаю что c# рослин тоже.


C# рассматривать нелепо:
— грамматика сильно однозначная;
— объем перемалываемых исходников смешон; для сравнения, в современной С++ программе из каждого CPP-фала может быть подключено до половины Буста (утрирую, но оно близко к такому положению дел).


F>Только GLR нафиг никому не впился:

F> — сложно восстанавливаться после ошибок;

Наоборот, если речь о неоднозначных участках кода.
При рекурсивном спуске проще генерить ошибку только о простых ситуациях, типа, тут идёт объявление класса, а после имени класса написано, скажем, const — и генерим ошибку "это не ожидается здесь". ))


F> — сложно сообразить вменяемый еррор репортинг;


Еще раз, медленно — ровно наоборот.

LR-разбор в состоянии подсказать множество верных ожидаемых символов. В реальности там выбор из 1-2-х вариантов максимум, потому что в С++ неоднозначность происходит в выборе м/у идентификатором типа или переменой, вот и вся неоднозначность, которой "болеет" С++.

Т.е. типа такого:
id1 id2(id3);

В этом месте id1 — всегда идентификатор типа, а вот чем является id2 зависит от id3.

Если id3 — это значение (переменная/константа/перечисление), то id2 — это идентификатор переменной, а всё выражение означает объявление переменной типа id1 и вызов соотв. конструктора этого типа. А если id3 — это имя типа, то всё выражение означает объявление сигнатуры некоей ф-ии id2.

С другой стороны, подобную неоднозначность НЕ обязательно сваливать на парсер и её не сваливают — для такой конструкции заводится отдельный "недоопределённый" нетерминал и его ресолвят до однозначного через таблицу идентификаторов ручками. Т.е. на скорости работы именно парсера по алгоритму *LR это не сказывается (если убрать ресолвинг). Это конкретные заморочки конкретно С++, которые верны для ЛЮБОГО алгоритма парсинга.


F> — сложно саппортить.


Сложно изменять мелкими шажками, ты хотел сказать.
Т.е. сложно экспериментировать на коленке, верно?
Но к лексерам это точно так же относится, однако же лексеры часто всё-равно идут автогенерённые.

Тут принцип простой — если нужен наколенный вариант для экспериментов, то ОК, пусть будет рукопашный код c предпросмотром (обязательно с предпросмотром, увы).

Собсно, команда GCC пишет о своём переходе на рукописный вариант:

the main benefits are facilitating of future enhancements


Но пишет так же о рисках:

Code may be wrongly accepted which should be rejected, or wrongly rejected which should be accepted.

Кароч, тут можно было бы вести две ветки: на одной наколенно экспериментировать с новыми фичами языка, а на другой уже иметь автоматизированную и оптимизированную генерацию парсера по текущей "наэкспериментированной" версии грамматики. Тогда будет убран человеческий фактор, являющийся основой описанных рисков.

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

Каждый метод имеет свои плюсы и минусы. Когда в виде явной таблицы, то парсер может настраиваться в рантайм, для некоторых предметных областей это важно (я работал именно с такими). Когда не нужно настраивать грамматики в рантайм, то эффективней может оказаться на goto.

Вот у Вольфхаунда, в последний раз, когда я смотрел на генерируемый им код (давно это было) — шла техника на goto. Как сейчас — не знаю. Давно не интересовался, т.к. он не исполнил данное 8 лет назад обещание сделать генерацию парсера на произвольные технологии, в том числе нейтивные.
Это много и долго.
В итоге, он уже скоро 10 лет занимается этой темой, а полезность выхлопа (востребованность результата) приближается к 0-лю.
Поэтому, он там может надуваться сколько ему вздумается, но нужен пригодный для потребления результат.


F> Любой табличный метод который невозможно нормально отдебажить — в длинной перспективе обречены на провал — никто просто не хочет с этим возиться.


Дебажить надо исходную грамматику, а не автоегенерённый парсер.
Тут опять декомпозиция: отдельно отлаживается грамматика и отдельно генератор.


F>Именно поэтому ни один нормальный фронтэнд не использует *L*.


"ни один нормальный фронтэнд"

Как раз наоборот.
Все "нормальные фронтенды" (С) для С++ используют *LR парсеры от EDG:
— MSVC;
— Intel compiler;
— Comeau;

Плюс всевозможные встраиваемые диалекты С/С++, включая многочисленные диалекты шейдеров (С-подобные языки):
— Analog Devices;
— ARM;
— AT&T;
— Axivion;
— Fujitsu Siemens Computers;
— Hewlett-Packard;
— Parasoft;
— и т.д. до бесконечности.

Вот что такое на сегодня мейнстрим.
Остальное рядом с ними тормозит как программист после бессонной ночи. ))

А конкретно GCC — это бесконечное экспериментаторство и баги на багах. Блин, уже 2017-й год, а у них до сих пор работоспособность (т.е. семантика) программы зависит от ключей оптимизации. У меня не всегда на -O3 программы продолжают работать.
Это как вообще? ))


F>При этом местами могут применяться всякие выверты и оптимизации основанные на автоматах.


Не важно. Промышленного кач-ва у GCC нет.

Для критичных вещей с серьезной оптимизацией под линухами используют icc (Intel compiler), который имеет режим совместимости бинарного кода библиотек с GCC. Потому что, повторюсь, уровень оптимизации -O3 до сих пор является де-факто не работающим в GCC. А если мы компиляем в продакшн на GCC, то только на -O2, как и весь остальной мир, ес-но.


F> Мне тут сказать вам только обоим — фейспалм. Нитра — хороша — но это не парсер. Это язык сам в себе. Спасибо, но это не то что нужно. (Хотя мне очень нравится инструмент). Проблема тока что авторы почему-то решили что бутстрап нужен только им — поэтому и имеют что имеют.


Проблема в том, что тот же EDG генерит парсеры под несколько технологий, а Нитра — только под дотнет. Никаких других проблем там нет.
В принципе, подход неплох, но целеполагание было ошибочным, ведь рынок парсеров именно под дотнет, считай, нулевой — там же монополия.


F>А так — хваставство у обоих. Правда у WH — есть на что ссылаться.


Я только что сослался много на чего — на весь коммерческий мейнстрим, собсно. Т.е. на вообще весь.
Данную мою инфу ты можешь проверить прямо сейчас.


F>У тебя нет.


Т.е., если у меня нет генератора парсера, а есть только его рукописная реализация, то я не могу обсуждать преимуществ алгоритмов разбора с Великим и Ужасным Волфхаундом? Т.е. только потому, что у него есть генератор под дотнет? ))

Кароч, это детсад, но.
Я могу интересующимся в личку выслать ключевые слова, по которым можно найти использование моей разработки. Работа была сделана на заказ когда-то и под NDA, в сфере EDI с этим строго. Заказчик из Штатов, это был госзаказ. Одна из систем ГОСУДАРСТВЕННОЙ СЕРТИФИКАЦИИ участников электронного документооборота уже много лет юзает моё поделие. А кто широко юзает поделие нашего Великого и Ужасного, ы? ))

===========
В общем, не люблю переходить на пенисометрию, но Великий и Ужасный задалбывает именно этим и сходу.

Рассуждать просто о технологиях с честной аргументацией, т.е. в отрыве от неких "личных достижений" — у него это как разрыв шаблона каждый раз.
С т.з. технаря — некрасивые замашки. Инфатильность.