Что такое мета-объектное правило для именования правил грамматики - PullRequest
0 голосов
/ 26 мая 2018

Как указано в этой проблеме , некоторые имена токенов конфликтуют с именами методов в иерархии классов грамматики (которая включает в себя Соответствие , Capture , Круто , Любой и очевидно Мой .).Например, `Mu.item

grammar g {
    token TOP { <item> };
    token item { 'defined' }
};
say g.parse('defined');

выдает ошибку, подобную этой:

Too many positionals passed; expected 1 argument but got 2␤  
in regex item at xxx

item является частью Anys методы тоже ;Я не нашел никаких других методов в других классах, чье имя, как правило, неверно, но тогда не определены никакие подэлементы (кроме item);большинство из них являются мультисимвольными или фактически определены как method.

Это также происходит, когда такие субметоды, как TWEAK из BUILD, используются для имен токенов, но ошибка в этом случае отличается:

Cannot find method 'match': no method cache and no .^find_method␤
at xxx

Однако другие субметоды, такие как FALLBACK, вообще не имеют проблем:

grammar g { 
  token TOP { <FALLBACK> }; 
  token FALLBACK { 'defined' } 
}; 
say g.parse('defined') # OUTPUT: «「defined」␤ FALLBACK => 「defined」␤»  

и то же самое для некоторых других методов в иерархии классов грамматики, таких как rand или, как правило, большинство методов, определенных как таковые.

То, что проблемные имена, похоже, имеют общее, так это то, что они объявлены как sub, но это не всегда так: CREATE, который изначально вызвал всю проблему, объявляется как method.Так что мне совершенно не ясно, каких имен следует избегать, а какие можно использовать на законных основаниях.Может кто-нибудь уточнить?

Ответы [ 3 ]

0 голосов
/ 27 мая 2018

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

Немного изменив пример:

grammar g { 
  token TOP { <blah> }; 
  token FALLBACK($name) { {note "$name called" } 'defined' } 
}; 
say g.parse('defined')

Производит

blah called
「defined」
blah => 「defined」
0 голосов
/ 27 мая 2018

Правило выглядит так: «если механизм грамматики сам вызывает метод, вы не можете переопределить его как регулярное выражение / токен».

К сожалению, документации по этому поводу нет, и, скорее всего, это оченьзависит от реализации.

0 голосов
/ 27 мая 2018

Это почти полностью о множестве неуклюжих ошибок.

item и т. Д.

См. RT # 127945 - Mu методы не могут быть использованы в качестве грамматических токенов из-заКласс действий по умолчанию .Также имя токена совпадает с внутренним именем? .К сожалению, это нелегко исправить.

Ниже приведено объяснение этой ошибки и ее влияния.

За механизм действий , если правило грамматики соответствует, .parse вызов немедленно пытается вызвать соответственно именованный метод действия.

Если вы явно не передаете класс / объект действия методу .parse, тогда он использует значение по умолчанию, равное Mu.Затем, когда правило в вашей грамматике совпадает, оно ищет метод Mu с тем же именем.Если он не находит, все хорошо.Но если он находит его, он вызывает этот метод в Mu с текущим Match объектом в качестве первого и единственного аргумента.Почти во всех случаях это будет плохо.item является примером этого.

Если вы делаете , чтобы указать .parse методу на использование определенного класса / объекта действий, возникает другая складка:

grammar g           { rule all { all } };
class actions       { }
g.parse: 'all',
         rule    => 'all',
         actions => actions, 

Это приводит к ошибке, аналогичной item, за исключением того, что на этот раз метод all происходит из Any.Это потому, что MRO класса действий включает в себя Any:

say class actions   { }.^mro ; # ((actions) (Any) (Mu))

Вы можете устранить эту складку, объявив свои классы действий с помощью is Mu:

grammar g           { rule all { all } };
class actions is Mu { }
g.parse: 'all',
         rule    => 'all',
         actions => actions, 

Это работает нормально, потому что теперьдействия наследуются только от Mu - и Mu не имеет метода all.

Было бы замечательно, если бы вы могли наследовать от ничего, но не можете;is Mu минимально возможный.

Что мы можем сделать по поводу этой первой ошибки?

Поскольку более новые версии Perl 6 и / или Rakudo могут поставляться с новыми методами Muдля защиты от этой ошибки самое безопасное - всегда объявлять класс действий и всегда объявлять метод, соответствующий каждому правилу в вашей грамматике.Если вы делаете это, вам не нужно следовать никаким правилам именования, чтобы избежать этой ошибки.

TWEAK и т. Д.

Я сообщу об ошибке RT об этом, если не смогу найтисуществующий.

Гольф:

grammar g { rule TWEAK {} }

Это взрывается в время компиляции (сразу после анализа закрывающей фигурной скобки объявления грамматики).Так что это определенно не та же ошибка, что и ошибка item, поскольку последняя вызвана механизмом run-time Actions, который срабатывает только после совпадения правила.

Thisне взрывается:

grammar g { method TWEAK {} }

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

Однако другие субметоды, такие как FALLBACK, не имеют никаких проблем

TWEAK и BUILD методы или подметоды в классе являются частью стандартной конструкции объекта.Они играют совершенно иную роль, чем FALLBACK (которая вызывается, если метод отсутствует).

Что мы можем сделать по поводу этой второй ошибки?

Очевидно, что происходит нечто очень специфическоес TWEAK и BUILD, и они вполне могут быть единственными именами правил, с которыми они сталкиваются.Так что просто избегайте этих двух имен, и вы, надеюсь, избавитесь от этой ошибки.

Случайно используйте встроенные имена правил

См. RT # 125518 - Грамматическое переопределение "идент."поведение .

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

As dwarring notes"Это, безусловно, вызывает путаницу, если вы случайно объявите [правило] с тем же именем, что и встроенное правило. ".

Таким образом, ключевой вопрос заключается в том, каков окончательный источник знания встроенных правил и как можно управлять вещамиучитывая, что они могут меняться со временем?

(Да, очень расплывчато, я знаю. Кроме того, я думаю, что встроенные в Perl 6 обязательно должны расширять NQP, и это, вероятно, актуально. Кроме того, на каждом языке есть несколько сленгов и, возможно, это важно. Я планируючтобы обсудить этот вопрос более подробно в более поздней редакции.)

Другие существенные ошибки

См. также ответ Морица.

...