这是两个语法。一个使用proto token
而一个不使用proto
。他们都完成了同样的事情。这些基本上是S05 under "Variable (non-)interpolation"中的示例。在这个简单的例子中,他们都能够做同样的事情。
哪种情况可以证明所有额外的打字? proto
令牌在动作类中有不同的方法,也许在那里有一个小的好处。但是,您必须输入一些额外的东西才能获得这些好处。
是否有grammar NoProto {
token variable { <sigil> <identifier> }
token identifier { <ident>+ }
token sigil { < $ @ % & :: > }
}
grammar YesProto {
token variable { <sigil> <identifier> }
token identifier { <ident>+ }
proto token sigil { * }
token sigil:sym<$> { <sym> }
token sigil:sym<@> { <sym> }
token sigil:sym<%> { <sym> }
token sigil:sym<&> { <sym> }
token sigil:sym<::> { <sym> }
}
class Proto::Actions {
method variable ($/) {
say "found variable: " ~ $/;
}
method identifier ($/) {
say "found identifier: " ~ $/;
}
method sigil ($/) {
say "found sigil: " ~ $/;
}
method sigil:sym<$> ($/) {
say "found sym sigil: " ~ $/;
}
}
my $variable = '$butterfuly';
say "------No proto parsing";
my $no_proto_match = NoProto.parse(
$variable,
:rule<variable>,
:actions(Proto::Actions),
);
say "------Yes proto parsing";
my $yes_proto_match = YesProto.parse(
$variable,
:rule<variable>,
:actions(Proto::Actions),
);
的某些功能使语法的其他部分更容易?
proto
输出显示------No proto parsing
found sigil: $
found identifier: butterfuly
found variable: $butterfuly
------Yes proto parsing
found sym sigil: $
found identifier: butterfuly
found variable: $butterfuly
在操作类中调用不同的方法:
/content/geometrixx/en/toolbar/
答案 0 :(得分:8)
从技术上讲,如果您未自行指定,则会为您制作proto
。它基本上为特定的token
创建了多方法调度处理程序(就像它与sub
和method
一样)。你通常不需要关心。
为什么要指定proto
?我可以想到很多原因:
token
分享一些特征是的,{ * }
可能包含可执行代码。裸Whatever
表示向适当的候选人发送。使用sub
:
proto a(|) { say "before"; {*}; say "after" }
multi a(Int) { say "Int" }
multi a(Str) { say "Str" }
a 42; a "42"
所示:
before
Int
after
before
Str
after
希望这会有所帮助: - )
答案 1 :(得分:7)
在动作类中调用它可以用于分离逻辑。除了语法之外,它与多方法基本相同。
(我wrote this用于评估Code Golf)的答案
grammar Mathemania {
token TOP { <cmd-list> }
token cmd-list { <cmd>+ }
token cmd { <op> <argument>? }
proto token op { * }
token op:sym<exp> { e } # notice that the name doesn't have to match
token op:sym<factorial> { f }
token op:sym<root> { r }
token op:sym<ceil> { c }
token op:sym<floor> { l }
token argument { '(' ~ ')' <cmd-list> }
}
class Calculate {
method TOP ($/) { make $<cmd-list>.made }
method argument ($/) { make $<cmd-list>.made }
method cmd-list ($/) {
my $result = 2;
$result = .made.($result).narrow for @<cmd>;
make $result;
}
method cmd ($/) {
if $<argument> {
make $<op>.made.assuming( *, $<argument>.made );
} else {
make $<op>.made;
}
}
method op:sym<exp> ($/) { make -> \n, \e = 2 { n ** e } }
method op:sym<factorial> ($/) { make -> \n, \k = 2 { [*] n, n - k + 1 ...^ 0 } }
method op:sym<root> ($/) { make -> \n, \r = 2 { n ** (1/r) } }
method op:sym<ceil> ($/) { make &ceiling }
method op:sym<floor> ($/) { make &floor }
}
它还使得子类化语法可以将其标记与已存在的标记一起添加,并且子类化动作类可以执行相同的操作。 (try it)
grammar Mathmania-Plus is Mathemania {
token op:sym<negate> { n }
token op:sym<abs> { a }
}
class Calculate-Plus is Calculate {
method op:sym<negate> ($/) { make &prefix:<-> }
method op:sym<abs> ($/) { make &abs }
}
答案 2 :(得分:7)
将您的替代品拆分为proto和multis的一个好处是您可以更可靠地扩展它。您可以在语法中将multis添加到语法中,该语法继承了声明proto的语法,并且您不需要列出所有可能的替代方案(如果是a,则必须执行此操作单一规则)。
这意味着您甚至可以对同一语法进行多次独立扩展,例如通过混合使用多个规则来为不同的符号提供匹配。
这基本上是Perl 6在定义自定义运算符时使用的机制:有匹配不同类型运算符的规则(如中缀,前缀,后缀,...),并声明新运算符派生来自当前活动的新语法,为新运算符添加了多个候选语法。由于proto令牌机制的可扩展性,脚本可以从几个彼此不了解的模块中导入操作符。