Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

More than enough "Always succeed"? [ RAKU ]

In the documentation of Grammars under Section :

"Always succeed" assertion

I reproduced the example presented there, with added code to show the table produced, in each stage of the parsing mechanism :

use v6.d;

grammar Digifier {
    rule TOP { [ <.succ> <digit>+ ]+ }
    token succ   { <?> }
    token digit { <[0..9]> }
}

class Letters {
    has @!numbers;

    method digit ($/) { @!numbers.tail ~= <a b c d e f g h i j>[$/]; say '---> ' ~ @!numbers }
    method succ  ($/) { @!numbers.push: '!'; say @!numbers }
    method TOP   ($/) { make @!numbers[^(*-1)] }
}

say 'FINAL ====> ' ~ Digifier.parse('123 456 789', actions => Letters.new).made;

The result is the following:

[!]
---> !b
---> !bc
---> !bcd
[!bcd !]
---> !bcd !e
---> !bcd !ef
---> !bcd !efg
[!bcd !efg !]
---> !bcd !efg !h
---> !bcd !efg !hi
---> !bcd !efg !hij
[!bcd !efg !hij !]

FINAL ====> !bcd !efg !hij

I expected only 3 pushes in table @!numbers but I got 4. I am puzzled about the need for an exclusion of the last value of table @!numbers in method "TOP".

Yes I know that the code produces the correct result but why?

Where does the last "Always Succeed" assertion come from?

like image 807
jakar Avatar asked Mar 04 '20 16:03

jakar


1 Answers

A quantified group, eg [ A B ]+, is effectively a loop, repeatedly attempting to match A, and iff that matches, attempting to match B.

Unless it's an infinite loop -- in which case your program will hang -- it will eventually match N times and then move on. If A always matches, but your program doesn't hang, then that must mean B eventually failed. If so, A is guaranteed to have matched one more time than B.

In your code, A is <.succ> which reduces to <?>, which always matches. There are 4 attempts and thus A matches 4 times. In contrast B, which is <digit>+, fails on the fourth attempt so only matches 3 times.

like image 200
raiph Avatar answered Nov 02 '22 13:11

raiph