如何编写 Raku 正则表达式的别名?

lov*_*ato 10 grammar alias raku

我写了一个这样的语法:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我可以用它来解析像“someone %v %n %a”这样的字符串。

但是,我发现有很多像“%v %n %a”这样的用法,我想给它一个别名,比如“%b”,这样解析“someone %b”就相当于解析“someone %” v %n %a”。

那么有没有办法做到这一点?

当然token alias { 'b' { ... } }可以做到。但是那样我需要重复那个动作代码。我想知道是否存在更简单的方法。

mor*_*itz 11

因此,有一种显而易见的方法,即简单地将操作的代码放入子例程中,然后在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($/);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但那有什么乐趣呢?

相反,我建议你使用内置的一个ction对象语法的特点

它是这样的:你有一个单独的类,将动作作为方法,与语法动作同名:

class StatementFormatActions {
    method verb($/) { ... }
    method noun($/) { ... }
    method adverb($/) { ... }

}
Run Code Online (Sandbox Code Playgroud)

当您调用 时parse,您将传递该操作类的一个实例:

StatementFormat.parse($string, :actions(StatementFormatActions.new));
Run Code Online (Sandbox Code Playgroud)

那么在引入aliastoken的时候,也可以引入一个alias方法:

method alias($/) {
    self.verb($/);
    self.noun($/);
    self.adverb($/);
}
Run Code Online (Sandbox Code Playgroud)

在操作中,您还可以调用make$/.make(...)将操作的结果附加到匹配对象(然后在 中可用$/.made)以从解析树填充 AST。

(你可能也喜欢我的语法书,它有几个例子和更深入的解释。对不起,插件,无法抗拒)。