Разница в области захвата и не захвата регулярных выражений в Perl 6 / Raku - PullRequest
5 голосов
/ 29 сентября 2019

Несмотря на то, что в документации указано, что вызов токена / правила / регулярного выражения как <.foo> вместо <foo> делает их не захватывающими, похоже, что существует разница в области видимости, но я не уверен, предназначен ли он для этого.

Вот упрощенный тест. В файле модуля:

unit module Foo;
my token y           {     y  }
my token a is export { x  <y> }
my token b is export { x <.y> }

Внутри другого файла скрипта:

grammar A {
  use Foo;
  token TOP { <a> }
}

grammar B {
  use Foo;
  token TOP { <b> }
}

Если мы вызываем A.parse("xy"), все работает как положено. Однако вызов B.parse("xy") приводит к ошибке No such method 'y' for invocant of type 'B'. Это ожидаемое поведение или потенциальная ошибка?

1 Ответ

6 голосов
/ 29 сентября 2019

Намерение в соответствии с S05

Намерение в соответствии с соответствующим документом по спекуляции / дизайну включает в себя:

<foo ...>

Эта форма всегда отдает предпочтениеобъявление регулярного выражения в лексической области, отправляющее непосредственно к нему, как если бы оно было функцией. Если в области действия нет такого лексического регулярного выражения (или лексического метода), вызов отправляется на текущую грамматику, при условии, что она существует.

...

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

...

Вызов <foo> завершится неудачно, если нет лексического выраженияподпрограмма с таким именем, которую он может вызывать, или любой метод с таким именем, доступный через диспетчеризацию метода. (Решение о том, какой диспетчер использовать, принимается во время компиляции, а не во время выполнения; вызов метода не является резервным механизмом.)

Примеры форм

  • <bar> как описано выше. Он предпочтительно разрешает раннюю лексическую (my / our) процедуру / правило с именем &bar. В противном случае он разрешает позднюю связанную попытку вызова , имеющего (has) метод / правило с именем bar. Если это удается, он сохраняет совпадение под перехватом с именем bar.

  • <.bar>, вызывает имеет (has) метод / правило с именем bar если найдетОн не захватывает.

  • <bar=.bar> вызывает имеет (has) метод / правило с именем bar, если он его находит. Если это удастся, он сохраняет совпадение под перехватом с именем bar. Другими словами, он такой же, как <bar>, за исключением того, что он только пытается вызвать , имеет метод с именем .bar;сначала он не пытается разрешить лексический &bar.

  • <&bar> и <.&bar> означают одно и то же. Они вызывают лексическую процедуру с именем &bar и делают , а не перехват. Чтобы сделать то же самое, но захватить, используйте <bar=&bar> или <bar=.&bar>.

(Если вы прочитаете документацию по спекуляции / дизайну, приведенную выше, и попробуете что-то, вы найдете большинстводеталей дизайна, о которых упоминается в документе, уже были реализованы в Rakudo, даже если они официально не поддерживаются / не печатаются / не документируются.)

Примеры областей применения

Первый общий случай:

grammar c {
  has rule TOP { <bar> }
  has rule bar { . { say 'has rule' } }
}
say c.parse: 'a';

отображает:

has rule
「a」
 bar => 「a」

(объявители has являются необязательными, и их идиоматично исключать.)

Теперь вводим правило, лексически ограниченное областью грамматического блока:

grammar c {
  my  rule bar { . { say 'inner my rule' } }
  has rule TOP { <bar> }
  has rule bar { . { say 'has rule' } }
}
say c.parse: 'a';

отображает:

inner my rule
「a」
 bar => 「a」

Даже лексическое правило, объявленное за пределами , грамматический блок имеет приоритет над , имеет правила:

my rule bar { . { say 'outer my rule' } }
grammar c {
  has rule TOP { <bar> }
  has rule bar { . { say 'has rule' } }
}
say c.parse: 'a';

отображает:

outer my rule
「a」
 bar => 「a」
...