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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With