More than enough "Always succeed"? [ RAKU ]
Asked Answered
C

1

5

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?

Claudineclaudio answered 4/3, 2020 at 16:18 Comment(0)
O
6

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.

Opprobrious answered 4/3, 2020 at 20:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.