<?xml version="1.0"?>
<xsl:transform version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text"/>

<xsl:template match="language">
  <xsl:text>A Rough Grammar For </xsl:text>
  <xsl:value-of select="@name"/>
  <xsl:text>&#xa;&#xa;</xsl:text>

  <xsl:if test="//symbol[@optional = 'true']">
    <xsl:text>Note: The enumeration of optional symbols (X?) </xsl:text>
    <xsl:text>omits empty productions.&#xa;&#xa;</xsl:text>
    </xsl:if>

  <xsl:text>Grammatical Productions:</xsl:text>
  <xsl:if test="parser/@expected_conflicts">
    <xsl:text> (expect </xsl:text>
    <xsl:value-of select="parser/@expected_conflicts"/>
    <xsl:text> conflicts)</xsl:text>
    </xsl:if>
  <xsl:text>&#xa;&#xa;</xsl:text>

  <xsl:if test="parser/@start and parser/@start != parser/nonterm[1]/@name">
    <xsl:text>Grammar starts at: </xsl:text>
    <xsl:value-of select="parser/@start"/>
    <xsl:text>&#xa;&#xa;</xsl:text>
    </xsl:if>

  <xsl:for-each select="parser/nonterm">

    <xsl:value-of select="@name"/>
    <xsl:text>&#xa;  : </xsl:text>

    <xsl:for-each select="production">
      <xsl:if test="position() != 1">| </xsl:if>
      <xsl:for-each select="symbol">

        <xsl:value-of select="."/>
        <xsl:if test="@optional and @optional='true'">?</xsl:if>

        <xsl:if test="position() != last()"><xsl:text> </xsl:text></xsl:if>
        </xsl:for-each>

        <xsl:text>&#xa;  </xsl:text>
      </xsl:for-each>

      <xsl:if test="@epsilon and @epsilon = 'true'">
        <xsl:if test="production">| </xsl:if>
        <xsl:text>/* empty */&#xa;  </xsl:text>
        </xsl:if>
      <xsl:text>;&#xa;</xsl:text>

    </xsl:for-each>

  <xsl:text>&#xa;</xsl:text>
  <xsl:text>&#xa;</xsl:text>

  <xsl:text>Lexical Rules:&#xa;&#xa;</xsl:text>

  <xsl:for-each select="lexer/option">
    <xsl:text>%option </xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>&#xa;</xsl:text>
    <xsl:if test="position() = last()">
      <xsl:text>&#xa;</xsl:text>
      </xsl:if>
    </xsl:for-each>

  <xsl:for-each select="lexer/pattern">
    <xsl:call-template name="leftfield">
      <xsl:with-param name="str" select="concat(@name, ' ')"/>
      <xsl:with-param name="width" select="16"/>
      </xsl:call-template>
    <xsl:value-of select="."/>
    <xsl:text>&#xa;</xsl:text>
    </xsl:for-each>

  <xsl:text>&#xa;</xsl:text>

  <xsl:for-each select="lexer/*[name() != 'pattern' and name() != 'option']">
    
    <xsl:call-template name="leftfield">
      <xsl:with-param name="str" select="concat(., '  ')"/>
      <xsl:with-param name="width" select="16"/>
      </xsl:call-template>

    <xsl:if test="name() = 'ignore'">/* ignore */</xsl:if>
    <xsl:if test="name() = 'error'">{return LEX_ERROR;}</xsl:if>
    <xsl:if test="name() = 'match'">
      <xsl:text>{return </xsl:text>
      <xsl:value-of select="@term"/>
      <xsl:text>;}</xsl:text>
      </xsl:if>

    <xsl:text>&#xa;</xsl:text>
    </xsl:for-each>

  <xsl:text>&#xa;</xsl:text>

  </xsl:template>

<xsl:template name="leftfield">
<xsl:param name="str"/>
<xsl:param name="width"/>
  <xsl:choose>
    <xsl:when test="string-length($str) >= $width">
      <xsl:value-of select="$str"/>
      </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="leftfield">
        <xsl:with-param name="str" select="concat($str, ' ')"/>
        <xsl:with-param name="width" select="$width"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:transform>
