The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

use strict;
use warnings FATAL => 'all';
use Moo;
# ABSTRACT: Parsing of a ClassFile
our $VERSION = '0.009'; # VERSION
our $AUTHORITY = 'cpan:JDDPAUSE'; # AUTHORITY
use Data::Section -setup;
use Types::Standard qw/ArrayRef Str/;
use Types::Common::Numeric qw/PositiveOrZeroInt/;
use Scalar::Util qw/blessed/;
#
# require because we do not import ANYTHING from these module, just require they are loaded
#
require Marpa::R2;
has _nonweak_constant_pool => ( is => 'rwp', prod_isa(ArrayRef), default => sub { [] } );
my $_data = ${ __PACKAGE__->section_data('bnf') };
my $_grammar = Marpa::R2::Scanless::G->new( { source => \__PACKAGE__->bnf($_data) } );
# --------------------------------------------------------
# What role MarpaX::Java::ClassFile::Role::Parser requires
# --------------------------------------------------------
sub grammar { $_grammar }
sub callbacks {
return {
#
# Size of constant pool array is constant_pool_count - 1 as per the spec.
# Implicitely from the spec, indices in constant pool start at 1:
# - The final action on Constant pool will insert a fake undef entry at position 0
#
'constant_pool_count$' => sub {
$_[0]->constant_pool_count($_[0]->literalU2('constant_pool_count'));
my $constant_pool = $_[0]->inner('ConstantPoolArray', size => $_[0]->constant_pool_count - 1);
#
# Keep the version with references. This will go in the structure.
# C.f. call to MarpaX::Java::ClassFile::Struct::ClassFile->new().
#
$_[0]->_set__nonweak_constant_pool([ @{$constant_pool} ]);
#
# The default constant_pool attribute is weakened.
# Thus this can be propagated to any other subgrammar, thus any other
# sub structure -;
#
$_[0]->arrayRefWeakenisator($constant_pool);
$_[0]->constant_pool($constant_pool);
#
# Pass this information to any child, weakened, so that they can pass it
# to their child as well, and so on.
#
foreach (@{$constant_pool}) {
$_->_constant_pool($constant_pool) if (blessed($_) && ($_->can('_constant_pool')))
}
},
'interfaces_count$' => sub { $_[0]->inner('InterfacesArray', size => $_[0]->literalU2('interfaces_count')) },
'fields_count$' => sub { $_[0]->inner('FieldsArray', size => $_[0]->literalU2('fields_count')) },
'methods_count$' => sub { $_[0]->inner('MethodsArray', size => $_[0]->literalU2('methods_count')) },
'attributes_count$' => sub { $_[0]->inner('AttributesArray', size => $_[0]->literalU2('attributes_count')) }
}
}
# ---------------
# Grammar actions
# ---------------
sub _ClassFile {
my ($self,
$magic,
$minor_version,
$major_version,
$constant_pool_count,
# $constant_pool,
$access_flags,
$this_class,
$super_class,
$interfaces_count,
$interfaces,
$fields_count,
$fields,
$methods_count,
$methods,
$attributes_count,
$attributes) = @_;
MarpaX::Java::ClassFile::Struct::ClassFile->new(
magic => $magic,
minor_version => $minor_version,
major_version => $major_version,
constant_pool_count => $constant_pool_count,
constant_pool => $_[0]->_nonweak_constant_pool,
access_flags => $access_flags,
this_class => $this_class,
super_class => $super_class,
interfaces_count => $interfaces_count,
interfaces => $interfaces,
fields_count => $fields_count,
fields => $fields,
methods_count => $methods_count,
methods => $methods,
attributes_count => $attributes_count,
attributes => $attributes
)
}
#
# We want to say that exhaustion is definitely fatal
#
has '+exhaustion' => (default => sub { 'fatal' });
#
# We want to take control over constant_pool count and content in this class (and only here btw)
#
has '+constant_pool_count' => ( is => 'rw' );
has '+constant_pool' => ( is => 'rw' );
1;
=pod
=encoding UTF-8
=head1 NAME
MarpaX::Java::ClassFile::BNF::ClassFile - Parsing of a ClassFile
=head1 VERSION
version 0.009
=head1 AUTHOR
Jean-Damien Durand <jeandamiendurand@free.fr>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2016 by Jean-Damien Durand.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
__DATA__
__[ bnf ]__
:default ::= action => ::first
event 'constant_pool_count$' = completed constant_pool_count
event 'interfaces_count$' = completed interfaces_count
event 'fields_count$' = completed fields_count
event 'methods_count$' = completed methods_count
event 'attributes_count$' = completed attributes_count
ClassFile ::=
magic
minor_version
major_version
constant_pool_count
(constant_pool) # C.f. in the constant_pool_count$ event
access_flags
this_class
super_class
interfaces_count
interfaces
fields_count
fields
methods_count
methods
attributes_count
attributes
action => _ClassFile
magic ::= U4 action => u4
minor_version ::= U2 action => u2
major_version ::= U2 action => u2
constant_pool_count ::= U2 action => u2
constant_pool ::= MANAGED action => ::first
access_flags ::= U2 action => u2
this_class ::= U2 action => u2
super_class ::= U2 action => u2
interfaces_count ::= U2 action => u2
interfaces ::= MANAGED action => ::first
fields_count ::= U2 action => u2
fields ::= MANAGED action => ::first
methods_count ::= U2 action => u2
methods ::= MANAGED action => ::first
attributes_count ::= U2 action => u2
attributes ::= MANAGED action => ::first