1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <!-- 4 xml2dot.xsl - transform Bison XML Report into DOT. 5 6 Copyright (C) 2007-2012 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 (a] 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: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 refered 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 refered 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="point" select="@point"/> 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="point"/> 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="$point = 0"> 202 <xsl:text> .</xsl:text> 203 </xsl:if> 204 <xsl:for-each select="rhs/symbol|rhs/empty"> 205 <xsl:apply-templates select="."/> 206 <xsl:if test="$point = position()"> 207 <xsl:text> .</xsl:text> 208 </xsl:if> 209 </xsl:for-each> 210 </xsl:template> 211 212 <xsl:template match="symbol"> 213 <xsl:text> </xsl:text> 214 <xsl:value-of select="."/> 215 </xsl:template> 216 217 <xsl:template match="empty"/> 218 219 <xsl:template match="lookaheads"> 220 <xsl:text> [</xsl:text> 221 <xsl:apply-templates select="symbol"/> 222 <xsl:text>]</xsl:text> 223 </xsl:template> 224 225 <xsl:template match="lookaheads/symbol"> 226 <xsl:value-of select="."/> 227 <xsl:if test="position() != last()"> 228 <xsl:text>, </xsl:text> 229 </xsl:if> 230 </xsl:template> 231 232 <xsl:template name="reduction-edge-start"> 233 <xsl:param name="state"/> 234 <xsl:param name="rule"/> 235 <xsl:param name="enabled"/> 236 237 <xsl:text> </xsl:text> 238 <xsl:value-of select="$state"/> 239 <xsl:text> -> "</xsl:text> 240 <xsl:value-of select="$state"/> 241 <xsl:text>R</xsl:text> 242 <xsl:value-of select="$rule"/> 243 <xsl:if test='$enabled = "false"'> 244 <xsl:text>d</xsl:text> 245 </xsl:if> 246 <xsl:text>" [</xsl:text> 247 </xsl:template> 248 249 <xsl:template name="reduction-node"> 250 <xsl:param name="state"/> 251 <xsl:param name="rule"/> 252 <xsl:param name="color"/> 253 254 <xsl:text> "</xsl:text> 255 <xsl:value-of select="$state"/> 256 <xsl:text>R</xsl:text> 257 <xsl:value-of select="$rule"/> 258 <xsl:if test="$color = 5"> 259 <xsl:text>d</xsl:text> 260 </xsl:if> 261 <xsl:text>" [label="</xsl:text> 262 <xsl:choose> 263 <xsl:when test="$rule = 0"> 264 <xsl:text>Acc", fillcolor=1</xsl:text> 265 </xsl:when> 266 <xsl:otherwise> 267 <xsl:text>R</xsl:text> 268 <xsl:value-of select="$rule"/> 269 <xsl:text>", fillcolor=</xsl:text> 270 <xsl:value-of select="$color"/> 271 </xsl:otherwise> 272 </xsl:choose> 273 <xsl:text>, shape=diamond, style=filled] </xsl:text> 274 </xsl:template> 275 276 <xsl:template match="transition"> 277 <xsl:call-template name="output-edge"> 278 <xsl:with-param name="src" select="../../../@number"/> 279 <xsl:with-param name="dst" select="@state"/> 280 <xsl:with-param name="style"> 281 <xsl:choose> 282 <xsl:when test="@symbol = 'error'"> 283 <xsl:text>dotted</xsl:text> 284 </xsl:when> 285 <xsl:when test="@type = 'shift'"> 286 <xsl:text>solid</xsl:text> 287 </xsl:when> 288 <xsl:otherwise> 289 <xsl:text>dashed</xsl:text> 290 </xsl:otherwise> 291 </xsl:choose> 292 </xsl:with-param> 293 <xsl:with-param name="label"> 294 <xsl:if test="not(@symbol = 'error')"> 295 <xsl:value-of select="@symbol"/> 296 </xsl:if> 297 </xsl:with-param> 298 </xsl:call-template> 299 </xsl:template> 300 301 <xsl:template name="output-node"> 302 <xsl:param name="number"/> 303 <xsl:param name="label"/> 304 <xsl:text> </xsl:text> 305 <xsl:value-of select="$number"/> 306 <xsl:text> [label="</xsl:text> 307 <xsl:text>State </xsl:text> 308 <xsl:value-of select="$number"/> 309 <xsl:text>\n</xsl:text> 310 <xsl:call-template name="escape"> 311 <xsl:with-param name="subject" select="$label"/> 312 </xsl:call-template> 313 <xsl:text>\l"] </xsl:text> 314 </xsl:template> 315 316 <xsl:template name="output-edge"> 317 <xsl:param name="src"/> 318 <xsl:param name="dst"/> 319 <xsl:param name="style"/> 320 <xsl:param name="label"/> 321 <xsl:text> </xsl:text> 322 <xsl:value-of select="$src"/> 323 <xsl:text> -> </xsl:text> 324 <xsl:value-of select="$dst"/> 325 <xsl:text> [style=</xsl:text> 326 <xsl:value-of select="$style"/> 327 <xsl:if test="$label and $label != ''"> 328 <xsl:text> label="</xsl:text> 329 <xsl:call-template name="escape"> 330 <xsl:with-param name="subject" select="$label"/> 331 </xsl:call-template> 332 <xsl:text>"</xsl:text> 333 </xsl:if> 334 <xsl:text>] </xsl:text> 335 </xsl:template> 336 337 <xsl:template name="escape"> 338 <xsl:param name="subject"/> <!-- required --> 339 <xsl:call-template name="string-replace"> 340 <xsl:with-param name="subject"> 341 <xsl:call-template name="string-replace"> 342 <xsl:with-param name="subject"> 343 <xsl:call-template name="string-replace"> 344 <xsl:with-param name="subject" select="$subject"/> 345 <xsl:with-param name="search" select="'\'"/> 346 <xsl:with-param name="replace" select="'\\'"/> 347 </xsl:call-template> 348 </xsl:with-param> 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="'\l'"/> 355 </xsl:call-template> 356 </xsl:template> 357 358 <xsl:template name="string-replace"> 359 <xsl:param name="subject"/> 360 <xsl:param name="search"/> 361 <xsl:param name="replace"/> 362 <xsl:choose> 363 <xsl:when test="contains($subject, $search)"> 364 <xsl:variable name="before" select="substring-before($subject, $search)"/> 365 <xsl:variable name="after" select="substring-after($subject, $search)"/> 366 <xsl:value-of select="$before"/> 367 <xsl:value-of select="$replace"/> 368 <xsl:call-template name="string-replace"> 369 <xsl:with-param name="subject" select="$after"/> 370 <xsl:with-param name="search" select="$search"/> 371 <xsl:with-param name="replace" select="$replace"/> 372 </xsl:call-template> 373 </xsl:when> 374 <xsl:otherwise> 375 <xsl:value-of select="$subject"/> 376 </xsl:otherwise> 377 </xsl:choose> 378 </xsl:template> 379 380 <xsl:template name="lpad"> 381 <xsl:param name="str" select="''"/> 382 <xsl:param name="pad" select="0"/> 383 <xsl:variable name="diff" select="$pad - string-length($str)" /> 384 <xsl:choose> 385 <xsl:when test="$diff < 0"> 386 <xsl:value-of select="$str"/> 387 </xsl:when> 388 <xsl:otherwise> 389 <xsl:call-template name="space"> 390 <xsl:with-param name="repeat" select="$diff"/> 391 </xsl:call-template> 392 <xsl:value-of select="$str"/> 393 </xsl:otherwise> 394 </xsl:choose> 395 </xsl:template> 396 397 </xsl:stylesheet> 398