在Perl 6中用sub构建一个正则表达式

时间:2017-11-10 20:35:23

标签: perl6

在学习how to pass regexes as arguments之后,我尝试使用sub构建我的第一个正则表达式,并且我再次陷入困境。对于下面的复杂规则感到抱歉,我已尽力简化它们。我至少需要一些线索来解决这个问题。

regex应由更改组成,每个更改由leftmiddleright组成,其中leftright应该成对出现middle的变体取决于选择right

Pairs数组包含leftright对:

my Pair @leftright =
  A => 'a',
  ...
  Z => 'z',
  ;
从散列中读取

Middle变体:

my Regex %middle = 
  z => / foo /,
  a => / bar /,
  m => / twi /,
  r => / bin /,
  ...
  ;
如果%middle<z>rightz - 如果%middle<a>right等,则应选择{p> a

因此,生成的正则表达式应该是

my token word {
    | A <%middle[a]> a
    | Z <%middle[z]> z
    | ...
}

或更常见的

my token word {
    | <left=@leftright[0].key> 
      <middle=%middle{@leftright[0].value}> 
      <right=@leftright[0].value> 
    | (the same for index == 1)
    | (the same for index == 2)
    | (the same for index == 3)
 ...
}

它应与AbaraZfooz匹配。

如何构建token word(可以在grammar中使用sub),@leftright将从%middle{}中获取每对,放置合适的right取决于regex的值,然后将它们全部合并为一个my Regex sub sub_word(Pair @l_r, Regex %m) { ... } my token word { <{sub_word(@leftright, %middle)}> }

left

比赛结束后,我需要知道middleright"Abara" ~~ &word; say join '|', $<left>, $<middle>, $<right> # A|bar|a 的值:

import re
line = "7654 16.317 8.651 7.70.582 17.487"
val = line.split(" ")[3]
m = re.search('^([0-9]+\.[0-9]+).*', val)
m.group(1)

1 个答案:

答案 0 :(得分:2)

我无法使用token执行此操作,但此处是EVALRegex的解决方案(我还使用%middle作为哈希Str而不是Regex的哈希值:

my Regex sub build_pattern (%middle, @leftrigth) {
    my $str = join '|', @leftright.map(
        {join ' ',"\$<left>='{$_.key}'", "\$<middle>='{%middle{$_.value}}'", "\$<right>='{$_.value}'"});
    );
    my Regex $regex = "rx/$str/".EVAL;

    return $regex;
}

my Regex $pat = build_pattern(%middle, @leftright);

say $pat;
my $res = "Abara" ~~ $pat;
say $res;

<强>输出

rx/$<left>='A' $<middle>='bar' $<right>='a'|$<left>='Z' $<middle>='foo' $<right>='z'/
「Abara」
 left => 「A」
 middle => 「bar」
 right => 「a」

有关我选择使用EVAL的原因的详细信息,请参阅How can I interpolate a variable into a Perl 6 regex?