]> git.saurik.com Git - bison.git/blob - data/xslt/xml2text.xsl
* data/xslt/bison.xsl (bison:ruleNumber): Rename to...
[bison.git] / data / xslt / xml2text.xsl
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 <!--
4 xml2text.xsl - transform Bison XML Report into plain text.
5 $Id$
6
7 Copyright (C) 2007 Free Software Foundation, Inc.
8
9 This file is part of Bison, the GNU Compiler Compiler.
10
11 This program is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23
24 Written by Wojciech Polak <polak@gnu.org>.
25 -->
26
27 <xsl:stylesheet version="1.0"
28 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
29 xmlns:bison="http://www.gnu.org/software/bison/">
30
31 <xsl:import href="bison.xsl"/>
32 <xsl:output method="text" encoding="UTF-8" indent="no"/>
33
34 <xsl:template match="/">
35 <xsl:apply-templates select="bison-xml-report"/>
36 </xsl:template>
37
38 <xsl:template match="bison-xml-report">
39 <xsl:apply-templates select="grammar" mode="reductions"/>
40 <xsl:apply-templates select="grammar" mode="useless-in-parser"/>
41 <xsl:apply-templates select="automaton" mode="conflicts"/>
42 <xsl:apply-templates select="grammar"/>
43 <xsl:apply-templates select="automaton"/>
44 </xsl:template>
45
46 <xsl:template match="grammar" mode="reductions">
47 <xsl:apply-templates select="nonterminals" mode="useless-in-grammar"/>
48 <xsl:apply-templates select="terminals" mode="unused-in-grammar"/>
49 <xsl:apply-templates select="rules" mode="useless-in-grammar"/>
50 </xsl:template>
51
52 <xsl:template match="nonterminals" mode="useless-in-grammar">
53 <xsl:if test="nonterminal[@usefulness='useless-in-grammar']">
54 <xsl:text>Nonterminals useless in grammar&#10;&#10;</xsl:text>
55 <xsl:for-each select="nonterminal[@usefulness='useless-in-grammar']">
56 <xsl:text> </xsl:text>
57 <xsl:value-of select="@name"/>
58 <xsl:text>&#10;</xsl:text>
59 </xsl:for-each>
60 <xsl:text>&#10;&#10;</xsl:text>
61 </xsl:if>
62 </xsl:template>
63
64 <xsl:template match="terminals" mode="unused-in-grammar">
65 <xsl:if test="terminal[@usefulness='unused-in-grammar']">
66 <xsl:text>Terminals unused in grammar&#10;&#10;</xsl:text>
67 <xsl:for-each select="terminal[@usefulness='unused-in-grammar']">
68 <xsl:sort select="@symbol-number" data-type="number"/>
69 <xsl:text> </xsl:text>
70 <xsl:value-of select="@name"/>
71 <xsl:text>&#10;</xsl:text>
72 </xsl:for-each>
73 <xsl:text>&#10;&#10;</xsl:text>
74 </xsl:if>
75 </xsl:template>
76
77 <xsl:template match="rules" mode="useless-in-grammar">
78 <xsl:variable name="set" select="rule[@usefulness='useless-in-grammar']"/>
79 <xsl:if test="$set">
80 <xsl:text>Rules useless in grammar&#10;</xsl:text>
81 <xsl:call-template name="style-rule-set">
82 <xsl:with-param name="rule-set" select="$set"/>
83 </xsl:call-template>
84 <xsl:text>&#10;&#10;</xsl:text>
85 </xsl:if>
86 </xsl:template>
87
88 <xsl:template match="grammar" mode="useless-in-parser">
89 <xsl:variable
90 name="set" select="rules/rule[@usefulness='useless-in-parser']"
91 />
92 <xsl:if test="$set">
93 <xsl:text>Rules useless in parser due to conflicts&#10;</xsl:text>
94 <xsl:call-template name="style-rule-set">
95 <xsl:with-param name="rule-set" select="$set"/>
96 </xsl:call-template>
97 <xsl:text>&#10;&#10;</xsl:text>
98 </xsl:if>
99 </xsl:template>
100
101 <xsl:template match="grammar">
102 <xsl:text>Grammar&#10;</xsl:text>
103 <xsl:call-template name="style-rule-set">
104 <xsl:with-param
105 name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']"
106 />
107 </xsl:call-template>
108 <xsl:text>&#10;&#10;</xsl:text>
109 <xsl:apply-templates select="terminals"/>
110 <xsl:apply-templates select="nonterminals"/>
111 </xsl:template>
112
113 <xsl:template name="style-rule-set">
114 <xsl:param name="rule-set"/>
115 <xsl:for-each select="$rule-set">
116 <xsl:apply-templates select=".">
117 <xsl:with-param name="pad" select="'3'"/>
118 <xsl:with-param name="prev-lhs">
119 <xsl:if test="position()>1">
120 <xsl:variable name="position" select="position()"/>
121 <xsl:value-of select="$rule-set[$position - 1]/lhs"/>
122 </xsl:if>
123 </xsl:with-param>
124 </xsl:apply-templates>
125 </xsl:for-each>
126 </xsl:template>
127
128 <xsl:template match="grammar/terminals">
129 <xsl:text>Terminals, with rules where they appear&#10;&#10;</xsl:text>
130 <xsl:apply-templates select="terminal"/>
131 <xsl:text>&#10;&#10;</xsl:text>
132 </xsl:template>
133
134 <xsl:template match="grammar/nonterminals">
135 <xsl:text>Nonterminals, with rules where they appear&#10;&#10;</xsl:text>
136 <xsl:apply-templates select="nonterminal[@usefulness!='useless-in-grammar']"/>
137 </xsl:template>
138
139 <xsl:template match="terminal">
140 <xsl:value-of select="@name"/>
141 <xsl:call-template name="line-wrap">
142 <xsl:with-param name="first-line-length">
143 <xsl:choose>
144 <xsl:when test="string-length(@name) &gt; 66">0</xsl:when>
145 <xsl:otherwise>
146 <xsl:value-of select="66 - string-length(@name)" />
147 </xsl:otherwise>
148 </xsl:choose>
149 </xsl:with-param>
150 <xsl:with-param name="line-length" select="66" />
151 <xsl:with-param name="text">
152 <xsl:value-of select="concat(' (', @token-number, ')')"/>
153 <xsl:for-each select="key('bison:ruleByRhs', @name)">
154 <xsl:value-of select="concat(' ', @number)"/>
155 </xsl:for-each>
156 </xsl:with-param>
157 </xsl:call-template>
158 </xsl:template>
159
160 <xsl:template match="nonterminal">
161 <xsl:value-of select="@name"/>
162 <xsl:value-of select="concat(' (', @symbol-number, ')')"/>
163 <xsl:text>&#10;</xsl:text>
164 <xsl:variable name="output">
165 <xsl:call-template name="line-wrap">
166 <xsl:with-param name="line-length" select="66" />
167 <xsl:with-param name="text">
168 <xsl:text> </xsl:text>
169 <xsl:if test="key('bison:ruleByLhs', @name)">
170 <xsl:text>on@left:</xsl:text>
171 <xsl:for-each select="key('bison:ruleByLhs', @name)">
172 <xsl:value-of select="concat(' ', @number)"/>
173 </xsl:for-each>
174 </xsl:if>
175 <xsl:if test="key('bison:ruleByRhs', @name)">
176 <xsl:if test="key('bison:ruleByLhs', @name)">
177 <xsl:text>, </xsl:text>
178 </xsl:if>
179 <xsl:text>on@right:</xsl:text>
180 <xsl:for-each select="key('bison:ruleByRhs', @name)">
181 <xsl:value-of select="concat(' ', @number)"/>
182 </xsl:for-each>
183 </xsl:if>
184 </xsl:with-param>
185 </xsl:call-template>
186 </xsl:variable>
187 <xsl:value-of select="translate($output, '@', ' ')" />
188 </xsl:template>
189
190 <xsl:template match="automaton" mode="conflicts">
191 <xsl:variable name="conflict-report">
192 <xsl:apply-templates select="state" mode="conflicts"/>
193 </xsl:variable>
194 <xsl:if test="string-length($conflict-report) != 0">
195 <xsl:value-of select="$conflict-report"/>
196 <xsl:text>&#10;&#10;</xsl:text>
197 </xsl:if>
198 </xsl:template>
199
200 <xsl:template match="state" mode="conflicts">
201 <xsl:variable name="conflict-counts">
202 <xsl:apply-templates select="." mode="bison:count-conflicts" />
203 </xsl:variable>
204 <xsl:variable
205 name="sr-count" select="substring-before($conflict-counts, ',')"
206 />
207 <xsl:variable
208 name="rr-count" select="substring-after($conflict-counts, ',')"
209 />
210 <xsl:if test="$sr-count > 0 or $rr-count > 0">
211 <xsl:value-of select="concat('State ', @number, ' conflicts:')"/>
212 <xsl:if test="$sr-count > 0">
213 <xsl:value-of select="concat(' ', $sr-count, ' shift/reduce')"/>
214 <xsl:if test="$rr-count > 0">
215 <xsl:value-of select="(',')"/>
216 </xsl:if>
217 </xsl:if>
218 <xsl:if test="$rr-count > 0">
219 <xsl:value-of select="concat(' ', $rr-count, ' reduce/reduce')"/>
220 </xsl:if>
221 <xsl:value-of select="'&#10;'"/>
222 </xsl:if>
223 </xsl:template>
224
225 <xsl:template match="automaton">
226 <xsl:apply-templates select="state">
227 <xsl:with-param name="pad" select="'3'"/>
228 </xsl:apply-templates>
229 </xsl:template>
230
231 <xsl:template match="automaton/state">
232 <xsl:param name="pad"/>
233 <xsl:text>&#10;&#10;</xsl:text>
234 <xsl:text>state </xsl:text>
235 <xsl:value-of select="@number"/>
236 <xsl:text>&#10;&#10;</xsl:text>
237 <xsl:apply-templates select="itemset/item">
238 <xsl:with-param name="pad" select="$pad"/>
239 </xsl:apply-templates>
240 <xsl:apply-templates select="actions/transitions">
241 <xsl:with-param name="type" select="'shift'"/>
242 </xsl:apply-templates>
243 <xsl:apply-templates select="actions/errors"/>
244 <xsl:apply-templates select="actions/reductions"/>
245 <xsl:apply-templates select="actions/transitions">
246 <xsl:with-param name="type" select="'goto'"/>
247 </xsl:apply-templates>
248 <xsl:apply-templates select="solved-conflicts"/>
249 </xsl:template>
250
251 <xsl:template match="actions/transitions">
252 <xsl:param name="type"/>
253 <xsl:if test="transition[@type = $type]">
254 <xsl:text>&#10;</xsl:text>
255 <xsl:apply-templates select="transition[@type = $type]">
256 <xsl:with-param name="pad">
257 <xsl:call-template name="max-width-symbol">
258 <xsl:with-param name="node" select="transition[@type = $type]"/>
259 </xsl:call-template>
260 </xsl:with-param>
261 </xsl:apply-templates>
262 </xsl:if>
263 </xsl:template>
264
265 <xsl:template match="actions/errors">
266 <xsl:if test="error">
267 <xsl:text>&#10;</xsl:text>
268 <xsl:apply-templates select="error">
269 <xsl:with-param name="pad">
270 <xsl:call-template name="max-width-symbol">
271 <xsl:with-param name="node" select="error"/>
272 </xsl:call-template>
273 </xsl:with-param>
274 </xsl:apply-templates>
275 </xsl:if>
276 </xsl:template>
277
278 <xsl:template match="actions/reductions">
279 <xsl:if test="reduction">
280 <xsl:text>&#10;</xsl:text>
281 <xsl:apply-templates select="reduction">
282 <xsl:with-param name="pad">
283 <xsl:call-template name="max-width-symbol">
284 <xsl:with-param name="node" select="reduction"/>
285 </xsl:call-template>
286 </xsl:with-param>
287 </xsl:apply-templates>
288 </xsl:if>
289 </xsl:template>
290
291 <xsl:template match="item">
292 <xsl:param name="pad"/>
293 <xsl:param name="prev-rule-number"
294 select="preceding-sibling::item[1]/@rule-number"/>
295 <xsl:apply-templates
296 select="key('bison:ruleByNumber', current()/@rule-number)"
297 >
298 <xsl:with-param name="itemset" select="'true'"/>
299 <xsl:with-param name="pad" select="$pad"/>
300 <xsl:with-param
301 name="prev-lhs"
302 select="key('bison:ruleByNumber', $prev-rule-number)/lhs[text()]"
303 />
304 <xsl:with-param name="point" select="@point"/>
305 <xsl:with-param name="lookaheads">
306 <xsl:apply-templates select="lookaheads"/>
307 </xsl:with-param>
308 </xsl:apply-templates>
309 </xsl:template>
310
311 <xsl:template match="rule">
312 <xsl:param name="itemset"/>
313 <xsl:param name="pad"/>
314 <xsl:param name="prev-lhs"/>
315 <xsl:param name="point"/>
316 <xsl:param name="lookaheads"/>
317
318 <xsl:if test="$itemset != 'true' and not($prev-lhs = lhs[text()])">
319 <xsl:text>&#10;</xsl:text>
320 </xsl:if>
321
322 <xsl:text> </xsl:text>
323 <xsl:call-template name="lpad">
324 <xsl:with-param name="str" select="string(@number)"/>
325 <xsl:with-param name="pad" select="number($pad)"/>
326 </xsl:call-template>
327 <xsl:text> </xsl:text>
328
329 <!-- LHS -->
330 <xsl:choose>
331 <xsl:when test="$itemset != 'true' and $prev-lhs = lhs[text()]">
332 <xsl:call-template name="lpad">
333 <xsl:with-param name="str" select="'|'"/>
334 <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/>
335 </xsl:call-template>
336 </xsl:when>
337 <xsl:when test="$itemset = 'true' and $prev-lhs = lhs[text()]">
338 <xsl:call-template name="lpad">
339 <xsl:with-param name="str" select="'|'"/>
340 <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/>
341 </xsl:call-template>
342 </xsl:when>
343 <xsl:otherwise>
344 <xsl:value-of select="lhs"/>
345 <xsl:text>:</xsl:text>
346 </xsl:otherwise>
347 </xsl:choose>
348
349 <!-- RHS -->
350 <xsl:for-each select="rhs/*">
351 <xsl:if test="position() = $point + 1">
352 <xsl:text> .</xsl:text>
353 </xsl:if>
354 <xsl:if test="$itemset = 'true' and name(.) != 'empty'">
355 <xsl:apply-templates select="."/>
356 </xsl:if>
357 <xsl:if test="$itemset != 'true'">
358 <xsl:apply-templates select="."/>
359 </xsl:if>
360 <xsl:if test="position() = last() and position() = $point">
361 <xsl:text> .</xsl:text>
362 </xsl:if>
363 </xsl:for-each>
364 <xsl:if test="$lookaheads">
365 <xsl:value-of select="$lookaheads"/>
366 </xsl:if>
367
368 <xsl:text>&#10;</xsl:text>
369 </xsl:template>
370
371 <xsl:template match="symbol">
372 <xsl:text> </xsl:text>
373 <xsl:value-of select="."/>
374 </xsl:template>
375
376 <xsl:template match="empty">
377 <xsl:text> /* empty */</xsl:text>
378 </xsl:template>
379
380 <xsl:template match="lookaheads">
381 <xsl:text> [</xsl:text>
382 <xsl:apply-templates select="symbol"/>
383 <xsl:text>]</xsl:text>
384 </xsl:template>
385
386 <xsl:template match="lookaheads/symbol">
387 <xsl:value-of select="."/>
388 <xsl:if test="position() != last()">
389 <xsl:text>, </xsl:text>
390 </xsl:if>
391 </xsl:template>
392
393 <xsl:template match="transition">
394 <xsl:param name="pad"/>
395 <xsl:text> </xsl:text>
396 <xsl:call-template name="rpad">
397 <xsl:with-param name="str" select="string(@symbol)"/>
398 <xsl:with-param name="pad" select="number($pad) + 2"/>
399 </xsl:call-template>
400 <xsl:choose>
401 <xsl:when test="@type = 'shift'">
402 <xsl:text>shift, and go to state </xsl:text>
403 <xsl:value-of select="@state"/>
404 </xsl:when>
405 <xsl:when test="@type = 'goto'">
406 <xsl:text>go to state </xsl:text>
407 <xsl:value-of select="@state"/>
408 </xsl:when>
409 </xsl:choose>
410 <xsl:text>&#10;</xsl:text>
411 </xsl:template>
412
413 <xsl:template match="error">
414 <xsl:param name="pad"/>
415 <xsl:text> </xsl:text>
416 <xsl:call-template name="rpad">
417 <xsl:with-param name="str" select="string(@symbol)"/>
418 <xsl:with-param name="pad" select="number($pad) + 2"/>
419 </xsl:call-template>
420 <xsl:text>error</xsl:text>
421 <xsl:text> (</xsl:text>
422 <xsl:value-of select="text()"/>
423 <xsl:text>)</xsl:text>
424 <xsl:text>&#10;</xsl:text>
425 </xsl:template>
426
427 <xsl:template match="reduction">
428 <xsl:param name="pad"/>
429 <xsl:text> </xsl:text>
430 <xsl:call-template name="rpad">
431 <xsl:with-param name="str" select="string(@symbol)"/>
432 <xsl:with-param name="pad" select="number($pad) + 2"/>
433 </xsl:call-template>
434 <xsl:if test="@enabled = 'false'">
435 <xsl:text>[</xsl:text>
436 </xsl:if>
437 <xsl:choose>
438 <xsl:when test="@rule = 'accept'">
439 <xsl:text>accept</xsl:text>
440 </xsl:when>
441 <xsl:otherwise>
442 <xsl:text>reduce using rule </xsl:text>
443 <xsl:value-of select="@rule"/>
444 <xsl:text> (</xsl:text>
445 <xsl:value-of
446 select="key('bison:ruleByNumber', current()/@rule)/lhs[text()]"/>
447 <xsl:text>)</xsl:text>
448 </xsl:otherwise>
449 </xsl:choose>
450 <xsl:if test="@enabled = 'false'">
451 <xsl:text>]</xsl:text>
452 </xsl:if>
453 <xsl:text>&#10;</xsl:text>
454 </xsl:template>
455
456 <xsl:template match="solved-conflicts">
457 <xsl:if test="resolution">
458 <xsl:text>&#10;</xsl:text>
459 <xsl:apply-templates select="resolution"/>
460 </xsl:if>
461 </xsl:template>
462
463 <xsl:template match="resolution">
464 <xsl:text> Conflict between rule </xsl:text>
465 <xsl:value-of select="@rule"/>
466 <xsl:text> and token </xsl:text>
467 <xsl:value-of select="@symbol"/>
468 <xsl:text> resolved as </xsl:text>
469 <xsl:if test="@type = 'error'">
470 <xsl:text>an </xsl:text>
471 </xsl:if>
472 <xsl:value-of select="@type"/>
473 <xsl:text> (</xsl:text>
474 <xsl:value-of select="."/>
475 <xsl:text>).&#10;</xsl:text>
476 </xsl:template>
477
478 <xsl:template name="max-width-symbol">
479 <xsl:param name="node"/>
480 <xsl:variable name="longest">
481 <xsl:for-each select="$node">
482 <xsl:sort data-type="number" select="string-length(@symbol)"
483 order="descending"/>
484 <xsl:if test="position() = 1">
485 <xsl:value-of select="string-length(@symbol)"/>
486 </xsl:if>
487 </xsl:for-each>
488 </xsl:variable>
489 <xsl:value-of select="$longest"/>
490 </xsl:template>
491
492 <xsl:template name="lpad">
493 <xsl:param name="str" select="''"/>
494 <xsl:param name="pad" select="0"/>
495 <xsl:variable name="diff" select="$pad - string-length($str)" />
496 <xsl:choose>
497 <xsl:when test="$diff &lt; 0">
498 <xsl:value-of select="$str"/>
499 </xsl:when>
500 <xsl:otherwise>
501 <xsl:call-template name="space">
502 <xsl:with-param name="repeat" select="$diff"/>
503 </xsl:call-template>
504 <xsl:value-of select="$str"/>
505 </xsl:otherwise>
506 </xsl:choose>
507 </xsl:template>
508
509 <xsl:template name="rpad">
510 <xsl:param name="str" select="''"/>
511 <xsl:param name="pad" select="0"/>
512 <xsl:variable name="diff" select="$pad - string-length($str)"/>
513 <xsl:choose>
514 <xsl:when test="$diff &lt; 0">
515 <xsl:value-of select="$str"/>
516 </xsl:when>
517 <xsl:otherwise>
518 <xsl:value-of select="$str"/>
519 <xsl:call-template name="space">
520 <xsl:with-param name="repeat" select="$diff"/>
521 </xsl:call-template>
522 </xsl:otherwise>
523 </xsl:choose>
524 </xsl:template>
525
526 <xsl:template name="space">
527 <xsl:param name="repeat">0</xsl:param>
528 <xsl:param name="fill" select="' '"/>
529 <xsl:if test="number($repeat) &gt;= 1">
530 <xsl:call-template name="space">
531 <xsl:with-param name="repeat" select="$repeat - 1"/>
532 <xsl:with-param name="fill" select="$fill"/>
533 </xsl:call-template>
534 <xsl:value-of select="$fill"/>
535 </xsl:if>
536 </xsl:template>
537
538 <xsl:template name="line-wrap">
539 <xsl:param name="line-length"/> <!-- required -->
540 <xsl:param name="first-line-length" select="$line-length"/>
541 <xsl:param name="text"/> <!-- required -->
542 <xsl:choose>
543 <xsl:when test="normalize-space($text) = ''" />
544 <xsl:when test="string-length($text) &lt;= $first-line-length">
545 <xsl:value-of select="concat($text, '&#10;')" />
546 </xsl:when>
547 <xsl:otherwise>
548 <xsl:variable name="break-pos">
549 <xsl:call-template name="ws-search">
550 <xsl:with-param name="text" select="$text" />
551 <xsl:with-param name="start" select="$first-line-length+1" />
552 </xsl:call-template>
553 </xsl:variable>
554 <xsl:value-of select="substring($text, 1, $break-pos - 1)" />
555 <xsl:text>&#10;</xsl:text>
556 <xsl:call-template name="line-wrap">
557 <xsl:with-param name="line-length" select="$line-length" />
558 <xsl:with-param
559 name="text" select="concat(' ', substring($text, $break-pos+1))"
560 />
561 </xsl:call-template>
562 </xsl:otherwise>
563 </xsl:choose>
564 </xsl:template>
565
566 <xsl:template name="ws-search">
567 <xsl:param name="text"/> <!-- required -->
568 <xsl:param name="start"/> <!-- required -->
569 <xsl:variable name="search-text" select="substring($text, $start)" />
570 <xsl:choose>
571 <xsl:when test="not(contains($search-text, ' '))">
572 <xsl:value-of select="string-length($text)+1" />
573 </xsl:when>
574 <xsl:otherwise>
575 <xsl:value-of
576 select="$start + string-length(substring-before($search-text, ' '))"
577 />
578 </xsl:otherwise>
579 </xsl:choose>
580 </xsl:template>
581
582 </xsl:stylesheet>