Perl6语法:匹配实线

时间:2015-12-29 07:01:11

标签: grammar perl6

我刚刚开始探索perl6语法。如何组成一个标记“行”,它匹配行的开头和结尾之间的所有内容?我尝试了以下但没有成功:

my $txt = q:to/EOS/;
    row 1
    row 2
    row 3
    EOS


grammar sample {
    token TOP {
        <line>
    }

    token line {
        ^^.*$$
    }
}

my $match = sample.parse($txt);

say $match<line>[0];

4 个答案:

答案 0 :(得分:11)

我可以在你的语法中看到2个问题,这里的第一个是令牌行,^^和$$是开始和结束的锚点,但你可以在它们之间有新的行。为了说明,我们首先使用一个简单的正则表达式,而不使用语法:

my $txt = q:to/EOS/;
    row 1
    row 2
    row 3
    EOS

if $txt ~~ m/^^.*$$/ {
    say "match";
    say $/;
}

运行它,输出为:

match
「row 1
row 2
row 3」

你看到正则表达式与期望的匹配更多,但是第一个问题不存在,这是因为棘轮,与令牌匹配将不起作用:

my $txt = q:to/EOS/;
    row 1
    row 2
    row 3
    EOS

my regex r {^^.*$$};
if $txt ~~ &r {
    say "match regex";
    say $/;
} else {
    say "does not match regex";
}
my token t {^^.*$$};
if $txt ~~ &t {
    say "match token";
    say $/;
} else {
    say "does not match token";
}

运行它,输出为:

match regex
「row 1
row 2
row 3」
does not match token

我不确定为什么,但令牌和锚点$$似乎并不能很好地协同工作。但你想要的是搜索除换行符之外的所有内容,即\ N * 以下语法主要解决您的问题:

grammar sample {
    token TOP {<line>}
    token line {\N+}
}

然而它只匹配第一次出现,因为你只搜索一行,你可能想要做的是搜索一行+一个可选的垂直空格(在你的情况下,你的结尾有一个新行)字符串,但我想你想在最后一行采取最后一行,即使最后没有新行),重复几次:

my $txt = q:to/EOS/;
    row 1
    row 2
    row 3
    EOS

grammar sample {
    token TOP {[<line>\v?]*}
    token line {\N+}
}

my $match = sample.parse($txt);
for $match<line> -> $l {
    say $l;
}

该脚本的输出开始:

「row 1」
「row 2」
「row 3」

还帮助您使用和调试语法,2个非常有用的模块:Grammar :: Tracer和Grammar :: Debugger。只需将它们包含在脚本的开头即可。 Tracer展示了由您的语法完成的匹配的彩色树。调试器允许您实时地逐步查看它。

答案 1 :(得分:8)

您的原始方法可以通过

工作
grammar sample {
    token TOP { <line>+ %% \n }
    token line { ^^ .*? $$ }
}

就个人而言,我不会尝试锚定line并使用\N代替已经建议。

答案 2 :(得分:2)

my $txt = q:to/EOS/;
row 1
row 2
row 3
EOS


grammar sample {
    token TOP {
        <line>+
    }
    token line {
        \N+ \n
    }
}

my $match = sample.parse($txt);

say $match<line>[0];

或者,如果您可以具体说明该行:

grammar sample {
    token TOP {
        <line>+
    }
    rule line {
        \w+ \d
    }
}

答案 3 :(得分:-3)

my $txt = q:to/EOS/;
    row 1
    row 2
    row 3
    EOS

grammar sample {
    token TOP { <line> }
    token line { .* }
}

for $txt.lines -> $line {
    ## An single line of text....
    say $line;
    ## Parse line of text to find match obj...
    my $match = sample.parse($line);
    say $match<line>;
}