xref: /aosp_15_r20/prebuilts/build-tools/common/bison/xslt/xml2text.xsl (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
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-2015, 2018-2021 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 <https://www.gnu.org/licenses/>.
22
23    Written by Wojciech Polak <[email protected]>.
24  -->
25
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/">
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: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>
162
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>
196
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>
206
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, ',')"
213  />
214  <xsl:variable
215    name="rr-count" select="substring-after($conflict-counts, ',')"
216  />
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>
231
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>
237
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>
257
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>
271
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>
284
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>
297
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)"
304  >
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()]"
310   />
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>
317
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"/>
324
325  <xsl:if test="$itemset != 'true' and not($prev-lhs = lhs[text()])">
326    <xsl:text>&#10;</xsl:text>
327  </xsl:if>
328
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>
335
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>
355
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>
369
370  <xsl:text>&#10;</xsl:text>
371</xsl:template>
372
373<xsl:template match="symbol">
374  <xsl:text> </xsl:text>
375  <xsl:value-of select="."/>
376</xsl:template>
377
378<xsl:template match="empty">
379  <xsl:text> %empty</xsl:text>
380</xsl:template>
381
382<xsl:template match="lookaheads">
383  <xsl:text>  [</xsl:text>
384  <xsl:apply-templates select="symbol"/>
385  <xsl:text>]</xsl:text>
386</xsl:template>
387
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>
394
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>
414
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>
428
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>
457
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>
464
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>
479
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>
493
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>
510
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>
527
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))"
550        />
551      </xsl:call-template>
552    </xsl:otherwise>
553  </xsl:choose>
554</xsl:template>
555
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, ' '))"
567      />
568    </xsl:otherwise>
569  </xsl:choose>
570</xsl:template>
571
572</xsl:stylesheet>
573