File Coverage

XSP.yp
Criterion Covered Total %
statement 200 223 89.6
branch 13 20 65.0
condition 2 3 66.6
subroutine 113 130 86.9
pod n/a
total 328 376 87.2


line stmt bran cond sub pod time code
1             #############################################################################
2             ## Name: XSP.yp
3             ## Purpose: Grammar file for xsubppp.pl
4             ## Author: Mattia Barbon
5             ## Modified by:
6             ## Created: 01/03/2003
7             ## RCS-ID: $Id: XSP.yp,v 1.5 2007/03/10 20:38:57 mbarbon Exp $
8             ## Copyright: (c) 2003, 2007, 2009 Mattia Barbon
9             ## Licence: This program is free software; you can redistribute it and/or
10             ## modify it under the same terms as Perl itself
11             #############################################################################
12              
13             %token OPCURLY CLCURLY OPPAR CLPAR OPANG CLANG SEMICOLON TILDE DCOLON
14             %token STAR AMP COMMA EQUAL OPSPECIAL CLSPECIAL
15             %token INTEGER RAW_CODE COMMENT ID COLON
16             %expect 2
17              
18             %%
19              
20             top_list:
21             top
22 229     229   381 | top_list top { push @{$_[1]}, @{$_[2]}; $_[1] }
  229         452  
  229         453  
  229         567  
23             | p__type OPCURLY type CLCURLY
24 0     0   0 { $_[3] }
25             ;
26              
27 315 100   315   1571 top: _top { !$_[1] ? [] :
    100          
28             ref $_[1] eq 'ARRAY' ? $_[1] :
29             [ $_[1] ] };
30              
31             _top: raw | class | directive | enum
32 44     44   224 | function { process_function( $_[0], $_[1] ) };
33              
34             directive: perc_module SEMICOLON
35 82     82   927 { ExtUtils::XSpp::Node::Module->new( module => $_[1] ) }
36             | perc_package SEMICOLON
37 30     30   335 { ExtUtils::XSpp::Node::Package->new( perl_name => $_[1] ) }
38             | perc_file SEMICOLON
39 8     8   79 { ExtUtils::XSpp::Node::File->new( file => $_[1] ) }
40             | perc_loadplugin SEMICOLON
41 9     9   42 { $_[0]->YYData->{PARSER}->load_plugin( $_[1] ); undef }
  9         26  
42             | perc_include SEMICOLON
43 2     2   9 { $_[0]->YYData->{PARSER}->include_file( $_[1] ); undef }
  2         4  
44             | perc_any SEMICOLON
45 2     2   3 { add_top_level_directive( $_[0], %{$_[1][1]} ) }
  2         11  
46 26     26   57 | typemap { }
47 14     14   32 | exceptionmap { }
48             ;
49              
50             typemap: p_typemap OPCURLY type CLCURLY OPCURLY ID CLCURLY
51             special_blocks SEMICOLON
52 15     15   185 { my $c = 0;
53 0         0 my %args = map { "arg" . ++$c => $_ }
  0         0  
54 15 50       127 map { join( '', @$_ ) }
55 15         26 @{$_[8] || []};
56 15         89 add_typemap( $_[6], $_[3], %args );
57 15         43 undef }
58             | p_typemap OPCURLY type CLCURLY OPCURLY ID CLCURLY
59             OPCURLY perc_any_args CLCURLY SEMICOLON
60             { # this assumes that there will be at most one named
61             # block for each directive inside the typemap
62 9     9   28 for( my $i = 1; $i <= $#{$_[9]}; $i += 2 ) {
  21         69  
63 12 100 66     91 $_[9][$i] = join "\n", @{$_[9][$i][0]}
  11         59  
64             if ref( $_[9][$i] ) eq 'ARRAY'
65             && ref( $_[9][$i][0] ) eq 'ARRAY';
66             }
67 9         22 add_typemap( $_[6], $_[3], @{$_[9]} );
  9         47  
68 9         24 undef }
69             | p_typemap OPCURLY type CLCURLY SEMICOLON
70 2     2   8 { add_typemap( 'simple', $_[3] );
71 2         8 add_typemap( 'reference', make_ref($_[3]->clone) );
72 2         5 undef }
73             ;
74              
75             exceptionmap: p_exceptionmap OPCURLY ID CLCURLY OPCURLY type_name CLCURLY
76             OPCURLY ID CLCURLY
77             mixed_blocks SEMICOLON
78 14     14   39 { my $package = "ExtUtils::XSpp::Exception::" . $_[9];
79 14         49 my $type = make_type($_[6]); my $c = 0;
  14         25  
80 3         15 my %args = map { "arg" . ++$c => $_ }
  3         10  
81 14 50       46 map { join( "\n", @$_ ) }
82 14         18 @{$_[11] || []};
83 14         159 my $e = $package->new( name => $_[3], type => $type, %args );
84 14         80 ExtUtils::XSpp::Exception->add_exception( $e );
85 14         39 undef };
86              
87             mixed_blocks: mixed_blocks special_block
88 10     10   19 { [ @{$_[1]}, $_[2] ] }
  10         37  
89             | mixed_blocks simple_block
90 16     16   28 { [ @{$_[1]}, [ $_[2] ] ] }
  16         66  
91 44     44   122 | { [] };
92              
93             simple_block: OPCURLY ID CLCURLY
94 16     16   55 { $_[2] };
95              
96 18     18   95 raw: RAW_CODE { add_data_raw( $_[0], [ $_[1] ] ) }
97 5     5   27 | COMMENT { add_data_comment( $_[0], $_[1] ) }
98 22     22   345 | PREPROCESSOR { ExtUtils::XSpp::Node::Preprocessor->new
99             ( rows => [ $_[1][0] ],
100             symbol => $_[1][1],
101             ) }
102 6     6   20 | special_block { add_data_raw( $_[0], [ @{$_[1]} ] ) };
  6         59  
103              
104             enum:
105             'enum' OPCURLY enum_element_list CLCURLY SEMICOLON
106 1     1   5 { ExtUtils::XSpp::Node::Enum->new
107             ( elements => $_[3],
108             condition => $_[0]->get_conditional,
109             ) }
110             | 'enum' ID OPCURLY enum_element_list CLCURLY SEMICOLON
111 2     2   23 { ExtUtils::XSpp::Node::Enum->new
112             ( name => $_[2],
113             elements => $_[4],
114             condition => $_[0]->get_conditional,
115             ) }
116             ;
117              
118             enum_element_list:
119 3     3   9 { [] }
120             | enum_element_list enum_element
121 3 50   3   35 { push @{$_[1]}, $_[2] if $_[2]; $_[1] }
  3         11  
  3         8  
122             | enum_element_list enum_element COMMA
123 7 50   7   22 { push @{$_[1]}, $_[2] if $_[2]; $_[1] }
  7         85  
  7         18  
124             ;
125              
126             enum_element:
127             ID
128 5     5   18 { ExtUtils::XSpp::Node::EnumValue->new
129             ( name => $_[1],
130             condition => $_[0]->get_conditional,
131             ) }
132             | ID EQUAL expression
133 3     3   25 { ExtUtils::XSpp::Node::EnumValue->new
134             ( name => $_[1],
135             value => $_[3],
136             condition => $_[0]->get_conditional,
137             ) }
138             | raw
139             ;
140              
141             class: class_decl SEMICOLON | decorate_class SEMICOLON;
142             function: function_decl SEMICOLON;
143             method: method_decl SEMICOLON;
144             member: member_decl SEMICOLON;
145              
146             decorate_class:
147 2     2   24 perc_name class_decl { $_[2]->set_perl_name( $_[1] ); $_[2] };
  2         5  
148              
149             class_decl: 'class' class_name base_classes class_metadata OPCURLY class_body_list CLCURLY
150 51     51   273 { create_class( $_[0], $_[2], $_[3], $_[4], $_[6],
151             $_[0]->get_conditional ) };
152              
153             base_classes:
154 2     2   5 COLON base_class { [ $_[2] ] }
155 1 50   1   5 | base_classes COMMA base_class { push @{$_[1]}, $_[3] if $_[3]; $_[1] }
  1         4  
  1         3  
156             | ;
157              
158             base_class:
159 3     3   8 'public' class_name_rename { $_[2] }
160 0     0   0 | 'protected' class_name_rename { $_[2] }
161 0     0   0 | 'private' class_name_rename { $_[2] }
162             ;
163              
164             class_name_rename:
165 2     2   15 class_name { create_class( $_[0], $_[1], [], [] ) }
166 1     1   6 | perc_name class_name { my $klass = create_class( $_[0], $_[2], [], [] );
167 1         11 $klass->set_perl_name( $_[1] );
168 1         3 $klass
169             }
170             ;
171              
172 3     3   7 class_metadata: class_metadata perc_catch { [ @{$_[1]}, @{$_[2]} ] }
  3         6  
  3         10  
173 0     0   0 | class_metadata perc_any { [ @{$_[1]}, @{$_[2]} ] }
  0         0  
  0         0  
174 51     51   158 | { [] }
175             ;
176              
177             class_body_list:
178 51     51   138 { [] }
179             | class_body_list class_body_element
180 76 50   76   264 { push @{$_[1]}, $_[2] if $_[2]; $_[1] }
  76         228  
  76         185  
181             ;
182              
183             class_body_element:
184             method | raw | typemap | exceptionmap | access_specifier | member
185             | perc_any SEMICOLON
186 8     8   11 { ExtUtils::XSpp::Node::PercAny->new( %{$_[1][1]} ) }
  8         67  
187             ;
188              
189             access_specifier:
190 0     0   0 'public' COLON { ExtUtils::XSpp::Node::Access->new( access => $_[1] ) }
191 0     0   0 | 'protected' COLON { ExtUtils::XSpp::Node::Access->new( access => $_[1] ) }
192 0     0   0 | 'private' COLON { ExtUtils::XSpp::Node::Access->new( access => $_[1] ) }
193             ;
194              
195 18     18   23 member_metadata: member_metadata _member_metadata { [ @{$_[1]}, @{$_[2]} ] }
  18         33  
  18         59  
196 12     12   34 | { [] }
197             ;
198              
199             _member_metadata: perc_any;
200              
201             member_decl:
202             | looks_like_member
203             | perc_name looks_like_member
204 7     7   36 { $_[2]->set_perl_name( $_[1] ); $_[2] };
  7         16  
205              
206             looks_like_member:
207             type ID member_metadata
208 12         54 { create_member( $_[0],
209             name => $_[2],
210             type => $_[1],
211             condition => $_[0]->get_conditional,
212 12     12   66 @{$_[3]} ) };
213              
214             method_decl: nmethod | vmethod | ctor | dtor;
215              
216 2     2   5 const: 'const' { 1 }
217 86     86   214 | { 0 };
218              
219             virtual: 'virtual';
220              
221             static: 'package_static'
222             | 'class_static'
223 0     0   0 | 'static' { 'package_static' }
224             ;
225              
226             looks_like_function:
227             type ID OPPAR arg_list CLPAR const
228             {
229 88     88   773 return { ret_type => $_[1],
230             name => $_[2],
231             arguments => $_[4],
232             const => $_[6],
233             };
234             };
235              
236             looks_like_renamed_function:
237             looks_like_function
238             | perc_name looks_like_function
239 12     12   40 { $_[2]->{perl_name} = $_[1]; $_[2] };
  12         27  
240              
241             function_decl: looks_like_renamed_function function_metadata
242 44         223 { add_data_function( $_[0],
243             name => $_[1]->{name},
244             perl_name => $_[1]->{perl_name},
245             ret_type => $_[1]->{ret_type},
246             arguments => $_[1]->{arguments},
247             condition => $_[0]->get_conditional,
248 44     44   398 @{$_[2]} ) };
249              
250             ctor: ID OPPAR arg_list CLPAR function_metadata
251 4         22 { add_data_ctor( $_[0], name => $_[1],
252             arguments => $_[3],
253             condition => $_[0]->get_conditional,
254 4     4   30 @{ $_[5] } ) }
255 2     2   42 | perc_name ctor { $_[2]->set_perl_name( $_[1] ); $_[2] };
  2         5  
256              
257             dtor: TILDE ID OPPAR CLPAR function_metadata
258 3         18 { add_data_dtor( $_[0], name => $_[2],
259             condition => $_[0]->get_conditional,
260 3     3   21 @{ $_[5] },
261             ) }
262 1     1   9 | perc_name dtor { $_[2]->set_perl_name( $_[1] ); $_[2] }
  1         2  
263 1     1   9 | virtual dtor { $_[2]->set_virtual( 1 ); $_[2] };
  1         3  
264              
265 43     43   261 function_metadata: function_metadata _function_metadata { [ @{$_[1]}, @{$_[2]} ] }
  43         76  
  43         125  
266 95     95   268 | { [] }
267             ;
268              
269             nmethod:
270             looks_like_renamed_function function_metadata
271 40         232 { my $m = add_data_method
272             ( $_[0],
273             name => $_[1]->{name},
274             perl_name => $_[1]->{perl_name},
275             ret_type => $_[1]->{ret_type},
276             arguments => $_[1]->{arguments},
277             const => $_[1]->{const},
278             condition => $_[0]->get_conditional,
279 40     40   386 @{$_[2]},
280             );
281 40         153 $m
282             }
283             | static nmethod
284 1     1   12 { $_[2]->set_static( $_[1] ); $_[2] };
  1         2  
285              
286             vmethod:
287             _vmethod
288             | perc_name vmethod
289 2     2   15 { $_[2]->set_perl_name( $_[1] ); $_[2] }
  2         5  
290             ;
291              
292             _vmethod:
293             virtual looks_like_function function_metadata
294 2         8 { my $m = add_data_method
295             ( $_[0],
296             name => $_[2]->{name},
297             perl_name => $_[2]->{perl_name},
298             ret_type => $_[2]->{ret_type},
299             arguments => $_[2]->{arguments},
300             const => $_[2]->{const},
301             condition => $_[0]->get_conditional,
302 2     2   15 @{$_[3]},
303             );
304 2         8 $m->set_virtual( 1 );
305 2         4 $m
306             }
307             | virtual looks_like_function EQUAL INTEGER function_metadata
308 2         10 { my $m = add_data_method
309             ( $_[0],
310             name => $_[2]->{name},
311             perl_name => $_[2]->{perl_name},
312             ret_type => $_[2]->{ret_type},
313             arguments => $_[2]->{arguments},
314             const => $_[2]->{const},
315             condition => $_[0]->get_conditional,
316 2     2   14 @{$_[5]},
317             );
318 2 50       8 die "Invalid pure virtual method" unless $_[4] eq '0';
319 2         9 $m->set_virtual( 2 );
320 2         4 $m
321             }
322             ;
323              
324             _function_metadata: perc_code
325             | perc_cleanup
326             | perc_postcall
327             | perc_catch
328             | perc_alias
329             | perc_any
330             ;
331              
332 28     28   87 perc_name: p_name OPCURLY class_name CLCURLY { $_[3] };
333 5     5   19 perc_alias: p_alias OPCURLY ID EQUAL INTEGER CLCURLY { [ alias => [$_[3], $_[5]] ] };
334 30     30   105 perc_package: p_package OPCURLY class_name CLCURLY { $_[3] };
335 82     82   251 perc_module: p_module OPCURLY class_name CLCURLY { $_[3] };
336 8     8   25 perc_file: p_file OPCURLY file_name CLCURLY { $_[3] };
337 9     9   22 perc_loadplugin: p_loadplugin OPCURLY class_name CLCURLY { $_[3] };
338 2     2   5 perc_include: p_include OPCURLY file_name CLCURLY { $_[3] };
339 11     11   167 perc_code: p_code special_block { [ code => $_[2] ] };
340 3     3   14 perc_cleanup: p_cleanup special_block { [ cleanup => $_[2] ] };
341 3     3   14 perc_postcall: p_postcall special_block { [ postcall => $_[2] ] };
342 17     17   24 perc_catch: p_catch OPCURLY class_name_list CLCURLY { [ map {(catch => $_)} @{$_[3]} ] };
  21         169  
  17         28  
343              
344             # this expands mixed_blocks to avoid ambiguity in the OPCURLY case
345             perc_any:
346             p_any OPCURLY perc_any_args CLCURLY
347 6     6   38 { [ tag => { any => $_[1], named => $_[3] } ] }
348             | p_any OPCURLY ID CLCURLY mixed_blocks
349 7     7   14 { [ tag => { any => $_[1], positional => [ $_[3], @{$_[5]} ] } ] }
  7         56  
350             | p_any special_block mixed_blocks
351 0     0   0 { [ tag => { any => $_[1], positional => [ $_[2], @{$_[3]} ] } ] }
  0         0  
352             | p_any
353 23     23   119 { [ tag => { any => $_[1] } ] }
354             ;
355              
356             perc_any_args:
357 15     15   39 perc_any_arg { $_[1] }
358 9     9   17 | perc_any_args perc_any_arg { [ @{$_[1]}, @{$_[2]} ] }
  9         19  
  95         102910  
359             ;
360              
361             perc_any_arg:
362 109     23   3439 p_any mixed_blocks SEMICOLON { [ $_[1] => $_[2] ] }
363 1     1   7 | perc_name SEMICOLON { [ name => $_[1] ] }
364             ;
365              
366             type:
367 16     16   60 'const' nconsttype { make_const( $_[2] ) }
368             | nconsttype
369             ;
370              
371             nconsttype:
372 9     9   36 nconsttype STAR { make_ptr( $_[1] ) }
373 11     11   61 | nconsttype AMP { make_ref( $_[1] ) }
374 242     242   874 | type_name { make_type( $_[1] ) }
375             | template
376             ;
377              
378             type_name:
379             class_name
380             | basic_type
381             | 'void'
382 1     1   4 | 'unsigned' { 'unsigned int' }
383 10     10   226 | 'unsigned' basic_type { 'unsigned' . ' ' . $_[2] }
384             ;
385              
386             basic_type: 'char' | 'int' | 'long' | 'short' | 'long' 'int' | 'short' 'int';
387              
388             template:
389 9     9   34 class_name OPANG type_list CLANG { make_template( $_[1], $_[3] ) }
390             ;
391              
392             type_list:
393 9     9   30 type { [ $_[1] ] }
394 2     2   3 | type_list COMMA type { push @{$_[1]}, $_[3]; $_[1] }
  2         7  
  2         5  
395             ;
396              
397             class_name: ID
398 33     33   120 | ID class_suffix { $_[1] . '::' . $_[2] };
399              
400             class_name_list:
401 17     17   50 class_name { [ $_[1] ] }
402 4     4   8 | class_name_list COMMA class_name { push @{$_[1]}, $_[3]; $_[1] }
  4         11  
  4         7  
403             ;
404              
405 33     33   88 class_suffix: DCOLON ID { $_[2] }
406 7     7   29 | class_suffix DCOLON ID { $_[1] . '::' . $_[3] };
407              
408 4     4   15 file_name: DASH { '-' }
409 6     6   26 | ID DOT ID { $_[1] . '.' . $_[3] }
410 6     6   24 | ID SLASH file_name { $_[1] . '/' . $_[3] };
411              
412             arg_list: nonvoid_arg_list
413 1     1   4 | 'void' { undef };
414              
415             nonvoid_arg_list:
416 76     76   241 argument { [ $_[1] ] }
417 38     38   73 | nonvoid_arg_list COMMA argument { push @{$_[1]}, $_[3]; $_[1] }
  38         107  
  38         97  
418             | ;
419              
420 1     1   3 argument_metadata: argument_metadata _argument_metadata { [ @{$_[1]}, @{$_[2]} ] }
  1         2  
  1         4  
421 111     111   299 | { [] }
422             ;
423              
424             _argument_metadata: perc_any;
425              
426             argument: type p_length OPCURLY ID CLCURLY
427 3     3   43 { make_argument( @_[0, 1], "length($_[4])" ) }
428             | type ID argument_metadata EQUAL expression
429 4     4   8 { make_argument( @_[0, 1, 2, 5], @{$_[3]} ) }
  4         17  
430             | type ID argument_metadata
431 107     107   251 { make_argument( @_[0, 1, 2], undef, @{$_[3]} ) };
  107         444  
432              
433             value: INTEGER
434 0     0   0 | DASH INTEGER { '-' . $_[2] }
435             | FLOAT
436             | QUOTED_STRING
437             | class_name
438 0     0   0 | class_name OPPAR value_list CLPAR { "$_[1]($_[3])" }
439             ;
440              
441             value_list:
442             value
443 0     0   0 | value_list COMMA value { "$_[1], $_[2]" }
444 0     0   0 | { "" }
445             ;
446              
447             expression:
448             value
449             | value AMP value
450 0     0   0 { "$_[1] & $_[3]" }
451             | value PIPE value
452 1     1   4 { "$_[1] | $_[3]" }
453             ;
454              
455             special_blocks: special_block
456 0     0   0 { [ $_[1] ] }
457             | special_blocks special_block
458 0     0   0 { [ @{$_[1]}, $_[2] ] }
  0         0  
459             | ;
460              
461             special_block: special_block_start lines special_block_end
462 33     33   86 { $_[2] }
463             | special_block_start special_block_end
464 0     0   0 { [] }
465             ;
466              
467 33     33   168 special_block_start: OPSPECIAL { push_lex_mode( $_[0], 'special' ) };
468              
469 33     33   153 special_block_end: CLSPECIAL { pop_lex_mode( $_[0], 'special' ) };
470              
471 33     33   135 lines: line { [ $_[1] ] }
472 15     15   26 | lines line { push @{$_[1]}, $_[2]; $_[1] };
  15         63  
  15         37  
473              
474             %%
475              
476 21     21   11829 use ExtUtils::XSpp::Lexer;
  21         70  
  21         1067