File Coverage

blib/lib/Pegex/Grammar.pm
Criterion Covered Total %
statement 12 73 16.4
branch 4 34 11.7
condition 2 6 33.3
subroutine 3 5 60.0
pod 1 3 33.3
total 22 121 18.1


line stmt bran cond sub pod time code
1             package Pegex::Grammar;
2 11     11   69392 use Pegex::Base;
  11         22  
  11         72  
3              
4             # Grammar can be in text or tree form. Tree will be compiled from text.
5             # Grammar can also be stored in a file.
6             has file => ();
7             has text => (
8             builder => 'make_text',
9             lazy => 1,
10             );
11             has tree => (
12             builder => 'make_tree',
13             lazy => 1,
14             );
15             has start_rules => [];
16              
17             sub make_text {
18 0     0 0 0 my ($self) = @_;
19 0 0       0 my $filename = $self->file
20             or return '';
21 0 0       0 open TEXT, "<", $filename
22             or die "Can't open '$filename' for input\n:$!";
23 0         0 return do {local $/; }
  0         0  
  0         0  
24             }
25              
26             sub make_tree {
27 9     9 1 23 my ($self) = @_;
28             # Turn off ENV debugging for grammar compile step:
29             local (
30             $ENV{PERL_PEGEX_DEBUG},
31             $ENV{PERL_PEGEX_RECURSION_LIMIT},
32             $ENV{PERL_PEGEX_RECURSION_WARN_LIMIT},
33             $ENV{PERL_PEGEX_ITERATION_LIMIT},
34 9         69 );
35 9 50       42 my $text = $self->text
36             or die "Can't create a '" . ref($self) .
37             "' grammar. No tree or text or file.";
38 9         3219 require Pegex::Compiler;
39             return Pegex::Compiler->new->compile(
40             $text,
41 9 100       54 @{$self->start_rules || []}
  9         39  
42             )->tree;
43             }
44              
45             # This import is to support: perl -MPegex::Grammar::Module=compile
46             sub import {
47 15     15   3593 my ($package) = @_;
48 15 0 33     104 if (((caller))[1] =~ /^-e?$/ and @_ == 2 and $_[1] eq 'compile') {
      33        
49 0         0 $package->compile_into_module();
50 0         0 exit;
51             }
52 15 50       380 if (my $env = $ENV{PERL_PEGEX_AUTO_COMPILE}) {
53 0           my %modules = map {($_, 1)} split ',', $env;
  0            
54 0 0         if ($modules{$package}) {
55 0 0         if (my $grammar_file = $package->file) {
56 0 0         if (-f $grammar_file) {
57 0           my $module = $package;
58 0           $module =~ s!::!/!g;
59 0           $module .= '.pm';
60 0           my $module_file = $INC{$module};
61 0 0         if (-M $grammar_file < -M $module_file) {
62 0           $package->compile_into_module();
63 0           local $SIG{__WARN__};
64 0           delete $INC{$module};
65 0           require $module;
66             }
67             }
68             }
69             }
70             }
71             }
72              
73             sub compile_into_module {
74 0     0 0   my ($package) = @_;
75 0           my $grammar_file = $package->file;
76 0 0         open GRAMMAR, "<", $grammar_file
77             or die "Can't open $grammar_file for input";
78 0           my $grammar_text = do {local $/; };
  0            
  0            
79 0           close GRAMMAR;
80 0           my $module = $package;
81 0           $module =~ s!::!/!g;
82 0           $module = "$module.pm";
83 0 0         my $file = $INC{$module} or return;
84 0           my $perl;
85             my @rules;
86 0 0         if ($package->can('start_rules')) {
87 0 0         @rules = @{$package->start_rules || []};
  0            
88             }
89 0 0         if ($module eq 'Pegex/Pegex/Grammar.pm') {
90 0           require Pegex::Bootstrap;
91 0           $perl = Pegex::Bootstrap->new->compile($grammar_text, @rules)->to_perl;
92             }
93             else {
94 0           require Pegex::Compiler;
95 0           $perl = Pegex::Compiler->new->compile($grammar_text, @rules)->to_perl;
96             }
97 0 0         open IN, "<", $file or die $!;
98 0           my $module_text = do {local $/; };
  0            
  0            
99 0           require Pegex;
100 0           my $msg = " # Generated/Inlined by Pegex::Grammar ($Pegex::VERSION)";
101 0           close IN;
102 0           $perl =~ s/^/ /gm;
103 0           $module_text =~ s/^(sub\s+make_tree\s*\{).*?(^\})/$1$msg\n$perl$2/ms;
104 0           $module_text =~ s/^(sub\s+tree\s*\{).*?(^\})/$1$msg\n$perl$2/ms;
105 0           chomp $grammar_text;
106 0           $grammar_text = "<<'...';\n$grammar_text\n...\n";
107 0           $module_text =~ s/^(sub\s+text\s*\{).*?(^\})/$1$msg\n$grammar_text$2/ms;
108 0           $grammar_text =~ s/^/# /gm;
109 0           $module_text =~ s/^(# sub\s+text\s*\{).*?(^# \})/$1$msg\n$grammar_text$2/ms;
110 0 0         open OUT, '>', $file or die $!;
111 0           print OUT $module_text;
112 0           close OUT;
113 0           print "Compiled '$grammar_file' into '$file'.\n";
114             }
115              
116             1;