[glibmm/gmmproc-refactor: 18/23] Some rework of Gir::Parser and Gir::State.



commit 8952c461ee9624d9f23d7bfc1a3e8d5b4431d563
Author: Krzesimir Nowak <qdlacz gmail com>
Date:   Mon Sep 26 14:54:14 2011 +0200

    Some rework of Gir::Parser and Gir::State.

 tools/pm/Gir/Parser.pm |  170 ++++++++++++++++++++++++++++++++++++++----------
 tools/pm/Gir/State.pm  |   56 +++++++++++++++-
 2 files changed, 187 insertions(+), 39 deletions(-)
---
diff --git a/tools/pm/Gir/Parser.pm b/tools/pm/Gir/Parser.pm
index 289ceac..89f5fca 100644
--- a/tools/pm/Gir/Parser.pm
+++ b/tools/pm/Gir/Parser.pm
@@ -1,62 +1,147 @@
-package GirParser;
+## Copyright 2011 Krzesimir Nowak
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+##
+
+package Gir::Parser;
 
 use strict;
 use warnings;
 
-use Gir::Handlers::Store;
+use Encode;
+
+use Gir::Config;
+use Gir::Handlers::Generated::Common::Store;
 use Gir::State;
 
-use XML::Parser;
+use IO::File;
 
-sub _init ($)
-{
-  my $self = shift;
-  my $new_state = Gir::State->new ();
-  my $state_stack = $self->{'states_stack'};
+use XML::Parser::Expat;
 
-  push (@{$state_stack}, $new_state);
-  $self->{'state'} = $new_state;
+sub _print_error ($$$)
+{
+  my ($state, $error, $elem) = @_;
+  my $xml_parser = $state->get_xml_parser ();
+  my $msg = $state->get_parsed_file ()
+    . ':'
+    . $xml_parser->current_line ()
+    . ': '
+    . $error
+    . "\nTags stack:\n";
+  my @context = $xml_parser->context ();
+
+  foreach my $tag (@context)
+  {
+    $msg .= '  ' . $tag . "\n";
+  }
+  if (defined ($elem))
+  {
+    $msg .= '  ' . $elem . "\n";
+  }
+  print STDERR $msg;
 }
 
-sub _final ($)
+sub _get_file_contents_as_utf8 ($)
 {
-  my $self = shift;
-  my $state_stack = $self->{'states_stack'};
+  my $real_filename = shift;
+  my $xml = IO::File->new ($real_filename, 'r');
 
-  pop (@{$state_stack});
-  $self->{'state'} = $state_stack->[-1];
+  unless (defined ($xml))
+  {
+    #TODO: error;
+    print STDERR 'Could not open file: ' . $real_filename . ".\n";
+    exit (1);
+  }
+
+  my $file_size = ($xml->stat ())[7];
+  my $contents = undef;
+
+  unless ($xml->binmode (':raw'))
+  {
+    #TODO: error;
+    print STDERR "Calling binmode on " . $real_filename . " failed.\n";
+    exit (1);
+  }
+
+  my $bytes_read = $xml->read ($contents, $file_size);
+
+  if ($bytes_read != $file_size)
+  {
+    #TODO: error;
+    if (defined ($bytes_read))
+    {
+      print STDERR 'Read ' . $bytes_read . ' bytes from ' . $real_filename . ', wanted: ' . $file_size . " bytes.\n";
+    }
+    else
+    {
+      print STDERR 'Read error from ' . $real_filename . ".\n";
+    }
+    exit (1);
+  }
+  unless ($xml->close ())
+  {
+    print STDERR 'Closing ' . $real_filename . " failed.\n";
+    exit (1);
+  }
+  return decode ('utf-8', $contents);
 }
 
 sub _start ($$$@)
 {
-  my ($self, undef, $elem, @attval) = @_;
-  my $state = $self->{'current_state'};
+  my ($self, undef, $elem, @atts_vals) = @_;
+  my $state = $self->get_current_state ();
   my $handlers = $state->get_current_handlers ();
   my $start_handlers = $handlers->get_start_handlers ();
 
-  if ($start_handlers->has_method_for ($elem))
+  if (defined ($start_handlers))
   {
-    my $method = $start_handlers->get_method_for ($elem);
-    my $subhandlers = $handlers->get_subhandlers_for ($elem);
-
-    if (defined ($subhandlers))
+    if ($start_handlers->has_method_for ($elem))
     {
-      $state->push_handlers ($subhandlers);
-      return $handlers->$method ($self, @attval);
+      my $method = $start_handlers->get_method_for ($elem);
+      my $subhandlers = $handlers->get_subhandlers_for ($elem);
+
+      if (defined ($subhandlers))
+      {
+        $state->push_handlers ($subhandlers);
+        return $handlers->$method ($self, @atts_vals);
+      }
+      # TODO: internal error - wrong implementation of get_subhandlers_for?
+      _print_error ($state, 'Internal error - wrong implementation of get_subhandlers_for?', $elem);
+      exit (1);
     }
-    # TODO: internal error - wrong implementation of get_subhandlers_for?
+    # TODO: unknown elem?
+    _print_error ($state, 'Unknown tag: ' . $elem . '.', $elem);
+    exit (1);
   }
-  # TODO: unknown elem?
+  _print_error ($state, 'No start handlers: ' . $elem . '.', $elem);
+  exit (1);
 }
 
 sub _end ($$$)
 {
   my ($self, undef, $elem) = @_;
-  my $state = $self->{'current_state'};
+  my $state = $self->get_current_state ();
 
   $state->pop_handlers ();
 
   my $handlers = $state->get_current_handlers ();
+  unless (defined $handlers)
+  {
+    _print_error ($state, 'No handlers for tag: ' . $elem . '.', $elem);
+    exit (1);
+  }
   my $end_handlers = $handlers->get_end_handlers ();
 
   if ($end_handlers->has_method_for ($elem))
@@ -65,7 +150,8 @@ sub _end ($$$)
 
     return $handlers->$method ($self);
   }
-  # TODO: unknown elem?
+  _print_error ($state, 'Unknown tag: ' . $elem . '.', $elem);
+  exit (1);
 }
 
 #
@@ -80,8 +166,7 @@ sub new($)
   {
     'states_stack' => [],
     'parsed_girs' => {},
-    'state' => undef,
-    'api' => {} # TODO: replace with Gir::Api->new () or something like that.
+    'api' => {}, # TODO: replace with Gir::Api->new () or something like that.
   };
 
   return bless ($self, $class);
@@ -90,7 +175,7 @@ sub new($)
 sub _create_xml_parser ($)
 {
   my $self = shift;
-  my $xml_parser = XML::Parser->new ();
+  my $xml_parser = XML::Parser::Expat->new ();
 
   #TODO: implement commented methods.
   $xml_parser->setHandlers
@@ -99,8 +184,6 @@ sub _create_xml_parser ($)
 #    Comment => sub { $self->_comment (@_); },
 #    Default => sub { $self->_default (@_); },
     End => sub { $self->_end (@_); },
-    Final => sub { $self->_final (@_); },
-    Init => sub { $self->_init (@_); },
     Start => sub { $self ->_start (@_); },
 #    XMLDecl => sub { $self->_xmldecl (@_); }
   );
@@ -115,11 +198,20 @@ sub parse_file ($$)
 
   unless (exists ($parsed_girs->{$filename}))
   {
-    my $real_filename = File::Spec->catfile (GirConfig::get_girdir(), $filename);
+    my $real_filename = File::Spec->catfile (Gir::Config::get_girdir(), $filename);
     my $xml_parser = $self->_create_xml_parser ();
+    my $new_state = Gir::State->new ($real_filename, $xml_parser);
+    my $states_stack = $self->{'states_stack'};
 
     $parsed_girs->{$filename} = undef;
-    $xml_parser->parsefile ($real_filename);
+    push (@{$states_stack}, $new_state);
+
+    my $contents = _get_file_contents_as_utf8 ($real_filename);
+
+    $xml_parser->parse ($contents);
+    $xml_parser->release ();
+    pop (@{$states_stack});
+    #print STDOUT 'Parsed ' . $real_filename . "\n";
   }
 }
 
@@ -130,4 +222,12 @@ sub get_api ($)
   return $self->{'api'};
 }
 
+sub get_current_state ($)
+{
+  my $self = shift;
+  my $states_stack = $self->{'states_stack'};
+
+  return $states_stack->[-1];
+}
+
 1;
diff --git a/tools/pm/Gir/State.pm b/tools/pm/Gir/State.pm
index 18cfd01..d266c5f 100644
--- a/tools/pm/Gir/State.pm
+++ b/tools/pm/Gir/State.pm
@@ -1,3 +1,20 @@
+## Copyright 2011 Krzesimir Nowak
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+##
+
 package Gir::State;
 
 use strict;
@@ -7,13 +24,16 @@ use Gir::Handlers::TopLevel;
 ##
 ## public:
 ##
-sub new ($)
+sub new ($$$)
 {
-  my $type = shift;
+  my ($type, $parsed_file, $xml_parser) = @_;
   my $class = (ref ($type) or $type or 'Gir::State');
   my $self =
   {
-    'handlers_stack' => [Gir::Handlers::TopLevel->new ()]
+    'handlers_stack' => [Gir::Handlers::TopLevel->new ()],
+    'current_namespace' => undef,
+    'parsed_file' => $parsed_file,
+    'xml_parser' => $xml_parser
   };
 
   return bless ($self, $class);
@@ -43,4 +63,32 @@ sub get_current_handlers ($)
   return ${handlers_stack}->[-1];
 }
 
-1;
+sub get_current_namespace ($)
+{
+  my $self = shift;
+
+  return $self->{'current_namespace'};
+}
+
+sub set_current_namespace ($$)
+{
+  my ($self, $namespace) = @_;
+
+  $self->{'current_namespace'} = $namespace;
+}
+
+sub get_parsed_file ($)
+{
+  my $self = shift;
+
+  return $self->{'parsed_file'};
+}
+
+sub get_xml_parser ($)
+{
+  my $self = shift;
+
+  return $self->{'xml_parser'};
+}
+
+1; # indicate proper module load.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]