如何编写 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,里面有几个例子和更深入的解释。对不起,插件,无法抗拒)。