[PEG] Не типизируется правило с предикатами
От: Mumitroller Беларусь  
Дата: 03.06.11 10:16
Оценка:
Привет

Вот эта грамматика (совершенно бессмысленная!), как и ожидается, вполне нормально компилируется:
[PegGrammar(
    Options = None,
    start,
    grammar
    {
      start : int = rule;
      rule = ['0'..'9'] (space / &comma);
      comma : void = ',';
      space : void = ' ';
    })]
  class Parser
  {
    start(_ : Nemerle.Peg.NToken) : int
    {
        1
    }
  }

Однако, если попытаться указать какой-нибудь тип для правила 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. Например, вот так:
...
      rule : int = ['0'..'9'] (space / space? &comma);
...

Может есть какой-нибудь более красивый способ? А то сильно не хочется замусоривать грамматику.

И, конечно-же, хотелось бы видеть внятное сообщение об ошибке вместо ничего не говорящего assert'а.

Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re: [PEG] Не типизируется правило с предикатами
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.06.11 15:49
Оценка:
Здравствуйте, Mumitroller, Вы писали:

M>Может есть какой-нибудь более красивый способ? А то сильно не хочется замусоривать грамматику.

M>И, конечно-же, хотелось бы видеть внятное сообщение об ошибке вместо ничего не говорящего assert'а.

Способ только один — чинить баг. Заведи, плиз, запись в багтреккере. Будет время, пофиксим.

ЗЫ

Немного позанудствую. В парсерах лучше не терять информацию о токенах (вроде ","). Даже если для решения задачи они не нужны, они могу пригодиться в IDE или при выдаче сообщений об ошибках. Так что делать void-ом "," — это не лучшее решение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: [PEG] Не типизируется правило с предикатами
От: Mumitroller Беларусь  
Дата: 04.06.11 08:02
Оценка: 1 (1)
Здравствуйте, VladD2, Вы писали:

VD>Способ только один — чинить баг. Заведи, плиз, запись в багтреккере. Будет время, пофиксим.


Сделал — Issue 1340

VD>ЗЫ


VD>Немного позанудствую. В парсерах лучше не терять информацию о токенах (вроде ","). Даже если для решения задачи они не нужны, они могу пригодиться в IDE или при выдаче сообщений об ошибках. Так что делать void-ом "," — это не лучшее решение.


Для полноценных применений — согласен. А в учебных или исследовательских целях все же лучше отбрасывать детали, не имеющие принципиального значения.

Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[3]: [PEG] Не типизируется правило с предикатами
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.06.11 13:52
Оценка:
Здравствуйте, Mumitroller, Вы писали:

M>Для полноценных применений — согласен. А в учебных или исследовательских целях все же лучше отбрасывать детали, не имеющие принципиального значения.


В учебных целях надо делать реальные проекты. Тогда обучение не пройдет даром.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: [PEG] Не типизируется правило с предикатами
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.06.11 01:40
Оценка: 2 (1)
Здравствуйте, Mumitroller, Вы писали:

M>
M>      rule : int = ['0'..'9'] (space / &comma);
M>

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] Не типизируется правило с предикатами
От: Mumitroller Беларусь  
Дата: 07.06.11 05:48
Оценка:
Здравствуйте, 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] Не типизируется правило с предикатами
От: hardcase Пират http://nemerle.org
Дата: 07.06.11 07:41
Оценка:
Здравствуйте, Mumitroller, Вы писали:

VD>>Рассматривать отсутствие возвращаемого типа как void нехорошо, так как это может маскировать ошибки (как приведенный пример).


M>Ээээ... Лично я void понимаю именно как отсутствие возвращаемого значения


А на самом деле void это не отсутствие значения — это унитарное значение. Предикаты действительно не могут возвращать значения (даже void) — они используются парсером для "заглядывания вперед".
/* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: [PEG] Не типизируется правило с предикатами
От: Mumitroller Беларусь  
Дата: 07.06.11 08:02
Оценка:
Здравствуйте, hardcase, Вы писали:

H>А на самом деле void это не отсутствие значения — это унитарное значение. Предикаты действительно не могут возвращать значения (даже void) — они используются парсером для "заглядывания вперед".


Спасибо за ликбез, но я немного о другом — вполне логично считать, что варианты выражения приоритетного выбора, состоящие только из предикатов, имеют тип void. Или даже option.None, если другие варианты возвращают значение.

Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[5]: [PEG] Не типизируется правило с предикатами
От: hardcase Пират http://nemerle.org
Дата: 07.06.11 08:17
Оценка:
Здравствуйте, Mumitroller, Вы писали:

M>Спасибо за ликбез, но я немного о другом — вполне логично считать, что варианты выражения приоритетного выбора, состоящие только из предикатов, имеют тип void. Или даже option.None, если другие варианты возвращают значение.


Хм по мне так использовать предикаты в конструкции приоритетного выбора вообще не логично.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[6]: [PEG] Не типизируется правило с предикатами
От: Mumitroller Беларусь  
Дата: 07.06.11 09:29
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Хм по мне так использовать предикаты в конструкции приоритетного выбора вообще не логично.


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

Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[7]: [PEG] Не типизируется правило с предикатами
От: hardcase Пират http://nemerle.org
Дата: 07.06.11 10:05
Оценка:
Здравствуйте, Mumitroller, Вы писали:

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


H>>Хм по мне так использовать предикаты в конструкции приоритетного выбора вообще не логично.


M>Почему не логично?


Потому что это конфликтует с возможностью создавать AST.


M>Как по мне, так условие наподобие "должно заканчиваться пробелом, если дальше не идет запятая" — вполне нормально.


"Должно заканчиваться пробелом, если дальше не идет запятая": space !comma
/* иЗвиНите зА неРовнЫй поЧерК */
Re[8]: [PEG] Не типизируется правило с предикатами
От: Mumitroller Беларусь  
Дата: 07.06.11 10:47
Оценка:
Здравствуйте, 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] Не типизируется правило с предикатами
От: hardcase Пират http://nemerle.org
Дата: 07.06.11 12:46
Оценка: +1
Здравствуйте, Mumitroller, Вы писали:
M>>>Как по мне, так условие наподобие "должно заканчиваться пробелом, если дальше не идет запятая" — вполне нормально.
H>>"Должно заканчиваться пробелом, если дальше не идет запятая": space !comma

M>Совершенно верно! Но это правило съест запятую.


Оно не съест запятую. Предикаты не сдвигают позицию разбора.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[9]: [PEG] Не типизируется правило с предикатами
От: hardcase Пират http://nemerle.org
Дата: 07.06.11 12:55
Оценка:
Здравствуйте, Mumitroller, Вы писали:

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


H>>>>Хм по мне так использовать предикаты в конструкции приоритетного выбора вообще не логично.

M>>>Почему не логично?
H>>Потому что это конфликтует с возможностью создавать AST.

M>Каким образом? Для уже упомянутого примера

M>
grammar
M>{
M>  start : int = rule;
M>  rule : int = ['0'..'9'] (space / &comma);
M>  comma : void = ',';
M>  space : void = ' ';
M>}

M>обработчик будет иметь сигнатуру
M>
rule(_ : NToken) : int

M>А если поменять тип правила comma с void на int, то
M>
rule(_ : NToken, _ : option[int]) : int

M>В обоих случаях я не вижу, что может помешать построению узла AST. Или я что-то неправильно понял? Хотя да, если для построения узла AST важно знать, какой именно из чисто предикатных вариантов отработал, тогда да — придется как-то по-другому это правило построить.

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

Что мешает переписать правило так:
rule : int = ['0'..'9'] (space !comma)?;
/* иЗвиНите зА неРовнЫй поЧерК */
Re[10]: [PEG] Не типизируется правило с предикатами
От: Mumitroller Беларусь  
Дата: 07.06.11 13:03
Оценка:
Здравствуйте, hardcase, Вы писали:

M>>>>Как по мне, так условие наподобие "должно заканчиваться пробелом, если дальше не идет запятая" — вполне нормально.

H>>>"Должно заканчиваться пробелом, если дальше не идет запятая": space !comma
M>>Совершенно верно! Но это правило съест запятую.
H>Оно не съест запятую. Предикаты не сдвигают позицию разбора.

Точно! Торможу уже...

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

Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[10]: [PEG] Не типизируется правило с предикатами
От: Mumitroller Беларусь  
Дата: 07.06.11 13:12
Оценка:
Здравствуйте, hardcase, Вы писали:

M>>
grammar
M>>{
M>>  start : int = rule;
M>>  rule : int = ['0'..'9'] (space / &comma);
M>>  comma : void = ',';
M>>  space : void = ' ';
M>>}

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] Не типизируется правило с предикатами
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.06.11 13:27
Оценка:
Здравствуйте, Mumitroller, Вы писали:

M>Ээээ... Лично я void понимаю именно как отсутствие возвращаемого значения, поэтому мне кажется достаточно логичным, что в выражении приоритетного выбора могут присутствовать вперемешку чисто предикатные варианты и варианты с правилами, возвращающими void,


Приведи хотя бы один случай в котором такое смешение окажется осмысленным. Я пока что таких не вижу. А раз их нет — это ошибка. Разделение типов на void и none дает возможность отлавливать такие ошибки.

M>так как в этом случае тип выражения приоритетного выбора однозначно вычисляется в void. Также можно что-то придумать и для использования в этой ситуации правил, возвращающих значение. Например, возвращать option[TType], но это уже не так очевидно imho.


Я ничего разумного придумать не могу. Технически, None можно интерпретировать как void, но зачем? Прощать глупости в грамматиках? А будет ли это полезно? Лучше получить внятное сообщение об ошибке и понять, что в грамматике косяк.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: [PEG] Не типизируется правило с предикатами
От: Mumitroller Беларусь  
Дата: 07.06.11 14:00
Оценка:
Здравствуйте, VladD2, Вы писали:

M>>Ээээ... Лично я void понимаю именно как отсутствие возвращаемого значения, поэтому мне кажется достаточно логичным, что в выражении приоритетного выбора могут присутствовать вперемешку чисто предикатные варианты и варианты с правилами, возвращающими void,


VD>Приведи хотя бы один случай в котором такое смешение окажется осмысленным. Я пока что таких не вижу. А раз их нет — это ошибка. Разделение типов на void и none дает возможность отлавливать такие ошибки.


M>>так как в этом случае тип выражения приоритетного выбора однозначно вычисляется в void. Также можно что-то придумать и для использования в этой ситуации правил, возвращающих значение. Например, возвращать option[TType], но это уже не так очевидно imho.


VD>Я ничего разумного придумать не могу. Технически, None можно интерпретировать как void, но зачем? Прощать глупости в грамматиках? А будет ли это полезно? Лучше получить внятное сообщение об ошибке и понять, что в грамматике косяк.


В Паскале после последнего statement в блоке begin-end может не указываться ";". А у меня эти последовательности парсятся разными правилами, поэтому я хочу сматчить ";" в одном правиле, а если его нет — проверить, что дальше идет "end". Примерно так:

block = "begin" statementList "end";
statementList = (statement ";")* (statement (";" / &"end"))?;

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

Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[5]: [PEG] Не типизируется правило с предикатами
От: WolfHound  
Дата: 07.06.11 14:12
Оценка:
Здравствуйте, Mumitroller, Вы писали:

M>
block = "begin" statementList "end";
M>statementList = (statement ";")* (statement (";" / &"end"))?;

M>Вероятно, это можно переписать по-другому, но я пока не вижу в этом никакой необходимости. В чем косяк (глупость) такой грамматики — я тоже пока не понимаю. Поэтому мне проще использовать workaround. Если потом вылезут какие-то более серьезные проблемы — тогда и буду думать над изменением структуры грамматики.
А вот так не проще:
statementList = statement (";" statement)* ";"?;

Или еще лучше добавляем к statement emptyStatement и тогда можно будет писать так:
statementList = statement (";" statement)*;

За одно будут сматчены несколько ";" подряд.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: [PEG] Не типизируется правило с предикатами
От: Mumitroller Беларусь  
Дата: 07.06.11 14:34
Оценка:
Здравствуйте, WolfHound, Вы писали:

M>>
block = "begin" statementList "end";
M>>statementList = (statement ";")* (statement (";" / &"end"))?;

M>>Вероятно, это можно переписать по-другому, но я пока не вижу в этом никакой необходимости. В чем косяк (глупость) такой грамматики — я тоже пока не понимаю. Поэтому мне проще использовать workaround. Если потом вылезут какие-то более серьезные проблемы — тогда и буду думать над изменением структуры грамматики.
WH>А вот так не проще:
WH>
WH>statementList = statement (";" statement)* ";"?;
WH>

WH>Или еще лучше добавляем к statement emptyStatement и тогда можно будет писать так:
WH>
WH>statementList = statement (";" statement)*;
WH>

WH>За одно будут сматчены несколько ";" подряд.

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

Спасибо за обсуждение!

Mumitroller
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.