<!DOCTYPE xsl:stylesheet PUBLIC 'http://www.w3.org/1999/XSL/Transform'
      'http://www.w3.org/People/cmsmcq/lib/xslt10.dtd' [

<!--*

/* show-asts.xsl:  stylesheet for translating from an XML dump of
 * an abstract syntax tree into a simple HTML display of the tree.
 */

/* Copyright (c) 2008, 2011 World Wide Web Consortium, 
 * (Massachusetts Institute of Technology, European Research 
 * Consortium for Informatics and Mathematics, Keio University). 
 * All Rights Reserved. This work is distributed under the 
 * W3C(TM) Software License [1] in the hope that it will be 
 * useful, but WITHOUT ANY WARRANTY; without even the implied 
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
 */

/* This file is part of Xerophily, a parser for XSD regular expressions. */

*-->


<!ATTLIST xsl:stylesheet 
  xmlns:xsl CDATA "http://www.w3.org/1999/XSL/Transform" 
  xmlns:xsd CDATA "http://www.w3.org/2001/XMLSchema" 
  xmlns:h   CDATA "http://www.w3.org/1999/xhtml"
>
<!ENTITY mdash  "&#x2014;" ><!--=em dash-->
<!ENTITY ldquo  "&#x201C;" ><!--=double quotation mark, left-->
<!ENTITY rdquo  "&#x201D;" ><!--=double quotation mark, right-->

]>
<xsl:stylesheet 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
 xmlns:h="http://www.w3.org/1999/xhtml"
 version="1.0">
 <xsl:output method="html"/>

 <!--* We're developing this stylesheet incrementally, so we may
     * occasionally encounter elements we don't have templates
     * for.  We display them in red so as to call attention to the
     * gap. *-->
 <xsl:template match="*">
  <xsl:element name="span">
   <xsl:attribute name="style">color: red;</xsl:attribute>
   <xsl:value-of select="concat('&lt;',name(),'/&gt;')"/>
  </xsl:element>
 </xsl:template>

 <!--* The outermost element in the expected input is a
     * schema element. We handle the overall structure of
     * the HTML page here. 
     *-->
 <xsl:template match="xsd:schema">
  <xsl:element name="html">
   <xsl:element name="head">
    <xsl:element name="title">Regex syntax trees</xsl:element>
   </xsl:element>
   <xsl:element name="body">
    <xsl:element name="h1">
     Abstract syntax trees for XSD regexes
    </xsl:element>
    <xsl:if test="count(xsd:simpleType) > 1">
      <xsl:element name="div">
	<xsl:element name="ul">
	  <xsl:apply-templates select="xsd:simpleType" mode="toc"/>
	</xsl:element>
      </xsl:element>
    </xsl:if>
    <xsl:apply-templates/>
   </xsl:element>
  </xsl:element>
 </xsl:template>
 
 <!--* For many XSD elements, we just recur, in case there are 
     * any patterns inside them.
     *-->
 <xsl:template match="xsd:annotation|xsd:documentation|xsd:appinfo|xsd:restriction">
  <xsl:apply-templates/>
 </xsl:template>

 <!--* Any HTML elements (they can and should occur within annotation
     * elements) get written out to the output.
     *-->
 <xsl:template match="h:*">
  <xsl:element name="{name()}">
   <xsl:apply-templates/>
  </xsl:element>
 </xsl:template>

 <!--* Each simpleType element makes a div with a heading.
     * If it has more than one pattern, or if any pattern has
     * more than one parse, we do a table of contents
     *-->
 <xsl:template match="xsd:simpleType">
  <xsl:element name="h2">
   <xsl:element name="a">
    <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
    <xsl:attribute name="id"><xsl:value-of select="@name"/></xsl:attribute>
    <xsl:value-of select="@name"/>
   </xsl:element>   
  </xsl:element>
  <xsl:element name="div">
   <xsl:attribute name="style">margin-left: 7%;</xsl:attribute>
   <xsl:if test="count(.//ast) > 1">
     <xsl:element name="ul">
       <xsl:apply-templates mode="toc" select="./xsd:restriction/xsd:pattern"/>
     </xsl:element>
   </xsl:if>
   <xsl:apply-templates/>
  </xsl:element>
 </xsl:template>

 <!--* Each pattern is presented in a paragraph, followed by
     * a list of parses.
     *-->
 <xsl:template match="xsd:pattern">
  <xsl:element name="h3">
   <xsl:element name="a">
     <xsl:attribute name="name">
       <xsl:value-of 
	   select="concat(../../@name,'-',1 + count(preceding-sibling::xsd:pattern))"/>
     </xsl:attribute>
   </xsl:element>
   <xsl:text>Pattern &ldquo;</xsl:text>
   <xsl:element name="code">
    <xsl:value-of select="@value"/>
   </xsl:element>
   <xsl:text>&rdquo;</xsl:text>
  </xsl:element>
  <xsl:apply-templates/>
 </xsl:template>

 <!--* Each parse is displayed with a list of which grammars produced it. *-->
 <xsl:template match="ast">
   <xsl:variable name="n"
		 select="1 + count(preceding-sibling::ast)"/>
   <xsl:element name="h4">
     <xsl:element name="a">
       <xsl:attribute name="name">
	 <xsl:value-of 
	     select="concat(ancestor::xsd:simpleType/@name,'-',
		     1 + count(ancestor::xsd:pattern/preceding-sibling::xsd:pattern),
		     '-',
		     $n
		     )"/>
       </xsl:attribute>
     </xsl:element>
     <xsl:choose>
       <xsl:when test="count(../ast) > 1">
	 <xsl:value-of select="concat('Parse ', $n)"/>
       </xsl:when>
       <xsl:otherwise>
	 <xsl:text>Sole parse</xsl:text>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:element>
   <xsl:element name="p">
     <xsl:text>Produced by:  </xsl:text>
     <xsl:call-template name="grammarlist-nodups">
       <xsl:with-param name="grammars" 
		       select="normalize-space(@grammar)"/>
     </xsl:call-template>
   </xsl:element>
   <xsl:element name="ul">
     <xsl:apply-templates/>
   </xsl:element> 
 </xsl:template>

 <xsl:template name="grammarlist-nodups">
   <xsl:param name="grammars" select="@grammar"/>
   <xsl:choose>
     <xsl:when test="normalize-space($grammars) = ''"/>
     <xsl:otherwise>
       <xsl:variable name="g0"
		     select="substring-before(concat($grammars,' '),' ')"/>
       <xsl:variable name="gs">
	 <xsl:call-template name="lose-dups">
	   <xsl:with-param name="grammar"
			   select="$g0"/>
	   <xsl:with-param name="grammars"
			   select="$grammars"/>
	 </xsl:call-template>
       </xsl:variable>
       <xsl:value-of select="$g0"/>
       <xsl:if test="normalize-space($gs) != ''">
	 <xsl:text>, </xsl:text>
	 <xsl:call-template name="grammarlist-nodups">
	   <xsl:with-param name="grammars" 
			   select="$gs"/>
	 </xsl:call-template>
       </xsl:if>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>

 <xsl:template name="lose-dups">
   <xsl:param name="grammar"/>
   <xsl:param name="grammars"/>
   <xsl:choose>
     <xsl:when test="$grammar = ''"/>
     <xsl:when test="$grammars = ''"/>
     <xsl:when test="contains($grammars, $grammar)">
       <xsl:call-template name="lose-dups">
	 <xsl:with-param name="grammar"
			 select="$grammar"/>
	 <xsl:with-param name="grammars"
			 select="concat(
				 substring-before($grammars,$grammar),
				 ' ',
				 substring-after($grammars,$grammar)
				 )"/>
       </xsl:call-template>       
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="normalize-space($grammars)"/>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>

 <xsl:template match="ast[no_parse]">
  <xsl:element name="p">
   <xsl:value-of select="@grammar"/>
   <xsl:text> &mdash; No parse.</xsl:text>
  </xsl:element> 
 </xsl:template>
 
 <xsl:template name="do-children">
  <xsl:choose>
   <xsl:when test="count(*) > 1">
    <xsl:element name="ul">
     <xsl:apply-templates>
      <xsl:with-param name="wrap">li</xsl:with-param>
     </xsl:apply-templates>
    </xsl:element>
   </xsl:when>
   <xsl:when test="count(*) = 1">
    <xsl:apply-templates>
     <xsl:with-param name="wrap">span</xsl:with-param>
    </xsl:apply-templates>
   </xsl:when>
  </xsl:choose>
 </xsl:template>

 <xsl:template match="seq[count(*) > 1]">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>sequence of:</xsl:text>
   <xsl:element name="ul">
    <xsl:apply-templates>
     <xsl:with-param name="wrap">li</xsl:with-param>
    </xsl:apply-templates>
   </xsl:element>
  </xsl:element> 
 </xsl:template>

 <xsl:template match="seq[count(*) = 1]">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:apply-templates>
   <xsl:with-param name="wrap" select="$wrap"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="count[@min='1' and @max='1']">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>one </xsl:text>
   <xsl:call-template name="do-children"/>
  </xsl:element> 
 </xsl:template>

 <xsl:template match="count[@min='1' and @max='unbounded']">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>one or more </xsl:text>
   <xsl:call-template name="do-children"/>
  </xsl:element>  
 </xsl:template>

 <xsl:template match="count[@min='0' and @max='unbounded']">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>zero or more </xsl:text>
   <xsl:call-template name="do-children"/>
  </xsl:element>  
 </xsl:template>

 <xsl:template match="count">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:value-of select="concat(@min,' to ',@max,' occurrences of ')"/>
   <xsl:call-template name="do-children"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="re">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>(</xsl:text>
   <xsl:call-template name="do-children"/>
   <xsl:text>)</xsl:text>
  </xsl:element>
 </xsl:template>

 <xsl:template match="or">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>choice of:  </xsl:text>
   <xsl:call-template name="do-children"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="charClass[mce[@kw]]" mode="old">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:value-of select="concat('Character class:  ',mce/@kw)"/>
   <xsl:call-template name="do-children"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="charClass[mce[@not_kw]]" mode="old">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:value-of select="concat('Character class:  NOT ',mce/@not_kw)"/>
   <xsl:call-template name="do-children"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="charClass">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>Character class: </xsl:text>
   <xsl:call-template name="do-children"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="mce">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>mce </xsl:text>
   <xsl:choose>
    <xsl:when test="@kw"><xsl:value-of select="@kw"/></xsl:when>
    <xsl:when test="@not_kw"><xsl:value-of select="concat('NOT ',@not_kw)"/></xsl:when>
    <xsl:otherwise> MCE NOT HANDLED.</xsl:otherwise>
   </xsl:choose>
   <xsl:call-template name="do-children"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="sce">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>single-character (escaped) "</xsl:text>
   <xsl:value-of select="."/>
   <xsl:text>"</xsl:text>
  </xsl:element>
 </xsl:template>

 <xsl:template match="any_of">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>any of </xsl:text>
   <xsl:call-template name="do-children"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="none_of">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>any EXCEPT </xsl:text>
   <xsl:call-template name="do-children"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="c">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:value-of select="concat('character &quot;',.,'&quot;')"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="simple_range">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:value-of select="concat('from &quot;',@from,'&quot; to &quot;',@to,'&quot;')"/>
   <xsl:call-template name="do-children"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="difference">
  <xsl:param name="wrap">li</xsl:param>
  <xsl:element name="{$wrap}">
   <xsl:text>Subtraction: any </xsl:text>
   <xsl:element name="ul">
    <xsl:apply-templates select="*[1]">
     <xsl:with-param name="wrap">li</xsl:with-param>
    </xsl:apply-templates>
   </xsl:element>
   <xsl:text>EXCEPT FOR </xsl:text>
   <xsl:element name="ul">
    <xsl:apply-templates select="*[2]">
     <xsl:with-param name="wrap">li</xsl:with-param>
    </xsl:apply-templates>
   </xsl:element>
  </xsl:element>
 </xsl:template>


 <!--* toc mode *-->
 <xsl:template match="xsd:simpleType" mode="toc">
  <xsl:element name="li">
   <xsl:element name="a">
    <xsl:attribute name="href">#<xsl:value-of select="@name"/></xsl:attribute>
    <xsl:value-of select="@name"/>
   </xsl:element>   
   <xsl:if test=".//xsd:pattern">
     <xsl:apply-templates select=".//xsd:pattern" mode="toc"/>
   </xsl:if>
  </xsl:element>
 </xsl:template>
 
 <xsl:template match="xsd:pattern" mode="toc">
  <xsl:element name="li">
   <xsl:element name="a">
    <xsl:attribute name="href">#<xsl:value-of 
      select="concat(../../@name,'-',1 + count(preceding-sibling::xsd:pattern))"/></xsl:attribute>
    <xsl:value-of select="@value"/>
   </xsl:element>   
   <xsl:if test="count(.//ast) > 1">
     <ul>
       <xsl:apply-templates select=".//ast" mode="toc"/>
     </ul>
   </xsl:if>
  </xsl:element>
 </xsl:template>

 <xsl:template match="ast" mode="toc">
   <xsl:variable name="n"
		 select="1 + count(preceding-sibling::ast)"/>
   <xsl:element name="li">
     <xsl:element name="a">
       <xsl:attribute name="href">
	 <xsl:text>#</xsl:text>
	 <xsl:value-of 
	     select="concat(ancestor::xsd:simpleType/@name,'-',
		     1 + count(ancestor::xsd:pattern/preceding-sibling::xsd:pattern),
		     '-',
		     $n
		     )"/>
       </xsl:attribute>     
       <xsl:choose>
	 <xsl:when test="count(../ast) > 1">
	   <xsl:value-of select="concat('Parse ', $n)"/>
	 </xsl:when>
	 <xsl:otherwise>
	   <xsl:text>Sole parse</xsl:text>
	 </xsl:otherwise>
       </xsl:choose>
     </xsl:element>
     <xsl:text> </xsl:text>
     <xsl:call-template name="grammarlist-nodups">
       <xsl:with-param name="grammars" 
		       select="normalize-space(@grammar)"/>
     </xsl:call-template>
   </xsl:element>
 </xsl:template>

 
</xsl:stylesheet>
<!-- Keep this comment at the end of the file
Local variables:
mode: xml
sgml-default-dtd-file:"/Library/SGML/Public/Emacs/xslt.ced"
sgml-omittag:t
sgml-shorttag:t
sgml-indent-data:t
sgml-indent-step:1
End:
-->

