Attached is my use case which is parsing of PDF cross reference indices.
There are normally three numeric entries per line. e.g.
xref
0 8
0000000000 65535 f
0000000009 00000 n
0000000074 00000 n
0000000120 00000 n
Which populates nicely into an array of 'n' lines of shape 3.
There's the rare, but possible case of an xref section with zero entries
xref
0 0
(I've encountered real-world PDF's like this).
The attached grammar/actions attempted to handle it as an array of shape
[0;3],
but wont work on current Rakudo.
Just my preferred solution for the above case.
- David
On Sun, Aug 27, 2017 at 12:38 PM, Brandon Allbery via RT <
[email protected]> wrote:
> > Well, what do you mean? Of course you can't put anything into it, and any
> > attempt to index it will throw. It may seem useless, however, if you can
> > have
> > an empty array, why can't you have a shaped empty array?
> >
>
> Only if all dimensions are unindexable. Otherwise you have something with
> inaccessible slots (and, potentially thereby, not truly leaked but
> unusable, memory).
>
> And an empty unshaped array, in addition to being usable as such
> (degenerate case of all shaped dimensions being size 0), can be made
> non-empty. Shaped arrays cannot.
>
>
grammar XRef {
rule TOP { xref\n<xref-section>+ }
rule xref-section {<obj-first-num=.int> <obj-count=.int>' '*\n<xref-entry>*}
rule xref-entry {<byte-offset=.int> <gen-number=.int> <obj-status>' '?\n}
token int { < + - >? \d+ }
token obj-status:sym<free> {f}
proto token obj-status {*}
token obj-status:sym<inuse> {n}
}
class XRef::Actions {
method TOP ($/) {
my $xref = [ $<xref-section>>>.ast ];
make $xref;
}
method xref-section($/) {
my uint $obj-count = $<obj-count>.ast.value;
my uint $obj-first-num = $<obj-first-num>.ast.value;
my @entries[$obj-count;3] = $<xref-entry>».ast.List;
make { :$obj-first-num, :$obj-count, :@entries };
}
method xref-entry($/) {
my UInt @entry = $<byte-offset>.ast.value, $<gen-number>.ast.value, $<obj-status>.ast;
make @entry;
}
method int($/) {
make (:int($/.Int));
}
method obj-status:sym<free>($/) { make 0 }
method obj-status:sym<inuse>($/) { make 1 }
}
use Test;
plan 2;
my $xref-regular = "xref
0 8
0000000000 65535 f
0000000009 00000 n
0000000074 00000 n
0000000120 00000 n
0000000179 00000 n
0000000322 00000 n
0000000415 00000 n
0000000445 00000 n
";
my $xref-empty = "xref
0 0
";
my $actions = XRef::Actions.new;
lives-ok {XRef.parse($xref-regular, :$actions)};
lives-ok {XRef.parse($xref-empty, :$actions)};