Raku模块可以用不同的方式指定,例如:
MyModule
MyModule:ver<1.0.3>
MyModule:ver<1.0.3>:auth<Name ([email protected])>;
MyModule:ver<1.0.3>:auth<Name <[email protected]>>;
我写了下面的grammar
来解析对于大多数规范都适用的模块规范,但是如果auth
字段包含<
或>
,则它将失败。在这种情况下,我如何也可以匹配语法?
我不知道该怎么说<
和>
之间的所有内容,包括任何<
和>
。
#!/usr/bin/env perl6
grammar Spec {
token TOP { <spec> }
token spec { <name> <keyval>* }
token name { [<-[./:<>()\h]>+]+ % '::' }
token keyval { ':' <key> <value> }
proto token key { * }
token key:sym<ver> { <sym> }
token key:sym<version> { <sym> }
token key:sym<auth> { <sym> }
token key:sym<api> { <sym> }
token key:sym<from> { <sym> }
# BUG: fix specs that contains '<>' inside value;
token value { '<' ~ '>' $<val>=<-[<>]>* | '(' ~ ')' $<val>=<-[()]>* }
}
my \tests = (
'MyModule:ver<1.0.3>:auth<Name ([email protected])>',
'MyModule:ver<1.0.3>:auth<Name <[email protected]>>',
);
for tests -> \spec {
say so Spec.parse: spec;
}
# Output:
True
False
[如果您知道内部字段基本上与值令牌具有相同的格式,则可以使用$<val>=[.*? <value>?]
递归匹配值。这甚至可以让您分别捕获内部字段的内容:
token value { '<' ~ '>' $<val>=[.*? <value>?] | '(' ~ ')' $<val>=<-[()]>* }
如果您不想要内部内容,则可以使用递归<~~>
代替<value>
token value { '<' ~ '>' $<val>=[.*? <~~>?] | '(' ~ ')' $<val>=<-[()]>* }