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

时间:2019-07-01 07:33:10

标签: grammar perl6

example for 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␤» 

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

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

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

3 个答案:

答案 0 :(得分:5)

  

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

它不是WhateverCodeWhatever 1

<...>中的foo:sym<...>是一个引号构造函数,因此...只是一个文字字符串。

这就是为什么这样的原因:

grammar g { proto token foo {*}; token foo:sym<*> { <sym> } }
say g.parse: '*', rule => 'foo'; # matches

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

对于其余的答案,我会写JJ而不是*,只要后者只是P6的任意字符串。


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

grammar g { proto token foo {*}; token foo:sym<JJ> { '*' } }
say g.parse: '*', rule => 'foo'; # matches

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

:sym<...>

但是您可以在rule / token / regex正文中编写任何您喜欢的内容。 grammar g { proto token foo {*}; token foo:sym<JJ> { <sym> } } say g.parse: 'JJ', rule => 'foo'; # matches 与单个字符匹配:

.
  

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

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

如果您将语法改回原始编码(除了较长的grammar g { proto token foo {*}; token foo:sym<JJ> { . } } say g.parse: '*', rule => 'foo'; # matches 之外),它将可以正常工作:

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␤» 令牌在机翼中等待与任何单个字符匹配,并且该字符包含单个空格,因此它与那些匹配并且将被处理。

但是在修改中,您在letter:sym<JJ>令牌中的令牌之间添加了必需空格。有两个效果:

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

  • 在将“ a”与TOP匹配后,“ a”和“ m”之间缺少空格表示此时整体匹配失败。

  

letter:sym<JJ>本身可用于具有多个字符的符号

是的。 sym所做的只是添加:

  • token foo:sym<bar> { ... };

  • 的多调度替代方法
  • 令牌foo,在词法上作用于sym令牌的主体,与foo匹配。

  

我们如何定义与一组字符匹配的默认'bar'令牌?

您可以编写这样的sym令牌,但是要清楚一点,因为您不希望它与固定的字符串匹配,所以不能在正文中使用sym。(因为<sym>必须是固定的字符串。)如果您仍然想在键<sym>下进行 capture ,则可以像Håkon所示在令牌主体中写上sym在他们的答案下发表评论。但也可能是$<sym>=,其中letter:whatever在体内。

我将其写为$<sym>=令牌以强调它是letter:default并没有什么不同。 (如上所述,:sym<something>以及其他:sym<something>:baz<...>都是替代品,唯一的补充是如果是:bar<...>,还会 在关联规则的正文中提供一个:sym<something>子规则,该子规则(如果使用的话)与固定字符串<sym>相匹配。)

'something'开始的规则中,根据LTM logic选择所有rule foo:bar:baz:qux<...>备选方案中的获胜分配。因此,您需要编写这样的令牌,该令牌不会作为最长的令牌前缀获胜,而只有在没有其他匹配条件时才匹配。

要立即在LTM竞赛中返回背包,请在规则正文 2 的开头插入foo

{}

现在,从背包的背面开始,如果有此规则,它将与token letter:default { {} \w+ } 模式匹配,该模式将在遇到非单词字符时停止令牌。

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

\w+
  

那根本不是导致它的原因...“ bee ama”不应该在您的语法中起作用

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

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

脚注

1 并非所有这些都与实际发生的事情有关,但是...在P6中,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␤» 中“术语位置”(英语,名词所属的名词) ,在一般的编程术语中,值所属的语言)是Whatever,而不是WhateverCode。即使*是用运算符编写的,例如*+*,而不是单独使用,* + *只是*,它们仍然静止,但是编译器会自动将大多数此类组合带有一个或多个运算符的一个或多个Whatever的一个子类,称为*的子类Code。 (例外情况列在表here中。)

2 参见my answer to SO "perl6 grammar , not sure about some syntax in an example"中的脚注2。

答案 1 :(得分:3)

print(lst[-1])的内容用于程序的读者,而不用于编译器,用于区分名称相同的多个标记。

碰巧的是,程序员开始写这样的语法:

:sym<...>

为避免重复符号(此处为token operator:sym<+> { '+' } token operator:sym<-> { '-' } token operator:sym</> { '/' } +-),引入了特殊规则/,该规则与<sym>中的内容匹配为文字,因此您可以将上述标记写为

:sym<...>

如果您不在正则表达式中使用token operator:sym<+> { <sym> } token operator:sym<-> { <sym> } token operator:sym</> { <sym> } ,则可以在<sym>内部随意编写任何内容,因此可以编写类似

的内容
:sym<...>

答案 2 :(得分:1)

也许是这样的:

grammar Foo {
    token TOP { <action>+ % " " }
    proto token action {*}
    token action:sym<come> { <sym> }
    token action:sym<bebe> { <sym> }
    token action:sym<default> { \w+ }
}.parse("come bebe ama").say;

输出

「come bebe ama」
 action => 「come」
  sym => 「come」
 action => 「bebe」
  sym => 「bebe」
 action => 「ama」