如何编写 Raku 正则表达式的别名?
How can I write an alias of Raku regexes?
我写了这样一个语法:
grammar StatementFormat {
token TOP { (<plain> | '%' <placeholder>)* }
token plain { <-[%]> }
token placeholder {
| <verb>
| <noun>
| <adverb>
}
token verb {
'v'
{
# some actions
}
}
token noun {
'n'
{
# some actions
}
}
token adverb {
'a'
{
# some actions
}
}
}
所以我可以用它来解析像“someone %v %n %a”这样的字符串。
但是,我发现像“%v %n %a”这样的用法太多了,我想给它起一个别名,比如“%b”,这样解析“someone %b”是等价的解析“某人 %v %n %a”。
那么有办法吗?
当然,token alias { 'b' { ... } }
可以做到。但是那样我需要重复那个动作代码。想知道有没有更简单的方法
所以,有一种显而易见的方法,就是将操作代码简单地放入子例程中,然后在 b
别名中调用它们:
sub verb-action($/) { }
sub noun-action($/) { }
sub adverb-action($/) { }
grammar StatementFormat {
# rest goes here
token verb {
'v'
{ verb-action($/) }
}
token noun {
'n'
{ noun-action($/) }
}
token adverb {
'a'
{ adverb-action($/) }
}
token alias {
'b'
{
verb-action($/);
noun-action($/);
adverb-action($/);
}
}
}
但这有什么乐趣呢?
相反,我建议使用内置的 action object feature of grammars。
它是这样的:你有一个单独的 class,其中的动作作为方法,与语法动作同名:
class StatementFormatActions {
method verb($/) { ... }
method noun($/) { ... }
method adverb($/) { ... }
}
并且当您调用 parse
时,您会传递该操作的一个实例 class:
StatementFormat.parse($string, :actions(StatementFormatActions.new));
那么在引入alias
令牌的同时,还可以引入一个alias
方法:
method alias($/) {
self.verb($/);
self.noun($/);
self.adverb($/);
}
在操作中,您还可以调用 make
或 $/.make(...)
将您的操作结果附加到匹配对象(然后在 $/.made
中可用)以从您的解析树。
(你可能也喜欢my book on grammars,里面有几个例子和更深入的解释。对不起,插件,无法抗拒)。
我写了这样一个语法:
grammar StatementFormat {
token TOP { (<plain> | '%' <placeholder>)* }
token plain { <-[%]> }
token placeholder {
| <verb>
| <noun>
| <adverb>
}
token verb {
'v'
{
# some actions
}
}
token noun {
'n'
{
# some actions
}
}
token adverb {
'a'
{
# some actions
}
}
}
所以我可以用它来解析像“someone %v %n %a”这样的字符串。
但是,我发现像“%v %n %a”这样的用法太多了,我想给它起一个别名,比如“%b”,这样解析“someone %b”是等价的解析“某人 %v %n %a”。
那么有办法吗?
当然,token alias { 'b' { ... } }
可以做到。但是那样我需要重复那个动作代码。想知道有没有更简单的方法
所以,有一种显而易见的方法,就是将操作代码简单地放入子例程中,然后在 b
别名中调用它们:
sub verb-action($/) { }
sub noun-action($/) { }
sub adverb-action($/) { }
grammar StatementFormat {
# rest goes here
token verb {
'v'
{ verb-action($/) }
}
token noun {
'n'
{ noun-action($/) }
}
token adverb {
'a'
{ adverb-action($/) }
}
token alias {
'b'
{
verb-action($/);
noun-action($/);
adverb-action($/);
}
}
}
但这有什么乐趣呢?
相反,我建议使用内置的 action object feature of grammars。
它是这样的:你有一个单独的 class,其中的动作作为方法,与语法动作同名:
class StatementFormatActions {
method verb($/) { ... }
method noun($/) { ... }
method adverb($/) { ... }
}
并且当您调用 parse
时,您会传递该操作的一个实例 class:
StatementFormat.parse($string, :actions(StatementFormatActions.new));
那么在引入alias
令牌的同时,还可以引入一个alias
方法:
method alias($/) {
self.verb($/);
self.noun($/);
self.adverb($/);
}
在操作中,您还可以调用 make
或 $/.make(...)
将您的操作结果附加到匹配对象(然后在 $/.made
中可用)以从您的解析树。
(你可能也喜欢my book on grammars,里面有几个例子和更深入的解释。对不起,插件,无法抗拒)。