Raku modules can be specified in different ways, for example:
MyModule
MyModule:ver<1.0.3>
MyModule:ver<1.0.3>:auth<Name (email@example.com)>;
MyModule:ver<1.0.3>:auth<Name <email@example.com>>;
I wrote the below grammar to parse the module spec which works fine for most of specs but it fails if the auth field contains < or >. How can I fix the grammar to match in this case as well?
I can't figure out how to say match everything in between < and > including any < and > as well.
#!/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@example.com)>',
'MyModule:ver<1.0.3>:auth<Name <email@example.com>>',
);
for tests -> \spec {
say so Spec.parse: spec;
}
# Output:
True
False
Run Code Online (Sandbox Code Playgroud)
If you know that the inner field will basically be in the same format as the value token, you can recursively match for value with $<val>=[.*? <value>?]. This even lets you capture the contents of the inner field seperately:
token value { '<' ~ '>' $<val>=[.*? <value>?] | '(' ~ ')' $<val>=<-[()]>* }
Run Code Online (Sandbox Code Playgroud)
If you don't want the inner contents than you can use the recursive <~~> in place of <value>
token value { '<' ~ '>' $<val>=[.*? <~~>?] | '(' ~ ')' $<val>=<-[()]>* }
Run Code Online (Sandbox Code Playgroud)