File Coverage

blib/lib/SGML/DTDParse/ContentModel.pm
Criterion Covered Total %
statement 15 151 9.9
branch 0 48 0.0
condition 0 16 0.0
subroutine 5 20 25.0
pod 0 4 0.0
total 20 239 8.3


line stmt bran cond sub pod time code
1             # -*- Perl -*-
2              
3             package SGML::DTDParse::ContentModel;
4 1     1   6 use strict;
  1         2  
  1         36  
5 1     1   5 use vars qw($VERSION $CVS);
  1         1  
  1         98  
6              
7             $VERSION = do { my @r=(q$Revision: 2.1 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r };
8             $CVS = '$Id: ContentModel.pm,v 2.1 2005/07/02 23:51:18 ehood Exp $ ';
9              
10 1     1   5 use strict;
  1         2  
  1         27  
11 1     1   12 use Text::DelimMatch;
  1         2  
  1         41  
12 1     1   5 use SGML::DTDParse::Tokenizer;
  1         2  
  1         2128  
13              
14             require 5.000;
15             require Carp;
16              
17             {
18             package SGML::DTDParse::ContentModel::Group;
19              
20             sub new {
21 0     0     my($type, $tok) = @_;
22 0   0       my($class) = ref($type) || $type;
23 0           my($self) = {};
24 0           my(@toks);
25             my(@model);
26 0           local($_);
27              
28 0           bless $self, $class;
29              
30             # print "Group:\n";
31             # $tok->print();
32             # print "\n";
33              
34 0           foreach $_ ('CONTENT_MODEL_STRING',
35             'OCCURRENCE') {
36 0           $self->{$_} = $tok->{$_};
37             }
38              
39 0           $self->{'CONNECTOR'} = '';
40              
41 0           @toks = @{$tok->{'CONTENT_MODEL'}->{'MODEL'}};
  0            
42 0 0         if ($toks[1]) { # if there is a connector...
43 0 0         if (ref $toks[1] eq 'SGML::DTDParse::Tokenizer::Connector') {
44 0           $self->{'CONNECTOR'} = $toks[1]->{'CONNECTOR'};
45             }
46             }
47              
48 0           $self->{'CONTENT_MODEL'} = new SGML::DTDParse::ContentModel $tok->{'CONTENT_MODEL'};
49              
50 0           return $self;
51             }
52              
53             sub content_model {
54 0     0     my $self = shift;
55 0           return $self->{'CONTENT_MODEL'};
56             }
57              
58             sub print {
59 0     0     my($self, $depth) = @_;
60              
61 0           print "\t" x $depth, "(connector: ", $self->{'CONNECTOR'}, "\n";
62 0           $self->{'CONTENT_MODEL'}->print($depth+1);
63 0           print "\t" x $depth, ")\n";
64             }
65              
66             sub xml {
67 0     0     my($self, $depth) = @_;
68 0           my($con) = $self->{'CONNECTOR'};
69 0           my($occ) = $self->{'OCCURRENCE'};
70 0           my($type) = "";
71 0           my($xml) = "";
72              
73 0           $xml .= " " x $depth;
74              
75 0 0         if ($con eq '|') {
    0          
76 0           $type = "or-group";
77             } elsif ($con eq '&') {
78 0           $type = 'and-group';
79             } else {
80 0           $type = 'sequence-group';
81             }
82              
83 0 0         if ($occ) {
84 0           $xml .= "<$type occurrence=\"$occ\">\n";
85             } else {
86 0           $xml .= "<$type>\n";
87             }
88              
89 0           $xml .= $self->{'CONTENT_MODEL'}->xml($depth+1,1);
90              
91 0           $xml .= " " x $depth;
92              
93 0           $xml .= "\n";
94              
95 0           return $xml;
96             }
97             }
98              
99             {
100             package SGML::DTDParse::ContentModel::Element;
101              
102             sub new {
103 0     0     my($type, $tok) = @_;
104 0   0       my($class) = ref($type) || $type;
105 0           my($self) = {};
106 0           my($model);
107              
108 0           bless $self, $class;
109              
110 0           foreach $_ ('ELEMENT',
111             'OCCURRENCE') {
112 0           $self->{$_} = $tok->{$_};
113             }
114              
115 0           return $self;
116             }
117              
118             sub element {
119 0     0     my $self = shift;
120 0           return $self->{'ELEMENT'};
121             }
122              
123             sub print {
124 0     0     my($self, $depth) = @_;
125              
126 0           print "\t" x $depth, $self->{'ELEMENT'}, $self->{'OCCURRENCE'}, "\n";
127             }
128              
129             sub xml {
130 0     0     my($self, $depth) = @_;
131 0           my($occ) = $self->{'OCCURRENCE'};
132 0           my($xml) = "";
133              
134 0           $xml .= " " x $depth;
135              
136 0 0         if ($self->{'ELEMENT'} eq '#PCDATA') {
    0          
    0          
    0          
    0          
137 0           $xml .= "\n";
138             } elsif ($self->{'ELEMENT'} eq 'ANY') {
139 0           $xml .= "\n";
140             } elsif ($self->{'ELEMENT'} eq 'EMPTY') {
141 0           $xml .= "\n";
142             } elsif ($self->{'ELEMENT'} eq 'CDATA') {
143 0           $xml .= "\n";
144             } elsif ($self->{'ELEMENT'} eq 'RCDATA') {
145 0           $xml .= "\n";
146             } else {
147 0           $xml .= "{'ELEMENT'} . "\"";
148 0 0         $xml .= " occurrence=\"$occ\"" if $occ;
149 0           $xml .= "/>\n";
150             }
151              
152 0           return $xml;
153             }
154             }
155              
156             {
157             package SGML::DTDParse::ContentModel::ParameterEntity;
158              
159             sub new {
160 0     0     my($type, $tok) = @_;
161 0   0       my($class) = ref($type) || $type;
162 0           my($self) = {};
163 0           my($model);
164              
165 0           bless $self, $class;
166              
167 0           $self->{'PARAMETER_ENTITY'} = $tok->{'PARAMETER_ENTITY'};
168              
169 0           return $self;
170             }
171              
172             sub print {
173 0     0     my($self, $depth) = @_;
174              
175 0           print "\t" x $depth, "%", $self->{'PARAMETER_ENTITY'}, ";\n";
176             }
177              
178             sub xml {
179 0     0     my($self, $depth) = @_;
180 0           my($xml) = "";
181              
182 0           $xml .= " " x $depth;
183              
184 0           $xml .= "{'PARAMETER_ENTITY'} . "\"";
185 0           $xml .= "/>\n";
186              
187 0           return $xml;
188             }
189             }
190              
191             sub new {
192 0     0 0   my($type, $model) = @_;
193 0   0       my $class = ref($type) || $type;
194 0           my $self = {};
195 0           my(@toks) = ();
196 0           my(@model) = ();
197              
198 0           bless $self, $class;
199              
200 0           $self->{'CONTENT_MODEL_STRING'} = $model->{'CONTENT_MODEL_STRING'};
201 0           @toks = @{$model->{'MODEL'}};
  0            
202              
203             # Note: we know that the first token will always be a group, unless
204             # the content model is declard content. See new() in Tokenizer.
205             #
206 0           while (@toks) {
207 0           my($tok) = shift @toks;
208              
209 0 0         if (ref $tok eq 'SGML::DTDParse::Tokenizer::Group') {
    0          
    0          
    0          
210 0           push (@model, new SGML::DTDParse::ContentModel::Group $tok);
211             } elsif (ref $tok eq 'SGML::DTDParse::Tokenizer::Element') {
212 0           push (@model, new SGML::DTDParse::ContentModel::Element $tok);
213             } elsif (ref $tok eq 'SGML::DTDParse::Tokenizer::ParameterEntity') {
214 0           push (@model, new SGML::DTDParse::ContentModel::ParameterEntity $tok);
215             } elsif (ref $tok eq 'SGML::DTDParse::Tokenizer::Connector') {
216             #nop;
217             } else {
218 0           die "Bad token in SGML::DTDParse::ContentModel";
219             }
220             }
221              
222 0           @{$self->{'MODEL'}} = @model;
  0            
223              
224 0           return $self;
225             }
226              
227             sub type {
228 0     0 0   my $self = shift;
229 0           my $depth = shift;
230 0           my @model = @{$self->{'MODEL'}};
  0            
231              
232 0 0         $depth = 0 if !defined($depth);
233              
234 0           while (@model) {
235 0           my $tok = shift @model;
236 0 0         if ((ref $tok) =~ /Element$/) {
    0          
237 0 0         return 'mixed' if $tok->element() eq '#PCDATA';
238 0 0         if ($depth == 0) {
239 0 0         return 'cdata' if $tok->element() eq 'CDATA';
240 0 0         return 'rcdata' if $tok->element() eq 'RCDATA';
241 0 0         return 'empty' if $tok->element() eq 'RCDATA';
242             }
243             } elsif ((ref $tok) =~ /Group$/) {
244 0           my $cm = $tok->content_model();
245 0           return $cm->type($depth+1);
246             }
247             }
248              
249 0           return 'element';
250             }
251              
252             sub print {
253 0     0 0   my($self) = shift;
254 0   0       my($depth) = shift || 1;
255 0           my(@model) = @{$self->{'MODEL'}};
  0            
256 0           local($_);
257              
258 0           foreach $_ (@model) {
259 0           $_->print($depth);
260             }
261             }
262              
263             sub xml {
264 0     0 0   my($self) = shift;
265 0   0       my($depth) = shift || 1;
266 0           my($internal) = shift;
267 0           my(@model) = @{$self->{'MODEL'}};
  0            
268 0           my($xml) = "";
269 0           my($tag);
270 0           local($_);
271              
272 0 0         if (!$internal) {
273 0           $tag = $depth;
274 0           $depth = 1;
275              
276             # $xml .= "<$tag string=\"";
277             # $xml .= $self->{'CONTENT_MODEL_STRING'};
278             # $xml .= "\">\n";
279             }
280              
281 0           foreach $_ (@model) {
282 0           $xml .= $_->xml($depth);
283             }
284              
285             # if (!$internal) {
286             # $xml .= "\n";
287             # }
288              
289 0           return $xml;
290             }
291              
292             1;