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 <
perl6-bugs-follo...@perl.org> 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)};

Reply via email to