comparison xsls.pl @ 5:2d6764d9980b

XSLScript: various fixes. This version is able to convert all nginx.org xsls files to xslt ones. Result seems to work.
author Maxim Dounin <mdounin@mdounin.ru>
date Fri, 21 Feb 2014 17:14:57 +0400
parents eb959dce273b
children
comparison
equal deleted inserted replaced
4:eb959dce273b 5:2d6764d9980b
97 # comments, <!-- ... --> 97 # comments, <!-- ... -->
98 # not sure if it's something to be interpreted specially 98 # not sure if it's something to be interpreted specially
99 # likely an artifact of our dump process 99 # likely an artifact of our dump process
100 100
101 comment : /((?!-->).)*/ms "-->" 101 comment : /((?!-->).)*/ms "-->"
102 { $return = "<!-- " . $item[1] . "-->"; 1; } 102 { $return = ""; 1 }
103 103
104 # special chars: ', ", {, }, \ 104 # special chars: ', ", {, }, \
105 # if used in text, they needs to be escaped with backslash 105 # if used in text, they needs to be escaped with backslash
106 106
107 text : quoted | unreserved | "'" | "\"" | "{" 107 text : quoted | unreserved | "'" | "\"" | "{"
108 quoted : "\\" special 108 quoted : "\\" special
109 { $return = $item{special}; 1; } 109 { $return = $item{special}; 1; }
110 special : "'" | "\"" | "\\" | "{" | "}" 110 special : "'" | "\"" | "\\" | "{" | "}"
111 unreserved : /[^'"\\{}]/ 111 unreserved : /[^'"\\{}<\s]+\s*/
112 112
113 # shortcuts: 113 # shortcuts:
114 # 114 #
115 # !! for X:apply-templates 115 # !! for X:apply-templates
116 # !{xpath-expression} for X:value-of select="xpath-expression"; 116 # !{xpath-expression} for X:value-of select="xpath-expression";
119 # !root (path = { !{ substring($DIRNAME, 2) } }) 119 # !root (path = { !{ substring($DIRNAME, 2) } })
120 # !root (path = "substring-after($path, '/')") 120 # !root (path = "substring-after($path, '/')")
121 121
122 exclam_double : value(?) params(?) attrs ";" 122 exclam_double : value(?) params(?) attrs ";"
123 { $return = [ 123 { $return = [
124 "X:apply-templates", "select", $item{value}, $item{attrs}, 124 "X:apply-templates", "select", $item[1][0], $item{attrs},
125 $item{params} 125 $item[2][0]
126 ]; 1 } 126 ]; 1 }
127 127
128 exclam_xpath : xpath "}" 128 exclam_xpath : xpath "}"
129 { $return = [ 129 { $return = [
130 "X:value-of", "select", $item{xpath}, [] 130 "X:value-of", "select", $item{xpath}, []
141 value : /"[^"]*"/ 141 value : /"[^"]*"/
142 142
143 # template parameters 143 # template parameters
144 # ( bar="init", baz={markup} ) 144 # ( bar="init", baz={markup} )
145 145
146 params : "(" param(s /,/) ")" 146 params : "(" param(s? /,/) ")"
147 { $return = $item[2]; 1 } 147 { $return = $item[2]; 1 }
148 param : name "=" value 148 param : name "=" value
149 { $return = [ 149 { $return = [
150 "X:with-param", 150 "X:with-param",
151 "select", $item{value}, 151 "select", $item{value},
153 [] 153 []
154 ]; 1 } 154 ]; 1 }
155 | name "=" <commit> "{" item(s) "}" 155 | name "=" <commit> "{" item(s) "}"
156 { $return = [ 156 { $return = [
157 "X:with-param", "name", $item{name}, [], 157 "X:with-param", "name", $item{name}, [],
158 $item{item} 158 $item[5]
159 ]; 1 } 159 ]; 1 }
160 | name 160 | name
161 { $return = [ 161 { $return = [
162 "X:with-param", "name", $item{name}, [] 162 "X:param", "name", $item{name}, []
163 ]; 1 } 163 ]; 1 }
164 164
165 # instruction body 165 # instruction body
166 # ";" for empty body, "{ ... }" otherwise 166 # ";" for empty body, "{ ... }" otherwise
167 167
180 [ "X:otherwise", [], $item[5] ] 180 [ "X:otherwise", [], $item[5] ]
181 ] 181 ]
182 ]; 1 } 182 ]; 1 }
183 | value attrs body 183 | value attrs body
184 { $return = [ 184 { $return = [
185 "X:if", "test", $item[1], $item{attrs}, $item{body}, 185 "X:if", "test", $item{value}, $item{attrs}, $item{body},
186 ]; 1 } 186 ]; 1 }
187 | attrs body 187 | attrs body
188 { $return = [ 188 { $return = [
189 "X:if", $item{attrs}, $item{body}, 189 "X:if", $item{attrs}, $item{body},
190 ]; 1 } 190 ]; 1 }
195 195
196 xtemplate : name(?) params(?) ( "=" value )(?) attrs body 196 xtemplate : name(?) params(?) ( "=" value )(?) attrs body
197 { $return = [ 197 { $return = [
198 "X:template", "name", $item[1][0], "match", $item[3][0], 198 "X:template", "name", $item[1][0], "match", $item[3][0],
199 $item{attrs}, 199 $item{attrs},
200 [ ($item{params} ? @{$item{params}} : ()), @{$item{body}} ] 200 [ ($item[2][0] ? @{$item[2][0]} : ()), @{$item{body}} ]
201 ]; 1 } 201 ]; 1 }
202 202
203 # X:var LINK = "/article/@link"; 203 # X:var LINK = "/article/@link";
204 # X:var year = { ... } 204 # X:var year = { ... }
205 # semicolon is optional 205 # semicolon is optional
311 311
312 sub format_tree { 312 sub format_tree {
313 my ($tree, $indent) = @_; 313 my ($tree, $indent) = @_;
314 my $s = ''; 314 my $s = '';
315 315
316 $indent ||= 0; 316 if (!defined $indent) {
317 $indent = 0;
318 $s .= '<?xml version="1.0" encoding="utf-8"?>' . "\n";
319 }
320
317 my $space = " " x $indent; 321 my $space = " " x $indent;
318 322
319 foreach my $el (@{$tree}) { 323 foreach my $el (@{$tree}) {
320 if (!defined $el) { 324 if (!defined $el) {
325 warn "Undefined element in output.\n";
321 $s .= $space . "(undef)" . "\n"; 326 $s .= $space . "(undef)" . "\n";
322 next; 327 next;
323 } 328 }
324 329
325 if (not ref($el) && defined $el) { 330 if (not ref($el) && defined $el) {
326 $s .= $space . $el . "\n"; 331 #$s .= $space . $el . "\n";
332 $s .= $el;
327 next; 333 next;
328 } 334 }
329 335
330 die if ref($el) ne 'ARRAY'; 336 die if ref($el) ne 'ARRAY';
331 337
334 if ($tag eq 'tag') { 340 if ($tag eq 'tag') {
335 my (undef, $name, $attrs, $body) = @{$el}; 341 my (undef, $name, $attrs, $body) = @{$el};
336 342
337 $s .= $space . "<" . join(" ", $name, @{$attrs}); 343 $s .= $space . "<" . join(" ", $name, @{$attrs});
338 if ($body) { 344 if ($body) {
339 $s .= ">\n"; 345 my $t = format_tree($body, $indent + 1);
340 $s .= format_tree($body, $indent + 1); 346 if ($t =~ /\n/) {
341 $s .= $space . "</$name>\n"; 347 $s .= ">\n" . $t
348 . $space . "</$name>\n";
349 } else {
350 $s .= ">$t</$name>\n";
351 }
342 } else { 352 } else {
343 $s .= "/>\n"; 353 $s .= "/>\n";
344 } 354 }
345 355
346 next; 356 next;
360 unless $value =~ /^"/; 370 unless $value =~ /^"/;
361 push @attrs, "$name=$value"; 371 push @attrs, "$name=$value";
362 } 372 }
363 373
364 if ($name eq "xsl:stylesheet") { 374 if ($name eq "xsl:stylesheet") {
365 $s .= '<?xml version="1.0" encoding="utf-8"?>' . "\n";
366 push @attrs, 'xmlns:xsl="http://www.w3.org/1999/XSL/Transform"'; 375 push @attrs, 'xmlns:xsl="http://www.w3.org/1999/XSL/Transform"';
367 push @attrs, 'version="1.0"'; 376 push @attrs, 'version="1.0"';
368 } 377 }
369 378
370 my ($attrs, $body) = @a; 379 my ($attrs, $body) = @a;
371 $attrs = [ @{$attrs}, @attrs ]; 380 $attrs = [ @{$attrs}, @attrs ];
372 381
373 $s .= $space . "<" . join(" ", $name, @{$attrs}); 382 $s .= $space . "<" . join(" ", $name, @{$attrs});
374 383
375 if ($body) { 384 if ($body && scalar @{$body} > 0) {
376 $s .= ">\n"; 385 my $t = format_tree($body, $indent + 1);
377 $s .= format_tree($body, $indent + 1); 386 if ($t =~ /\n/) {
378 $s .= $space . "</$name>\n"; 387 $s .= ">\n" . $t
388 . $space . "</$name>\n";
389 } else {
390 $s .= ">$t</$name>\n";
391 }
379 } else { 392 } else {
380 $s .= "/>\n\n"; 393 $s .= "/>\n";
381 } 394 }
382 395
383 next; 396 next;
384 } 397 }
385 398
403 416
404 my $tree = $parser->startrule($lines) 417 my $tree = $parser->startrule($lines)
405 or die "Failed to parse $ARGV.\n"; 418 or die "Failed to parse $ARGV.\n";
406 419
407 #print Dumper($tree); 420 #print Dumper($tree);
408 #print join("\n", @{$tree});
409
410 print format_tree($tree); 421 print format_tree($tree);
411 422
412 ############################################################################### 423 ###############################################################################