1 <?xml version=
"1.0" encoding=
"UTF-8"?>
4 xml2text.xsl - transform Bison XML Report into plain text.
6 Copyright (C) 2007-2013 Free Software Foundation, Inc.
8 This file is part of Bison, the GNU Compiler Compiler.
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 Written by Wojciech Polak <polak@gnu.org>.
26 <xsl:stylesheet version=
"1.0"
27 xmlns:
xsl=
"http://www.w3.org/1999/XSL/Transform"
28 xmlns:
bison=
"http://www.gnu.org/software/bison/">
30 <xsl:import href=
"bison.xsl"/>
31 <xsl:output method=
"text" encoding=
"UTF-8" indent=
"no"/>
33 <xsl:template match=
"/">
34 <xsl:apply-templates select=
"bison-xml-report"/>
37 <xsl:template match=
"bison-xml-report">
38 <xsl:apply-templates select=
"grammar" mode=
"reductions"/>
39 <xsl:apply-templates select=
"grammar" mode=
"useless-in-parser"/>
40 <xsl:apply-templates select=
"automaton" mode=
"conflicts"/>
41 <xsl:apply-templates select=
"grammar"/>
42 <xsl:apply-templates select=
"automaton"/>
45 <xsl:template match=
"grammar" mode=
"reductions">
46 <xsl:apply-templates select=
"nonterminals" mode=
"useless-in-grammar"/>
47 <xsl:apply-templates select=
"terminals" mode=
"unused-in-grammar"/>
48 <xsl:apply-templates select=
"rules" mode=
"useless-in-grammar"/>
51 <xsl:template match=
"nonterminals" mode=
"useless-in-grammar">
52 <xsl:if test=
"nonterminal[@usefulness='useless-in-grammar']">
53 <xsl:text>Nonterminals useless in grammar
</xsl:text>
54 <xsl:for-each select=
"nonterminal[@usefulness='useless-in-grammar']">
55 <xsl:text> </xsl:text>
56 <xsl:value-of select=
"@name"/>
57 <xsl:text> </xsl:text>
59 <xsl:text> </xsl:text>
63 <xsl:template match=
"terminals" mode=
"unused-in-grammar">
64 <xsl:if test=
"terminal[@usefulness='unused-in-grammar']">
65 <xsl:text>Terminals unused in grammar
</xsl:text>
66 <xsl:for-each select=
"terminal[@usefulness='unused-in-grammar']">
67 <xsl:sort select=
"@symbol-number" data-type=
"number"/>
68 <xsl:text> </xsl:text>
69 <xsl:value-of select=
"@name"/>
70 <xsl:text> </xsl:text>
72 <xsl:text> </xsl:text>
76 <xsl:template match=
"rules" mode=
"useless-in-grammar">
77 <xsl:variable name=
"set" select=
"rule[@usefulness='useless-in-grammar']"/>
79 <xsl:text>Rules useless in grammar
</xsl:text>
80 <xsl:call-template name=
"style-rule-set">
81 <xsl:with-param name=
"rule-set" select=
"$set"/>
83 <xsl:text> </xsl:text>
87 <xsl:template match=
"grammar" mode=
"useless-in-parser">
89 name=
"set" select=
"rules/rule[@usefulness='useless-in-parser']"
92 <xsl:text>Rules useless in parser due to conflicts
</xsl:text>
93 <xsl:call-template name=
"style-rule-set">
94 <xsl:with-param name=
"rule-set" select=
"$set"/>
96 <xsl:text> </xsl:text>
100 <xsl:template match=
"grammar">
101 <xsl:text>Grammar
</xsl:text>
102 <xsl:call-template name=
"style-rule-set">
104 name=
"rule-set" select=
"rules/rule[@usefulness!='useless-in-grammar']"
107 <xsl:text> </xsl:text>
108 <xsl:apply-templates select=
"terminals"/>
109 <xsl:apply-templates select=
"nonterminals"/>
112 <xsl:template name=
"style-rule-set">
113 <xsl:param name=
"rule-set"/>
114 <xsl:for-each select=
"$rule-set">
115 <xsl:apply-templates select=
".">
116 <xsl:with-param name=
"pad" select=
"'3'"/>
117 <xsl:with-param name=
"prev-lhs">
118 <xsl:if test=
"position()>1">
119 <xsl:variable name=
"position" select=
"position()"/>
120 <xsl:value-of select=
"$rule-set[$position - 1]/lhs"/>
123 </xsl:apply-templates>
127 <xsl:template match=
"grammar/terminals">
128 <xsl:text>Terminals, with rules where they appear
</xsl:text>
129 <xsl:apply-templates select=
"terminal"/>
130 <xsl:text> </xsl:text>
133 <xsl:template match=
"grammar/nonterminals">
134 <xsl:text>Nonterminals, with rules where they appear
</xsl:text>
135 <xsl:apply-templates select=
"nonterminal[@usefulness!='useless-in-grammar']"/>
138 <xsl:template match=
"terminal">
139 <xsl:value-of select=
"@name"/>
140 <xsl:call-template name=
"line-wrap">
141 <xsl:with-param name=
"first-line-length">
143 <xsl:when test=
"string-length(@name) > 66">0</xsl:when>
145 <xsl:value-of select=
"66 - string-length(@name)" />
149 <xsl:with-param name=
"line-length" select=
"66" />
150 <xsl:with-param name=
"text">
151 <xsl:value-of select=
"concat(' (', @token-number, ')')"/>
152 <xsl:for-each select=
"key('bison:ruleByRhs', @name)">
153 <xsl:value-of select=
"concat(' ', @number)"/>
159 <xsl:template match=
"nonterminal">
160 <xsl:value-of select=
"@name"/>
161 <xsl:value-of select=
"concat(' (', @symbol-number, ')')"/>
162 <xsl:text> </xsl:text>
163 <xsl:variable name=
"output">
164 <xsl:call-template name=
"line-wrap">
165 <xsl:with-param name=
"line-length" select=
"66" />
166 <xsl:with-param name=
"text">
167 <xsl:text> </xsl:text>
168 <xsl:if test=
"key('bison:ruleByLhs', @name)">
169 <xsl:text>on@left:
</xsl:text>
170 <xsl:for-each select=
"key('bison:ruleByLhs', @name)">
171 <xsl:value-of select=
"concat(' ', @number)"/>
174 <xsl:if test=
"key('bison:ruleByRhs', @name)">
175 <xsl:if test=
"key('bison:ruleByLhs', @name)">
176 <xsl:text>,
</xsl:text>
178 <xsl:text>on@right:
</xsl:text>
179 <xsl:for-each select=
"key('bison:ruleByRhs', @name)">
180 <xsl:value-of select=
"concat(' ', @number)"/>
186 <xsl:value-of select=
"translate($output, '@', ' ')" />
189 <xsl:template match=
"automaton" mode=
"conflicts">
190 <xsl:variable name=
"conflict-report">
191 <xsl:apply-templates select=
"state" mode=
"conflicts"/>
193 <xsl:if test=
"string-length($conflict-report) != 0">
194 <xsl:value-of select=
"$conflict-report"/>
195 <xsl:text> </xsl:text>
199 <xsl:template match=
"state" mode=
"conflicts">
200 <xsl:variable name=
"conflict-counts">
201 <xsl:apply-templates select=
"." mode=
"bison:count-conflicts" />
204 name=
"sr-count" select=
"substring-before($conflict-counts, ',')"
207 name=
"rr-count" select=
"substring-after($conflict-counts, ',')"
209 <xsl:if test=
"$sr-count > 0 or $rr-count > 0">
210 <xsl:value-of select=
"concat('State ', @number, ' conflicts:')"/>
211 <xsl:if test=
"$sr-count > 0">
212 <xsl:value-of select=
"concat(' ', $sr-count, ' shift/reduce')"/>
213 <xsl:if test=
"$rr-count > 0">
214 <xsl:value-of select=
"(',')"/>
217 <xsl:if test=
"$rr-count > 0">
218 <xsl:value-of select=
"concat(' ', $rr-count, ' reduce/reduce')"/>
220 <xsl:value-of select=
"' '"/>
224 <xsl:template match=
"automaton">
225 <xsl:apply-templates select=
"state">
226 <xsl:with-param name=
"pad" select=
"'3'"/>
227 </xsl:apply-templates>
230 <xsl:template match=
"automaton/state">
231 <xsl:param name=
"pad"/>
232 <xsl:text> </xsl:text>
233 <xsl:text>State
</xsl:text>
234 <xsl:value-of select=
"@number"/>
235 <xsl:text> </xsl:text>
236 <xsl:apply-templates select=
"itemset/item">
237 <xsl:with-param name=
"pad" select=
"$pad"/>
238 </xsl:apply-templates>
239 <xsl:apply-templates select=
"actions/transitions">
240 <xsl:with-param name=
"type" select=
"'shift'"/>
241 </xsl:apply-templates>
242 <xsl:apply-templates select=
"actions/errors"/>
243 <xsl:apply-templates select=
"actions/reductions"/>
244 <xsl:apply-templates select=
"actions/transitions">
245 <xsl:with-param name=
"type" select=
"'goto'"/>
246 </xsl:apply-templates>
247 <xsl:apply-templates select=
"solved-conflicts"/>
250 <xsl:template match=
"actions/transitions">
251 <xsl:param name=
"type"/>
252 <xsl:if test=
"transition[@type = $type]">
253 <xsl:text> </xsl:text>
254 <xsl:apply-templates select=
"transition[@type = $type]">
255 <xsl:with-param name=
"pad">
256 <xsl:call-template name=
"max-width-symbol">
257 <xsl:with-param name=
"node" select=
"transition[@type = $type]"/>
260 </xsl:apply-templates>
264 <xsl:template match=
"actions/errors">
265 <xsl:if test=
"error">
266 <xsl:text> </xsl:text>
267 <xsl:apply-templates select=
"error">
268 <xsl:with-param name=
"pad">
269 <xsl:call-template name=
"max-width-symbol">
270 <xsl:with-param name=
"node" select=
"error"/>
273 </xsl:apply-templates>
277 <xsl:template match=
"actions/reductions">
278 <xsl:if test=
"reduction">
279 <xsl:text> </xsl:text>
280 <xsl:apply-templates select=
"reduction">
281 <xsl:with-param name=
"pad">
282 <xsl:call-template name=
"max-width-symbol">
283 <xsl:with-param name=
"node" select=
"reduction"/>
286 </xsl:apply-templates>
290 <xsl:template match=
"item">
291 <xsl:param name=
"pad"/>
292 <xsl:param name=
"prev-rule-number"
293 select=
"preceding-sibling::item[1]/@rule-number"/>
295 select=
"key('bison:ruleByNumber', current()/@rule-number)"
297 <xsl:with-param name=
"itemset" select=
"'true'"/>
298 <xsl:with-param name=
"pad" select=
"$pad"/>
301 select=
"key('bison:ruleByNumber', $prev-rule-number)/lhs[text()]"
303 <xsl:with-param name=
"point" select=
"@point"/>
304 <xsl:with-param name=
"lookaheads">
305 <xsl:apply-templates select=
"lookaheads"/>
307 </xsl:apply-templates>
310 <xsl:template match=
"rule">
311 <xsl:param name=
"itemset"/>
312 <xsl:param name=
"pad"/>
313 <xsl:param name=
"prev-lhs"/>
314 <xsl:param name=
"point"/>
315 <xsl:param name=
"lookaheads"/>
317 <xsl:if test=
"$itemset != 'true' and not($prev-lhs = lhs[text()])">
318 <xsl:text> </xsl:text>
321 <xsl:text> </xsl:text>
322 <xsl:call-template name=
"lpad">
323 <xsl:with-param name=
"str" select=
"string(@number)"/>
324 <xsl:with-param name=
"pad" select=
"number($pad)"/>
326 <xsl:text> </xsl:text>
330 <xsl:when test=
"$itemset != 'true' and $prev-lhs = lhs[text()]">
331 <xsl:call-template name=
"lpad">
332 <xsl:with-param name=
"str" select=
"'|'"/>
333 <xsl:with-param name=
"pad" select=
"number(string-length(lhs[text()])) + 1"/>
336 <xsl:when test=
"$itemset = 'true' and $prev-lhs = lhs[text()]">
337 <xsl:call-template name=
"lpad">
338 <xsl:with-param name=
"str" select=
"'|'"/>
339 <xsl:with-param name=
"pad" select=
"number(string-length(lhs[text()])) + 1"/>
343 <xsl:value-of select=
"lhs"/>
344 <xsl:text>:
</xsl:text>
349 <xsl:for-each select=
"rhs/*">
350 <xsl:if test=
"position() = $point + 1">
351 <xsl:text> .
</xsl:text>
353 <xsl:if test=
"$itemset = 'true' and name(.) != 'empty'">
354 <xsl:apply-templates select=
"."/>
356 <xsl:if test=
"$itemset != 'true'">
357 <xsl:apply-templates select=
"."/>
359 <xsl:if test=
"position() = last() and position() = $point">
360 <xsl:text> .
</xsl:text>
363 <xsl:if test=
"$lookaheads">
364 <xsl:value-of select=
"$lookaheads"/>
367 <xsl:text> </xsl:text>
370 <xsl:template match=
"symbol">
371 <xsl:text> </xsl:text>
372 <xsl:value-of select=
"."/>
375 <xsl:template match=
"empty">
376 <xsl:text> %empty
</xsl:text>
379 <xsl:template match=
"lookaheads">
380 <xsl:text> [
</xsl:text>
381 <xsl:apply-templates select=
"symbol"/>
382 <xsl:text>]
</xsl:text>
385 <xsl:template match=
"lookaheads/symbol">
386 <xsl:value-of select=
"."/>
387 <xsl:if test=
"position() != last()">
388 <xsl:text>,
</xsl:text>
392 <xsl:template match=
"transition">
393 <xsl:param name=
"pad"/>
394 <xsl:text> </xsl:text>
395 <xsl:call-template name=
"rpad">
396 <xsl:with-param name=
"str" select=
"string(@symbol)"/>
397 <xsl:with-param name=
"pad" select=
"number($pad) + 2"/>
400 <xsl:when test=
"@type = 'shift'">
401 <xsl:text>shift, and go to state
</xsl:text>
402 <xsl:value-of select=
"@state"/>
404 <xsl:when test=
"@type = 'goto'">
405 <xsl:text>go to state
</xsl:text>
406 <xsl:value-of select=
"@state"/>
409 <xsl:text> </xsl:text>
412 <xsl:template match=
"error">
413 <xsl:param name=
"pad"/>
414 <xsl:text> </xsl:text>
415 <xsl:call-template name=
"rpad">
416 <xsl:with-param name=
"str" select=
"string(@symbol)"/>
417 <xsl:with-param name=
"pad" select=
"number($pad) + 2"/>
419 <xsl:text>error
</xsl:text>
420 <xsl:text> (
</xsl:text>
421 <xsl:value-of select=
"text()"/>
422 <xsl:text>)
</xsl:text>
423 <xsl:text> </xsl:text>
426 <xsl:template match=
"reduction">
427 <xsl:param name=
"pad"/>
428 <xsl:text> </xsl:text>
429 <xsl:call-template name=
"rpad">
430 <xsl:with-param name=
"str" select=
"string(@symbol)"/>
431 <xsl:with-param name=
"pad" select=
"number($pad) + 2"/>
433 <xsl:if test=
"@enabled = 'false'">
434 <xsl:text>[
</xsl:text>
437 <xsl:when test=
"@rule = 'accept'">
438 <xsl:text>accept
</xsl:text>
441 <xsl:text>reduce using rule
</xsl:text>
442 <xsl:value-of select=
"@rule"/>
443 <xsl:text> (
</xsl:text>
445 select=
"key('bison:ruleByNumber', current()/@rule)/lhs[text()]"/>
446 <xsl:text>)
</xsl:text>
449 <xsl:if test=
"@enabled = 'false'">
450 <xsl:text>]
</xsl:text>
452 <xsl:text> </xsl:text>
455 <xsl:template match=
"solved-conflicts">
456 <xsl:if test=
"resolution">
457 <xsl:text> </xsl:text>
458 <xsl:apply-templates select=
"resolution"/>
462 <xsl:template match=
"resolution">
463 <xsl:text> Conflict between rule
</xsl:text>
464 <xsl:value-of select=
"@rule"/>
465 <xsl:text> and token
</xsl:text>
466 <xsl:value-of select=
"@symbol"/>
467 <xsl:text> resolved as
</xsl:text>
468 <xsl:if test=
"@type = 'error'">
469 <xsl:text>an
</xsl:text>
471 <xsl:value-of select=
"@type"/>
472 <xsl:text> (
</xsl:text>
473 <xsl:value-of select=
"."/>
474 <xsl:text>).
</xsl:text>
477 <xsl:template name=
"max-width-symbol">
478 <xsl:param name=
"node"/>
479 <xsl:variable name=
"longest">
480 <xsl:for-each select=
"$node">
481 <xsl:sort data-type=
"number" select=
"string-length(@symbol)"
483 <xsl:if test=
"position() = 1">
484 <xsl:value-of select=
"string-length(@symbol)"/>
488 <xsl:value-of select=
"$longest"/>
491 <xsl:template name=
"lpad">
492 <xsl:param name=
"str" select=
"''"/>
493 <xsl:param name=
"pad" select=
"0"/>
494 <xsl:variable name=
"diff" select=
"$pad - string-length($str)" />
496 <xsl:when test=
"$diff < 0">
497 <xsl:value-of select=
"$str"/>
500 <xsl:call-template name=
"space">
501 <xsl:with-param name=
"repeat" select=
"$diff"/>
503 <xsl:value-of select=
"$str"/>
508 <xsl:template name=
"rpad">
509 <xsl:param name=
"str" select=
"''"/>
510 <xsl:param name=
"pad" select=
"0"/>
511 <xsl:variable name=
"diff" select=
"$pad - string-length($str)"/>
513 <xsl:when test=
"$diff < 0">
514 <xsl:value-of select=
"$str"/>
517 <xsl:value-of select=
"$str"/>
518 <xsl:call-template name=
"space">
519 <xsl:with-param name=
"repeat" select=
"$diff"/>
525 <xsl:template name=
"line-wrap">
526 <xsl:param name=
"line-length"/> <!-- required -->
527 <xsl:param name=
"first-line-length" select=
"$line-length"/>
528 <xsl:param name=
"text"/> <!-- required -->
530 <xsl:when test=
"normalize-space($text) = ''" />
531 <xsl:when test=
"string-length($text) <= $first-line-length">
532 <xsl:value-of select=
"concat($text, ' ')" />
535 <xsl:variable name=
"break-pos">
536 <xsl:call-template name=
"ws-search">
537 <xsl:with-param name=
"text" select=
"$text" />
538 <xsl:with-param name=
"start" select=
"$first-line-length+1" />
541 <xsl:value-of select=
"substring($text, 1, $break-pos - 1)" />
542 <xsl:text> </xsl:text>
543 <xsl:call-template name=
"line-wrap">
544 <xsl:with-param name=
"line-length" select=
"$line-length" />
546 name=
"text" select=
"concat(' ', substring($text, $break-pos+1))"
553 <xsl:template name=
"ws-search">
554 <xsl:param name=
"text"/> <!-- required -->
555 <xsl:param name=
"start"/> <!-- required -->
556 <xsl:variable name=
"search-text" select=
"substring($text, $start)" />
558 <xsl:when test=
"not(contains($search-text, ' '))">
559 <xsl:value-of select=
"string-length($text)+1" />
563 select=
"$start + string-length(substring-before($search-text, ' '))"