The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#  You may distribute under the terms of either the GNU General Public License
#  or the Artistic License (the same terms as Perl itself)
#
#  (C) Paul Evans, 2013 -- leonerd@leonerd.org.uk

package Tickit::Style::Parser;

use strict;
use warnings;
use base qw( Parser::MGC );

our $VERSION = '0.46';

use Struct::Dumb;

# Identifiers can include hypens
use constant pattern_ident => qr/[A-Z0-9_-]+/i;

sub parse
{
   my $self = shift;
   $self->sequence_of( \&parse_def );
}

sub token_typename
{
   my $self = shift;
   $self->generic_token( typename => qr/(?:${\pattern_ident}::)*${\pattern_ident}/ );
}

struct Definition => [qw( type class tags style )];

sub parse_def
{
   my $self = shift;

   my $type = $self->token_typename;
   $self->commit;

   my $class;
   if( $self->maybe_expect( '.' ) ) {
      $class = $self->token_ident;
   }

   my %tags;
   while( $self->maybe_expect( ':' ) ) {
      $tags{$self->token_ident}++;
   }

   my %style;
   $self->scope_of(
      '{',
      sub { $self->sequence_of( sub {
         $self->any_of(
            sub {
               my $delete = $self->maybe_expect( '!' );
               my $key = $self->token_ident;
               $self->commit;

               $key =~ s/-/_/g;

               if( $delete ) {
                  $style{$key} = undef;
               }
               else {
                  $self->expect( ':' );
                  my $value = $self->any_of(
                     $self->can( "token_int" ),
                     $self->can( "token_string" ),
                     \&token_boolean,
                  );
                  $style{$key} = $value;
               }

            },
            sub {
               $self->expect( '<' ); $self->commit;
               my $key = $self->maybe_expect( '>' ) || $self->substring_before( '>' );
               $self->expect( '>' );

               $self->expect( ':' );

               $style{"<$key>"} = $self->token_ident;
            }
         );
         $self->expect( ';' );
      } ) },
      '}'
   );

   return Definition( $type, $class, \%tags, \%style );
}

sub token_boolean
{
   my $self = shift;
   return $self->token_kw(qw( true false )) eq "true";
}

0x55AA;