changeset 6:d3340fdeadf6

XSLScript: better file names.
author Maxim Dounin <mdounin@mdounin.ru>
date Fri, 21 Feb 2014 18:53:17 +0400
parents 2d6764d9980b
children 9a283d72ddc3
files xsls.pl xsls.txt xslscript.pl xslscript.txt
diffstat 4 files changed, 599 insertions(+), 599 deletions(-) [+]
line wrap: on
line diff
--- a/xsls.pl	Fri Feb 21 17:14:57 2014 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,423 +0,0 @@
-#!/usr/bin/perl
-
-# (C) Maxim Dounin
-
-# Convert from XSLScript to XSLT.
-# 
-# Originally XSLScript was written by Paul Tchistopolskii.  It is believed
-# to be mostly identical to XSLT, but uses shorter syntax.  Original
-# implementation has major Java dependency, no longer supported and hard
-# to find.
-# 
-# This code doesn't pretend to be a full replacement, but rather an attempt
-# to provide functionality needed for nginx documentation.
-
-###############################################################################
-
-use warnings;
-use strict;
-
-use Parse::RecDescent;
-use Getopt::Long;
-use Data::Dumper qw/Dumper/;
-
-###############################################################################
-
-GetOptions(
-	"trace!" => \$::RD_TRACE,
-	"hint!" => \$::RD_HINT,
-)
-	or die "oops\n";
-
-###############################################################################
-
-my $grammar = <<'EOF';
-
-# XSLTScript grammar, reconstructed
-
-startrule	: item(s) eofile
-	{ $return = $item[1]; 1 }
-
-item		: "<!--" <commit> comment
-		| "!!" <commit> exclam_double
-		| "!{" <commit> exclam_xpath
-		| "!" name <commit> params
-	{ $return = [
-		"X:call-template", "name", $item{name}, [],
-		$item{params}
-	]; 1 }
-		| "<%" <commit> instruction "%>"
-	{ $return = $item{instruction}; 1 }
-		| "<" name attrs ">" <commit> item(s?) "</" name ">"
-	{ $return = [ "tag", $item{name}, $item{attrs}, $item[6] ]; 1 }
-		| "<" <commit> name attrs "/" ">"
-	{ $return = [ "tag", $item{name}, $item{attrs} ]; 1 }
-		| "X:variable" <commit> xvariable
-		| "X:var" <commit> xvariable
-		| "X:template" <commit> xtemplate
-		| "X:if" <commit> xif
-		| "X:param" <commit> xparam
-		| "X:for-each" <commit> xforeach
-		| "X:sort" <commit> xsort
-		| "X:when" <commit> xwhen
-		| "X:attribute" <commit> xattribute
-		| "X:output" <commit> xoutput
-		| "X:copy-of" <commit> xcopyof
-		| instruction <commit> attrs body
-	{ $return = [ $item{instruction}, $item{attrs}, $item{body} ]; 1 }
-		| text
-		| <error>
-
-# list of simple instructions
-
-instruction	: "X:stylesheet"
-		| "X:transform"
-		| "X:attribute-set"
-		| "X:element"
-		| "X:apply-templates"
-		| "X:choose"
-		| "X:otherwise"
-		| "X:value-of"
-		| "X:apply-imports"
-		| "X:number"
-		| "X:include"
-		| "X:import"
-		| "X:strip-space"
-		| "X:preserve-space"
-		| "X:copy"
-		| "X:text"
-		| "X:comment"
-		| "X:processing-instruction"
-		| "X:decimal-format"
-		| "X:namespace-alias"
-		| "X:key"
-		| "X:fallback"
-		| "X:message"
-
-# comments, <!-- ... -->
-# not sure if it's something to be interpreted specially
-# likely an artifact of our dump process
-
-comment		: /((?!-->).)*/ms "-->"
-	{ $return = ""; 1 }
-
-# special chars: ', ", {, }, \
-# if used in text, they needs to be escaped with backslash
-
-text		: quoted | unreserved | "'" | "\"" | "{"
-quoted		: "\\" special
-	{ $return = $item{special}; 1; }
-special		: "'" | "\"" | "\\" | "{" | "}"
-unreserved	: /[^'"\\{}<\s]+\s*/
-
-# shortcuts:
-#
-# !! for X:apply-templates
-# !{xpath-expression} for X:value-of select="xpath-expression";
-# !foo() for X:call-template name="foo"
-
-# !root (path = { !{ substring($DIRNAME, 2) } })
-# !root (path = "substring-after($path, '/')")
-
-exclam_double	: value(?) params(?) attrs ";"
-	{ $return = [
-		"X:apply-templates", "select", $item[1][0], $item{attrs},
-		$item[2][0]
-	]; 1 }
-
-exclam_xpath	: xpath "}"
-	{ $return = [
-		"X:value-of", "select", $item{xpath}, []
-	]; 1 }
-xpath		: /("[^"]*"|'[^']*'|[^}'"])*/ms
-
-# instruction attributes
-# name="value"
-
-attrs		: attr(s?)
-attr		: name "=" value
-	{ $return = $item{name} . "=" . $item{value}; }
-name		: /[a-z0-9_:-]+/i
-value		: /"[^"]*"/
-
-# template parameters
-# ( bar="init", baz={markup} )
-
-params		: "(" param(s? /,/) ")" 
-	{ $return = $item[2]; 1 }
-param		: name "=" value
-	{ $return = [
-		"X:with-param",
-		"select", $item{value},
-		"name", $item{name},
-		[]
-	]; 1 }
-		| name "=" <commit> "{" item(s) "}"
-	{ $return = [
-		"X:with-param", "name", $item{name}, [],
-		$item[5]
-	]; 1 }
-		| name
-	{ $return = [
-		"X:param", "name", $item{name}, []
-	]; 1 }
-
-# instruction body
-# ";" for empty body, "{ ... }" otherwise
-
-body		: ";"
-	{ $return = ""; }
-		| "{" <commit> item(s?) "}"
-	{ $return = $item[3]; 1 }
-
-# special handling of some instructions
-# X:if attribute is test=
-
-xif		: value body "else" <commit> body
-	{ $return = [
-		"X:choose", [], [
-			[ "X:when", "test", $item[1], [], $item[2] ],
-			[ "X:otherwise", [], $item[5] ]
-		]
-	]; 1 }
-		| value attrs body
-	{ $return = [
-		"X:if", "test", $item{value}, $item{attrs}, $item{body},
-	]; 1 }
-		| attrs body
-	{ $return = [
-		"X:if", $item{attrs}, $item{body},
-	]; 1 }
-		| <error>
-
-# X:template name(params) = "match" {
-# X:template name( bar="init", baz={markup} ) = "match" mode="some" {
-
-xtemplate	: name(?) params(?) ( "=" value )(?) attrs body
-	{ $return = [
-		"X:template", "name", $item[1][0], "match", $item[3][0],
-		$item{attrs},
-		[ ($item[2][0] ? @{$item[2][0]} : ()), @{$item{body}} ]
-	]; 1 }
-
-# X:var LINK = "/article/@link";
-# X:var year = { ... }
-# semicolon is optional
-
-xvariable	: name "=" value attrs body
-	{ $return = [
-		"X:variable",
-		"select", $item{value},
-		"name", $item{name},
-		$item{attrs}, $item{body}
-	]; 1 }
-		| name "=" attrs body
-	{ $return = [
-		"X:variable",
-		"name", $item{name},
-		$item{attrs}, $item{body}
-	]; 1 }
-		| name "=" value
-	{ $return = [
-		"X:variable",
-		"select", $item{value},
-		"name", $item{name},
-		[]
-	]; 1 }
-		| name "=" 
-	{ $return = [
-		"X:variable",
-		"name", $item{name},
-		[]
-	]; 1 }
-		| <error>
-
-# X:param XML = "'../xml'";
-# X:param YEAR;
-
-xparam		: name "=" value attrs body
-	{ $return = [
-		"X:param",
-		"select", $item{value},
-		"name", $item{name},
-		$item{attrs}, $item{body}
-	]; 1 }
-		| name attrs body
-	{ $return = [
-		"X:param", "name", $item{name},
-		$item{attrs}, $item{body}
-	]; 1 }
-
-# X:for-each "section[@id and @name]" { ... }
-# X:for-each "link", X:sort "@id" {
-
-xforeach	: value attrs body
-	{ $return = [
-		"X:for-each", "select", $item{value}, $item{attrs}, $item{body}
-	]; 1 }
-		| value attrs "," "X:sort" <commit> value attrs body
-	{ $return = [
-		"X:for-each", "select", $item[1], $item[2], [
-			[ "X:sort", "select", $item[6], $item[7] ],
-			@{$item{body}}
-		]
-	]; 1 }
-
-# X:sort select
-# X:sort "@id"
-
-xsort		: value attrs body
-	{ $return = [
-		"X:sort", "select", $item{value}, $item{attrs}, $item{body}
-	]; 1 }
-
-# X:when "position() = 1" { ... }
-
-xwhen		: value attrs body
-	{ $return = [
-		"X:when", "test", $item{value}, $item{attrs}, $item{body}
-	]; 1 }
-
-# X:attribute "href" { ... }
-
-xattribute	: value attrs body
-	{ $return = [
-		"X:attribute", "name", $item{value}, $item{attrs}, $item{body}
-	]; 1 }
-
-# X:output
-# semicolon is optional
-
-xoutput		: attrs body(?)
-	{ $return = [
-		"X:output", undef, undef, $item{attrs}, $item{body}
-	]; 1 }
-
-# "X:copy-of"
-# semicolon is optional
-
-xcopyof		: value attrs body(?)
-	{ $return = [
-		"X:copy-of", "select", $item{value}, $item{attrs}, $item{body}
-	]; 1 }
-
-# eof
-
-eofile		: /^\Z/
-
-EOF
-
-###############################################################################
-
-sub format_tree {
-	my ($tree, $indent) = @_;
-	my $s = '';
-
-	if (!defined $indent) {
-		$indent = 0;
-		$s .= '<?xml version="1.0" encoding="utf-8"?>' . "\n";
-	}
-
-	my $space = "   " x $indent;
-
-	foreach my $el (@{$tree}) {
-		if (!defined $el) {
-			warn "Undefined element in output.\n";
-			$s .= $space . "(undef)" . "\n";
-			next;
-		}
-
-		if (not ref($el) && defined $el) {
-			#$s .= $space . $el . "\n";
-			$s .= $el;
-			next;
-		}
-
-		die if ref($el) ne 'ARRAY';
-
-		my $tag = $el->[0];
-
-		if ($tag eq 'tag') {
-			my (undef, $name, $attrs, $body) = @{$el};
-
-			$s .= $space . "<" . join(" ", $name, @{$attrs});
-			if ($body) {
-				my $t = format_tree($body, $indent + 1);
-				if ($t =~ /\n/) {
-					$s .= ">\n" . $t
-						. $space . "</$name>\n";
-				} else {
-					$s .= ">$t</$name>\n";
-				}
-			} else {
-				$s .= "/>\n";
-			}
-
-			next;
-		}
-
-		if ($tag =~ m/^X:(.*)/) {
-			my $name = "xsl:" . $1;
-			my (undef, @a) = @{$el};
-			my @attrs;
-
-			while (@a) {
-				last if ref($a[0]) eq 'ARRAY';
-				my $name = shift @a;
-				my $value = shift @a;
-				next unless defined $value;
-				$value = '"' . $value . '"'
-					unless $value =~ /^"/;
-				push @attrs, "$name=$value";
-			}
-
-			if ($name eq "xsl:stylesheet") {
-				push @attrs, 'xmlns:xsl="http://www.w3.org/1999/XSL/Transform"';
-				push @attrs, 'version="1.0"';
-			}
-
-			my ($attrs, $body) = @a;
-			$attrs = [ @{$attrs}, @attrs ];
-
-			$s .= $space . "<" . join(" ", $name, @{$attrs});
-			
-			if ($body && scalar @{$body} > 0) {
-				my $t = format_tree($body, $indent + 1);
-				if ($t =~ /\n/) {
-					$s .= ">\n" . $t
-						. $space . "</$name>\n";
-				} else {
-					$s .= ">$t</$name>\n";
-				}
-			} else {
-				$s .= "/>\n";
-			}
-
-			next;
-		}
-
-		$s .= format_tree($el, $indent + 1);
-	}
-
-	return $s;
-}
-
-###############################################################################
-
-my $parser = Parse::RecDescent->new($grammar)
-	or die "Failed to create parser.\n";
-
-my $lines;
-
-{
-	local $/;
-	$lines = <>;
-}
-
-my $tree = $parser->startrule($lines)
-	or die "Failed to parse $ARGV.\n";
-
-#print Dumper($tree);
-print format_tree($tree);
-
-###############################################################################
--- a/xsls.txt	Fri Feb 21 17:14:57 2014 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-JAR can be found here:
-
-http://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/www/hiawatha/README.html
-
-Recovered from:
-
-http://moemesto.ru/link/6865082
-http://moemesto.ru/philonov/page/6865082/download/INODE.RU%20/%20ProgrammaZm%20/%20XSLScript%20-%20%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD%D0%B0%20XSLT
-
-XSLScript - замена XSLT
-[ 2004/07/16 ProgrammaZm ]
-
-Возможно удобная замена XSLT. Файлы XSLScript преобразуются в xslt.
-
-
- // Источник: http://pault.com/pault/XSLScript/
- 
-Since Year 2000
-Version 0.7 
-Check out TerseXML project
-
-XSLScript is for those, who are writing complex XSLT stylesheets.
-
-XSLScript is a terse notation for writing complex XSLT stylesheets. XSLScript is part of  Hiawatha web-server, but XSLScript also can be used stand-alone.
-
-To execute XSLScript script: 
-
-xsls some.xml some.xsls
-The XSLScript script (some.xsls) gets compiled into corresponding XSLT stylesheet and then generated XSLT stylesheet is applied to the file some.xml (no temporary .xsl file is created, this all happens in the memory). The actual XSLT tranformation is performed by SAXON. There is 1-1 lines mapping between XSLScript script and generated XSLT ( this means if some XSLScript construction starts on line 5, the corresponding XSLT construction will also start on the same line 5. )
-
-To generate the XSLT stylesheet out of XSLScript script: 
-
-xslsdump some.xsls
-or
-
-xslsdump-indent some.xsls
-if you want a nice looking indentation.
-
-Why XSLScript ? 
-
-XSLT syntax is not for human beings.
-
-One can write complex XSLT code in XSLScript and then generate the 100% XSLT stylesheet. Like I do. Occasionaly.
-
-Can I use my XSLT stylesheets with XSLScript? 
-
-You can use xsl:import / xsl:include to include .xsl into .xsls and to include .xsls into .xsl.
-
-What if I like writing <xsl:something? 
-
-You can write XSLT instructions in plain XSLT, XSLScript preprocessor will not touch them and will pass those constructions as-is.
-
-Top-level elements should be plain XSLScript.
-
-What is XSLScript ? 
-
-XSLScript is just syntax sugar, 1-1 mapping of XSLT. The only exception is that XSLScript has 'else' (which is missing in XSLT). In XSLScript if-else is translated into appropriate xsl:choose-when-otherwise. XSLScript could get more 'non-xslt' semantics if you ask me for something you need.
-
-OK, but what is XSLScript ? 
-
-Snippet 1
-
-X:stylesheet {
-
-X:template = "poem" {
-	<html>
-	<head>
-		<title> !{title} </title>
-	</head>
-	<body>
-		!! "title";
-		!! "author";
-		X:apply-templates "stanza";
-		X:apply-templates "date";
-	</body>
-	</html>
-}
-
-X:template = "title"  { <div align="center"><h1> !{.} </h1></div> }
-X:template = "author" { <div align="center"><h2> By <% !{.} %> </h2></div> }
-X:template = "stanza" { <p> !! "line"; </p> }
-
-X:template = "line" {
-    X:if "position() mod 2 = 0" {&#160;&#160;} 
-    !{.} <br/>
-}
-
-X:template = "date" { <p><i> !{.} </i></p> }
-
-}
-
-	
-Snippet 2
-
-X:transform {
-
-X:template max( list ) {
-    X:if "$list" {
-	   X:variable first="count($list[1]/LINE)"
-	   X:variable max-of-rest={ !max( list="$list[position()!=1]" ) }
-
-	   X:if "$first &gt; $max-of-rest"  {
-		!{$first}
-	   } else {
-		!{$max-of-rest}
-	   }
-    } else {
-	   0
-    } 
-}
- 
- X:template ="/" {
-  Longest speech is <% X:text; !max( list="//SPEECH" ) X:text; %> lines.   
- } 
-
-}
-	
-Syntax overview
-
-Rather than drawing the mapping for all of 35 XSLT elements, I'l just provide the mapping rules. If this is not enough, please note that XSLScript distribution contains more than 10 examples of XSLScript code. Those examples are XSLT stylesheets from Michael Kay's XSLT Programming Reference (available for download from Wrox website) rewritten in XSLScript. This results in XSLScript examples being educational and covering almost every XSLT (XSLScript) command.
-
-Rules 
-
-There are top-level XSLScript constructions and instructions. (exactly like it is in XSLT). Instructions could be separated from the content with <% and %> ( optional ).
-Instruction has body and header. Body is separated from header with { }
-'match', 'select', 'test' and 'name' are not written (but also could be written in some exotic cases.)
-Symbols ', ", {, are special. Use \{ e t.c. if you need those special symbols in tne content of your stylesheet.
-xsl:apply-templates, !! and xsl:number should end with ";"
-Syntax of apply-templates is extremely close to the syntax of call-template.
-There are few shortcuts:
-You can use !{xpath-expression} for 
-X:value-of select="xpath-expression";
-!! for X:apply-templates
-!foo() for X:call-template name="foo"
-X:var for X:variable
-There is 'comma' shortcut. It exists for X:stylesheet (see date.xsls for example of XSLT-engine independent java binding). And also it exists for X:for-each and X:apply-templates.
-X:for-each "//*" , X:sort { 
-You can not write X:sort as an element, but you should use 'comma' shortcut.
-The shortcut for template allows : 
-X:template foo( bar="init", baz={markup} ) = "match" mode="some" {
-Download
-
-Because SAXON (http://users.iclway.co.uk/mhkay/saxon/) is 100% free, XSLScript distribution contains everything you need to run XSLScript.
-
-xsls.jar includes not only .class files, but also the source code of XSLScript
-
-XSLScript is 100% free.
-
-Contact
-
-Paul Tchistopolskii.  
-http://www.pault.com  
-paul@pault.com  
-
-Changes in version 0.7
-
-(major rewrite)
-
-<% %> are optional.
-Some verbose forms are dropped ( no X:with-param and call-template ever, e t.c. )
-Parser is less forgiving and some things become not intuitive.
-\{ \' " required.
-Nice dumping of generated stylesheet.
-1-1 line mapping.
-Based on SAXON / SAX2, but still should work with XT.
-Changes in version 0.51
-
-(small bugfixes)
-
-':' was not allowed in #NAME token. ( Allows xmlns:some= )
-Multiple <!-- comments bugfixed.
-\{ bugfixed and \' allowed. This is actually not obvious, I should explain how to use \{ and \' ... some day ...
-Few examples from XSL-list are included.
- 
-
-// Источник: http://pault.com/pault/XSLScript/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xslscript.pl	Fri Feb 21 18:53:17 2014 +0400
@@ -0,0 +1,423 @@
+#!/usr/bin/perl
+
+# (C) Maxim Dounin
+
+# Convert from XSLScript to XSLT.
+# 
+# Originally XSLScript was written by Paul Tchistopolskii.  It is believed
+# to be mostly identical to XSLT, but uses shorter syntax.  Original
+# implementation has major Java dependency, no longer supported and hard
+# to find.
+# 
+# This code doesn't pretend to be a full replacement, but rather an attempt
+# to provide functionality needed for nginx documentation.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Parse::RecDescent;
+use Getopt::Long;
+use Data::Dumper qw/Dumper/;
+
+###############################################################################
+
+GetOptions(
+	"trace!" => \$::RD_TRACE,
+	"hint!" => \$::RD_HINT,
+)
+	or die "oops\n";
+
+###############################################################################
+
+my $grammar = <<'EOF';
+
+# XSLTScript grammar, reconstructed
+
+startrule	: item(s) eofile
+	{ $return = $item[1]; 1 }
+
+item		: "<!--" <commit> comment
+		| "!!" <commit> exclam_double
+		| "!{" <commit> exclam_xpath
+		| "!" name <commit> params
+	{ $return = [
+		"X:call-template", "name", $item{name}, [],
+		$item{params}
+	]; 1 }
+		| "<%" <commit> instruction "%>"
+	{ $return = $item{instruction}; 1 }
+		| "<" name attrs ">" <commit> item(s?) "</" name ">"
+	{ $return = [ "tag", $item{name}, $item{attrs}, $item[6] ]; 1 }
+		| "<" <commit> name attrs "/" ">"
+	{ $return = [ "tag", $item{name}, $item{attrs} ]; 1 }
+		| "X:variable" <commit> xvariable
+		| "X:var" <commit> xvariable
+		| "X:template" <commit> xtemplate
+		| "X:if" <commit> xif
+		| "X:param" <commit> xparam
+		| "X:for-each" <commit> xforeach
+		| "X:sort" <commit> xsort
+		| "X:when" <commit> xwhen
+		| "X:attribute" <commit> xattribute
+		| "X:output" <commit> xoutput
+		| "X:copy-of" <commit> xcopyof
+		| instruction <commit> attrs body
+	{ $return = [ $item{instruction}, $item{attrs}, $item{body} ]; 1 }
+		| text
+		| <error>
+
+# list of simple instructions
+
+instruction	: "X:stylesheet"
+		| "X:transform"
+		| "X:attribute-set"
+		| "X:element"
+		| "X:apply-templates"
+		| "X:choose"
+		| "X:otherwise"
+		| "X:value-of"
+		| "X:apply-imports"
+		| "X:number"
+		| "X:include"
+		| "X:import"
+		| "X:strip-space"
+		| "X:preserve-space"
+		| "X:copy"
+		| "X:text"
+		| "X:comment"
+		| "X:processing-instruction"
+		| "X:decimal-format"
+		| "X:namespace-alias"
+		| "X:key"
+		| "X:fallback"
+		| "X:message"
+
+# comments, <!-- ... -->
+# not sure if it's something to be interpreted specially
+# likely an artifact of our dump process
+
+comment		: /((?!-->).)*/ms "-->"
+	{ $return = ""; 1 }
+
+# special chars: ', ", {, }, \
+# if used in text, they needs to be escaped with backslash
+
+text		: quoted | unreserved | "'" | "\"" | "{"
+quoted		: "\\" special
+	{ $return = $item{special}; 1; }
+special		: "'" | "\"" | "\\" | "{" | "}"
+unreserved	: /[^'"\\{}<\s]+\s*/
+
+# shortcuts:
+#
+# !! for X:apply-templates
+# !{xpath-expression} for X:value-of select="xpath-expression";
+# !foo() for X:call-template name="foo"
+
+# !root (path = { !{ substring($DIRNAME, 2) } })
+# !root (path = "substring-after($path, '/')")
+
+exclam_double	: value(?) params(?) attrs ";"
+	{ $return = [
+		"X:apply-templates", "select", $item[1][0], $item{attrs},
+		$item[2][0]
+	]; 1 }
+
+exclam_xpath	: xpath "}"
+	{ $return = [
+		"X:value-of", "select", $item{xpath}, []
+	]; 1 }
+xpath		: /("[^"]*"|'[^']*'|[^}'"])*/ms
+
+# instruction attributes
+# name="value"
+
+attrs		: attr(s?)
+attr		: name "=" value
+	{ $return = $item{name} . "=" . $item{value}; }
+name		: /[a-z0-9_:-]+/i
+value		: /"[^"]*"/
+
+# template parameters
+# ( bar="init", baz={markup} )
+
+params		: "(" param(s? /,/) ")" 
+	{ $return = $item[2]; 1 }
+param		: name "=" value
+	{ $return = [
+		"X:with-param",
+		"select", $item{value},
+		"name", $item{name},
+		[]
+	]; 1 }
+		| name "=" <commit> "{" item(s) "}"
+	{ $return = [
+		"X:with-param", "name", $item{name}, [],
+		$item[5]
+	]; 1 }
+		| name
+	{ $return = [
+		"X:param", "name", $item{name}, []
+	]; 1 }
+
+# instruction body
+# ";" for empty body, "{ ... }" otherwise
+
+body		: ";"
+	{ $return = ""; }
+		| "{" <commit> item(s?) "}"
+	{ $return = $item[3]; 1 }
+
+# special handling of some instructions
+# X:if attribute is test=
+
+xif		: value body "else" <commit> body
+	{ $return = [
+		"X:choose", [], [
+			[ "X:when", "test", $item[1], [], $item[2] ],
+			[ "X:otherwise", [], $item[5] ]
+		]
+	]; 1 }
+		| value attrs body
+	{ $return = [
+		"X:if", "test", $item{value}, $item{attrs}, $item{body},
+	]; 1 }
+		| attrs body
+	{ $return = [
+		"X:if", $item{attrs}, $item{body},
+	]; 1 }
+		| <error>
+
+# X:template name(params) = "match" {
+# X:template name( bar="init", baz={markup} ) = "match" mode="some" {
+
+xtemplate	: name(?) params(?) ( "=" value )(?) attrs body
+	{ $return = [
+		"X:template", "name", $item[1][0], "match", $item[3][0],
+		$item{attrs},
+		[ ($item[2][0] ? @{$item[2][0]} : ()), @{$item{body}} ]
+	]; 1 }
+
+# X:var LINK = "/article/@link";
+# X:var year = { ... }
+# semicolon is optional
+
+xvariable	: name "=" value attrs body
+	{ $return = [
+		"X:variable",
+		"select", $item{value},
+		"name", $item{name},
+		$item{attrs}, $item{body}
+	]; 1 }
+		| name "=" attrs body
+	{ $return = [
+		"X:variable",
+		"name", $item{name},
+		$item{attrs}, $item{body}
+	]; 1 }
+		| name "=" value
+	{ $return = [
+		"X:variable",
+		"select", $item{value},
+		"name", $item{name},
+		[]
+	]; 1 }
+		| name "=" 
+	{ $return = [
+		"X:variable",
+		"name", $item{name},
+		[]
+	]; 1 }
+		| <error>
+
+# X:param XML = "'../xml'";
+# X:param YEAR;
+
+xparam		: name "=" value attrs body
+	{ $return = [
+		"X:param",
+		"select", $item{value},
+		"name", $item{name},
+		$item{attrs}, $item{body}
+	]; 1 }
+		| name attrs body
+	{ $return = [
+		"X:param", "name", $item{name},
+		$item{attrs}, $item{body}
+	]; 1 }
+
+# X:for-each "section[@id and @name]" { ... }
+# X:for-each "link", X:sort "@id" {
+
+xforeach	: value attrs body
+	{ $return = [
+		"X:for-each", "select", $item{value}, $item{attrs}, $item{body}
+	]; 1 }
+		| value attrs "," "X:sort" <commit> value attrs body
+	{ $return = [
+		"X:for-each", "select", $item[1], $item[2], [
+			[ "X:sort", "select", $item[6], $item[7] ],
+			@{$item{body}}
+		]
+	]; 1 }
+
+# X:sort select
+# X:sort "@id"
+
+xsort		: value attrs body
+	{ $return = [
+		"X:sort", "select", $item{value}, $item{attrs}, $item{body}
+	]; 1 }
+
+# X:when "position() = 1" { ... }
+
+xwhen		: value attrs body
+	{ $return = [
+		"X:when", "test", $item{value}, $item{attrs}, $item{body}
+	]; 1 }
+
+# X:attribute "href" { ... }
+
+xattribute	: value attrs body
+	{ $return = [
+		"X:attribute", "name", $item{value}, $item{attrs}, $item{body}
+	]; 1 }
+
+# X:output
+# semicolon is optional
+
+xoutput		: attrs body(?)
+	{ $return = [
+		"X:output", undef, undef, $item{attrs}, $item{body}
+	]; 1 }
+
+# "X:copy-of"
+# semicolon is optional
+
+xcopyof		: value attrs body(?)
+	{ $return = [
+		"X:copy-of", "select", $item{value}, $item{attrs}, $item{body}
+	]; 1 }
+
+# eof
+
+eofile		: /^\Z/
+
+EOF
+
+###############################################################################
+
+sub format_tree {
+	my ($tree, $indent) = @_;
+	my $s = '';
+
+	if (!defined $indent) {
+		$indent = 0;
+		$s .= '<?xml version="1.0" encoding="utf-8"?>' . "\n";
+	}
+
+	my $space = "   " x $indent;
+
+	foreach my $el (@{$tree}) {
+		if (!defined $el) {
+			warn "Undefined element in output.\n";
+			$s .= $space . "(undef)" . "\n";
+			next;
+		}
+
+		if (not ref($el) && defined $el) {
+			#$s .= $space . $el . "\n";
+			$s .= $el;
+			next;
+		}
+
+		die if ref($el) ne 'ARRAY';
+
+		my $tag = $el->[0];
+
+		if ($tag eq 'tag') {
+			my (undef, $name, $attrs, $body) = @{$el};
+
+			$s .= $space . "<" . join(" ", $name, @{$attrs});
+			if ($body) {
+				my $t = format_tree($body, $indent + 1);
+				if ($t =~ /\n/) {
+					$s .= ">\n" . $t
+						. $space . "</$name>\n";
+				} else {
+					$s .= ">$t</$name>\n";
+				}
+			} else {
+				$s .= "/>\n";
+			}
+
+			next;
+		}
+
+		if ($tag =~ m/^X:(.*)/) {
+			my $name = "xsl:" . $1;
+			my (undef, @a) = @{$el};
+			my @attrs;
+
+			while (@a) {
+				last if ref($a[0]) eq 'ARRAY';
+				my $name = shift @a;
+				my $value = shift @a;
+				next unless defined $value;
+				$value = '"' . $value . '"'
+					unless $value =~ /^"/;
+				push @attrs, "$name=$value";
+			}
+
+			if ($name eq "xsl:stylesheet") {
+				push @attrs, 'xmlns:xsl="http://www.w3.org/1999/XSL/Transform"';
+				push @attrs, 'version="1.0"';
+			}
+
+			my ($attrs, $body) = @a;
+			$attrs = [ @{$attrs}, @attrs ];
+
+			$s .= $space . "<" . join(" ", $name, @{$attrs});
+			
+			if ($body && scalar @{$body} > 0) {
+				my $t = format_tree($body, $indent + 1);
+				if ($t =~ /\n/) {
+					$s .= ">\n" . $t
+						. $space . "</$name>\n";
+				} else {
+					$s .= ">$t</$name>\n";
+				}
+			} else {
+				$s .= "/>\n";
+			}
+
+			next;
+		}
+
+		$s .= format_tree($el, $indent + 1);
+	}
+
+	return $s;
+}
+
+###############################################################################
+
+my $parser = Parse::RecDescent->new($grammar)
+	or die "Failed to create parser.\n";
+
+my $lines;
+
+{
+	local $/;
+	$lines = <>;
+}
+
+my $tree = $parser->startrule($lines)
+	or die "Failed to parse $ARGV.\n";
+
+#print Dumper($tree);
+print format_tree($tree);
+
+###############################################################################
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xslscript.txt	Fri Feb 21 18:53:17 2014 +0400
@@ -0,0 +1,176 @@
+JAR can be found here:
+
+http://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/www/hiawatha/README.html
+
+Recovered from:
+
+http://moemesto.ru/link/6865082
+http://moemesto.ru/philonov/page/6865082/download/INODE.RU%20/%20ProgrammaZm%20/%20XSLScript%20-%20%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD%D0%B0%20XSLT
+
+XSLScript - замена XSLT
+[ 2004/07/16 ProgrammaZm ]
+
+Возможно удобная замена XSLT. Файлы XSLScript преобразуются в xslt.
+
+
+ // Источник: http://pault.com/pault/XSLScript/
+ 
+Since Year 2000
+Version 0.7 
+Check out TerseXML project
+
+XSLScript is for those, who are writing complex XSLT stylesheets.
+
+XSLScript is a terse notation for writing complex XSLT stylesheets. XSLScript is part of  Hiawatha web-server, but XSLScript also can be used stand-alone.
+
+To execute XSLScript script: 
+
+xsls some.xml some.xsls
+The XSLScript script (some.xsls) gets compiled into corresponding XSLT stylesheet and then generated XSLT stylesheet is applied to the file some.xml (no temporary .xsl file is created, this all happens in the memory). The actual XSLT tranformation is performed by SAXON. There is 1-1 lines mapping between XSLScript script and generated XSLT ( this means if some XSLScript construction starts on line 5, the corresponding XSLT construction will also start on the same line 5. )
+
+To generate the XSLT stylesheet out of XSLScript script: 
+
+xslsdump some.xsls
+or
+
+xslsdump-indent some.xsls
+if you want a nice looking indentation.
+
+Why XSLScript ? 
+
+XSLT syntax is not for human beings.
+
+One can write complex XSLT code in XSLScript and then generate the 100% XSLT stylesheet. Like I do. Occasionaly.
+
+Can I use my XSLT stylesheets with XSLScript? 
+
+You can use xsl:import / xsl:include to include .xsl into .xsls and to include .xsls into .xsl.
+
+What if I like writing <xsl:something? 
+
+You can write XSLT instructions in plain XSLT, XSLScript preprocessor will not touch them and will pass those constructions as-is.
+
+Top-level elements should be plain XSLScript.
+
+What is XSLScript ? 
+
+XSLScript is just syntax sugar, 1-1 mapping of XSLT. The only exception is that XSLScript has 'else' (which is missing in XSLT). In XSLScript if-else is translated into appropriate xsl:choose-when-otherwise. XSLScript could get more 'non-xslt' semantics if you ask me for something you need.
+
+OK, but what is XSLScript ? 
+
+Snippet 1
+
+X:stylesheet {
+
+X:template = "poem" {
+	<html>
+	<head>
+		<title> !{title} </title>
+	</head>
+	<body>
+		!! "title";
+		!! "author";
+		X:apply-templates "stanza";
+		X:apply-templates "date";
+	</body>
+	</html>
+}
+
+X:template = "title"  { <div align="center"><h1> !{.} </h1></div> }
+X:template = "author" { <div align="center"><h2> By <% !{.} %> </h2></div> }
+X:template = "stanza" { <p> !! "line"; </p> }
+
+X:template = "line" {
+    X:if "position() mod 2 = 0" {&#160;&#160;} 
+    !{.} <br/>
+}
+
+X:template = "date" { <p><i> !{.} </i></p> }
+
+}
+
+	
+Snippet 2
+
+X:transform {
+
+X:template max( list ) {
+    X:if "$list" {
+	   X:variable first="count($list[1]/LINE)"
+	   X:variable max-of-rest={ !max( list="$list[position()!=1]" ) }
+
+	   X:if "$first &gt; $max-of-rest"  {
+		!{$first}
+	   } else {
+		!{$max-of-rest}
+	   }
+    } else {
+	   0
+    } 
+}
+ 
+ X:template ="/" {
+  Longest speech is <% X:text; !max( list="//SPEECH" ) X:text; %> lines.   
+ } 
+
+}
+	
+Syntax overview
+
+Rather than drawing the mapping for all of 35 XSLT elements, I'l just provide the mapping rules. If this is not enough, please note that XSLScript distribution contains more than 10 examples of XSLScript code. Those examples are XSLT stylesheets from Michael Kay's XSLT Programming Reference (available for download from Wrox website) rewritten in XSLScript. This results in XSLScript examples being educational and covering almost every XSLT (XSLScript) command.
+
+Rules 
+
+There are top-level XSLScript constructions and instructions. (exactly like it is in XSLT). Instructions could be separated from the content with <% and %> ( optional ).
+Instruction has body and header. Body is separated from header with { }
+'match', 'select', 'test' and 'name' are not written (but also could be written in some exotic cases.)
+Symbols ', ", {, are special. Use \{ e t.c. if you need those special symbols in tne content of your stylesheet.
+xsl:apply-templates, !! and xsl:number should end with ";"
+Syntax of apply-templates is extremely close to the syntax of call-template.
+There are few shortcuts:
+You can use !{xpath-expression} for 
+X:value-of select="xpath-expression";
+!! for X:apply-templates
+!foo() for X:call-template name="foo"
+X:var for X:variable
+There is 'comma' shortcut. It exists for X:stylesheet (see date.xsls for example of XSLT-engine independent java binding). And also it exists for X:for-each and X:apply-templates.
+X:for-each "//*" , X:sort { 
+You can not write X:sort as an element, but you should use 'comma' shortcut.
+The shortcut for template allows : 
+X:template foo( bar="init", baz={markup} ) = "match" mode="some" {
+Download
+
+Because SAXON (http://users.iclway.co.uk/mhkay/saxon/) is 100% free, XSLScript distribution contains everything you need to run XSLScript.
+
+xsls.jar includes not only .class files, but also the source code of XSLScript
+
+XSLScript is 100% free.
+
+Contact
+
+Paul Tchistopolskii.  
+http://www.pault.com  
+paul@pault.com  
+
+Changes in version 0.7
+
+(major rewrite)
+
+<% %> are optional.
+Some verbose forms are dropped ( no X:with-param and call-template ever, e t.c. )
+Parser is less forgiving and some things become not intuitive.
+\{ \' " required.
+Nice dumping of generated stylesheet.
+1-1 line mapping.
+Based on SAXON / SAX2, but still should work with XT.
+Changes in version 0.51
+
+(small bugfixes)
+
+':' was not allowed in #NAME token. ( Allows xmlns:some= )
+Multiple <!-- comments bugfixed.
+\{ bugfixed and \' allowed. This is actually not obvious, I should explain how to use \{ and \' ... some day ...
+Few examples from XSL-list are included.
+ 
+
+// Источник: http://pault.com/pault/XSLScript/