]> git.saurik.com Git - bison.git/blob - data/xslt/xml2text.xsl
4d34be1631fc0cdd71ec66155ac6458dc64ef539
[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
6 Copyright (C) 2007-2013 Free Software Foundation, Inc.
7
8 This file is part of Bison, the GNU Compiler Compiler.
9
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.
14
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.
19
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/>.
22
23 Written by Wojciech Polak <polak@gnu.org>.
24 -->
25
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/">
29
30 <xsl:import href="bison.xsl"/>
31 <xsl:output method="text" encoding="UTF-8" indent="no"/>
32
33 <xsl:template match="/">
34 <xsl:apply-templates select="bison-xml-report"/>
35 </xsl:template>
36
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>
44
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>
50
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>
62
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>
75
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>
86
87 <xsl:template match="grammar" mode="useless-in-parser">
88 <xsl:variable
89 name="set" select="rules/rule[@usefulness='useless-in-parser']"
90 />
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>
99
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']"
105 />
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>
111
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>
126
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>
132
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>
137
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">
142 <xsl:choose>
143 <xsl:when test="string-length(@name) &gt; 66">0</xsl:when>
144 <xsl:otherwise>
145 <xsl:value-of select="66 - string-length(@name)" />
146 </xsl:otherwise>
147 </xsl:choose>
148 </xsl:with-param>
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)"/>
154 </xsl:for-each>
155 </xsl:with-param>
156 </xsl:call-template>
157 </xsl:template>
158
159 <xsl:template match="nonterminal">
160 <xsl:value-of select="@name"/>
161 <xsl:value-of select="concat(' (', @symbol-number, ')')"/>
162 <xsl:text>&#10;</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)"/>
172 </xsl:for-each>
173 </xsl:if>
174 <xsl:if test="key('bison:ruleByRhs', @name)">
175 <xsl:if test="key('bison:ruleByLhs', @name)">
176 <xsl:text>, </xsl:text>
177 </xsl:if>
178 <xsl:text>on@right:</xsl:text>
179 <xsl:for-each select="key('bison:ruleByRhs', @name)">
180 <xsl:value-of select="concat(' ', @number)"/>
181 </xsl:for-each>
182 </xsl:if>
183 </xsl:with-param>
184 </xsl:call-template>
185 </xsl:variable>
186 <xsl:value-of select="translate($output, '@', ' ')" />
187 </xsl:template>
188
189 <xsl:template match="automaton" mode="conflicts">
190 <xsl:variable name="conflict-report">
191 <xsl:apply-templates select="state" mode="conflicts"/>
192 </xsl:variable>
193 <xsl:if test="string-length($conflict-report) != 0">
194 <xsl:value-of select="$conflict-report"/>
195 <xsl:text>&#10;&#10;</xsl:text>
196 </xsl:if>
197 </xsl:template>
198
199 <xsl:template match="state" mode="conflicts">
200 <xsl:variable name="conflict-counts">
201 <xsl:apply-templates select="." mode="bison:count-conflicts" />
202 </xsl:variable>
203 <xsl:variable
204 name="sr-count" select="substring-before($conflict-counts, ',')"
205 />
206 <xsl:variable
207 name="rr-count" select="substring-after($conflict-counts, ',')"
208 />
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="(',')"/>
215 </xsl:if>
216 </xsl:if>
217 <xsl:if test="$rr-count > 0">
218 <xsl:value-of select="concat(' ', $rr-count, ' reduce/reduce')"/>
219 </xsl:if>
220 <xsl:value-of select="'&#10;'"/>
221 </xsl:if>
222 </xsl:template>
223
224 <xsl:template match="automaton">
225 <xsl:apply-templates select="state">
226 <xsl:with-param name="pad" select="'3'"/>
227 </xsl:apply-templates>
228 </xsl:template>
229
230 <xsl:template match="automaton/state">
231 <xsl:param name="pad"/>
232 <xsl:text>&#10;&#10;</xsl:text>
233 <xsl:text>State </xsl:text>
234 <xsl:value-of select="@number"/>
235 <xsl:text>&#10;&#10;</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"/>
248 </xsl:template>
249
250 <xsl:template match="actions/transitions">
251 <xsl:param name="type"/>
252 <xsl:if test="transition[@type = $type]">
253 <xsl:text>&#10;</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]"/>
258 </xsl:call-template>
259 </xsl:with-param>
260 </xsl:apply-templates>
261 </xsl:if>
262 </xsl:template>
263
264 <xsl:template match="actions/errors">
265 <xsl:if test="error">
266 <xsl:text>&#10;</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"/>
271 </xsl:call-template>
272 </xsl:with-param>
273 </xsl:apply-templates>
274 </xsl:if>
275 </xsl:template>
276
277 <xsl:template match="actions/reductions">
278 <xsl:if test="reduction">
279 <xsl:text>&#10;</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"/>
284 </xsl:call-template>
285 </xsl:with-param>
286 </xsl:apply-templates>
287 </xsl:if>
288 </xsl:template>
289
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"/>
294 <xsl:apply-templates
295 select="key('bison:ruleByNumber', current()/@rule-number)"
296 >
297 <xsl:with-param name="itemset" select="'true'"/>
298 <xsl:with-param name="pad" select="$pad"/>
299 <xsl:with-param
300 name="prev-lhs"
301 select="key('bison:ruleByNumber', $prev-rule-number)/lhs[text()]"
302 />
303 <xsl:with-param name="point" select="@point"/>
304 <xsl:with-param name="lookaheads">
305 <xsl:apply-templates select="lookaheads"/>
306 </xsl:with-param>
307 </xsl:apply-templates>
308 </xsl:template>
309
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"/>
316
317 <xsl:if test="$itemset != 'true' and not($prev-lhs = lhs[text()])">
318 <xsl:text>&#10;</xsl:text>
319 </xsl:if>
320
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)"/>
325 </xsl:call-template>
326 <xsl:text> </xsl:text>
327
328 <!-- LHS -->
329 <xsl:choose>
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"/>
334 </xsl:call-template>
335 </xsl:when>
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"/>
340 </xsl:call-template>
341 </xsl:when>
342 <xsl:otherwise>
343 <xsl:value-of select="lhs"/>
344 <xsl:text>:</xsl:text>
345 </xsl:otherwise>
346 </xsl:choose>
347
348 <!-- RHS -->
349 <xsl:for-each select="rhs/*">
350 <xsl:if test="position() = $point + 1">
351 <xsl:text> .</xsl:text>
352 </xsl:if>
353 <xsl:apply-templates select="."/>
354 <xsl:if test="position() = last() and position() = $point">
355 <xsl:text> .</xsl:text>
356 </xsl:if>
357 </xsl:for-each>
358 <xsl:if test="$lookaheads">
359 <xsl:value-of select="$lookaheads"/>
360 </xsl:if>
361
362 <xsl:text>&#10;</xsl:text>
363 </xsl:template>
364
365 <xsl:template match="symbol">
366 <xsl:text> </xsl:text>
367 <xsl:value-of select="."/>
368 </xsl:template>
369
370 <xsl:template match="empty">
371 <xsl:text> %empty</xsl:text>
372 </xsl:template>
373
374 <xsl:template match="lookaheads">
375 <xsl:text> [</xsl:text>
376 <xsl:apply-templates select="symbol"/>
377 <xsl:text>]</xsl:text>
378 </xsl:template>
379
380 <xsl:template match="lookaheads/symbol">
381 <xsl:value-of select="."/>
382 <xsl:if test="position() != last()">
383 <xsl:text>, </xsl:text>
384 </xsl:if>
385 </xsl:template>
386
387 <xsl:template match="transition">
388 <xsl:param name="pad"/>
389 <xsl:text> </xsl:text>
390 <xsl:call-template name="rpad">
391 <xsl:with-param name="str" select="string(@symbol)"/>
392 <xsl:with-param name="pad" select="number($pad) + 2"/>
393 </xsl:call-template>
394 <xsl:choose>
395 <xsl:when test="@type = 'shift'">
396 <xsl:text>shift, and go to state </xsl:text>
397 <xsl:value-of select="@state"/>
398 </xsl:when>
399 <xsl:when test="@type = 'goto'">
400 <xsl:text>go to state </xsl:text>
401 <xsl:value-of select="@state"/>
402 </xsl:when>
403 </xsl:choose>
404 <xsl:text>&#10;</xsl:text>
405 </xsl:template>
406
407 <xsl:template match="error">
408 <xsl:param name="pad"/>
409 <xsl:text> </xsl:text>
410 <xsl:call-template name="rpad">
411 <xsl:with-param name="str" select="string(@symbol)"/>
412 <xsl:with-param name="pad" select="number($pad) + 2"/>
413 </xsl:call-template>
414 <xsl:text>error</xsl:text>
415 <xsl:text> (</xsl:text>
416 <xsl:value-of select="text()"/>
417 <xsl:text>)</xsl:text>
418 <xsl:text>&#10;</xsl:text>
419 </xsl:template>
420
421 <xsl:template match="reduction">
422 <xsl:param name="pad"/>
423 <xsl:text> </xsl:text>
424 <xsl:call-template name="rpad">
425 <xsl:with-param name="str" select="string(@symbol)"/>
426 <xsl:with-param name="pad" select="number($pad) + 2"/>
427 </xsl:call-template>
428 <xsl:if test="@enabled = 'false'">
429 <xsl:text>[</xsl:text>
430 </xsl:if>
431 <xsl:choose>
432 <xsl:when test="@rule = 'accept'">
433 <xsl:text>accept</xsl:text>
434 </xsl:when>
435 <xsl:otherwise>
436 <xsl:text>reduce using rule </xsl:text>
437 <xsl:value-of select="@rule"/>
438 <xsl:text> (</xsl:text>
439 <xsl:value-of
440 select="key('bison:ruleByNumber', current()/@rule)/lhs[text()]"/>
441 <xsl:text>)</xsl:text>
442 </xsl:otherwise>
443 </xsl:choose>
444 <xsl:if test="@enabled = 'false'">
445 <xsl:text>]</xsl:text>
446 </xsl:if>
447 <xsl:text>&#10;</xsl:text>
448 </xsl:template>
449
450 <xsl:template match="solved-conflicts">
451 <xsl:if test="resolution">
452 <xsl:text>&#10;</xsl:text>
453 <xsl:apply-templates select="resolution"/>
454 </xsl:if>
455 </xsl:template>
456
457 <xsl:template match="resolution">
458 <xsl:text> Conflict between rule </xsl:text>
459 <xsl:value-of select="@rule"/>
460 <xsl:text> and token </xsl:text>
461 <xsl:value-of select="@symbol"/>
462 <xsl:text> resolved as </xsl:text>
463 <xsl:if test="@type = 'error'">
464 <xsl:text>an </xsl:text>
465 </xsl:if>
466 <xsl:value-of select="@type"/>
467 <xsl:text> (</xsl:text>
468 <xsl:value-of select="."/>
469 <xsl:text>).&#10;</xsl:text>
470 </xsl:template>
471
472 <xsl:template name="max-width-symbol">
473 <xsl:param name="node"/>
474 <xsl:variable name="longest">
475 <xsl:for-each select="$node">
476 <xsl:sort data-type="number" select="string-length(@symbol)"
477 order="descending"/>
478 <xsl:if test="position() = 1">
479 <xsl:value-of select="string-length(@symbol)"/>
480 </xsl:if>
481 </xsl:for-each>
482 </xsl:variable>
483 <xsl:value-of select="$longest"/>
484 </xsl:template>
485
486 <xsl:template name="lpad">
487 <xsl:param name="str" select="''"/>
488 <xsl:param name="pad" select="0"/>
489 <xsl:variable name="diff" select="$pad - string-length($str)" />
490 <xsl:choose>
491 <xsl:when test="$diff &lt; 0">
492 <xsl:value-of select="$str"/>
493 </xsl:when>
494 <xsl:otherwise>
495 <xsl:call-template name="space">
496 <xsl:with-param name="repeat" select="$diff"/>
497 </xsl:call-template>
498 <xsl:value-of select="$str"/>
499 </xsl:otherwise>
500 </xsl:choose>
501 </xsl:template>
502
503 <xsl:template name="rpad">
504 <xsl:param name="str" select="''"/>
505 <xsl:param name="pad" select="0"/>
506 <xsl:variable name="diff" select="$pad - string-length($str)"/>
507 <xsl:choose>
508 <xsl:when test="$diff &lt; 0">
509 <xsl:value-of select="$str"/>
510 </xsl:when>
511 <xsl:otherwise>
512 <xsl:value-of select="$str"/>
513 <xsl:call-template name="space">
514 <xsl:with-param name="repeat" select="$diff"/>
515 </xsl:call-template>
516 </xsl:otherwise>
517 </xsl:choose>
518 </xsl:template>
519
520 <xsl:template name="line-wrap">
521 <xsl:param name="line-length"/> <!-- required -->
522 <xsl:param name="first-line-length" select="$line-length"/>
523 <xsl:param name="text"/> <!-- required -->
524 <xsl:choose>
525 <xsl:when test="normalize-space($text) = ''" />
526 <xsl:when test="string-length($text) &lt;= $first-line-length">
527 <xsl:value-of select="concat($text, '&#10;')" />
528 </xsl:when>
529 <xsl:otherwise>
530 <xsl:variable name="break-pos">
531 <xsl:call-template name="ws-search">
532 <xsl:with-param name="text" select="$text" />
533 <xsl:with-param name="start" select="$first-line-length+1" />
534 </xsl:call-template>
535 </xsl:variable>
536 <xsl:value-of select="substring($text, 1, $break-pos - 1)" />
537 <xsl:text>&#10;</xsl:text>
538 <xsl:call-template name="line-wrap">
539 <xsl:with-param name="line-length" select="$line-length" />
540 <xsl:with-param
541 name="text" select="concat(' ', substring($text, $break-pos+1))"
542 />
543 </xsl:call-template>
544 </xsl:otherwise>
545 </xsl:choose>
546 </xsl:template>
547
548 <xsl:template name="ws-search">
549 <xsl:param name="text"/> <!-- required -->
550 <xsl:param name="start"/> <!-- required -->
551 <xsl:variable name="search-text" select="substring($text, $start)" />
552 <xsl:choose>
553 <xsl:when test="not(contains($search-text, ' '))">
554 <xsl:value-of select="string-length($text)+1" />
555 </xsl:when>
556 <xsl:otherwise>
557 <xsl:value-of
558 select="$start + string-length(substring-before($search-text, ' '))"
559 />
560 </xsl:otherwise>
561 </xsl:choose>
562 </xsl:template>
563
564 </xsl:stylesheet>