Однако, если попытаться указать какой-нибудь тип для правила rule, то вылетает assert:
...
rule : int = ['0'..'9'] (space / &comma);
...
Exception Nemerle.Core.AssertionException: assertion failed in file Grammar\GrammarTyper.Utils.n, line 48
Проблема явно в том, что Peg не может определить тип выражения приоритетного выбора, хотя в данном конкретном случае логично было бы считать его void. Я пока нашел только один способ обойти эту проблему — добавить рядом с предикатом опциональную ссылку на какое-нибудь правило с типом void. Например, вот так:
Здравствуйте, Mumitroller, Вы писали:
M>Может есть какой-нибудь более красивый способ? А то сильно не хочется замусоривать грамматику. M>И, конечно-же, хотелось бы видеть внятное сообщение об ошибке вместо ничего не говорящего assert'а.
Способ только один — чинить баг. Заведи, плиз, запись в багтреккере. Будет время, пофиксим.
ЗЫ
Немного позанудствую. В парсерах лучше не терять информацию о токенах (вроде ","). Даже если для решения задачи они не нужны, они могу пригодиться в IDE или при выдаче сообщений об ошибках. Так что делать void-ом "," — это не лучшее решение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: [PEG] Не типизируется правило с предикатами
Здравствуйте, VladD2, Вы писали:
VD>Способ только один — чинить баг. Заведи, плиз, запись в багтреккере. Будет время, пофиксим.
Сделал — Issue 1340
VD>ЗЫ
VD>Немного позанудствую. В парсерах лучше не терять информацию о токенах (вроде ","). Даже если для решения задачи они не нужны, они могу пригодиться в IDE или при выдаче сообщений об ошибках. Так что делать void-ом "," — это не лучшее решение.
Для полноценных применений — согласен. А в учебных или исследовательских целях все же лучше отбрасывать детали, не имеющие принципиального значения.
Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[3]: [PEG] Не типизируется правило с предикатами
Здравствуйте, Mumitroller, Вы писали:
M>Для полноценных применений — согласен. А в учебных или исследовательских целях все же лучше отбрасывать детали, не имеющие принципиального значения.
В учебных целях надо делать реальные проекты. Тогда обучение не пройдет даром.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
M>Exception Nemerle.Core.AssertionException: assertion failed in file Grammar\GrammarTyper.Utils.n, line 48
M>
Ассерт пофиксил. Сделал более внятное сообщение об ошибке.
M>Проблема явно в том, что Peg не может определить тип выражения приоритетного выбора, хотя в данном конкретном случае логично было бы считать его void. Я пока нашел только один способ обойти эту проблему — добавить рядом с предикатом опциональную ссылку на какое-нибудь правило с типом void. Например, вот
Проблема в том, что предикаты вообще не могут иметь какой-то возвращаемый тип, так как они в принципе не могут захватывать текст. Предикат не имеет смысла если за ним или перед ним не идет правила которое съедает входной поток. По этому в выражении приоритетного выбора должны быть или только предикаты (во всех вхождениях) или кроме предикатов должны быть и осмысленные выражения.
Рассматривать отсутствие возвращаемого типа как void нехорошо, так как это может маскировать ошибки (как приведенный пример).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: [PEG] Не типизируется правило с предикатами
Здравствуйте, VladD2, Вы писали:
VD>Ассерт пофиксил. Сделал более внятное сообщение об ошибке.
Спасибо
M>>Проблема явно в том, что Peg не может определить тип выражения приоритетного выбора, хотя в данном конкретном случае логично было бы считать его void. Я пока нашел только один способ обойти эту проблему — добавить рядом с предикатом опциональную ссылку на какое-нибудь правило с типом void. Например, вот
VD>Проблема в том, что предикаты вообще не могут иметь какой-то возвращаемый тип, так как они в принципе не могут захватывать текст. Предикат не имеет смысла если за ним или перед ним не идет правила которое съедает входной поток. По этому в выражении приоритетного выбора должны быть или только предикаты (во всех вхождениях) или кроме предикатов должны быть и осмысленные выражения.
VD>Рассматривать отсутствие возвращаемого типа как void нехорошо, так как это может маскировать ошибки (как приведенный пример).
Ээээ... Лично я void понимаю именно как отсутствие возвращаемого значения, поэтому мне кажется достаточно логичным, что в выражении приоритетного выбора могут присутствовать вперемешку чисто предикатные варианты и варианты с правилами, возвращающими void, так как в этом случае тип выражения приоритетного выбора однозначно вычисляется в void. Также можно что-то придумать и для использования в этой ситуации правил, возвращающих значение. Например, возвращать option[TType], но это уже не так очевидно imho.
Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[3]: [PEG] Не типизируется правило с предикатами
Здравствуйте, Mumitroller, Вы писали:
VD>>Рассматривать отсутствие возвращаемого типа как void нехорошо, так как это может маскировать ошибки (как приведенный пример).
M>Ээээ... Лично я void понимаю именно как отсутствие возвращаемого значения
А на самом деле void это не отсутствие значения — это унитарное значение. Предикаты действительно не могут возвращать значения (даже void) — они используются парсером для "заглядывания вперед".
/* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: [PEG] Не типизируется правило с предикатами
Здравствуйте, hardcase, Вы писали:
H>А на самом деле void это не отсутствие значения — это унитарное значение. Предикаты действительно не могут возвращать значения (даже void) — они используются парсером для "заглядывания вперед".
Спасибо за ликбез, но я немного о другом — вполне логично считать, что варианты выражения приоритетного выбора, состоящие только из предикатов, имеют тип void. Или даже option.None, если другие варианты возвращают значение.
Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[5]: [PEG] Не типизируется правило с предикатами
Здравствуйте, Mumitroller, Вы писали:
M>Спасибо за ликбез, но я немного о другом — вполне логично считать, что варианты выражения приоритетного выбора, состоящие только из предикатов, имеют тип void. Или даже option.None, если другие варианты возвращают значение.
Хм по мне так использовать предикаты в конструкции приоритетного выбора вообще не логично.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[6]: [PEG] Не типизируется правило с предикатами
Здравствуйте, hardcase, Вы писали:
H>Хм по мне так использовать предикаты в конструкции приоритетного выбора вообще не логично.
Почему не логично? Как по мне, так условие наподобие "должно заканчиваться пробелом, если дальше не идет запятая" — вполне нормально. Конечно, можно переписать грамматику так, чтобы запятая съедалась этим же правилом, а не проверялась предикатом. Но это может быть весьма трудоемко, так как может потребовать серьезных изменений структуры грамматики. Поэтому есть смысл позволить пользоваться не совсем чистыми приемами.
Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[7]: [PEG] Не типизируется правило с предикатами
Здравствуйте, Mumitroller, Вы писали:
M>Здравствуйте, hardcase, Вы писали:
H>>Хм по мне так использовать предикаты в конструкции приоритетного выбора вообще не логично.
M>Почему не логично?
Потому что это конфликтует с возможностью создавать AST.
M>Как по мне, так условие наподобие "должно заканчиваться пробелом, если дальше не идет запятая" — вполне нормально.
"Должно заканчиваться пробелом, если дальше не идет запятая": space !comma
/* иЗвиНите зА неРовнЫй поЧерК */
Re[8]: [PEG] Не типизируется правило с предикатами
Здравствуйте, hardcase, Вы писали:
H>>>Хм по мне так использовать предикаты в конструкции приоритетного выбора вообще не логично. M>>Почему не логично? H>Потому что это конфликтует с возможностью создавать AST.
Каким образом? Для уже упомянутого примера
grammar
{
start : int = rule;
rule : int = ['0'..'9'] (space / &comma);
comma : void = ',';
space : void = ' ';
}
обработчик будет иметь сигнатуру
rule(_ : NToken) : int
А если поменять тип правила comma с void на int, то
rule(_ : NToken, _ : option[int]) : int
В обоих случаях я не вижу, что может помешать построению узла AST. Или я что-то неправильно понял? Хотя да, если для построения узла AST важно знать, какой именно из чисто предикатных вариантов отработал, тогда да — придется как-то по-другому это правило построить.
M>>Как по мне, так условие наподобие "должно заканчиваться пробелом, если дальше не идет запятая" — вполне нормально. H>"Должно заканчиваться пробелом, если дальше не идет запятая": space !comma
Совершенно верно! Но это правило съест запятую. Если грамматика построена так, что эту запятую должно съесть другое правило, то ее придется перестраивать, что может быть весьма трудоемко и далеко не всегда оправданно. Другими словами, есть очень неочевидные требования к структуре грамматики, что не очень хорошо.
Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[9]: [PEG] Не типизируется правило с предикатами
Здравствуйте, Mumitroller, Вы писали: M>>>Как по мне, так условие наподобие "должно заканчиваться пробелом, если дальше не идет запятая" — вполне нормально. H>>"Должно заканчиваться пробелом, если дальше не идет запятая": space !comma
M>Совершенно верно! Но это правило съест запятую.
Оно не съест запятую. Предикаты не сдвигают позицию разбора.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[9]: [PEG] Не типизируется правило с предикатами
Здравствуйте, Mumitroller, Вы писали:
M>Здравствуйте, hardcase, Вы писали:
H>>>>Хм по мне так использовать предикаты в конструкции приоритетного выбора вообще не логично. M>>>Почему не логично? H>>Потому что это конфликтует с возможностью создавать AST.
M>Каким образом? Для уже упомянутого примера M>
M>А если поменять тип правила comma с void на int, то M>
rule(_ : NToken, _ : option[int]) : int
M>В обоих случаях я не вижу, что может помешать построению узла AST. Или я что-то неправильно понял? Хотя да, если для построения узла AST важно знать, какой именно из чисто предикатных вариантов отработал, тогда да — придется как-то по-другому это правило построить.
Тем что сейчас в операторе приоритетного выбора правила должны возвращать унифицируемые типы, но с предикатами будет упомянутая вариация с option, имхо это ненужное усложнение на ровном месте.
Что мешает переписать правило так:
rule : int = ['0'..'9'] (space !comma)?;
/* иЗвиНите зА неРовнЫй поЧерК */
Re[10]: [PEG] Не типизируется правило с предикатами
Здравствуйте, hardcase, Вы писали:
M>>>>Как по мне, так условие наподобие "должно заканчиваться пробелом, если дальше не идет запятая" — вполне нормально. H>>>"Должно заканчиваться пробелом, если дальше не идет запятая": space !comma M>>Совершенно верно! Но это правило съест запятую. H>Оно не съест запятую. Предикаты не сдвигают позицию разбора.
Точно! Торможу уже...
Тем не менее, это выражение не эквивалентно изначальному, так как в словесной формулировке условия я опустил целую ветку. Целиком будет звучать примерно так: "должно заканчиваться пробелом, если дальше не идет запятая, либо пробела быть не должно, если дальше идет запятая". Причем пробел надо съесть в текущем правиле, а запятую оставить другому.
Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[10]: [PEG] Не типизируется правило с предикатами
H>Тем что сейчас в операторе приоритетного выбора правила должны возвращать унифицируемые типы, но с предикатами будет упомянутая вариация с option, имхо это ненужное усложнение на ровном месте.
H>Что мешает переписать правило так: H>
H>rule : int = ['0'..'9'] (space !comma)?;
H>
Они не полностью эквивалентны — на строке "1-" начальный вариант не сматчит rule, а твой — сматчит.
Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[3]: [PEG] Не типизируется правило с предикатами
Здравствуйте, Mumitroller, Вы писали:
M>Ээээ... Лично я void понимаю именно как отсутствие возвращаемого значения, поэтому мне кажется достаточно логичным, что в выражении приоритетного выбора могут присутствовать вперемешку чисто предикатные варианты и варианты с правилами, возвращающими void,
Приведи хотя бы один случай в котором такое смешение окажется осмысленным. Я пока что таких не вижу. А раз их нет — это ошибка. Разделение типов на void и none дает возможность отлавливать такие ошибки.
M>так как в этом случае тип выражения приоритетного выбора однозначно вычисляется в void. Также можно что-то придумать и для использования в этой ситуации правил, возвращающих значение. Например, возвращать option[TType], но это уже не так очевидно imho.
Я ничего разумного придумать не могу. Технически, None можно интерпретировать как void, но зачем? Прощать глупости в грамматиках? А будет ли это полезно? Лучше получить внятное сообщение об ошибке и понять, что в грамматике косяк.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: [PEG] Не типизируется правило с предикатами
Здравствуйте, VladD2, Вы писали:
M>>Ээээ... Лично я void понимаю именно как отсутствие возвращаемого значения, поэтому мне кажется достаточно логичным, что в выражении приоритетного выбора могут присутствовать вперемешку чисто предикатные варианты и варианты с правилами, возвращающими void,
VD>Приведи хотя бы один случай в котором такое смешение окажется осмысленным. Я пока что таких не вижу. А раз их нет — это ошибка. Разделение типов на void и none дает возможность отлавливать такие ошибки.
M>>так как в этом случае тип выражения приоритетного выбора однозначно вычисляется в void. Также можно что-то придумать и для использования в этой ситуации правил, возвращающих значение. Например, возвращать option[TType], но это уже не так очевидно imho.
VD>Я ничего разумного придумать не могу. Технически, None можно интерпретировать как void, но зачем? Прощать глупости в грамматиках? А будет ли это полезно? Лучше получить внятное сообщение об ошибке и понять, что в грамматике косяк.
В Паскале после последнего statement в блоке begin-end может не указываться ";". А у меня эти последовательности парсятся разными правилами, поэтому я хочу сматчить ";" в одном правиле, а если его нет — проверить, что дальше идет "end". Примерно так:
Вероятно, это можно переписать по-другому, но я пока не вижу в этом никакой необходимости. В чем косяк (глупость) такой грамматики — я тоже пока не понимаю. Поэтому мне проще использовать workaround. Если потом вылезут какие-то более серьезные проблемы — тогда и буду думать над изменением структуры грамматики.
Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[5]: [PEG] Не типизируется правило с предикатами
M>Вероятно, это можно переписать по-другому, но я пока не вижу в этом никакой необходимости. В чем косяк (глупость) такой грамматики — я тоже пока не понимаю. Поэтому мне проще использовать workaround. Если потом вылезут какие-то более серьезные проблемы — тогда и буду думать над изменением структуры грамматики.
А вот так не проще:
statementList = statement (";" statement)* ";"?;
Или еще лучше добавляем к statement emptyStatement и тогда можно будет писать так:
statementList = statement (";" statement)*;
За одно будут сматчены несколько ";" подряд.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: [PEG] Не типизируется правило с предикатами
M>>Вероятно, это можно переписать по-другому, но я пока не вижу в этом никакой необходимости. В чем косяк (глупость) такой грамматики — я тоже пока не понимаю. Поэтому мне проще использовать workaround. Если потом вылезут какие-то более серьезные проблемы — тогда и буду думать над изменением структуры грамматики. WH>А вот так не проще: WH>
Очень логичный вариант, но у меня почему-то так не получилось. Скорее всего я не учел (или не понял) какую-нибудь мелочь. Ну да ладно, раз эта фича вызывает такое неприятие, то меня вполне устроит и workaround. Эту грамматику я точно переделывать пока не буду, так как она вполне приемлемо делает то, что мне нужно и есть более насущные задачи.