原始令牌候选者排序

时间:2019-05-15 21:25:32

标签: regex grammar perl6 raku

perl6如何确定首先匹配哪个proto token

以下代码按预期工作,它与字符串1234匹配,并且Grammar::Tracer显示与之匹配的第一个令牌是s:sym<d>,这是有道理的,因为它是最长的令牌。 / p>

但是,如果我将文字更改为令牌,例如,将token的{​​{1}} three形式从'3'更改为<digit>,则它将不匹配,并且{{1} }显示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

1 个答案:

答案 0 :(得分:13)

  

perl6如何确定首先匹配哪个原型令牌?

它使用"Longest alternation" logic。在您(表现出色!)的情况下,相关的决定因素如下。

  

首先,选择具有最长声明性前缀的分支。

因此,首先要注意的是它不是“最长令牌”,而是最长声明性前缀,即除了连续的“声明性”内容之外,什么都不包含的模式的 start “原子”。

3是声明性原子。

<foo>可能会或可能不会;这取决于它包含的内容。

我还没有找到明确的官方文档来确定哪些内置模式是声明性的,哪些不是声明性的,但是看起来所有用斜杠声明的那些声明,例如\d都是声明性的而所有以<foo>形式声明的变量,例如<digit>都不是。 (尤其要注意,内置<ws>模式不是声明性的。rules中原子之后的空格被转换为<ws>,这意味着第一个这样的空格会终止该规则的声明性前缀。)

因此<digit>原子不是声明性前缀的一部分,而是终止了前缀。

  

s:sym<d>移到顶部,在两种情况下都匹配字符串,但是对此行为的解释是什么?

由于将<three>更改为调用<digit>,因此您已经更改了规则,使三个具有最长声明性前缀(<one> <two>)的关系。 other tie-breaking rules are used

如果所有其他规则都未能通过平局规则选出获胜者,则将选择最后一个“最左侧”规则,ignoring inheritance表示该规则在词汇上排在第一位。