src/xmlpatterns/qtokenautomaton/qautomaton2cpp.xsl
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 <?xml version='1.0' encoding="UTF-8"?>
       
     2 <xsl:stylesheet version="2.0"
       
     3                 xml:lang="en"
       
     4                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
       
     5                 xmlns:local="http://www.w3.org/2005/xquery-local-functions"
       
     6                 xmlns:xs="http://www.w3.org/2001/XMLSchema">
       
     7 
       
     8     <xsl:variable name="className" as="xs:string" select="tokenAutomaton/@className"/>
       
     9     <xsl:variable name="defaultToken" as="xs:string" select="tokenAutomaton/@defaultToken"/>
       
    10     <xsl:variable name="tokens" as="element(token)+" select="tokenAutomaton/tokens/token"/>
       
    11     <xsl:variable name="tokenEnum" as="xs:string" select="tokenAutomaton/@tokenEnum"/>
       
    12 
       
    13     <xsl:variable name="warningGenerated" as="xs:string">/* NOTE: This file is AUTO GENERATED by qautomaton2cpp.xsl. */&#xA;</xsl:variable>
       
    14 
       
    15     <xsl:template match="tokenAutomaton">
       
    16 
       
    17         <xsl:variable name="uniqueLengths" as="xs:integer+" select="distinct-values(tokens/token/string-length())"/>
       
    18 
       
    19         <xsl:result-document method="text" href="{@headerFile}">
       
    20 
       
    21             <xsl:variable name="includeGuardName" select="string(@includeGuardName)"/>
       
    22 
       
    23             <xsl:value-of select="boilerplate/prolog"/>
       
    24 
       
    25             <xsl:value-of select="$warningGenerated"/>
       
    26 
       
    27             <xsl:text>&#xA;#ifndef </xsl:text>
       
    28             <xsl:value-of select="$includeGuardName"/>
       
    29             <xsl:text>&#xA;#define </xsl:text>
       
    30             <xsl:value-of select="$includeGuardName"/>
       
    31             <xsl:text>&#xA;&#xA;</xsl:text>
       
    32 
       
    33             <xsl:text>#include &lt;QtCore/QString>&#xA;</xsl:text>
       
    34             <xsl:text>&#xA;</xsl:text>
       
    35             <xsl:text>QT_BEGIN_NAMESPACE&#xA;</xsl:text>
       
    36             <xsl:text>&#xA;</xsl:text>
       
    37 
       
    38             <xsl:if test="@namespace">
       
    39                 <xsl:text>namespace </xsl:text>
       
    40                 <xsl:value-of select="@namespace"/>
       
    41                 {
       
    42             </xsl:if>
       
    43 
       
    44             <xsl:text>class </xsl:text>
       
    45             <xsl:value-of select="@className"/>
       
    46                 {
       
    47                 <xsl:value-of select="@scope"/>:
       
    48                 <xsl:text>enum </xsl:text>
       
    49                 <xsl:value-of select="$tokenEnum"/>
       
    50                 <xsl:text>&#xA;</xsl:text>
       
    51                 {
       
    52                 <xsl:value-of separator=",&#xA;">
       
    53                     <xsl:sequence select="@defaultToken"/>
       
    54                     <xsl:perform-sort select="tokens/token/local:tokenToEnumName(.)">
       
    55                         <xsl:sort select="."/>
       
    56                     </xsl:perform-sort>
       
    57                 </xsl:value-of>
       
    58                 };
       
    59 
       
    60                 <xsl:text>static inline </xsl:text>
       
    61                 <xsl:value-of select="$tokenEnum"/>
       
    62                 <xsl:text> toToken(const QString &amp;value);&#xA;</xsl:text>
       
    63                 <xsl:text>static inline </xsl:text>
       
    64                 <xsl:value-of select="$tokenEnum"/>
       
    65                 <xsl:text> toToken(const QStringRef &amp;value);&#xA;</xsl:text>
       
    66                 <xsl:text>static </xsl:text>
       
    67                 <xsl:value-of select="$tokenEnum"/>
       
    68                 <xsl:text> toToken(const QChar *data, int length);&#xA;</xsl:text>
       
    69                     <xsl:if test="xs:boolean(@hasToString)">
       
    70                         <xsl:text>static QString toString(</xsl:text>
       
    71                         <xsl:value-of select="$tokenEnum"/>
       
    72                         <xsl:text> token);&#xA;</xsl:text>
       
    73                     </xsl:if>
       
    74 
       
    75                 private:
       
    76                     <xsl:for-each select="$uniqueLengths">
       
    77                         <xsl:sort select="."/>
       
    78                         <xsl:text>static inline </xsl:text>
       
    79                         <xsl:value-of select="$tokenEnum"/>
       
    80                         <xsl:text> classifier</xsl:text>
       
    81                         <xsl:value-of select="."/>
       
    82                         <xsl:text>(const QChar *data);&#xA;</xsl:text>
       
    83                     </xsl:for-each>
       
    84                 };
       
    85 
       
    86                 <xsl:text>inline </xsl:text>
       
    87                 <xsl:value-of select="@className"/>::<xsl:value-of select="$tokenEnum"/>
       
    88                 <xsl:text> </xsl:text>
       
    89                 <xsl:value-of select="@className"/>::toToken(const QString &amp;value)
       
    90                 {
       
    91                     return toToken(value.constData(), value.length());
       
    92                 }
       
    93 
       
    94                 <xsl:text>inline </xsl:text>
       
    95                 <xsl:value-of select="@className"/>::<xsl:value-of select="$tokenEnum"/>
       
    96                 <xsl:text> </xsl:text>
       
    97                 <xsl:value-of select="@className"/>::toToken(const QStringRef &amp;value)
       
    98                 {
       
    99                     return toToken(value.constData(), value.length());
       
   100                 }
       
   101 
       
   102                 <xsl:if test="@namespace">
       
   103                     <xsl:text>}&#xA;</xsl:text>
       
   104                 </xsl:if>
       
   105 
       
   106                 <xsl:text>&#xA;</xsl:text>
       
   107                 <xsl:text>QT_END_NAMESPACE&#xA;</xsl:text>
       
   108                 <xsl:text>&#xA;</xsl:text>
       
   109 
       
   110                 <xsl:text>#endif&#xA;</xsl:text>
       
   111         </xsl:result-document>
       
   112 
       
   113         <xsl:result-document method="text" href="{@sourceFile}">
       
   114             <xsl:value-of select="boilerplate/prolog"/>
       
   115 
       
   116             <xsl:value-of select="$warningGenerated"/>
       
   117 
       
   118             <xsl:text>&#xA;#include "</xsl:text>
       
   119             <xsl:value-of select="@headerFile"/>
       
   120             <xsl:text>"&#xA;</xsl:text>
       
   121             <xsl:text>&#xA;</xsl:text>
       
   122             <xsl:text>QT_BEGIN_NAMESPACE&#xA;</xsl:text>
       
   123 
       
   124             <xsl:if test="@namespace">
       
   125                 <xsl:text>&#xA;</xsl:text>
       
   126                 <xsl:text>using namespace </xsl:text>
       
   127                 <xsl:value-of select="@namespace"/>
       
   128                 <xsl:text>;&#xA;</xsl:text>
       
   129             </xsl:if>
       
   130 
       
   131             <xsl:text>&#xA;</xsl:text>
       
   132             <xsl:variable name="tokens" select="tokens/token"/>
       
   133 
       
   134             <xsl:for-each select="$uniqueLengths">
       
   135                 <xsl:sort select="."/>
       
   136                 <xsl:call-template name="generate-classifier">
       
   137                     <xsl:with-param name="strings" select="$tokens[string-length() eq current()]"/>
       
   138                 </xsl:call-template>
       
   139             </xsl:for-each>
       
   140 
       
   141             <xsl:value-of select="@className"/>::<xsl:value-of select="$tokenEnum"/>
       
   142             <xsl:text> </xsl:text>
       
   143             <xsl:value-of select="@className"/>::toToken(const QChar *data, int length)
       
   144             {
       
   145                 switch(length)
       
   146                 {
       
   147                     <xsl:for-each select="$uniqueLengths">
       
   148                         <xsl:sort data-type="number" select="."/>
       
   149                         case <xsl:value-of select="."/>:
       
   150                             return classifier<xsl:value-of select="."/>(data);
       
   151 
       
   152                     </xsl:for-each>
       
   153                         default:
       
   154                             return <xsl:value-of select="@defaultToken"/>;
       
   155                 }
       
   156             }
       
   157 
       
   158             <xsl:if test="xs:boolean(@hasToString)">
       
   159                 QString <xsl:value-of select="@className"/>::toString(<xsl:value-of select="$tokenEnum"/> token)
       
   160                 {
       
   161                     const unsigned short *data = 0;
       
   162                     int length = 0;
       
   163 
       
   164                     switch(token)
       
   165                     {
       
   166                     <xsl:for-each select="tokens/token">
       
   167                         <xsl:sort select="local:tokenToEnumName(.)"/>
       
   168                         case <xsl:sequence select="local:tokenToEnumName(.)"/>:
       
   169                         {<!-- Without these braces, the code doesn't compile on MSVC 2008. -->
       
   170                             static const unsigned short staticallyStored<xsl:value-of select="local:tokenToEnumName(.)"/>[] =
       
   171                             {
       
   172                             <xsl:value-of separator=", " select="string-to-codepoints(.), 0"/>
       
   173                             };
       
   174                             data = staticallyStored<xsl:value-of select="local:tokenToEnumName(.)"/>;
       
   175                             length = <xsl:value-of select="string-length(.)"/>;
       
   176                             break;
       
   177                         }
       
   178                     </xsl:for-each>
       
   179                         default:
       
   180                             /* It's either the default token, or an undefined enum
       
   181                              * value. We silence a compiler warning, and return the
       
   182                              * empty string. */
       
   183                             ;
       
   184                     }
       
   185 
       
   186                     union
       
   187                     {
       
   188                         const unsigned short *data;
       
   189                         const QChar *asQChar;
       
   190                     } converter;
       
   191                     converter.data = data;
       
   192 
       
   193                     return QString::fromRawData(converter.asQChar, length);
       
   194                 }
       
   195             </xsl:if>
       
   196 
       
   197             <xsl:text>&#xA;</xsl:text>
       
   198             <xsl:text>QT_END_NAMESPACE&#xA;</xsl:text>
       
   199             <xsl:text>&#xA;</xsl:text>
       
   200         </xsl:result-document>
       
   201 
       
   202     </xsl:template>
       
   203 
       
   204     <xsl:template name="generate-classifier">
       
   205         <xsl:param name="strings" as="xs:string+"/>
       
   206 
       
   207         <xsl:value-of select="$className"/>::<xsl:value-of select="$tokenEnum"/>
       
   208         <xsl:text> </xsl:text>
       
   209         <xsl:value-of select="$className"/>::classifier<xsl:value-of select="."/>(const QChar *data)
       
   210 
       
   211         {
       
   212             <xsl:sequence select="local:generateBranching($strings, 1, 1)"/>
       
   213 
       
   214             return <xsl:value-of select="$defaultToken"/>;
       
   215         }
       
   216     </xsl:template>
       
   217 
       
   218     <xsl:function name="local:generateBranching" ><!--as="xs:string+">-->
       
   219         <xsl:param name="strings" as="xs:string+"/>
       
   220         <xsl:param name="depth" as="xs:integer"/>
       
   221         <xsl:param name="currentPos" as="xs:integer"/>
       
   222 
       
   223         <xsl:choose>
       
   224             <xsl:when test="count($strings) eq 1">
       
   225                 <xsl:variable name="remainingLength" as="xs:integer" select="(string-length($strings) - $currentPos) + 1"/>
       
   226                 <xsl:variable name="toMatch" as="xs:integer+" select="string-to-codepoints(substring($strings, $currentPos))"/>
       
   227 
       
   228                 <xsl:if test="$remainingLength ne 0">
       
   229                     <xsl:choose>
       
   230                         <xsl:when test="$remainingLength eq 1">
       
   231                             if(data[<xsl:sequence select="$depth - 1"/>] == <xsl:sequence select="$toMatch"/>)
       
   232                         </xsl:when>
       
   233                         <xsl:when test="$remainingLength &gt; 1">
       
   234                             static const unsigned short string[] =
       
   235                             {
       
   236                                 <xsl:value-of separator=", " select="string-to-codepoints(substring($strings, $currentPos))"/>
       
   237                             };
       
   238                             if(memcmp(&amp;data[<xsl:sequence select="$depth - 1"/>], &amp;string, sizeof(QChar) * <xsl:value-of select="$remainingLength"/>) == 0)
       
   239                         </xsl:when>
       
   240                     </xsl:choose>
       
   241                 </xsl:if>
       
   242 
       
   243                 return <xsl:value-of select="local:tokenToEnumName($strings)"/>;
       
   244             </xsl:when>
       
   245             <xsl:otherwise>
       
   246                 <xsl:for-each select="distinct-values(for $i in $strings return substring($i, $currentPos, 1))">
       
   247                     <xsl:if test="position() &gt; 1">
       
   248                         <xsl:text>else </xsl:text>
       
   249                     </xsl:if>
       
   250 
       
   251                     <xsl:text>if (data[</xsl:text>
       
   252                     <xsl:sequence select="string($depth - 1)"/>
       
   253                     <xsl:text>] == </xsl:text>
       
   254                     <xsl:sequence select="string-to-codepoints(.)"/>
       
   255                     <xsl:text>)&#xA;</xsl:text>
       
   256 
       
   257                     {
       
   258                     <xsl:sequence select="local:generateBranching($strings[substring(., $currentPos, 1) eq current()], $depth + 1, $currentPos + 1)"/>
       
   259                     }
       
   260 
       
   261                 </xsl:for-each>
       
   262             </xsl:otherwise>
       
   263         </xsl:choose>
       
   264     </xsl:function>
       
   265 
       
   266     <xsl:function name="local:toCamelCase" as="xs:string">
       
   267         <xsl:param name="arg" as="xs:string"/>
       
   268 
       
   269         <xsl:sequence select="string-join((for $word in tokenize($arg,'[:-]+')
       
   270                                            return concat(upper-case(substring($word,1,1)),
       
   271                                                          substring($word, 2))) ,'')"/>
       
   272 
       
   273     </xsl:function>
       
   274 
       
   275     <xsl:function name="local:tokenToEnumName" as="xs:string">
       
   276         <xsl:param name="string" as="xs:string"/>
       
   277 
       
   278         <xsl:variable name="token" select="$tokens[. eq $string]"/>
       
   279 
       
   280         <xsl:choose>
       
   281             <xsl:when test="$token/@name">
       
   282                 <xsl:sequence select="$token/@name"/>
       
   283             </xsl:when>
       
   284             <xsl:otherwise>
       
   285                 <!-- We take the token's string value, and coerces into a C++
       
   286                      name. So get rid of invalid characters. Also do basic camel casing. -->
       
   287                 <xsl:variable name="normalized" select="translate($string, 'ABCDEFGHIJKLMNOPQRSTYXZabcdefghijklmnopqrstyxz1234567890_', 'ABCDEFGHIJKLMNOPQRSTYXZabcdefghijklmnopqrstyxz1234567890_')"/>
       
   288                 <xsl:value-of select="local:toCamelCase($normalized)"/>
       
   289             </xsl:otherwise>
       
   290         </xsl:choose>
       
   291 
       
   292     </xsl:function>
       
   293 
       
   294 </xsl:stylesheet>
       
   295 
       
   296 <!--
       
   297 vim: et:ts=4:sw=4:sts=4
       
   298 -->