Грамматика для разбора спецификации модуля - PullRequest
9 голосов
/ 30 сентября 2019

Модули Raku можно указывать по-разному, например:

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>>;

Я написал ниже 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@example.com)>',
  'MyModule:ver<1.0.3>:auth<Name <email@example.com>>',
);

for tests -> \spec {

  say so Spec.parse: spec;

}

# Output:
True
False

1 Ответ

7 голосов
/ 30 сентября 2019

Если вы знаете, что внутреннее поле будет в основном в том же формате, что и маркер значения, вы можете рекурсивно сопоставить значение со значением $<val>=[.*? <value>?]. Это даже позволяет вам захватывать содержимое внутреннего поля отдельно:

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

Если вам не нужно внутреннее содержимое, вы можете использовать рекурсивный <~~> вместо <value>

token value { '<' ~ '>' $<val>=[.*? <~~>?] | '(' ~ ')' $<val>=<-[()]>* }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...