1<?xml version="1.0" encoding="UTF-8"?> 2 3<!-- 4 xml2dot.xsl - transform Bison XML Report into DOT. 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:text>// Generated by GNU Bison </xsl:text> 39 <xsl:value-of select="@version"/> 40 <xsl:text>. </xsl:text> 41 <xsl:text>// Report bugs to <</xsl:text> 42 <xsl:value-of select="@bug-report"/> 43 <xsl:text>>. </xsl:text> 44 <xsl:text>// Home page: <</xsl:text> 45 <xsl:value-of select="@url"/> 46 <xsl:text>>. </xsl:text> 47 <xsl:apply-templates select="automaton"> 48 <xsl:with-param name="filename" select="filename"/> 49 </xsl:apply-templates> 50</xsl:template> 51 52<xsl:template match="automaton"> 53 <xsl:param name="filename"/> 54 <xsl:text>digraph "</xsl:text> 55 <xsl:call-template name="escape"> 56 <xsl:with-param name="subject" select="$filename"/> 57 </xsl:call-template> 58 <xsl:text>" { 59 node [fontname = courier, shape = box, colorscheme = paired6] 60 edge [fontname = courier] 61 62</xsl:text> 63 <xsl:apply-templates select="state"/> 64 <xsl:text>} </xsl:text> 65</xsl:template> 66 67<xsl:template match="automaton/state"> 68 <xsl:call-template name="output-node"> 69 <xsl:with-param name="number" select="@number"/> 70 <xsl:with-param name="label"> 71 <xsl:apply-templates select="itemset/item"/> 72 </xsl:with-param> 73 </xsl:call-template> 74 <xsl:apply-templates select="actions/transitions"/> 75 <xsl:apply-templates select="actions/reductions"> 76 <xsl:with-param name="staten"> 77 <xsl:value-of select="@number"/> 78 </xsl:with-param> 79 </xsl:apply-templates> 80</xsl:template> 81 82<xsl:template match="actions/reductions"> 83 <xsl:param name="staten"/> 84 <xsl:for-each select='reduction'> 85 <!-- These variables are needed because the current context can't be 86 referred to directly in XPath expressions. --> 87 <xsl:variable name="rul"> 88 <xsl:value-of select="@rule"/> 89 </xsl:variable> 90 <xsl:variable name="ena"> 91 <xsl:value-of select="@enabled"/> 92 </xsl:variable> 93 <!-- The foreach's body is protected by this, so that we are actually 94 going to iterate once per reduction rule, and not per lookahead. --> 95 <xsl:if test='not(preceding-sibling::*[@rule=$rul and @enabled=$ena])'> 96 <xsl:variable name="rule"> 97 <xsl:choose> 98 <!-- The acceptation state is referred to as 'accept' in the XML, but 99 just as '0' in the DOT. --> 100 <xsl:when test="@rule='accept'"> 101 <xsl:text>0</xsl:text> 102 </xsl:when> 103 <xsl:otherwise> 104 <xsl:value-of select="@rule"/> 105 </xsl:otherwise> 106 </xsl:choose> 107 </xsl:variable> 108 109 <!-- The edge's beginning --> 110 <xsl:call-template name="reduction-edge-start"> 111 <xsl:with-param name="state" select="$staten"/> 112 <xsl:with-param name="rule" select="$rule"/> 113 <xsl:with-param name="enabled" select="@enabled"/> 114 </xsl:call-template> 115 116 <!-- The edge's tokens --> 117 <!-- Don't show labels for the default action. In other cases, there will 118 always be at least one token, so 'label="[]"' will not occur. --> 119 <xsl:if test='$rule!=0 and not(../reduction[@enabled=$ena and @rule=$rule and @symbol="$default"])'> 120 <xsl:text>label="[</xsl:text> 121 <xsl:for-each select='../reduction[@enabled=$ena and @rule=$rule]'> 122 <xsl:call-template name="escape"> 123 <xsl:with-param name="subject" select="@symbol"/> 124 </xsl:call-template> 125 <xsl:if test="position() != last ()"> 126 <xsl:text>, </xsl:text> 127 </xsl:if> 128 </xsl:for-each> 129 <xsl:text>]", </xsl:text> 130 </xsl:if> 131 132 <!-- The edge's end --> 133 <xsl:text>style=solid] </xsl:text> 134 135 <!-- The diamond representing the reduction --> 136 <xsl:call-template name="reduction-node"> 137 <xsl:with-param name="state" select="$staten"/> 138 <xsl:with-param name="rule" select="$rule"/> 139 <xsl:with-param name="color"> 140 <xsl:choose> 141 <xsl:when test='@enabled="true"'> 142 <xsl:text>3</xsl:text> 143 </xsl:when> 144 <xsl:otherwise> 145 <xsl:text>5</xsl:text> 146 </xsl:otherwise> 147 </xsl:choose> 148 </xsl:with-param> 149 </xsl:call-template> 150 </xsl:if> 151 </xsl:for-each> 152</xsl:template> 153 154<xsl:template match="actions/transitions"> 155 <xsl:apply-templates select="transition"/> 156</xsl:template> 157 158<xsl:template match="item"> 159 <xsl:param name="prev-rule-number" 160 select="preceding-sibling::item[1]/@rule-number"/> 161 <xsl:apply-templates select="key('bison:ruleByNumber', @rule-number)"> 162 <xsl:with-param name="dot" select="@dot"/> 163 <xsl:with-param name="num" select="@rule-number"/> 164 <xsl:with-param name="prev-lhs" 165 select="key('bison:ruleByNumber', $prev-rule-number)/lhs[text()]" 166 /> 167 </xsl:apply-templates> 168 <xsl:apply-templates select="lookaheads"/> 169</xsl:template> 170 171<xsl:template match="rule"> 172 <xsl:param name="dot"/> 173 <xsl:param name="num"/> 174 <xsl:param name="prev-lhs"/> 175 <xsl:text> </xsl:text> 176 <xsl:choose> 177 <xsl:when test="$num < 10"> 178 <xsl:text> </xsl:text> 179 </xsl:when> 180 <xsl:when test="$num < 100"> 181 <xsl:text> </xsl:text> 182 </xsl:when> 183 <xsl:otherwise> 184 <xsl:text></xsl:text> 185 </xsl:otherwise> 186 </xsl:choose> 187 <xsl:value-of select="$num"/> 188 <xsl:text> </xsl:text> 189 <xsl:choose> 190 <xsl:when test="$prev-lhs = lhs[text()]"> 191 <xsl:call-template name="lpad"> 192 <xsl:with-param name="str" select="'|'"/> 193 <xsl:with-param name="pad" select="number(string-length(lhs[text()])) + 1"/> 194 </xsl:call-template> 195 </xsl:when> 196 <xsl:otherwise> 197 <xsl:value-of select="lhs"/> 198 <xsl:text>:</xsl:text> 199 </xsl:otherwise> 200 </xsl:choose> 201 <xsl:if test="$dot = 0"> 202 <xsl:text> .</xsl:text> 203 </xsl:if> 204 205 <!-- RHS --> 206 <xsl:for-each select="rhs/symbol|rhs/empty"> 207 <xsl:apply-templates select="."/> 208 <xsl:if test="$dot = position()"> 209 <xsl:text> .</xsl:text> 210 </xsl:if> 211 </xsl:for-each> 212</xsl:template> 213 214<xsl:template match="symbol"> 215 <xsl:text> </xsl:text> 216 <xsl:value-of select="."/> 217</xsl:template> 218 219<xsl:template match="empty"> 220 <xsl:text> %empty</xsl:text> 221</xsl:template> 222 223<xsl:template match="lookaheads"> 224 <xsl:text> [</xsl:text> 225 <xsl:apply-templates select="symbol"/> 226 <xsl:text>]</xsl:text> 227</xsl:template> 228 229<xsl:template match="lookaheads/symbol"> 230 <xsl:value-of select="."/> 231 <xsl:if test="position() != last()"> 232 <xsl:text>, </xsl:text> 233 </xsl:if> 234</xsl:template> 235 236<xsl:template name="reduction-edge-start"> 237 <xsl:param name="state"/> 238 <xsl:param name="rule"/> 239 <xsl:param name="enabled"/> 240 241 <xsl:text> </xsl:text> 242 <xsl:value-of select="$state"/> 243 <xsl:text> -> "</xsl:text> 244 <xsl:value-of select="$state"/> 245 <xsl:text>R</xsl:text> 246 <xsl:value-of select="$rule"/> 247 <xsl:if test='$enabled = "false"'> 248 <xsl:text>d</xsl:text> 249 </xsl:if> 250 <xsl:text>" [</xsl:text> 251</xsl:template> 252 253<xsl:template name="reduction-node"> 254 <xsl:param name="state"/> 255 <xsl:param name="rule"/> 256 <xsl:param name="color"/> 257 258 <xsl:text> "</xsl:text> 259 <xsl:value-of select="$state"/> 260 <xsl:text>R</xsl:text> 261 <xsl:value-of select="$rule"/> 262 <xsl:if test="$color = 5"> 263 <xsl:text>d</xsl:text> 264 </xsl:if> 265 <xsl:text>" [label="</xsl:text> 266 <xsl:choose> 267 <xsl:when test="$rule = 0"> 268 <xsl:text>Acc", fillcolor=1</xsl:text> 269 </xsl:when> 270 <xsl:otherwise> 271 <xsl:text>R</xsl:text> 272 <xsl:value-of select="$rule"/> 273 <xsl:text>", fillcolor=</xsl:text> 274 <xsl:value-of select="$color"/> 275 </xsl:otherwise> 276 </xsl:choose> 277 <xsl:text>, shape=diamond, style=filled] </xsl:text> 278</xsl:template> 279 280<xsl:template match="transition"> 281 <xsl:call-template name="output-edge"> 282 <xsl:with-param name="src" select="../../../@number"/> 283 <xsl:with-param name="dst" select="@state"/> 284 <xsl:with-param name="style"> 285 <xsl:choose> 286 <xsl:when test="@symbol = 'error'"> 287 <xsl:text>dotted</xsl:text> 288 </xsl:when> 289 <xsl:when test="@type = 'shift'"> 290 <xsl:text>solid</xsl:text> 291 </xsl:when> 292 <xsl:otherwise> 293 <xsl:text>dashed</xsl:text> 294 </xsl:otherwise> 295 </xsl:choose> 296 </xsl:with-param> 297 <xsl:with-param name="label"> 298 <xsl:if test="not(@symbol = 'error')"> 299 <xsl:value-of select="@symbol"/> 300 </xsl:if> 301 </xsl:with-param> 302 </xsl:call-template> 303</xsl:template> 304 305<xsl:template name="output-node"> 306 <xsl:param name="number"/> 307 <xsl:param name="label"/> 308 <xsl:text> </xsl:text> 309 <xsl:value-of select="$number"/> 310 <xsl:text> [label="</xsl:text> 311 <xsl:text>State </xsl:text> 312 <xsl:value-of select="$number"/> 313 <xsl:text>\n</xsl:text> 314 <xsl:call-template name="escape"> 315 <xsl:with-param name="subject" select="$label"/> 316 </xsl:call-template> 317 <xsl:text>\l"] </xsl:text> 318</xsl:template> 319 320<xsl:template name="output-edge"> 321 <xsl:param name="src"/> 322 <xsl:param name="dst"/> 323 <xsl:param name="style"/> 324 <xsl:param name="label"/> 325 <xsl:text> </xsl:text> 326 <xsl:value-of select="$src"/> 327 <xsl:text> -> </xsl:text> 328 <xsl:value-of select="$dst"/> 329 <xsl:text> [style=</xsl:text> 330 <xsl:value-of select="$style"/> 331 <xsl:if test="$label and $label != ''"> 332 <xsl:text> label="</xsl:text> 333 <xsl:call-template name="escape"> 334 <xsl:with-param name="subject" select="$label"/> 335 </xsl:call-template> 336 <xsl:text>"</xsl:text> 337 </xsl:if> 338 <xsl:text>] </xsl:text> 339</xsl:template> 340 341<xsl:template name="escape"> 342 <xsl:param name="subject"/> <!-- required --> 343 <xsl:call-template name="string-replace"> 344 <xsl:with-param name="subject"> 345 <xsl:call-template name="string-replace"> 346 <xsl:with-param name="subject"> 347 <xsl:call-template name="string-replace"> 348 <xsl:with-param name="subject" select="$subject"/> 349 <xsl:with-param name="search" select="'\'"/> 350 <xsl:with-param name="replace" select="'\\'"/> 351 </xsl:call-template> 352 </xsl:with-param> 353 <xsl:with-param name="search" select="'"'"/> 354 <xsl:with-param name="replace" select="'\"'"/> 355 </xsl:call-template> 356 </xsl:with-param> 357 <xsl:with-param name="search" select="' '"/> 358 <xsl:with-param name="replace" select="'\l'"/> 359 </xsl:call-template> 360</xsl:template> 361 362<xsl:template name="string-replace"> 363 <xsl:param name="subject"/> 364 <xsl:param name="search"/> 365 <xsl:param name="replace"/> 366 <xsl:choose> 367 <xsl:when test="contains($subject, $search)"> 368 <xsl:variable name="before" select="substring-before($subject, $search)"/> 369 <xsl:variable name="after" select="substring-after($subject, $search)"/> 370 <xsl:value-of select="$before"/> 371 <xsl:value-of select="$replace"/> 372 <xsl:call-template name="string-replace"> 373 <xsl:with-param name="subject" select="$after"/> 374 <xsl:with-param name="search" select="$search"/> 375 <xsl:with-param name="replace" select="$replace"/> 376 </xsl:call-template> 377 </xsl:when> 378 <xsl:otherwise> 379 <xsl:value-of select="$subject"/> 380 </xsl:otherwise> 381 </xsl:choose> 382</xsl:template> 383 384<xsl:template name="lpad"> 385 <xsl:param name="str" select="''"/> 386 <xsl:param name="pad" select="0"/> 387 <xsl:variable name="diff" select="$pad - string-length($str)" /> 388 <xsl:choose> 389 <xsl:when test="$diff < 0"> 390 <xsl:value-of select="$str"/> 391 </xsl:when> 392 <xsl:otherwise> 393 <xsl:call-template name="space"> 394 <xsl:with-param name="repeat" select="$diff"/> 395 </xsl:call-template> 396 <xsl:value-of select="$str"/> 397 </xsl:otherwise> 398 </xsl:choose> 399</xsl:template> 400 401</xsl:stylesheet> 402