changeset 1:f082f8c2ebb0

XSLScript: some preliminary grammar, incomplete.
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 19 Feb 2014 22:44:08 +0400
parents c9be645cc395
children bcd96c403898
files xsls.pl
diffstat 1 files changed, 184 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100755
--- /dev/null
+++ b/xsls.pl
@@ -0,0 +1,184 @@
+#!/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] }
+
+#item		: "<!--" <commit> comment
+#		| "!" <commit> shortcut
+#		| "<%" <commit> instruction "%>"
+#		| instruction_name <commit> 
+
+item		: comment | instruction | shortcut
+item_text	: comment | instruction | shortcut | text
+
+# comments, <!-- ... -->
+# not sure if it's something to be interpreted specially
+# likely an artifact of our dump process
+
+comment		: "<!--" <commit> /((?!-->).)*/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	: /[^'"\\{}]/
+
+# shortcuts:
+#
+# !{xpath-expression} for X:value-of select="xpath-expression";
+# !! for X:apply-templates
+# !foo() for X:call-template name="foo"
+
+shortcut	: double_exclam | exclam_xpath | exclam_name
+double_exclam	: "!!" <commit> param(s?) ";"
+exclam_xpath	: "!{" <commit> text(s) "}"
+exclam_name	: "!" <commit> name "(" param(s?) ")"
+name		: /[a-z0-9_:-]+/i
+
+param		: param_name "=" param_value
+param_name	: /[a-z0-9_:-]+/i
+param_value	: "\"" /[^"]*/ "\""
+
+body		: ";"
+		| "{" <commit> item_text(s?) "}"
+
+instructions	: xstylesheet | xtransform
+		| xattributeset | xattribute | xelement
+		| xparam | xapplytemplates 
+		| xforeach | xchoose | xwhen | xotherwise
+		| xvalueof | xapplyimports | xnumber
+		| xoutput | xinclude | ximport | xstripspace | xpreservespace
+		| xcopyof | xcopy | xtext | xsort | xcomment
+		| xprocessinginstruction | xdecimalformat | xnamespacealias
+		| xkey | xfallback | xmessage
+
+instruction	: "<%" instruction_simple "%>"
+		| instruction_simple
+
+instruction_simple : instructions <commit> param(s?) body
+		| xif
+		| xtemplate
+		| xvar
+
+# X:if parameter is test=
+
+xif		: "X:if" param_value(?) param(s?) body "else" <commit> body
+		| "X:if" <commit> param_value(?) param(s?) body
+
+# X:template name(params) = "match" {
+# X:template name( bar="init", baz={markup} ) = "match" mode="some" {
+
+xtemplate	: "X:template" param_name(?) xtemplate_params(?)
+		  xtemplate_match(?) param(s?) body
+xtemplate_params: "(" xtemplate_param ("," xtemplate_param)(s?) ")"
+xtemplate_param	: param_name ("=" param_value)(?)
+xtemplate_match	: "=" param_value
+
+# X:var LINK = "/article/@link";
+# X:var year = { ... }
+
+xvar		: xvar_name <commit> xvar_params
+xvar_params	: param_name "=" param_value ";"
+		| param_name "=" body
+		| <error>
+
+xvar_name	: "X:variable"
+		| "X:var"
+
+# normal instructions
+
+xstylesheet	: "X:stylesheet"
+xtransform	: "X:transform"
+xattributeset	: "X:attribute-set"
+xattribute	: "X:attribute"
+xelement	: "X:element"
+xvariable	: "X:variable"
+xvar		: "X:var"
+xparam		: "X:param"
+xapplytemplates	: "X:apply-templates"
+xforeach	: "X:for-each"
+xchoose		: "X:choose"
+xwhen		: "X:when"
+xotherwise	: "X:otherwise"
+xvalueof	: "X:value-of"
+xapplyimports	: "X:apply-imports"
+xnumber		: "X:number"
+xoutput		: "X:output"
+xinclude	: "X:include"
+ximport		: "X:import"
+xstripspace	: "X:strip-space"
+xpreservespace	: "X:preserve-space"
+xcopyof		: "X:copy-of"
+xcopy		: "X:copy"
+xtext		: "X:text"
+xsort		: "X:sort"
+xcomment	: "X:comment"
+xprocessinginstruction : "X:processing-instruction"
+xdecimalformat	: "X:decimal-format"
+xnamespacealias	: "X:namespace-alias"
+xkey		: "X:key"
+xfallback	: "X:fallback"
+xmessage	: "X:message"
+
+eofile		: /^\Z/
+
+EOF
+
+###############################################################################
+
+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);
+
+###############################################################################
+###############################################################################