]> git.saurik.com Git - bison.git/blob - data/xslt/xml2text.xsl
866efe3bc360caa64d064ecbeec913fba0c95620
[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-2010 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:if test="$itemset = 'true' and name(.) != 'empty'">
354 <xsl:apply-templates select="."/>
355 </xsl:if>
356 <xsl:if test="$itemset != 'true'">
357 <xsl:apply-templates select="."/>
358 </xsl:if>
359 <xsl:if test="position() = last() and position() = $point">
360 <xsl:text> .</xsl:text>
361 </xsl:if>
362 </xsl:for-each>
363 <xsl:if test="$lookaheads">
364 <xsl:value-of select="$lookaheads"/>
365 </xsl:if>
366
367 <xsl:text>&#10;</xsl:text>
368 </xsl:template>
369
370 <xsl:template match="symbol">
371 <xsl:text> </xsl:text>
372 <xsl:value-of select="."/>
373 </xsl:template>
374
375 <xsl:template match="empty">
376 <xsl:text> /* empty */</xsl:text>
377 </xsl:template>
378
379 <xsl:template match="lookaheads">
380 <xsl:text> [</xsl:text>
381 <xsl:apply-templates select="symbol"/>
382 <xsl:text>]</xsl:text>
383 </xsl:template>
384
385 <xsl:template match="lookaheads/symbol">
386 <xsl:value-of select="."/>
387 <xsl:if test="position() != last()">
388 <xsl:text>, </xsl:text>
389 </xsl:if>
390 </xsl:template>
391
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"/>
398 </xsl:call-template>
399 <xsl:choose>
400 <xsl:when test="@type = 'shift'">
401 <xsl:text>shift, and go to state </xsl:text>
402 <xsl:value-of select="@state"/>
403 </xsl:when>
404 <xsl:when test="@type = 'goto'">
405 <xsl:text>go to state </xsl:text>
406 <xsl:value-of select="@state"/>
407 </xsl:when>
408 </xsl:choose>
409 <xsl:text>&#10;</xsl:text>
410 </xsl:template>
411
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"/>
418 </xsl:call-template>
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>&#10;</xsl:text>
424 </xsl:template>
425
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"/>
432 </xsl:call-template>
433 <xsl:if test="@enabled = 'false'">
434 <xsl:text>[</xsl:text>
435 </xsl:if>
436 <xsl:choose>
437 <xsl:when test="@rule = 'accept'">
438 <xsl:text>accept</xsl:text>
439 </xsl:when>
440 <xsl:otherwise>
441 <xsl:text>reduce using rule </xsl:text>
442 <xsl:value-of select="@rule"/>
443 <xsl:text> (</xsl:text>
444 <xsl:value-of
445 select="key('bison:ruleByNumber', current()/@rule)/lhs[text()]"/>
446 <xsl:text>)</xsl:text>
447 </xsl:otherwise>
448 </xsl:choose>
449 <xsl:if test="@enabled = 'false'">
450 <xsl:text>]</xsl:text>
451 </xsl:if>
452 <xsl:text>&#10;</xsl:text>
453 </xsl:template>
454
455 <xsl:template match="solved-conflicts">
456 <xsl:if test="resolution">
457 <xsl:text>&#10;</xsl:text>
458 <xsl:apply-templates select="resolution"/>
459 </xsl:if>
460 </xsl:template>
461
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>
470 </xsl:if>
471 <xsl:value-of select="@type"/>
472 <xsl:text> (</xsl:text>
473 <xsl:value-of select="."/>
474 <xsl:text>).&#10;</xsl:text>
475 </xsl:template>
476
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)"
482 order="descending"/>
483 <xsl:if test="position() = 1">
484 <xsl:value-of select="string-length(@symbol)"/>
485 </xsl:if>
486 </xsl:for-each>
487 </xsl:variable>
488 <xsl:value-of select="$longest"/>
489 </xsl:template>
490
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)" />
495 <xsl:choose>
496 <xsl:when test="$diff &lt; 0">
497 <xsl:value-of select="$str"/>
498 </xsl:when>
499 <xsl:otherwise>
500 <xsl:call-template name="space">
501 <xsl:with-param name="repeat" select="$diff"/>
502 </xsl:call-template>
503 <xsl:value-of select="$str"/>
504 </xsl:otherwise>
505 </xsl:choose>
506 </xsl:template>
507
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)"/>
512 <xsl:choose>
513 <xsl:when test="$diff &lt; 0">
514 <xsl:value-of select="$str"/>
515 </xsl:when>
516 <xsl:otherwise>
517 <xsl:value-of select="$str"/>
518 <xsl:call-template name="space">
519 <xsl:with-param name="repeat" select="$diff"/>
520 </xsl:call-template>
521 </xsl:otherwise>
522 </xsl:choose>
523 </xsl:template>
524
525 <xsl:template name="space">
526 <xsl:param name="repeat">0</xsl:param>
527 <xsl:param name="fill" select="' '"/>
528 <xsl:if test="number($repeat) &gt;= 1">
529 <xsl:call-template name="space">
530 <xsl:with-param name="repeat" select="$repeat - 1"/>
531 <xsl:with-param name="fill" select="$fill"/>
532 </xsl:call-template>
533 <xsl:value-of select="$fill"/>
534 </xsl:if>
535 </xsl:template>
536
537 <xsl:template name="line-wrap">
538 <xsl:param name="line-length"/> <!-- required -->
539 <xsl:param name="first-line-length" select="$line-length"/>
540 <xsl:param name="text"/> <!-- required -->
541 <xsl:choose>
542 <xsl:when test="normalize-space($text) = ''" />
543 <xsl:when test="string-length($text) &lt;= $first-line-length">
544 <xsl:value-of select="concat($text, '&#10;')" />
545 </xsl:when>
546 <xsl:otherwise>
547 <xsl:variable name="break-pos">
548 <xsl:call-template name="ws-search">
549 <xsl:with-param name="text" select="$text" />
550 <xsl:with-param name="start" select="$first-line-length+1" />
551 </xsl:call-template>
552 </xsl:variable>
553 <xsl:value-of select="substring($text, 1, $break-pos - 1)" />
554 <xsl:text>&#10;</xsl:text>
555 <xsl:call-template name="line-wrap">
556 <xsl:with-param name="line-length" select="$line-length" />
557 <xsl:with-param
558 name="text" select="concat(' ', substring($text, $break-pos+1))"
559 />
560 </xsl:call-template>
561 </xsl:otherwise>
562 </xsl:choose>
563 </xsl:template>
564
565 <xsl:template name="ws-search">
566 <xsl:param name="text"/> <!-- required -->
567 <xsl:param name="start"/> <!-- required -->
568 <xsl:variable name="search-text" select="substring($text, $start)" />
569 <xsl:choose>
570 <xsl:when test="not(contains($search-text, ' '))">
571 <xsl:value-of select="string-length($text)+1" />
572 </xsl:when>
573 <xsl:otherwise>
574 <xsl:value-of
575 select="$start + string-length(substring-before($search-text, ' '))"
576 />
577 </xsl:otherwise>
578 </xsl:choose>
579 </xsl:template>
580
581 </xsl:stylesheet>