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

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


Оно не съест запятую. Предикаты не сдвигают позицию разбора.
/* иЗвиНите зА неРовнЫй поЧерК */
[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[3]: [PEG] Не типизируется правило с предикатами
От: VladD2 Российская Империя www.nemerle.org
Дата: 06.06.11 13:52
Оценка:
Здравствуйте, Mumitroller, Вы писали:

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


В учебных целях надо делать реальные проекты. Тогда обучение не пройдет даром.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
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: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>>
Re[5]: [PEG] Не типизируется правило с предикатами
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.06.11 15:09
Оценка:
Здравствуйте, Mumitroller, Вы писали:

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


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

M>Вероятно, это можно переписать по-другому, но я пока не вижу в этом никакой необходимости.

Это не правильный подход к решению данной задачи. Не нужно проверять идет там end сзади или нет. Надо просто сделать ";" необязательным и все. Вместо проверок лучше добавить восстановление после обнаружения ошибки с помощью атрибута FailureRecovery
Автор(ы): Чистяков Владислав Юрьевич
Дата: 07.06.2011
Макрос PegGrammar – это макрос Nemerle, позволяющий добавлять в приложения парсеры, описываемые в нотации PEG.
.

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


В общем, я пока не могу решить как лучше поступить. Оставлю пока сообщение об ошибке. Если будут еще жалобы на такое решение, то можно будет заменить тип на void. Благо это не сложно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.