Perl6 grammars: matching full string

I just started learning perl6 grammar. How can I make a token string that matches everything that is between the beginning of the string and its end? I tried the following without success:

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]; 
+5
source share
4 answers

Here I see problem 2 in your grammar, the first of which is the line of tokens, ^^ and $$ are anchors for the beginning and end of the line, and you can have a new line between them. To illustrate this, simply use a simple regular expression without the first grammar:

 my $txt = q:to/EOS/; row 1 row 2 row 3 EOS if $txt ~~ m/^^.*$$/ { say "match"; say $/; } 

By running this, the output will be:

 match 「row 1 row 2 row 3 

You see that the regular expression matches the desired one more, however, the first problem does not exist, this is due to ratcheting, matching with the token will not work:

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

By running this, the output will be:

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

I'm not quite sure why, but the $$ token and anchor don't seem to work together. But instead, you are looking for everything except a new line, which is \ N * The following grammar solves mainly your problem:

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

However, it matches only the first, since you are looking for only one line, what you might want is a line search + optional vertical space (in your case, you have a new line at the end of your string, but I think you would like to take the last line, even if there is no new line at the end), is repeated several times:

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

The output of this script begin:

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

Also, to help you use and debug your grammar, there are 2 really useful modules: Grammar :: Tracer and Grammar :: Debugger. Just include them at the beginning of the script. Tracer shows a colorful matching tree performed by your grammar. Debugger lets you see it in stages in real time.

+9
source

Your initial aproach can be made to work through

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

Personally, I would not try to bind line and use \N instead, as already suggested.

+7
source
 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]; 

Or, if you can specify a specific line:

 grammar sample { token TOP { <line>+ } rule line { \w+ \d } } 
+2
source
 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>; } 
-3
source

Source: https://habr.com/ru/post/1239404/


All Articles