File Coverage

blib/lib/SGML/DTDParse/Tokenizer.pm
Criterion Covered Total %
statement 12 114 10.5
branch 0 30 0.0
condition 0 26 0.0
subroutine 4 14 28.5
pod 0 2 0.0
total 16 186 8.6


line stmt bran cond sub pod time code
1             # -*- Perl -*-
2              
3             package SGML::DTDParse::Tokenizer;
4              
5 1     1   7 use strict;
  1         3  
  1         79  
6 1     1   8 use vars qw($VERSION $CVS);
  1         3  
  1         107  
7              
8             $VERSION = do { my @r=(q$Revision: 2.1 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r };
9             $CVS = '$Id: Tokenizer.pm,v 2.1 2005/07/02 23:51:18 ehood Exp $ ';
10              
11 1     1   6 use strict;
  1         3  
  1         41  
12 1     1   6 use Text::DelimMatch;
  1         2  
  1         1889  
13              
14             require 5.000;
15             require Carp;
16              
17             {
18             package SGML::DTDParse::Tokenizer::Group;
19              
20             sub new {
21 0     0     my($type, $cm) = @_;
22 0   0       my($class) = ref($type) || $type;
23 0           my($self) = {};
24              
25 0           bless $self, $class;
26              
27 0 0         die "Bad call to SGML::DTDParse::Tokenizer::Group: $cm\n"
28             if $cm !~ /^\((.*)\)(.?)$/s;
29              
30 0           $self->{'OCCURRENCE'} = $2;
31 0           $self->{'CONTENT_MODEL'} = new SGML::DTDParse::Tokenizer $1, 1;
32              
33 0           return $self;
34             }
35              
36             sub print {
37 0     0     my($self, $depth) = @_;
38              
39 0           print "\t" x $depth, "(\n";
40 0           $self->{'CONTENT_MODEL'}->print($depth+1);
41 0           print "\t" x $depth, ")\n";
42             }
43             }
44              
45             {
46             package SGML::DTDParse::Tokenizer::Element;
47              
48             sub new {
49 0     0     my($type, $elem) = @_;
50 0   0       my($class) = ref($type) || $type;
51 0           my($self) = {};
52              
53 0           bless $self, $class;
54              
55 0 0         die "Bad call to SGML::DTDParse::Tokenizer::Element: $elem\n"
56             if $elem !~ /^(\S+?)([\*\?\+]?)$/s;
57              
58 0           $self->{'ELEMENT'} = $1;
59 0           $self->{'OCCURRENCE'} = $2;
60              
61 0           return $self;
62             }
63              
64             sub print {
65 0     0     my($self, $depth) = @_;
66              
67 0           print "\t" x $depth, $self->{'ELEMENT'}, $self->{'OCCURRENCE'}, "\n";
68             }
69             }
70              
71             {
72             package SGML::DTDParse::Tokenizer::ParameterEntity;
73              
74             sub new {
75 0     0     my($type, $pe) = @_;
76 0   0       my($class) = ref($type) || $type;
77 0           my($self) = {};
78              
79 0           bless $self, $class;
80              
81 0 0         die "Bad call to SGML::DTDParse::Tokenizer::ParameterEntity: $pe\n"
82             if $pe !~ /^(\S+)$/s;
83              
84 0           $self->{'PARAMETER_ENTITY'} = $1;
85              
86 0           return $self;
87             }
88              
89             sub print {
90 0     0     my($self, $depth) = @_;
91              
92 0           print "\t" x $depth, "%", $self->{'PARAMETER_ENTITY'}, ";\n";
93             }
94             }
95              
96             {
97             package SGML::DTDParse::Tokenizer::Connector;
98              
99             sub new {
100 0     0     my($type, $con) = @_;
101 0   0       my($class) = ref($type) || $type;
102 0           my($self) = {};
103              
104 0           bless $self, $class;
105              
106 0 0         die "Bad call to SGML::DTDParse::Tokenizer::Connector: $con\n"
107             if $con !~ /^[\,\|\&]$/s;
108              
109 0           $self->{'CONNECTOR'} = $con;
110              
111 0           return $self;
112             }
113              
114             sub print {
115 0     0     my($self, $depth) = @_;
116              
117 0           print "\t" x $depth, $self->{'CONNECTOR'}, "\n";
118             }
119             }
120              
121             sub new {
122 0     0 0   my($type, $cm, $internal) = @_;
123 0   0       my($class) = ref($type) || $type;
124 0           my($self) = {};
125 0           my(@model) = ();
126              
127 0           bless $self, $class;
128              
129 0           $self->{'CONTENT_MODEL_STRING'} = $cm;
130              
131             # print "-->$cm\n";
132              
133 0 0         if ($cm =~ /(.*?)\s\-(\(.*)$/) {
134 0           my($excl) = $2;
135 0           my($exclcm) = new SGML::DTDParse::Tokenizer $excl;
136 0           $self->{'EXCLUSION'} = $exclcm;
137 0           $cm = $1;
138             }
139              
140 0 0         if ($cm =~ /(.*?)\s\+(\(.*)$/) {
141 0           my($incl) = $2;
142 0           my($inclcm) = new SGML::DTDParse::Tokenizer $incl;
143 0           $self->{'INCLUSION'} = $inclcm;
144 0           $cm = $1;
145             }
146              
147             # print "==>$cm\n";
148              
149 0           $cm =~ s/^\s+//sg;
150              
151             # Simplification: always make the content model a group; unless it's
152             # declared content.
153             #
154 0 0         if (!$internal) {
155             # print "$cm\n\n";
156              
157 0           my($mc) = new Text::DelimMatch '\(', '\)[\?\+\*]*';
158 0           my($pre, $match, $rest) = $mc->match($cm);
159              
160 0 0 0       if ($cm ne 'EMPTY' && $cm ne 'CDATA' && $cm ne 'RCDATA') {
      0        
161 0 0 0       if ($cm !~ /^\(/s || ($rest !~ /^\s*$/s)) {
162 0           $cm = "($cm)";
163             }
164             }
165             }
166              
167 0           while ($cm ne "") {
168 0 0         if ($cm =~ /^\(/s) {
    0          
    0          
169             # group;
170 0           my($mc) = new Text::DelimMatch '\(', '\)[\?\+\*]*';
171 0           my($pre, $match, $rest) = $mc->match($cm);
172 0           my($group);
173              
174             # print "\tgroup:\n";
175             # print "\t\tp:$pre\n";
176             # print "\t\tm:$match\n";
177             # print "\t\tr:$rest\n";
178              
179 0           $group = new SGML::DTDParse::Tokenizer::Group $match;
180 0           push (@model, $group);
181              
182 0           $cm = $rest;
183             } elsif ($cm =~ /^\%/s) {
184             # parameter entity
185 0           my($pe);
186             my($pent);
187 0 0         if ($cm =~ /%(.*?);?([\|\,\&\s].*)$/s) {
188 0           $pe = $1;
189 0           $cm = $2;
190             } else {
191 0           $pe = $cm;
192 0           $cm = "";
193 0 0         $pe = $1 if $pe =~ /^\%(.*?);?$/s;
194             }
195              
196 0           $pent = new SGML::DTDParse::Tokenizer::ParameterEntity $pe;
197 0           push (@model, $pent);
198             } elsif ($cm =~ /^[\,\|\&]/s) {
199             # connector
200 0           my($con) = new SGML::DTDParse::Tokenizer::Connector $&;
201 0           $cm = $';
202              
203             # print "\tconnector: $&\n";
204              
205 0           push (@model, $con);
206             } else {
207             # element
208 0           my($elem);
209             my($element);
210 0 0         if ($cm =~ /(.*?)([\|\,\&\s].*)$/s) {
211 0           $elem = $1;
212 0           $cm = $2;
213             } else {
214 0           $elem = $cm;
215 0           $cm = "";
216             }
217              
218 0           $element = new SGML::DTDParse::Tokenizer::Element $elem;
219 0           push (@model, $element);
220             }
221              
222 0           $cm =~ s/^\s+//sg;
223             }
224              
225             # print "<==\n";
226              
227 0           @{$self->{'MODEL'}} = @model;
  0            
228              
229 0           return $self;
230             }
231              
232             sub print {
233 0     0 0   my($self) = shift;
234 0   0       my($depth) = shift || 1;
235 0           my(@model) = @{$self->{'MODEL'}};
  0            
236 0           local($_);
237              
238 0           foreach $_ (@model) {
239 0           $_->print($depth);
240             }
241             }
242              
243             1;