Заказ кандидатов на прото токены - PullRequest
13 голосов
/ 16 мая 2019

Как perl6 решает, с каким proto token сопоставить первым?

Приведенный ниже код работает должным образом, он соответствует строке 1234, а Grammar::Tracer показывает, что первый сопоставленный токен равен s:sym<d>, что имеет смысл, поскольку это самый длинный токен.

Однако, если я изменил литерал на токен, например, изменив token three форму '3' на <digit>, он не сможет соответствовать, и Grammar::Tracer показывает, что s:sym<b> сопоставляется с первый.

Перемещение s:sym<d> наверх соответствует строке в обоих случаях, но как объяснить такое поведение?

#!/usr/bin/env perl6
no precompilation;
use Grammar::Tracer;

grammar G {

  token TOP { <s> }

  proto token s { * }

  token s:sym<a> { <one> }
  token s:sym<b> { <one> <two> }
  token s:sym<c> { <one> <two> <three> }
  token s:sym<d> { <one> <two> <three> <four> }

  token one   { '1' }
  token two   { '2' }
  token three { '3' }
  token four  { '4' }
}

my $g = G.new;

say $g.parse: '1234';
# Output: Match
# token three { '3' }

TOP
|  s
|  |  s:sym<d>
|  |  |  one
# Output No Match
# token three { <digit> }

TOP
|  s
|  |  s:sym<b>
|  |  |  one

1 Ответ

13 голосов
/ 16 мая 2019

Как perl6 решает, с каким протокеном сопоставить первым?

Используется логика "Самое длинное чередование" . В вашем (хорошо представленном!) Случае соответствующие решающие факторы заключаются в следующем.

Сначала выберите ветку, которая имеет самый длинный декларативный префикс .

Итак, первое, на что нужно обратить внимание, это то, что это не «самый длинный токен», а самый длинный декларативный префикс , начало шаблона, который содержит только непрерывные «декларативные» атомы ».

A 3 является декларативным атомом.

A <foo> может или не может быть; это зависит от того, что оно включает.

Я не нашел четкой официальной документации, определяющей, какие встроенные шаблоны являются декларативными, а какие нет, но похоже, что все объявленные с косой чертой, например \d, являются декларативными, тогда как все объявленные в форме <foo>, например <digit>, не являются. (В частности, обратите внимание, что встроенный шаблон <ws> является , а не декларативным. Учитывая, что пробелы после атомов в rules преобразуются в <ws>, это означает, что первый такой пробел завершает декларативный префикс этого править.)

То есть атом <digit> не является частью декларативного префикса и вместо этого завершает префикс.

Перемещение s:sym<d> наверх, соответствует строке в обоих случаях, но как объяснить такое поведение?

Потому что с изменением <three> на <digit> вы изменили свои правила, чтобы иметь три, которые связывают самый длинный декларативный префикс (<one> <two>). Так что используются другие правила разрыва связей .

Если в правилах разрыва связей все остальное не удается выбрать победителя, то выбирается последнее «крайнее левое» правило, которое, игнорирующее наследование , означает правило, которое стоит на первом месте лексически.

...