Added libextutils-xspp-perl
[pkg-perl] / deb-src / libextutils-xspp-perl / libextutils-xspp-perl-0.07 / lib / ExtUtils / XSpp / Parser.pm
1 package ExtUtils::XSpp::Parser;
2
3 use strict;
4 use warnings;
5
6 use IO::Handle;
7 use ExtUtils::XSpp::Grammar;
8
9 =head1 NAME
10
11 ExtUtils::XSpp::Parser - an XS++ parser
12
13 =cut
14
15 sub _my_open {
16   my $file = shift;
17
18   open my $in, "<", $file
19     or die "Failed to open '$file' for reading: $!";
20
21   return $in;
22 }
23
24 =head2 ExtUtils::XSpp::Parser::new( file => path )
25
26 Create a new XS++ parser.
27
28 =cut
29
30 sub new {
31   my $class = shift;
32   my $this = bless {}, $class;
33   my %args = @_;
34
35   $this->{FILE} = $args{file};
36   $this->{STRING} = $args{string};
37   $this->{PARSER} = ExtUtils::XSpp::Grammar->new;
38
39   return $this;
40 }
41
42 =head2 ExtUtils::XSpp::Parser::parse
43
44 Parse the file data; returns true on success, false otherwise,
45 on failure C<get_errors> will return the list of errors.
46
47 =cut
48
49 sub parse {
50   my $this = shift;
51   my $fh;
52   if( $this->{FILE} ) {
53       $fh = _my_open( $this->{FILE} );
54   } else {
55       open $fh, '<', \$this->{STRING}
56         or die "Failed to create file handle from in-memory string";
57   }
58   my $buf = '';
59
60   my $parser = $this->{PARSER};
61   $parser->YYData->{LEX}{FH} = $fh;
62   $parser->YYData->{LEX}{BUFFER} = \$buf;
63   local $parser->YYData->{PARSER} = $this;
64
65   $this->{DATA} = $parser->YYParse( yylex   => \&ExtUtils::XSpp::Grammar::yylex,
66                                     yyerror => \&ExtUtils::XSpp::Grammar::yyerror,
67                                     yydebug => 0x00,
68                                    );
69 }
70
71 sub include_file {
72   my $this = shift;
73   my( $file ) = @_;
74   my $buf = '';
75   my $new_lex = { FH     => _my_open( $file ),
76                   BUFFER => \$buf,
77                   NEXT   => $this->{PARSER}->YYData->{LEX},
78                   };
79
80   $this->{PARSER}->YYData->{LEX} = $new_lex;
81 }
82
83 =head2 ExtUtils::XSpp::Parser::get_data
84
85 Returns a list containing the parsed data. Each item of the list is
86 a subclass of C<ExtUtils::XSpp::Node>
87
88 =cut
89
90 sub get_data {
91   my $this = shift;
92   die "'parse' must be called before calling 'get_data'"
93     unless exists $this->{DATA};
94
95   return $this->{DATA};
96 }
97
98 =head2 ExtUtils::XSpp::Parser::get_errors
99
100 Returns the parsing errors as an array.
101
102 =cut
103
104 sub get_errors {
105   my $this = shift;
106
107   return @{$this->{ERRORS}};
108 }
109
110 =head2 ExtUtils::XSpp::Parser::load_plugin
111
112 Loads the specified plugin and calls its C<register_plugin> method.
113
114 =cut
115
116 sub load_plugin {
117   my $this = shift;
118   my( $package ) = @_;
119
120   if (eval "require ExtUtils::XSpp::Plugin::$package;") {
121     $package = "ExtUtils::XSpp::Plugin::$package";
122     $package->register_plugin( $this );
123   }
124   elsif (eval "require $package;") {
125     $package->register_plugin( $this );
126   }
127   else {
128     die "Could not load XS++ plugin '$package' (neither via the namespace "
129        ."'ExtUtils::XS++::Plugin::$package' nor via '$package'). Reason: $@";
130   }
131   return 1;
132 }
133
134 =head2 ExtUtils::XSpp::Parser::add_post_process_plugin
135
136 Adds the specified plugin to be called after parsing is complete to
137 modify the parse tree before it is emitted.
138
139 =cut
140
141 sub add_post_process_plugin {
142   my $this = shift;
143   my( $plugin ) = @_;
144
145   push @{$this->{PLUGINS}{POST_PROCESS}}, $plugin;
146 }
147
148 sub post_process_plugins { $_[0]->{PLUGINS}{POST_PROCESS} || [] }
149
150 1;