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

<xsl:output method="text"/>

<xsl:variable name="lang" select="/language/@name"/>

<!--
 ! This template gens the flex code for a <language/> file.
 +-->
<xsl:template match="language">
%{/* <xsl:value-of select="@name"/>_lexer.l */
/* This file generated by generate_flex_lexer.xsl */

#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdio.h&gt;

#include "<xsl:value-of select="@name"/>_parser.tab.h"
%}

%option 8bit

<!--
 ! Gen any options in the <lexer/>.
 +-->
<xsl:for-each select="/language/lexer/option">
%option <xsl:value-of select="."/>
  </xsl:for-each>

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

<!--
 ! Gen any patterns in the <lexer/>.
 +-->
<xsl:for-each select="/language/lexer/pattern">
  <xsl:value-of select="@name"/>
  <xsl:text>&#x9;</xsl:text>
  <xsl:value-of select="."/>
  <xsl:text>&#xa;</xsl:text>
  </xsl:for-each>

%%

<!-- This provides for line counting. -->
.	++column_number; REJECT;
\n	++line_number; column_number = 1; REJECT;

<!-- Generate the action code for each <match/>, <ignore/>, and <error/> -->
<xsl:for-each select="lexer/match | lexer/ignore | lexer/error">
  <!-- a few lines of space. -->
  <xsl:text>&#xa;&#xa;</xsl:text>

  <!-- print the regex. -->
  <xsl:apply-templates select="."/>

  <xsl:choose>
    <!--
     ! <match/> action code.
     +-->
    <xsl:when test="name() = 'match'"> {
	yylval = xmlNewNode(NULL, "<xsl:value-of select="@term"/>");

#ifdef DEBUG
	fprintf(stderr,
		"TERMINAL %s:{%s}\n",
		"<xsl:value-of select="@term"/>",
		yytext);
#endif

	if (track_token_position) {
		char buf[32];
		snprintf(buf, 32, "%d", line_number);
		xmlSetProp(yylval, "line", buf);
		snprintf(buf, 32, "%d", column_number);
		xmlSetProp(yylval, "column", buf);
	}

	/* yytext does not need to be escaped for XML,
	 * xmlNewText does the right thing. */
	xmlAddChild(yylval, xmlNewText(yytext));

	return <xsl:value-of select="concat($lang, '_sym_', @term)"/>;
}</xsl:when>

    <!--
     ! <ignore/> action code.
     +-->
    <xsl:when test="name() = 'ignore'"> {
	/* ignore */;
}</xsl:when>

    <!--
     ! <error/> action code.
     +-->
    <xsl:when test="name() = 'error'"> {
	yylval = NULL;
	return <xsl:value-of select="$lang"/>_lex_error;
}</xsl:when>

    </xsl:choose>
  </xsl:for-each>

.|\n {
	/* flex thinks of it's lexers as filters.
	 * As a result, all characters which match nothing get
	 * printed to stdout.
	 *
	 * As a general solution, we may implement a catch-all
	 * which either:
	 * a) Ignores these characters, or
	 * b) Throws an error.
	 *
	 * This rule chooses to ignore them. */
}

%%

</xsl:template>

</xsl:transform>

