语法解析模块规范

问题描述 投票:8回答:1

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
perl6 raku
1个回答
5
投票

[如果您知道内部字段基本上与值令牌具有相同的格式,则可以使用$<val>=[.*? <value>?]递归匹配值。这甚至可以让您分别捕获内部字段的内容:

token value { '<' ~ '>' $<val>=[.*? <value>?] | '(' ~ ')' $<val>=<-[()]>* }

如果您不想要内部内容,则可以使用递归<~~>代替<value>

token value { '<' ~ '>' $<val>=[.*? <~~>?] | '(' ~ ')' $<val>=<-[()]>* }
© www.soinside.com 2019 - 2024. All rights reserved.