*可以在符号令牌中使用多个字符吗?

jjm*_*elo 5 grammar perl6 raku

显示(WhateverCode)代表单个符号的示例sym*

grammar Foo {
    token TOP { <letter>+ }
    proto token letter {*}
    token letter:sym<P> { <sym> }
    token letter:sym<e> { <sym> }
    token letter:sym<r> { <sym> }
    token letter:sym<l> { <sym> }
    token letter:sym<*> {   .   }
}.parse("I ? Perl", actions => class {
    method TOP($/) { make $<letter>.grep(*.<sym>).join }
}).made.say; # OUTPUT: «Perl?» 
Run Code Online (Sandbox Code Playgroud)

但是,如果我们用它代替由几个字母组成的符号,它将失败:

grammar Foo {
    token TOP { <action>+ % " " }
    proto token action {*}
    token action:sym<come> { <sym> }
    token action:sym<bebe> { <sym> }
    token action:sym<*> { . }
}.parse("come bebe ama").say; # Nil
Run Code Online (Sandbox Code Playgroud)

由于sym本身可用于具有多个字符的符号,因此我们如何定义与一组字符匹配的默认sym令牌?

rai*_*iph 5

可以*sym令牌中使用多个字符吗?... sym显示*WhateverCode)代表单个符号的示例

不是WhateverCodeWhatever1个

<...>foo:sym<...>是一个报价的话构造,所以...只是一个字符串。

这就是为什么这样工作:

grammar g { proto token foo {*}; token foo:sym<*> { <sym> } }
say g.parse: '*', rule => 'foo'; # matches
Run Code Online (Sandbox Code Playgroud)

就P6而言,*in foo:sym<*>只是一个随机字符串。可能是abracadabra。我认为作者选择*代表“无论如何”的心理概念,因为它恰好与P6概念相匹配Whatever。也许他们太可爱了。

对于此答案的其余部分,我将编写JJ而不是*在P6涉及的任何地方,后者都不是任意字符串。


* 在原Whatever。但这与您的问题完全无关:

grammar g { proto token foo {*}; token foo:sym<JJ> { '*' } }
say g.parse: '*', rule => 'foo'; # matches
Run Code Online (Sandbox Code Playgroud)

在名称包括:sym<...>一部分的规则的主体(令牌和正则表达式为规则)中,您可以编写<sym>并且它将与角度之间的字符串匹配:sym<...>

grammar g { proto token foo {*}; token foo:sym<JJ> { <sym> } }
say g.parse: 'JJ', rule => 'foo'; # matches
Run Code Online (Sandbox Code Playgroud)

但是您可以在rule / token / regex正文中编写任何您喜欢的内容。A .与单个字符匹配:

grammar g { proto token foo {*}; token foo:sym<JJ> { . } }
say g.parse: '*', rule => 'foo'; # matches
Run Code Online (Sandbox Code Playgroud)

但是,如果我们用它代替由几个字母组成的符号,它将失败

不。那是因为您更改了语法。

如果将语法改回原始编码(除了long,letter:sym<...>则可以正常工作):

grammar Foo {
  token TOP { <letter>+ }
  proto token letter {*}
  token letter:sym<come> { <sym> }
  token letter:sym<bebe> { <sym> }
  token letter:sym<JJ> { . }
}.parse(
   "come bebe ama",
   actions => class { method TOP($/) { make $<letter>.grep(*.<sym>).join } })
 .made.say; # OUTPUT: «comebebe?»
Run Code Online (Sandbox Code Playgroud)

请注意,在原始版本中,letter:sym<JJ>令牌在机翼中等待以匹配任何单个字符-并且由于该字符包含单个空格,因此它与那些匹配并且被处理。

但是在修改中,您在令牌中的令牌之间添加了所需的空间TOP。这有两个影响:

  • 它匹配“ come”之后和“ bebe”之后的空间;

  • 在“ a”被匹配后letter:sym<JJ>,“ a”和“ m”之间没有空格表示此时整体匹配失败。

sym本身可用于具有多个字符的符号

是。所有token foo:sym<bar> { ... }要做的就是添加:

  • 多重调度的替代foo;

  • 一个在sym词法上作用域为foo令牌主体的令牌,与匹配'bar'

我们如何定义sym与一组字符匹配的默认标记?

您可以编写这样的sym令牌,但是要明确一点,因为您不希望它与固定字符串匹配,因此它不能<sym>在主体中使用(因为a <sym>必须是固定字符串。)如果您仍然想要在键下捕获sym然后您可以$<sym>=在令牌正文中写出内容,如Håkon在其答案下方的评论中所示。但它也可能letter:whatever存在$<sym>=于体内。

我将其写为letter:default令牌来强调它的存在:sym<something>没有任何区别。(如上面所解释的,:sym<something>只是大约是提供一种选择,与其他沿:baz<...>S和:bar<...>S,与只添加是如果它是:sym<something>,则它使得<sym>在相关联的规则的身体,这,如果使用的话,比赛可用的子规则固定字符串'something'。)

在所有rule foo:bar:baz:qux<...>备选方案中的获胜调度是根据LTM逻辑从以开头的规则中选择的foo。所以,你需要写这样一个令牌,它不会赢得作为一个最长前缀令牌,但只有当没有其他比赛相匹配。

要立即在LTM竞赛中返回背包{},请在规则主体2的开头插入a :

token letter:default { {} \w+ }
Run Code Online (Sandbox Code Playgroud)

现在,从包装的背面开始,如果此规则有机会与\w+模式匹配,则该模式将在击中非单词字符时停止标记。

如果没有其他匹配项,则使之匹配可能意味着最后将其列出。所以:

grammar Foo {
  token TOP { <letter>+ % ' ' }
  proto token letter {*}
  token letter:sym<come> { <sym> }    # matches come
  token letter:sym<bebe> { <sym> }    # matches bebe
  token letter:boo       { {} \w**6 } # match 6 char string except eg comedy
  token letter:default   { {} \w+ }   # matches any other word
}.parse(
   "come bebe amap",
   actions => class { method TOP($/) { make $<letter>.grep(*.<sym>).join } })
 .made.say; # OUTPUT: «comebebe?»
Run Code Online (Sandbox Code Playgroud)

那根本不可能是引起它的东西...“ bebe ama”不应该在您的语法中起作用

该代码中有错误,现在我已修复并对此表示歉意。如果您运行它,您会发现它可以像宣传的那样工作。

但是您的评论促使我扩大了答案。希望它现在可以正确回答您的问题。

脚注

1并不是所有这些都与实际发生的事情有关,而是...在P6 *中,“术语位置”(英语中,名词所属,在通用编程术语中,值所属)是a Whatever,而不是一个WhateverCode。即使在*与操作员一起写的时候,例如。+*或者* + *,而不是自己的,则*s为仍然只是WhateverS中,但编译器会自动打开一个或多个大多数这样的组合*s的一个或多个运营商进入一个子类Code叫做WhateverCode。(例外情况在此处的表中列出。)

2请参见我对SO的回答“ perl6语法,不确定示例中的某些语法”中的脚注2 。