maint: remove unnecessary casts before using gnulib functions
[bison.git] / data / xslt / xml2text.xsl
blob62d5fd453bdad9e5ff7d1065eb383fe2b72eae8f
1 <?xml version="1.0" encoding="UTF-8"?>
3 <!--
4 xml2text.xsl - transform Bison XML Report into plain text.
6 Copyright (C) 2007-2015, 2018-2022 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 <https://www.gnu.org/licenses/>.
23 Written by Wojciech Polak <polak@gnu.org>.
24 -->
26 <xsl:stylesheet version="1.0"
27 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
28 xmlns:bison="https://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"/>
35 </xsl:template>
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"/>
43 </xsl:template>
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"/>
49 </xsl:template>
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&#10;&#10;</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>&#10;</xsl:text>
58 </xsl:for-each>
59 <xsl:text>&#10;&#10;</xsl:text>
60 </xsl:if>
61 </xsl:template>
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&#10;&#10;</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>&#10;</xsl:text>
71 </xsl:for-each>
72 <xsl:text>&#10;&#10;</xsl:text>
73 </xsl:if>
74 </xsl:template>
76 <xsl:template match="rules" mode="useless-in-grammar">
77 <xsl:variable name="set" select="rule[@usefulness='useless-in-grammar']"/>
78 <xsl:if test="$set">
79 <xsl:text>Rules useless in grammar&#10;</xsl:text>
80 <xsl:call-template name="style-rule-set">
81 <xsl:with-param name="rule-set" select="$set"/>
82 </xsl:call-template>
83 <xsl:text>&#10;&#10;</xsl:text>
84 </xsl:if>
85 </xsl:template>
87 <xsl:template match="grammar" mode="useless-in-parser">
88 <xsl:variable
89 name="set" select="rules/rule[@usefulness='useless-in-parser']"
91 <xsl:if test="$set">
92 <xsl:text>Rules useless in parser due to conflicts&#10;</xsl:text>
93 <xsl:call-template name="style-rule-set">
94 <xsl:with-param name="rule-set" select="$set"/>
95 </xsl:call-template>
96 <xsl:text>&#10;&#10;</xsl:text>
97 </xsl:if>
98 </xsl:template>
100 <xsl:template match="grammar">
101 <xsl:text>Grammar&#10;</xsl:text>
102 <xsl:call-template name="style-rule-set">
103 <xsl:with-param
104 name="rule-set" select="rules/rule[@usefulness!='useless-in-grammar']"
106 </xsl:call-template>
107 <xsl:text>&#10;&#10;</xsl:text>
108 <xsl:apply-templates select="terminals"/>
109 <xsl:apply-templates select="nonterminals"/>
110 </xsl:template>
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"/>
121 </xsl:if>
122 </xsl:with-param>
123 </xsl:apply-templates>
124 </xsl:for-each>
125 </xsl:template>
127 <xsl:template match="grammar/terminals">
128 <xsl:text>Terminals, with rules where they appear&#10;&#10;</xsl:text>
129 <xsl:apply-templates select="terminal"/>
130 <xsl:text>&#10;&#10;</xsl:text>
131 </xsl:template>
133 <xsl:template match="grammar/nonterminals">
134 <xsl:text>Nonterminals, with rules where they appear&#10;&#10;</xsl:text>
135 <xsl:apply-templates select="nonterminal[@usefulness!='useless-in-grammar']"/>
136 </xsl:template>
138 <xsl:template match="terminal">
139 <xsl:text> </xsl:text>
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:if test="string-length(@type) != 0">
153 <xsl:value-of select="concat(' &lt;', @type, '&gt;')"/>
154 </xsl:if>
155 <xsl:value-of select="concat(' (', @token-number, ')')"/>
156 <xsl:for-each select="key('bison:ruleByRhs', @name)">
157 <xsl:value-of select="concat(' ', @number)"/>
158 </xsl:for-each>
159 </xsl:with-param>
160 </xsl:call-template>
161 </xsl:template>
163 <xsl:template match="nonterminal">
164 <xsl:text> </xsl:text>
165 <xsl:value-of select="@name"/>
166 <xsl:if test="string-length(@type) != 0">
167 <xsl:value-of select="concat(' &lt;', @type, '&gt;')"/>
168 </xsl:if>
169 <xsl:value-of select="concat(' (', @symbol-number, ')')"/>
170 <xsl:text>&#10;</xsl:text>
171 <xsl:variable name="output">
172 <xsl:call-template name="line-wrap">
173 <xsl:with-param name="line-length" select="66" />
174 <xsl:with-param name="text">
175 <xsl:text> </xsl:text>
176 <xsl:if test="key('bison:ruleByLhs', @name)">
177 <xsl:text>on@left:</xsl:text>
178 <xsl:for-each select="key('bison:ruleByLhs', @name)">
179 <xsl:value-of select="concat(' ', @number)"/>
180 </xsl:for-each>
181 </xsl:if>
182 <xsl:if test="key('bison:ruleByRhs', @name)">
183 <xsl:if test="key('bison:ruleByLhs', @name)">
184 <xsl:text>&#10; </xsl:text>
185 </xsl:if>
186 <xsl:text>on@right:</xsl:text>
187 <xsl:for-each select="key('bison:ruleByRhs', @name)">
188 <xsl:value-of select="concat(' ', @number)"/>
189 </xsl:for-each>
190 </xsl:if>
191 </xsl:with-param>
192 </xsl:call-template>
193 </xsl:variable>
194 <xsl:value-of select="translate($output, '@', ' ')" />
195 </xsl:template>
197 <xsl:template match="automaton" mode="conflicts">
198 <xsl:variable name="conflict-report">
199 <xsl:apply-templates select="state" mode="conflicts"/>
200 </xsl:variable>
201 <xsl:if test="string-length($conflict-report) != 0">
202 <xsl:value-of select="$conflict-report"/>
203 <xsl:text>&#10;&#10;</xsl:text>
204 </xsl:if>
205 </xsl:template>
207 <xsl:template match="state" mode="conflicts">
208 <xsl:variable name="conflict-counts">
209 <xsl:apply-templates select="." mode="bison:count-conflicts" />
210 </xsl:variable>
211 <xsl:variable
212 name="sr-count" select="substring-before($conflict-counts, ',')"
214 <xsl:variable
215 name="rr-count" select="substring-after($conflict-counts, ',')"
217 <xsl:if test="$sr-count > 0 or $rr-count > 0">
218 <xsl:value-of select="concat('State ', @number, ' conflicts:')"/>
219 <xsl:if test="$sr-count > 0">
220 <xsl:value-of select="concat(' ', $sr-count, ' shift/reduce')"/>
221 <xsl:if test="$rr-count > 0">
222 <xsl:value-of select="(',')"/>
223 </xsl:if>
224 </xsl:if>
225 <xsl:if test="$rr-count > 0">
226 <xsl:value-of select="concat(' ', $rr-count, ' reduce/reduce')"/>
227 </xsl:if>
228 <xsl:value-of select="'&#10;'"/>
229 </xsl:if>
230 </xsl:template>
232 <xsl:template match="automaton">
233 <xsl:apply-templates select="state">
234 <xsl:with-param name="pad" select="'3'"/>
235 </xsl:apply-templates>
236 </xsl:template>
238 <xsl:template match="automaton/state">
239 <xsl:param name="pad"/>
240 <xsl:text>&#10;&#10;</xsl:text>
241 <xsl:text>State </xsl:text>
242 <xsl:value-of select="@number"/>
243 <xsl:text>&#10;&#10;</xsl:text>
244 <xsl:apply-templates select="itemset/item">
245 <xsl:with-param name="pad" select="$pad"/>
246 </xsl:apply-templates>
247 <xsl:apply-templates select="actions/transitions">
248 <xsl:with-param name="type" select="'shift'"/>
249 </xsl:apply-templates>
250 <xsl:apply-templates select="actions/errors"/>
251 <xsl:apply-templates select="actions/reductions"/>
252 <xsl:apply-templates select="actions/transitions">
253 <xsl:with-param name="type" select="'goto'"/>
254 </xsl:apply-templates>
255 <xsl:apply-templates select="solved-conflicts"/>
256 </xsl:template>
258 <xsl:template match="actions/transitions">
259 <xsl:param name="type"/>
260 <xsl:if test="transition[@type = $type]">
261 <xsl:text>&#10;</xsl:text>
262 <xsl:apply-templates select="transition[@type = $type]">
263 <xsl:with-param name="pad">
264 <xsl:call-template name="max-width-symbol">
265 <xsl:with-param name="node" select="transition[@type = $type]"/>
266 </xsl:call-template>
267 </xsl:with-param>
268 </xsl:apply-templates>
269 </xsl:if>
270 </xsl:template>
272 <xsl:template match="actions/errors">
273 <xsl:if test="error">
274 <xsl:text>&#10;</xsl:text>
275 <xsl:apply-templates select="error">
276 <xsl:with-param name="pad">
277 <xsl:call-template name="max-width-symbol">
278 <xsl:with-param name="node" select="error"/>
279 </xsl:call-template>
280 </xsl:with-param>
281 </xsl:apply-templates>
282 </xsl:if>
283 </xsl:template>
285 <xsl:template match="actions/reductions">
286 <xsl:if test="reduction">
287 <xsl:text>&#10;</xsl:text>
288 <xsl:apply-templates select="reduction">
289 <xsl:with-param name="pad">
290 <xsl:call-template name="max-width-symbol">
291 <xsl:with-param name="node" select="reduction"/>
292 </xsl:call-template>
293 </xsl:with-param>
294 </xsl:apply-templates>
295 </xsl:if>
296 </xsl:template>
298 <xsl:template match="item">
299 <xsl:param name="pad"/>
300 <xsl:param name="prev-rule-number"
301 select="preceding-sibling::item[1]/@rule-number"/>
302 <xsl:apply-templates
303 select="key('bison:ruleByNumber', current()/@rule-number)"
305 <xsl:with-param name="itemset" select="'true'"/>
306 <xsl:with-param name="pad" select="$pad"/>
307 <xsl:with-param
308 name="prev-lhs"
309 select="key('bison:ruleByNumber', $prev-rule-number)/lhs[text()]"
311 <xsl:with-param name="dot" select="@dot"/>
312 <xsl:with-param name="lookaheads">
313 <xsl:apply-templates select="lookaheads"/>
314 </xsl:with-param>
315 </xsl:apply-templates>
316 </xsl:template>
318 <xsl:template match="rule">
319 <xsl:param name="itemset"/>
320 <xsl:param name="pad"/>
321 <xsl:param name="prev-lhs"/>
322 <xsl:param name="dot"/>
323 <xsl:param name="lookaheads"/>
325 <xsl:if test="$itemset != 'true' and not($prev-lhs = lhs[text()])">
326 <xsl:text>&#10;</xsl:text>
327 </xsl:if>
329 <xsl:text> </xsl:text>
330 <xsl:call-template name="lpad">
331 <xsl:with-param name="str" select="string(@number)"/>
332 <xsl:with-param name="pad" select="number($pad)"/>
333 </xsl:call-template>
334 <xsl:text> </xsl:text>
336 <!-- LHS -->
337 <xsl:choose>
338 <xsl:when test="$itemset != 'true' and $prev-lhs = lhs[text()]">
339 <xsl:call-template name="lpad">
340 <xsl:with-param name="str" select="'|'"/>
341 <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/>
342 </xsl:call-template>
343 </xsl:when>
344 <xsl:when test="$itemset = 'true' and $prev-lhs = lhs[text()]">
345 <xsl:call-template name="lpad">
346 <xsl:with-param name="str" select="'|'"/>
347 <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/>
348 </xsl:call-template>
349 </xsl:when>
350 <xsl:otherwise>
351 <xsl:value-of select="lhs"/>
352 <xsl:text>:</xsl:text>
353 </xsl:otherwise>
354 </xsl:choose>
356 <!-- RHS -->
357 <xsl:for-each select="rhs/*">
358 <xsl:if test="position() = $dot + 1">
359 <xsl:text></xsl:text>
360 </xsl:if>
361 <xsl:apply-templates select="."/>
362 <xsl:if test="position() = last() and position() = $dot">
363 <xsl:text></xsl:text>
364 </xsl:if>
365 </xsl:for-each>
366 <xsl:if test="$lookaheads">
367 <xsl:value-of select="$lookaheads"/>
368 </xsl:if>
370 <xsl:text>&#10;</xsl:text>
371 </xsl:template>
373 <xsl:template match="symbol">
374 <xsl:text> </xsl:text>
375 <xsl:value-of select="."/>
376 </xsl:template>
378 <xsl:template match="empty">
379 <xsl:text> %empty</xsl:text>
380 </xsl:template>
382 <xsl:template match="lookaheads">
383 <xsl:text> [</xsl:text>
384 <xsl:apply-templates select="symbol"/>
385 <xsl:text>]</xsl:text>
386 </xsl:template>
388 <xsl:template match="lookaheads/symbol">
389 <xsl:value-of select="."/>
390 <xsl:if test="position() != last()">
391 <xsl:text>, </xsl:text>
392 </xsl:if>
393 </xsl:template>
395 <xsl:template match="transition">
396 <xsl:param name="pad"/>
397 <xsl:text> </xsl:text>
398 <xsl:call-template name="rpad">
399 <xsl:with-param name="str" select="string(@symbol)"/>
400 <xsl:with-param name="pad" select="number($pad) + 2"/>
401 </xsl:call-template>
402 <xsl:choose>
403 <xsl:when test="@type = 'shift'">
404 <xsl:text>shift, and go to state </xsl:text>
405 <xsl:value-of select="@state"/>
406 </xsl:when>
407 <xsl:when test="@type = 'goto'">
408 <xsl:text>go to state </xsl:text>
409 <xsl:value-of select="@state"/>
410 </xsl:when>
411 </xsl:choose>
412 <xsl:text>&#10;</xsl:text>
413 </xsl:template>
415 <xsl:template match="error">
416 <xsl:param name="pad"/>
417 <xsl:text> </xsl:text>
418 <xsl:call-template name="rpad">
419 <xsl:with-param name="str" select="string(@symbol)"/>
420 <xsl:with-param name="pad" select="number($pad) + 2"/>
421 </xsl:call-template>
422 <xsl:text>error</xsl:text>
423 <xsl:text> (</xsl:text>
424 <xsl:value-of select="text()"/>
425 <xsl:text>)</xsl:text>
426 <xsl:text>&#10;</xsl:text>
427 </xsl:template>
429 <xsl:template match="reduction">
430 <xsl:param name="pad"/>
431 <xsl:text> </xsl:text>
432 <xsl:call-template name="rpad">
433 <xsl:with-param name="str" select="string(@symbol)"/>
434 <xsl:with-param name="pad" select="number($pad) + 2"/>
435 </xsl:call-template>
436 <xsl:if test="@enabled = 'false'">
437 <xsl:text>[</xsl:text>
438 </xsl:if>
439 <xsl:choose>
440 <xsl:when test="@rule = 'accept'">
441 <xsl:text>accept</xsl:text>
442 </xsl:when>
443 <xsl:otherwise>
444 <xsl:text>reduce using rule </xsl:text>
445 <xsl:value-of select="@rule"/>
446 <xsl:text> (</xsl:text>
447 <xsl:value-of
448 select="key('bison:ruleByNumber', current()/@rule)/lhs[text()]"/>
449 <xsl:text>)</xsl:text>
450 </xsl:otherwise>
451 </xsl:choose>
452 <xsl:if test="@enabled = 'false'">
453 <xsl:text>]</xsl:text>
454 </xsl:if>
455 <xsl:text>&#10;</xsl:text>
456 </xsl:template>
458 <xsl:template match="solved-conflicts">
459 <xsl:if test="resolution">
460 <xsl:text>&#10;</xsl:text>
461 <xsl:apply-templates select="resolution"/>
462 </xsl:if>
463 </xsl:template>
465 <xsl:template match="resolution">
466 <xsl:text> Conflict between rule </xsl:text>
467 <xsl:value-of select="@rule"/>
468 <xsl:text> and token </xsl:text>
469 <xsl:value-of select="@symbol"/>
470 <xsl:text> resolved as </xsl:text>
471 <xsl:if test="@type = 'error'">
472 <xsl:text>an </xsl:text>
473 </xsl:if>
474 <xsl:value-of select="@type"/>
475 <xsl:text> (</xsl:text>
476 <xsl:value-of select="."/>
477 <xsl:text>).&#10;</xsl:text>
478 </xsl:template>
480 <xsl:template name="max-width-symbol">
481 <xsl:param name="node"/>
482 <xsl:variable name="longest">
483 <xsl:for-each select="$node">
484 <xsl:sort data-type="number" select="string-length(@symbol)"
485 order="descending"/>
486 <xsl:if test="position() = 1">
487 <xsl:value-of select="string-length(@symbol)"/>
488 </xsl:if>
489 </xsl:for-each>
490 </xsl:variable>
491 <xsl:value-of select="$longest"/>
492 </xsl:template>
494 <xsl:template name="lpad">
495 <xsl:param name="str" select="''"/>
496 <xsl:param name="pad" select="0"/>
497 <xsl:variable name="diff" select="$pad - string-length($str)" />
498 <xsl:choose>
499 <xsl:when test="$diff &lt; 0">
500 <xsl:value-of select="$str"/>
501 </xsl:when>
502 <xsl:otherwise>
503 <xsl:call-template name="space">
504 <xsl:with-param name="repeat" select="$diff"/>
505 </xsl:call-template>
506 <xsl:value-of select="$str"/>
507 </xsl:otherwise>
508 </xsl:choose>
509 </xsl:template>
511 <xsl:template name="rpad">
512 <xsl:param name="str" select="''"/>
513 <xsl:param name="pad" select="0"/>
514 <xsl:variable name="diff" select="$pad - string-length($str)"/>
515 <xsl:choose>
516 <xsl:when test="$diff &lt; 0">
517 <xsl:value-of select="$str"/>
518 </xsl:when>
519 <xsl:otherwise>
520 <xsl:value-of select="$str"/>
521 <xsl:call-template name="space">
522 <xsl:with-param name="repeat" select="$diff"/>
523 </xsl:call-template>
524 </xsl:otherwise>
525 </xsl:choose>
526 </xsl:template>
528 <xsl:template name="line-wrap">
529 <xsl:param name="line-length"/> <!-- required -->
530 <xsl:param name="first-line-length" select="$line-length"/>
531 <xsl:param name="text"/> <!-- required -->
532 <xsl:choose>
533 <xsl:when test="normalize-space($text) = ''" />
534 <xsl:when test="string-length($text) &lt;= $first-line-length">
535 <xsl:value-of select="concat($text, '&#10;')" />
536 </xsl:when>
537 <xsl:otherwise>
538 <xsl:variable name="break-pos">
539 <xsl:call-template name="ws-search">
540 <xsl:with-param name="text" select="$text" />
541 <xsl:with-param name="start" select="$first-line-length+1" />
542 </xsl:call-template>
543 </xsl:variable>
544 <xsl:value-of select="substring($text, 1, $break-pos - 1)" />
545 <xsl:text>&#10;</xsl:text>
546 <xsl:call-template name="line-wrap">
547 <xsl:with-param name="line-length" select="$line-length" />
548 <xsl:with-param
549 name="text" select="concat(' ', substring($text, $break-pos+1))"
551 </xsl:call-template>
552 </xsl:otherwise>
553 </xsl:choose>
554 </xsl:template>
556 <xsl:template name="ws-search">
557 <xsl:param name="text"/> <!-- required -->
558 <xsl:param name="start"/> <!-- required -->
559 <xsl:variable name="search-text" select="substring($text, $start)" />
560 <xsl:choose>
561 <xsl:when test="not(contains($search-text, ' '))">
562 <xsl:value-of select="string-length($text)+1" />
563 </xsl:when>
564 <xsl:otherwise>
565 <xsl:value-of
566 select="$start + string-length(substring-before($search-text, ' '))"
568 </xsl:otherwise>
569 </xsl:choose>
570 </xsl:template>
572 </xsl:stylesheet>