initial commit
authorVolker Birk <vb@pep-project.org>
Mon, 11 Jul 2016 23:15:28 +0200
changeset 0 76005e62091d
child 1 23daf9d318ac
initial commit
.hgignore
Makefile
backend.py
features.en.yhtml2
format.css
gpl-2.0.txt
heading.en.yhtml2
hello.en.yhtml2
homepage.en.yhtml2
index.en.yhtml2
manpage.yml2
programming.en.yhtml2
pyPEG.py
samples/Customer.java
samples/address.yml2
samples/addresslistenhtml.ysl2
samples/adressliste.yml2
samples/backend.ysl2
samples/blub.svg
samples/blub.yml2
samples/browse.ysl2
samples/bumens.yml2
samples/clike.yml2
samples/ctest.yml2
samples/customer.java.target
samples/customer.xml
samples/customer.xsl
samples/customer.ysl2
samples/ddl.ysl2
samples/debug_test.ysl2
samples/delta.yml2
samples/demo.xmi
samples/dingens.idl
samples/dingens.sql
samples/dingens.xml
samples/dingens.yml2
samples/dml.ysl2
samples/double.yml2
samples/double.ysl2
samples/empty.xml
samples/empty.ysl2
samples/errortest.ysl2
samples/f.yml2
samples/f.ysl2
samples/function.xml
samples/function.yml2
samples/gen_addr_html.ysl2
samples/gen_again_java.ysl2
samples/gen_java.ysl2
samples/hello.xsl
samples/hello.yml2
samples/hello.ysl2
samples/i.yml2
samples/idl.yml2
samples/indention.ysl2
samples/list.yml2
samples/macros_test.yml2
samples/model.ymi
samples/namespace.ysl2
samples/opertest.ysl2
samples/rechner.ysl2
samples/sample.yml2
samples/simple.ysl2
samples/table.yml2
samples/table2ddl.ysl2
samples/text_test.yml2
samples/textest.xml
samples/types.xml
samples/types.yml2
samples/uml.yml2
samples/uml2idl.yml2
samples/uml2sql.yml2
samples/union.ysl2
samples/vorlesung.xmi
samples/webseite.ysl2
samples/xmi2ddl.uml2
samples/xmi2ddl.ysl2
samples/xmi2idl.uml2
samples/xml2.yml2
samples/ydl2idl.ysl2
standardlib.ysl2
toolchain.en.yhtml2
vim/syntax/yml2.vim
xml2yml.ysl2
yml2.py
yml2c
yml2proc
yslt.en.yhtml2
yslt.yml2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,2 @@
+syntax: glob
+*.pyc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,20 @@
+YML_PATH=
+YML2C=yml2c
+
+all: homepage
+
+homepage: index.html features.html yslt.html toolchain.html programming.html hello.html
+
+update: homepage format.css gpl-2.0.txt
+	rsync -avC *.html *.yml2 format.css *.yhtml2 gpl-2.0.txt samples dragon:fdik.org/yml2/
+
+update-all: update yml2c yml2.py pyPEG.py backend.py yml2proc
+	if test -z $(VERSION) ; then echo VERSION not set ; exit 1 ; fi
+	rsync -avC *.py yml2c Makefile yml2proc xml2yml.ysl2 standardlib.ysl2 samples dragon:fdik.org/yml2/
+	ssh dragon bash -c "cd ; cd fdik.org/; tar cvjf yml-$(VERSION).tar.bz2 yml2/{*.py,*.yml2,*.yhtml2,format.css,gpl-2.0.txt,yml2c,Makefile,yml2proc,xml2yml.ysl2,standardlib.ysl2,samples} ; rm yml2.tar.bz2 ; ln -s yml-$(VERSION).tar.bz2 yml2.tar.bz2"
+
+%.html: %.en.yhtml2 heading.en.yhtml2 homepage.en.yhtml2
+	$(YML2C) $< -o $@
+
+clean:
+	rm -f *.html *.pyc *.pyo
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backend.py	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,815 @@
+# 2.5.0 backend
+
+# written by VB.
+
+import re, codecs
+import fileinput
+import sys, traceback, exceptions, os
+from xml.sax.saxutils import escape, quoteattr
+from copy import deepcopy
+from glob import glob
+from pyPEG import code, parse, parseLine, u, Symbol
+from yml2 import ymlCStyle, comment, _inner
+
+ymlFunc, pointers, pythonFunc = {}, {}, {}
+in_ns = u""
+operator = []
+included = u""
+includePath = []
+emitlinenumbers = False
+encoding = "utf-8"
+
+first = True
+enable_tracing = False
+
+ymlFunc["decl"] = "#error"
+ymlFunc["define"] = "#error"
+ymlFunc["operator"] = "#error"
+
+def clearAll():
+    global ymlFunc, pointers, pythonFunc, in_ns, operator, included
+    ymlFunc, pointers, pythonFunc = {}, {}, {}
+    in_ns = u""
+    operator = []
+    included = u""
+
+lq = re.compile(r"\|(\>*)(.*)")
+sq = re.compile(r"(\d*)\>(.*)")
+ts = re.compile(r'(\|\|(?P<inds>\>*)\s*\n(?P<text1>.*?)\n(?P<base>\s*)\|\|)|("""(?P<text2>.*?)""")|(\>\>(?P<text3>.*?)\>\>)', re.S)
+tq = re.compile(r"(\]|\<)\s*(.*)")
+bq = re.compile(r"\`(.*?)\`", re.S)
+bqq = re.compile(r"\s*\`\`(.*)")
+all = re.compile(r".*", re.S)
+
+line = 1
+
+def pointer(name):
+    try:
+        return u(pointers[name[1:]])
+    except:
+        if name == "*_trace_info":
+            return u'""'
+        if included:
+            raise LookupError(u"in " + included + u":" + u(line) + u": pointer " + name)
+        else:
+            raise LookupError(u"in " + u(line) + u": pointer " + name)
+
+def evalPython(expr):
+    try:
+        result = eval(u(expr), pythonFunc)
+        if type(result) is str:
+            return codecs.decode(result, encoding)
+        else:
+            return result
+    except:
+        name, parm, tb = sys.exc_info()
+        msg = u"in python expression: " + u(parm)
+        if name is exceptions.SyntaxError:
+            tbl = traceback.format_exception(name, parm, tb)
+            msg += u"\n" + tbl[-3] + tbl[-2]
+        else:
+            msg += u": " + expr + u"\n"
+        if included:
+            raise name(u"in " + included + u":" + u(line) + u": " + msg)
+        else:
+            raise name(u"in " + u(line) + u": " + msg)
+    
+def execPython(script):
+    try:
+        if type(script) is unicode:
+            exec script in pythonFunc
+        else:
+            exec codecs.decode(script, encoding) in pythonFunc
+    except:
+        name, parm, tb = sys.exc_info()
+        msg = u"in python script: " + u(parm)
+        if name is exceptions.SyntaxError:
+            tbl = traceback.format_exception(name, parm, tb)
+            msg += u"\n" + tbl[-3] + tbl[-2]
+        else:
+            msg += u": " + expr + u"\n"
+        if included:
+            raise name(u"in " + included + u":" + u(line) + u": " + msg)
+        else:
+            raise name(u"in " + u(line) + u": " + msg)
+
+def textOut(text):
+    if not text:
+        return u""
+    if type(text) is not unicode:
+        text = codecs.decode(text, encoding)
+    text = text.replace(r'\"', r'\\"')
+    text = u'u"""' + text.replace('"', r'\"') + u'"""'
+    try:
+        textFunc = ymlFunc["text"]
+        parms = ['text', ('parm', [text])]
+        c, result = textFunc(parms)
+        if c:
+            if type(textFunc.alias) is unicode:
+                result += u"</" + textFunc.alias + u">"
+            else:
+                result += u"</" + codecs.decode(textFunc.alias, encoding) + u">"
+        return result
+    except:
+        return escape(eval(text))
+
+def strRepl(text):
+    if not text:
+        return u""
+    if type(text) is not unicode:
+        text = codecs.decode(text, encoding)
+    text = text.replace(r'\"', r'\\"')
+    text = u'u"""' + text.replace('"', r'\"') + u'"""'
+    if type(text) is unicode:
+        return escape(eval(text))
+
+def applyMacros(macros, text):
+    result = text
+    for key, value in macros.iteritems():
+        result = result.replace(key, value)
+    return result
+
+class YF:
+    def __init__(self, name):
+        self.name = name
+        self.parms = []
+        self.descends = []
+        self.values = {}
+        self.content = None
+        self.pointers = {}
+        self.macros = {}
+        if in_ns:
+            self.alias = in_ns + u":" + name.replace("_", "-")
+        else:
+            self.alias = name.replace("_", "-")
+        pythonFunc["yml_" + name] = self
+        if emitlinenumbers:
+            self.values["yml:declared"] = u(line)
+
+    def copy(self, newName):
+        yf = YF(newName)
+        yf.parms.extend(self.parms)
+        yf.descends.extend(self.descends)
+        yf.values = self.values.copy()
+        yf.content = self.content
+        yf.pointers = self.pointers.copy()
+        yf.macros = self.macros.copy()
+        yf.alias = self.alias
+        return yf
+
+    def patch(self, second):
+        self.parms.extend(second.parms)
+        self.descends.extend(second.descends)
+        self.values.update(second.values)
+        if second.content:
+            self.content = second.content
+        self.pointers.update(second.pointers)
+        self.macros.update(second.macros)
+
+    def __call__(self, called_with, hasContent = False, avoidTag = False):
+        global pointers
+        parms = []
+        vals = {}
+        if self.pointers:
+            pointers.update(self.pointers)
+   
+        for data in called_with:
+            if type(data) is tuple or type(data) is Symbol:
+                if data[0] == "parm":
+                    l = data[1]
+                    parm = l[0]
+                    if parm[0] == "*":
+                        parm = pointer(parm)
+                    if len(l) == 1:
+                        if type(parm) is tuple or type(parm) is Symbol:
+                            if parm[0] == "pyExp":
+                                val = evalPython(parm[1][0])
+                                parms.append(val)
+                        else:
+                            parms.append(evalPython((parm)))
+                    else:
+                        if type(parm) is tuple or type(parm) is Symbol:
+                            if parm[0] == "pyExp":
+                                parm = evalPython(parm[1][0])
+                        val = l[1]
+                        if type(val) is tuple or type(val) is Symbol:
+                            if val[0] == "pyExp":
+                                val = evalPython(val[1][0])
+                        if val[0] == "*":
+                            val = pointer(val)
+                        if u(val)[0] == '"' or u(val)[0] == "'":
+                            vals[parm] = evalPython(u(val))
+                        else:
+                            vals[parm] = u(val)
+                elif data[0] == "content":
+                    hasContent = True
+
+        if enable_tracing:
+            text = u(parms) + u", " + u(vals)
+            pointers["_trace_info"] = u'"' + u(line) + u": " + u(self.name) + u" " + text.replace(u'"', u'#') + u'"'
+
+        if emitlinenumbers:
+            global first
+            if first:
+                vals["xmlns:yml"] = u"http://fdik.org/yml"
+                first = False
+            vals["yml:called"] = u(line)
+        return self.xml(parms, vals, hasContent, avoidTag)
+
+    def addParm(self, parm):
+        if parm[0] == "%":
+            for i in range(len(self.parms)):
+                if self.parms[i][0] != "%":
+                    self.parms.insert(i, parm)
+                    return
+        self.parms.append(parm)
+
+    def addDescend(self, desc):
+        if desc[0] == "+" or desc[0] == "@":
+            self.descends.append(desc[1:])
+        else:
+            self.descends.append(desc)
+
+    def addValue(self, parm, value):
+        if type(value) is str or type(value) is unicode:
+            self.values[parm] = u(evalPython(value))
+        else:
+            self.values[parm] = u(evalPython(u(value)))
+
+    def xml(self, callParms, callValues, hasContent, avoidTag = False):
+        global pointers
+        extraContent = u""
+        if self.content:
+            hasContent = True
+        resultParms = self.values.copy()
+        macros = self.macros.copy()
+        toDelete = resultParms.keys()
+        for key in toDelete:
+            if key[0] == "*":
+                del resultParms[key]
+        for key, value in callValues.iteritems():
+            if key[0] == "%":
+                macros[key] = value
+            else:
+                resultParms[key] = value
+        i = 0
+        for cp in callParms:
+            if i < len(self.parms):
+                if self.parms[i][0] == "*":
+                    cp = u(cp)
+                    if "'" in cp:
+                        pointers[self.parms[i][1:]] = u'"' + cp + u'"'
+                    else:
+                        pointers[self.parms[i][1:]] = u"'" + cp + u"'"
+                elif self.parms[i][0] == "%":
+                    macros[self.parms[i]] = u(cp)
+                else:
+                    resultParms[self.parms[i]] = cp
+            else:
+                extraContent += u(cp)
+                hasContent = True
+            i += 1
+        result = u""
+        for p, v in resultParms.iteritems():
+            if p[0] == "'" or p[0] == '"':
+                p = eval(p)
+            result += u" "+ p + u"=" + quoteattr(applyMacros(macros, u(v)))
+        if hasContent:
+            if avoidTag:
+                return True, strRepl(extraContent)
+            else:
+                return True, u"<" + self.alias + result + u">" + strRepl(extraContent)
+        else:
+            if avoidTag:
+                return False, u""
+            else:
+                return False, u"<" + self.alias + result + u"/>"
+
+def replaceContent(tree, subtree):
+    n = 0
+    while n < len(tree):
+        obj = tree[n]
+        if obj[0] == "func":
+            l = obj[1]
+            if l[0] == "content":
+                d = 1
+                if subtree:
+                    for el in subtree:
+                        tree.insert(n+d, el)
+                        d += 1
+                del tree[n]
+                n += d
+            else:
+                try:
+                    if l[-1][0] == "content":
+                        replaceContent(l[-1][1], subtree)
+                except: pass
+        elif obj[0] == "funclist":
+            replaceContent(obj[1], subtree)
+        n += 1
+    return tree
+
+def executeCmd(text):
+    if type(text) is not unicode:
+        text = codecs.decode(text, encoding)
+    for (regex, pattern) in operator:
+        match = re.search(regex, text)
+        while match:
+            cmd = pattern
+            opt = match.groups()
+            for i in range(len(opt)):
+                cmd = cmd.replace(u"%" + u(i+1), opt[i])
+            text = text[:match.start()] + u"`" + cmd + u"`"+ text[match.end():]
+            match = re.search(regex, text)
+
+    result = u""
+    m = re.search(bq, text)
+    while text and m:
+        cmd  = m.group(1)
+        head = textOut(text[:m.start()])
+        text = text[m.end():]
+        try:
+            r, rest = parseLine(cmd, _inner, [], True, comment)
+            if rest: raise SyntaxError(cmd)
+        except SyntaxError:
+            if included:
+                raise SyntaxError(u"in " + included + u":" + u(line) + u": syntax error in executing command: " + cmd.strip())
+            else:
+                raise SyntaxError(u"in " + u(line) + u": syntax error in executing command: " + cmd.strip())
+        inner = _finish(r)
+        result += head + inner
+        m = re.search(bq, text)
+    result += textOut(text)
+
+    return result
+
+def codegen(obj):
+    global in_ns, pointers, line, included
+    ctype = obj[0]
+
+    if type(obj) is code:
+        return obj
+
+    try:
+        if ctype.line: line = ctype.line
+    except: pass
+
+    if ctype == "empty":
+        return code(u"")
+
+    if ctype == "in_ns":
+        in_ns = obj[1][0]
+        subtree = obj[1]
+        for sel in subtree:
+            codegen(sel)
+        in_ns = u""
+        return code(u"")
+
+    elif ctype == "decl":
+        name = u""
+        for data in obj[1]:
+            if type(data) is unicode or type(data) is str:
+                name = data
+                try:
+                    yf = ymlFunc[name]
+                    yf.alias
+                except:
+                    ymlFunc[name] = YF(name)
+                    yf = ymlFunc[name]
+                    if in_ns:
+                        yf.alias = in_ns + u":" + name
+                        if not enable_tracing:
+                            if in_ns == "xsl" and (name == "debug" or name=="assert" or name[:7]=="_trace_"):
+                                yf.alias = "-"
+                                yf.addParm("skip1")
+                                yf.addParm("skip2")
+                                break
+            elif type(data) is tuple or type(data) is Symbol:
+                if data[0] == "base":
+                    base = data[1][0]
+                    try:
+                        yf = ymlFunc[name] = ymlFunc[base].copy(name)
+                    except KeyError:
+                        if included:
+                            raise KeyError(u"in " + included + u":" + u(line) + u": " + base + u" as base for " + name)
+                        else:
+                            raise KeyError(u"in " + u(line) + u": " + base + u" as base for " + name)
+                elif data[0] == "shape":
+                    shape = ymlFunc[data[1]]
+                    try:
+                        yf = ymlFunc[name]
+                        yf.patch(shape)
+                    except KeyError:
+                        if included:
+                            raise KeyError(u"in " + included + u":" + u(line) + u": " + base + u" as shape for " + name)
+                        else:
+                            raise KeyError(u"in " + u(line) + u": " + base + u" as shape for " + name)
+                elif data[0] == "descend":
+                    yf.addDescend(data[1])
+                elif data[0] == "declParm":
+                    l = data[1]
+                    parmName = l[0]
+                    if len(l)==1:
+                        yf.addParm(parmName)
+                    else:
+                        value = l[1]
+                        if parmName[0] != "%":
+                            yf.addValue(parmName, value)
+                        if parmName[0] == "*":
+                            yf.pointers[parmName[1:]] = value
+                            yf.addParm(parmName)
+                        elif parmName[0] == "%":
+                            if type(value) is unicode or type(value) is str:
+                                yf.macros[parmName] = u(evalPython(value))
+                            else:
+                                yf.macros[parmName] = u(evalPython(u(value)))
+                            yf.addParm(parmName)
+                elif data[0] == "alias":
+                    if in_ns:
+                        yf.alias = in_ns + u":" + data[1][0]
+                    else:
+                        yf.alias = data[1][0]
+                elif data[0] == "content":
+                    yf.content = data[1]
+
+        return code(u"")
+
+    elif ctype == "funclist":
+        result = u""
+        for f in obj[1]:
+            result += codegen(f)
+        return code(result)
+
+    elif ctype == "parentheses":
+        if len(obj[1]):
+            return codegen(('func', ['_parentheses', ('content', [obj[1][0]])]))
+        else:
+            return u""
+
+    elif ctype == "fparm":
+        if len(obj[1]):
+            return codegen(('func', ['_parm', ('content', [obj[1][0]])]))
+        else:
+            return u""
+
+    elif ctype == "generic":
+        return codegen(('func', ['_generic', ('content', [obj[1][0]])]))
+
+    elif ctype == "xbase":
+        return codegen(('func', ['_base', ('content', [obj[1][0]])]))
+
+    elif ctype == "func":
+        avoidTag = False
+        name = obj[1][0]
+
+        if name == "decl":
+            if ymlFunc[name] == "#error":
+                if included:
+                    raise SyntaxError(u"in " + included + u":" + u(line) + u": syntax error in decl statement")
+                else:
+                    raise SyntaxError(u"in " + u(line) + u": syntax error in decl statement")
+        if name == "define" or name == "operator":
+            if ymlFunc[name] == "#error":
+                if included:
+                    raise SyntaxError(u"in " + included + u":" + u(line) + u": syntax error in define statement")
+                else:
+                    raise SyntaxError(u"in " + u(line) + u": syntax error in define statement")
+
+        if name[0] == "&":
+            avoidTag = True
+            name = name[1:]
+        hasContent = False
+
+        if len(name) > 2:
+            if name[0:2] == "**":
+                return code(eval('u'+pointer(name[1:])))
+
+        if name[0] == "*":
+            name = eval(pointer(name))
+            if name[0] == "&":
+                avoidTag = True
+                name = name[1:]
+
+        try:
+            ymlFunc[name]
+        except:
+            try:
+                ymlFunc["_"]
+                return codegen(('func', ['_', ('content', [('funclist', [obj])])]))
+            except:
+                ymlFunc[name] = YF(name)
+        
+        if ymlFunc[name].alias == "-": avoidTag = True
+
+        to_add = []
+        if len(ymlFunc[name].descends):
+            if obj[1][-1][0] != 'content':
+                if included:
+                    raise KeyError(u"in " + included + u":" + u(line) + u": " + name + u" has descending attributes, but no descendants are following")
+                else:
+                    raise KeyError(u"in " + u(line) + u": " + name + u" has descending attributes, but no descendants are following")
+
+            def first_func(obj):
+                if type(obj) is tuple or type(obj) is Symbol:
+                    if obj[0] == 'func':
+                        return obj
+                    elif obj[0] == 'funclist':
+                        return first_func(obj[1])
+                    elif obj[0] == 'content':
+                        return first_func(obj[1])
+                    else:
+                        return None
+                elif type(obj) == list:
+                    for e in obj:
+                        f = first_func(e)
+                        if f: return f
+                    return None
+
+            def copy_without_first_func(o, found = False):
+                c = []
+                for obj in o:
+                    if found:
+                        c.append(obj)
+                    else:
+                        if obj[0] == 'func':
+                            if obj[1][-1][0] == 'content':
+                                c.extend( obj[1][-1][1] )
+                            found = True
+                        else:
+                            c.append( ( obj[0], copy_without_first_func(obj[1], False ) ) )
+                return c
+
+            def get_parms(obj):
+                result = []
+                for e in obj[1]:
+                    if type(e) is tuple or type(e) is Symbol:
+                        if e[0] == "parm":
+                            result.append( e )
+                return result
+
+            try:
+                add_params = get_parms(obj)
+                for e in obj[1][-1][1]:
+                    c = e[1]
+                    for dname in ymlFunc[name].descends:
+                        f, c = first_func(c), copy_without_first_func(c)
+                        if dname[0] == "*":
+                            pointers[dname[1:]] = "'" + f[1][0] + "'"
+                        else:
+                            add_params.append( ('parm', [dname, u"'" + f[1][0] + u"'"]) )
+                        try:
+                            add_params.extend( get_parms(f) )
+                        except: pass
+
+                    new_things = [ e[1][0] ]
+                    new_things.extend( add_params )
+                    new_things.append( ('content', c) )
+                    
+                    to_add.append( ('func', new_things ) )
+            except:
+                if included:
+                    raise KeyError(u"in " + included + u":" + u(line) + u": " + name + u" has descending attributes, and too less descendants are following")
+                else:
+                    raise KeyError(u"in " + u(line) + u": " + name + u" has descending attributes, and too less descendants are following")
+
+        if not to_add:
+            to_add = ( obj, )
+
+        complete = u""
+
+        for obj in to_add:
+            subtree = None
+            try:
+                if obj[1][-1][0] == "content":
+                    subtree = obj[1][-1][1]
+            except: pass
+     
+            if ymlFunc[name].content:
+                hasContent = True
+                treetemplate = deepcopy(ymlFunc[name].content)
+                subtree = replaceContent(treetemplate, subtree)
+
+            if subtree:
+                hasContent = True
+
+            hasContent, result = ymlFunc[name](obj[1], hasContent, avoidTag)
+
+            if subtree:
+                for sel in subtree:
+                    result += codegen(sel)
+
+            if hasContent and not(avoidTag):
+                result += u"</" + ymlFunc[name].alias + u">"
+
+            complete += result
+
+        return code(complete)
+
+    elif ctype == "textsection":
+        result = u''
+        ll = obj[1].splitlines()
+        space = len(ll[-1]) - 2
+        for l in ll[1:-1]:
+            m = re.match(bqq, l)
+            if m:
+                cmd = m.group(1)
+                try:
+                    r, x = parseLine(cmd, _inner, [], True, comment)
+                    if x: raise SyntaxError(cmd)
+                    result += _finish(r)
+                except SyntaxError:
+                    if included:
+                        raise SyntaxError(u"in " + included + u":" + u(line) + u": syntax error in executing command: " + cmd.strip())
+                    else:
+                        raise SyntaxError(u"in " + u(line) + u": syntax error in executing command: " + cmd.strip())
+            else:
+                result += codegen(Symbol(u'lineQuote', u'| ' + l[space:]))
+        return code(result)
+
+    elif ctype == "lineQuote" or ctype == "quote":
+        m, text, base, inds = None, u"", 0, 0
+
+        if ctype == "lineQuote":
+            text = obj[1]
+            m = lq.match(text)
+            if m:
+                inds = len(m.group(1))
+                text = m.group(2)[1:]
+            else: inds = 0
+        elif ctype == "quote":
+            inds = -1
+            text = obj[1][0]
+            m = sq.match(text)
+            if m:
+                if m.group(1):
+                    inds = int(m.group(1))
+                text = m.group(2)[1:]
+            else:
+                if type(text) is unicode or type(text) is str:
+                    text = u(evalPython(text))
+
+        ind = u""
+        if inds > -1:
+            try:
+                cmd = evalPython(u"indent(" + u(inds) + u")")
+                result, rest = parseLine(u(cmd), _inner, [], True, comment)
+                if rest:
+                    raise SyntaxError()
+                ind = _finish(result)
+            except: pass
+        
+        if ctype == "lineQuote": text += u"\n"
+
+        hasTextFunc = False
+        try:
+            ymlFunc["text"]
+            hasTextFunc = True
+        except: pass
+
+        text = executeCmd(text)
+        return code(ind + text) 
+
+    elif ctype == "tagQuote":
+        m = tq.match(obj[1])
+        if m.group(1) == "<":
+            return code(u"<" + m.group(2))
+        else:
+            return code(m.group(2))
+
+    elif ctype == "operator":
+        operator.append((re.compile(evalPython(obj[1][0])), obj[1][1]))
+        return code(u"")
+
+    elif ctype == "constant":
+        name = obj[1][0]
+        if name[0] == "*":
+            name = name[1:]
+        value = obj[1][1]
+        pointers[name] = value
+        return code(u"")
+
+    elif ctype == "include":
+        reverse = False
+        ktext, kxml = False, False
+        for arg in obj[1]:
+            if type(arg) is tuple or type(arg) is Symbol:
+                if arg[0] == "reverse":
+                    reverse = True
+                elif arg[0] == "ktext":
+                    ktext = True
+                elif arg[0] == "kxml":
+                    kxml = True
+            elif type(arg) is unicode or type(arg) is str:
+                filemask = arg
+
+        if filemask[0] == '/' or filemask[0] == '.':
+            files = glob(filemask)
+        else:
+            files = []
+            for directory in includePath:
+                path = os.path.join(directory, filemask)
+                files.extend(glob(path))
+
+        if reverse:
+            files = files[-1::-1]
+
+        if not(files):
+            if included:
+                raise IOError(u"in " + included + ":" + u(line) + u": include file(s) '" + filemask + u"' not found")
+            else:
+                raise IOError(u"in " + u(line) + u": include file(s) '" + filemask + u"' not found")
+
+        includeFile = fileinput.input(files, mode="rU", openhook=fileinput.hook_encoded(encoding))
+        _included = included
+        if ktext or kxml:
+            text = u""
+            for line in includeFile:
+                included = includeFile.filename()
+                if kxml:
+                    if (not line[:6] == '<?xml ') and (not line[:6] == '<?XML '):
+                        text += line
+                else:
+                    text += executeCmd(line)
+            included = _included
+            return code(text)
+        else:
+            result = parse(ymlCStyle(), includeFile, True, comment)
+            included = u(filemask)
+            x = _finish(result)
+            included = _included
+            return code(x)
+
+    elif ctype == "pyExp":
+        exp = obj[1][0]
+        cmd = evalPython(exp)
+        result, rest = parseLine(u(cmd), _inner, [], True, comment)
+        if rest:
+            raise SyntaxError(cmd)
+        return code(_finish(result))
+
+    elif ctype == "pythonCall":
+        parms = []
+        data = obj[1]
+        for p in data:
+            if type(p) is unicode or type(p) is str:
+                name = p
+            elif type(p) is tuple or type(p) is Symbol:
+                ptype = p[0]
+                if ptype == "parm":
+                    if p[1][0][0] == "*":
+                        parms.append(pointer(p[1][0]))
+                    else:
+                        parms.append(p[1][0])
+        if len(parms) == 0:
+            exp = name + u"()"
+        elif len(parms) == 1:
+            exp = name + u"(" + u(parms[0]) + u")"
+        else:
+            exp = name + u(tuple(parms))
+        cmd = evalPython(exp)
+        result, rest = parseLine(u(cmd), _inner, [], True, comment)
+        if rest:
+            raise SyntaxError()
+        return code(_finish(result))
+
+    else:
+        return code(u"")
+
+def _finish(tree):
+    result = u""
+    python = u""
+
+    for el in tree:
+        if el[0] == "python":
+            if el[1][0][:2] == "!!":
+                python += el[1][0][2:-2]
+            else:
+                python += el[1][0][1:] + u"\n"
+            continue
+        else:
+            if python:
+                execPython(python)
+                python = u""
+
+        try:
+            result += codegen(el)
+        except RuntimeError:
+            if included:
+                raise RuntimeError(u"in " + included + u":" + u(line))
+            else:
+                raise RuntimeError(u"in " + u(line))
+
+    if python:
+        execPython(python)
+
+    return result
+
+def finish(tree):
+    global first
+    first = True
+    return _finish(tree)
+
+ymlFunc["_parentheses"] = YF("parms")
+ymlFunc["_parm"] = YF("parm")
+ymlFunc["_generic"] = YF("generic")
+ymlFunc["_base"] = YF("base")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/features.en.yhtml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,1090 @@
+include homepage.en.yhtml2
+
+page "The Features" {
+    h2 id=text > Text
+
+    p   >>
+        To output text nodes (¬http://www.w3.org/TR/2008/REC-xml-20081126/#syntax character data¬),
+        write literals. There are integer literals, floating point literals and text literals.
+        >>
+
+    p   >>
+        Literals are written
+        ¬http://docs.python.org/reference/lexical_analysis.html#id7 like in Python¬,
+        that means, text literals are in single or double quotes, or multiline
+        in triple double quotes:
+        >>
+
+    Code    ||
+            "text" 'also text' """some more text"""
+            42 "an integer and" 42.23 "a floating point literal"
+            ||
+
+    p   >>
+        Literals are being output by the ¬#textfunction text function¬.
+        >>
+
+    h2 id=functioncalls > Function Calls
+
+    p   >>
+        The main idea of YML scripts is calling functions which then generate
+        XML tags (¬http://www.w3.org/TR/2008/REC-xml-20081126/#syntax Markup¬).
+        Functions are generating single tags, lists or trees of tags.
+        >>
+    
+    p   >>
+        To call a function, write the name of the function, followed by a comma separated list
+        of function parameters (C like syntax) or just «attribute=value» pairs. Unlike C, you don't
+        need to insert the parameter list into parentheses. A simple function call can be terminated
+        by a semicolon «;» or by a period «.»
+        >>
+    
+    p   >>
+        It does not matter, if you're calling your function using parentheses or brackets or without.
+        So these statements are equal:
+        >>
+
+    Code    ||
+            foo "hello, world";
+            foo "hello, world".
+            foo("hello, world");
+            foo["hello, world"];
+            ||
+
+    h3 id=subtree > Subtrees
+
+    p   >>
+        If you omit the tailing semicolon, you're creating a Subtree; YML Subtrees can also be
+        opened and closed with braces:
+        >>
+
+    Code    ||
+            foo {
+                bar {
+                    something;
+                }
+            }
+            ||
+
+    p > If a Subtree only consists of one single subelement, then you may omit the braces:
+
+    Code    ||
+            foo
+                bar;
+            ||
+
+    h3 id=named > Named Parameters
+
+    p   >>
+        To generate ¬http://www.w3.org/TR/2008/REC-xml-20081126/#attdecls attributes¬ by calling
+        a function, you can use Named Parameters.
+        >>
+
+    p   >>
+        For that case, assign literals or symbols to attribute names like the following.
+        The name of the parameter then will be used as the name of the generated attribute.
+        An example:
+        >>
+
+    Code    ||
+            div id=sample {
+                "this is a " a href="#sample" "link sample"
+            }
+            ||
+
+    p > This generates:
+
+    Code | <div id="sample">this is a <a href="#sample">link sample</a></div>
+
+    h3 > Unnamed Parameters
+
+    p   >>
+        Unnamed Parameters prepare values for predefined attributes. The following example is
+        equivalent to the sample above:
+        >>
+
+    Code    ||
+            decl a(href);
+            decl div(id);
+
+            div "sample" {
+                "this is a " a "#sample" "link sample"
+            }
+            ||
+
+    p > If no predefined attribute can be allocated, the value of the parameter is added to the body.
+
+    h3 > Calling with &
+
+    p   >>
+        Especially if you have a ¬#defaultbody default body¬ for your function, calling with
+        a leading «&» can be sensible: then the tag itself is omitted and only the body is being output:
+        >>
+
+    Code    ||
+            decl something { tag1; tag2; };
+
+            list {
+                &something;
+            }
+            ||
+
+    p > results in:
+
+    Code    ||
+            <list>
+              <tag1/>
+              <tag2/>
+            </list>
+            ||
+
+    p   >>
+        This has the same result as ¬#alias aliasing¬ «something» to «-».
+        >>
+
+    h3 id=funclist > Function Lists
+
+    p   >>
+        Function Lists are a feature of YML to simulate a more C like syntax. Let's have some
+        examples. You can have a list of functions whereever you can have a function. Function
+        Lists are comma separated:
+        >>
+
+    Code    ||
+            x i, j, k
+            ||
+
+    p > compiles to:
+
+    Code    ||
+            <x>
+              <i/>
+              <j/>
+              <k/>
+            </x>
+            ||
+
+    h3 id=paramlists > Parameter Lists
+
+    p   >>
+        A sample together with ¬#descending Descending Attributes¬:
+        >>
+
+    Code    ||
+            decl Interface @name;
+            decl attr @type @name;
+            decl func @type @name;
+
+            Interface Icecream {
+                attr color flavour;
+                attr long number;
+                func int getPrice();
+                func void addFlavour(in color flavour, in long number);
+            }
+            ||
+
+    p > compiles to:
+    
+    Code    ||
+            <Interface name="Icecream">
+              <attr type="color" name="flavour"/>
+              <attr type="long" name="number"/>
+              <func type="int" name="getPrice"/>
+              <func type="void" name="addFlavour">
+                <parm>
+                  <in/>
+                  <color/>
+                  <flavour/>
+                </parm>
+                <parm>
+                  <in/>
+                  <long/>
+                  <number/>
+                </parm>
+              </func>
+            </Interface>
+            ||
+
+    p   >>
+        Note the «parm» tags – they're generated by default, if you write a Parameter List
+        behind a Function Call. That differs from calling the function with parameters –
+        ¬#functioncalls calling¬ means using ¬#text text¬ values.
+        >>
+
+    p   >>
+        The «parm» tags are emitted, because the «_parm» function is called each time
+        such a parameter will be emitted.
+        >>
+
+    p   >>
+        If you want to have the «_parm» function doing other things, just ¬#decl declare¬
+        it in another way.
+        >>
+
+    h3 id=generics > Generic Declarations
+
+    p   >>
+        Using Generic Declarations is just like using ¬#paramlists Parameter Lists¬ – use angle brackets
+        instead of parentheses. For Generic Declarations, the «_generic» function is called each
+        time such a Generic Declaration will be emitted, generating «generic» tags as the default:
+        >>
+
+    Code | max<int>(x, y)
+
+    p > compiles to:
+
+    Code    ||
+            <max>
+              <generic>
+                <int/>
+              </generic>
+              <parm>
+                <x/>
+              </parm>
+              <parm>
+                <y/>
+              </parm>
+            </max>
+            ||
+
+    h3 id=contentfc > The «content» function
+
+    p   >>
+        The «content;» Function Call has a special meaning (only in a ¬#defaultbody default body¬):
+        it does not generate a tag, but instead
+        the tags of a supplied body in a call will be inserted at each place where the «content;»
+        function call is existing in the ¬#defaultbody default body¬.
+        >>
+
+    h3 id=textfunction > The «text» function
+
+    p   >>
+        There is a special YML function named «text». Usually, it's just ¬#alias aliased¬ to «-» (and 
+        therefore outputting nothing). The «text» function is called each time a text literal will be
+        output.
+        >>
+
+    p   >>
+        If you ¬#decl declare¬ the «text» function, you can overload that behaviour. For example,
+        ¬yslt YSLT¬ is declaring «text» like this:
+        >>
+
+    Code    ||
+            decl text alias xsl:text;
+            
+            "test"
+            ||
+
+    p > generates:
+
+    Code | <xsl:text>test</xsl:text>
+
+    p   >>
+        The «text» function is not called, if you give text as a value for an attribute:
+        >>
+
+    Code    ||
+            decl text alias xsl:text;
+            
+            a "test"
+            ||
+
+    p > generates:
+
+    Code | <a>test</a>
+
+    p   >>
+        But it is called using the quoting operators:
+        >>
+
+    Code    ||
+            decl text alias xsl:text;
+            
+            a > test
+            ||
+
+    p > generates:
+
+    Code | <a><xsl:text>test</xsl:text></a>
+
+    h3 id=declfunction > The «decl», «define» and «operator» functions
+
+    p   >>
+        The «decl», «define» and «operator» functions are not defined, so they cannot be used
+        accidentally by having a syntax error i.e. in a «decl» statement. If you want to use such
+        a function, i.e. «decl()», you have to ¬#decl declare it explicitely¬:
+        >>
+
+    Code    ||
+            decl decl;
+            decl();
+            ||
+
+    p > will result in:
+
+    Code | <decl/>
+
+    h2 id=decl > Declaring Functions: decl
+
+    p   >>
+        As default, each Function Call generates one XML tag, which has the same name. To be exact,
+        the XML tag has dashes in it's name where the YML function has underscores.
+        >>
+
+    p   >>
+        To define, how tags and attributes look like, which are created by a Function Call, you
+        can use the «decl» statement.
+        >>
+
+    h3 > Trivial Declarations
+
+    p > In a trivial declaration, you're just declaring the Function Name and so the XML tag name:
+
+    Code | decl html, head, title, body, p, a;
+
+    p > As seen in the example, multiple declarations can be done in a comma separated list.
+
+    p   >>
+        Because trivial declarations are done automatically, if you're using a function for the
+        first time, you usually don't need to declare this way.
+        >>
+
+    h3 > Specifying Unnamed Parameters
+
+    p   >>
+        To specifiy Unnamed Parameters, give the parameter list comma separated in parentheses
+        or provide one or more brackets with parameter lists in them:
+        >>
+
+    Code | decl a(href), img[src];
+
+    p   >>
+        If you're using the corresponding functions a() and img() together with an unnamed parameter
+        in a call, then these attributes are used for applying the values, respectively:
+        >>
+
+    Code | a "http://www.ccc.de" "The Club Homepage" img "logo.png";
+
+    p > These Function Calls generate:
+    
+    Code | <a href="http://www.ccc.de">The Club Homepage</a><img src="logo.png"/>
+
+    h3 id=defaultattr > Giving Default Values for parameters
+
+    p   >>
+        To give default values for generating XML attributes, assign a literal to each named parameter
+        in the declaration parentheses or brackets. Two examples, which do the same:
+        >>
+
+    Code
+        ||
+        decl img(src, alt="picture");
+        decl img[src][alt="picture"];
+        ||
+
+    h3 id=alias > Aliasing: using different YML functions for the same XML tag for different tasks
+
+    p   >>
+        Sometimes tags are used in different ways to do different things. For this case, you can
+        use aliasing. Aliasing means, the YML function name and the XML tag name differ. For example:
+        >>
+
+    Code | decl a(href), target(name) alias a;
+
+    p > Both defined YML functions then generate «<a />» tags – but the Unnamed Parameter differs.
+
+    p   >>
+        The alias name «-» has a special meaning: it omits the tag in the output. That is especially
+        sensible if you have a ¬#defaultbody default body¬. Then an alias to «-» has the same meaning
+        as starting the function call with the «&» character: only the body is emitted.
+        >>
+
+    h3 id=descending > Specifying Descending Attributes
+
+    p   >>
+        Maybe you want to write something like this:
+        >>
+
+    Code    ||
+            Module ERP {
+                Interface Customer {
+                    // ...
+                }
+            }
+            ||
+
+    p > Without any extras, this compiles to:
+
+    Code    ||
+            <Module>
+                <ERP>
+                    <Interface>
+                        <Customer />
+                    </Interface>
+                </ERP>
+            </Module>
+            ||
+
+    p   >>
+        For this case, it would be practical, if «ERP» would not be interpreted as extra tag
+        but as value for an attribute «name». This you can achive with Descending Attributes:
+        >>
+
+    Code | decl Module @name, Interface @name;
+
+    p > With this declaration, the code sample above is compiling to:
+
+    Code    ||
+            <Module name="ERP">
+                <Interface name="Customer" />
+            </Module>
+            ||
+
+    p   >>
+        Descending attributes can also be used this way:
+        >>
+
+    Code    ||
+            decl module +name;
+            decl element +name;
+
+            module Some {
+                element {
+                    one;
+                    two;
+                    three;
+                }
+                element {
+                    four; five; six
+                }
+            }
+            ||
+
+    p   >>
+        The above generates:
+        >>
+
+    Code    ||
+            <?xml version='1.0' encoding='UTF-8'?>
+            <module name="Some">
+              <element name="one"/>
+              <element name="two"/>
+              <element name="three"/>
+              <element name="four"/>
+              <element name="five"/>
+              <element name="six"/>
+            </module>
+            ||
+
+    h3 id=descending_pointer > Specifying Descending Pointers
+
+    p   >>
+        Like with descending attributes, you can use descending ¬#pointer pointers¬. Instead of preceding the
+        name of an attribute with a «+» sign (like with ¬#descending descending attributes¬), precede it with an asterisk «*».
+        >>
+
+    p   >>
+        Like with ¬#pointer pointers¬ in general, it's a good idea to combine that with a ¬#defaultbody default body¬:
+        >>
+
+    Code    ||
+            decl f *p { some tags with *p };
+
+            f value;
+            ||
+
+    p   >>
+        This generates:
+        >>
+
+    Code    ||
+            <?xml version='1.0' encoding='UTF-8'?>
+            <f>
+              <some>
+                <tags>
+                  <with>value</with>
+                </tags>
+              </some>
+            </f>
+            ||
+
+    h3 id=defaultbody > Supplying a Default Body
+
+    p   >>
+        Additionally, you can supply a Default Body for each tag. For that case, add a YML function
+        block in braces to your declaration:
+        >>
+
+    Code    ||
+            decl pageContent alias body {
+                a name=top;
+                include heading.en.yhtml2;
+                div id=entries
+                content;
+            };
+            ||
+
+    p > The sample above is used for generating this homepage, for example.
+
+    p > See the ¬#contentfc content function¬.
+
+    h3 id=inheritance > Inheritance
+
+    p   >>
+        Declarations can ¬http://en.wikipedia.org/wiki/Inheritance_(computer_science) inherit¬
+        information from previous declarations. For that case, there is the
+        possibility to use an «is» clause to give a function name to inherit from.
+        >>
+
+    p > The following is an example from the YSLT specification:
+
+    Code    ||
+            decl stylesheet(version="1.0", xmlns:xsl="http://www.w3.org/1999/XSL/Transform");
+
+            decl estylesheet is stylesheet (
+                xmlns:exsl='http://exslt.org/common',
+                xmlns:math='http://exslt.org/math',
+                xmlns:func='http://exslt.org/functions',
+                xmlns:str='http://exslt.org/strings',
+                xmlns:dyn='http://exslt.org/dynamic',
+                xmlns:set='http://exslt.org/sets',
+                extension-element-prefixes='exsl func str dyn set math'
+            );
+
+            decl textstylesheet is estylesheet {
+                output "text";
+                const "space", !"'" + " " * 200 + "'"!;
+                param "autoindent", 4;
+                content;
+            }, tstylesheet is textstylesheet;
+            ||
+
+    p   >>
+        Here «estylesheet» inherits the tag name and the Default Values from «stylesheet»,
+        while «textstylesheet» inherits all from «estylesheet» again. «estylesheet» then adds
+        a Default Body, and «tstylesheet» does exactly the same as «textstylesheet».
+        >>
+
+    p > All of these YML functions output «stylesheet» XML tags, but with different defaults.
+
+    h3 id=shapes > Shapes
+
+    p   >>
+        Shapes are comparable to ¬#inheritance inheritance¬. Declaring a shape inherits
+        every property beside the name.
+        >>
+
+    Code    ||
+            decl coords(x=0, y=0);
+            decl point <coords> (name);
+
+            point "origin";
+            ||
+
+    p > compiles to:
+
+    Code | <point y="0" x="0" name="origin"/>
+  
+    p   >>
+        It's possible to have more than one shape, too. Multiple shapes
+        are patching each other in the sequence they're listed:
+        >>
+
+    Code    ||
+            decl coords(x=0, y=0);
+            decl named +name;
+            decl point <coords, named>;
+
+            point origin;
+            ||
+
+    p > compiles to:
+
+    Code | <point y="0" x="0" name="origin" />
+            
+    h3 > Namespaces
+
+    p   >>
+        ¬http://www.w3.org/TR/xml-names/ XML namespaces¬ can be used just by providing an
+        «alias» clause. Additionally, they can be used by an «in» clause; these two lines
+        are equivalent:
+        >>
+
+    Code    ||
+            decl apply(select) alias xsl:apply-templates;
+            in xsl decl apply(select) alias apply-templates;
+            ||
+
+    p > «in» clauses also can be used with a block of declarations in braces:
+
+    Code    ||
+            in xsl {
+                decl template(match);
+                decl apply(select) alias apply-templates;
+
+                decl function(name) alias template;
+                decl call(name) alias call-template;
+            }
+            ||
+
+    h3 id=pointer > Pointers
+
+    p   >>
+        In some situations, it is good to have information in a Function Call, which then
+        changes the way XML tags are generated. For this case, there are Pointers.
+        >>
+
+    p   >>
+        The name should not mislead you; I took it because I chose the «*» symbol to declare them,
+        and that is the meaning of this symbol in the programming language C. The concept behind
+        is very easy.
+        >>
+
+    p   >>
+        For example, it could be a good idea to generate a small HTML document containing some
+        content. For this case, the title of the page is a good case for using pointers:
+        >>
+
+    Code    ||
+            decl page(*title) alias html {
+                head {
+                    title *title;
+                }
+                body {
+                    h1 *title;
+                    content;
+                }
+            };
+            ||
+
+    p   >>
+        In the example above, calling «page('My Page') { p 'hello, world'; }» will result in
+        this XML output:
+        >>
+
+    Code    ||
+            <html>
+                <head>
+                    <title>My Page</title>
+                </head>
+                <body>
+                    <h1>My Page</h1>
+                    <p>hello, world</p>
+                </body>
+            </html>
+            ||
+
+    p   >>
+        Pointers can be referenced in any place in the Default Body of a «decl» statement, also for
+        generating extra tags. Then the value for a Pointer will be the tag name.
+        >>
+
+    p   >>
+        Additionally, you can insert the value of a pointer as text by calling it with two leading
+        asterisks, i.e. if the pointer is defined as «*x», you can insert its value as text using: «**x».
+        >>
+
+    h4 id=pwt > Pointers without tags
+
+    p   >>
+        To give a literal a name, you can define pointers to literals.
+        >>
+
+    Code    ||
+            define *answer = 42;
+            something *answer;
+            ||
+
+    p > will compile to:
+
+    Code | <something>42</something>
+
+    p   >>
+        The «define» keyword as well as the asterisk «*» can be omitted. So this is
+        equivalent to the statements above:
+        >>
+
+    Code    ||
+            answer = 42;
+            something *answer;
+            ||
+
+    h4 > The pointer *_debug_trace
+
+    p   >>
+        If you're calling ¬toolchain#processor yml2proc¬ with ¬toolchain#debug --debug¬, then this pointer is filled
+        with tracing info text, otherwise it's an empty string.
+        >>
+
+    h3 id=macros, "Macros";
+
+    p   >>
+        Macros are a way to generate values for attributes with variable content. Macros can be set
+        like any other parameters; they're used for a text search & replace in the values of attributes
+        when attributes are generated.
+        >>
+
+    p   >>
+        Parameters, which represent macros, are determined with a preceding «%» sign. They're
+        accounted for before any other parameter is accounted for in a function call, even if
+        they were defined after other parameters.
+        >>
+
+    p > An example:
+
+    Code    ||
+            decl foo(%macro, myAttr="something %macro for testing");
+
+            testing
+                foo "nice";
+            ||
+
+    p > This generates:
+
+    Code    ||
+            <testing>
+              <foo myAttr="something nice for testing"/>
+            </testing>
+            ||
+
+    h3 id=nullfunction > The Null Function
+
+    p   >>
+        The function with the name «_» (underscore) is called Null Function. If you define this
+        function, then you're switching off the default behaviour, that trivial declares are done
+        automatically.
+        >>
+
+    p   >>
+        Instead, unknown functions now call the Null Function. This can be very sensible together
+        with ¬#descending Descending Attributes¬:
+        >>
+
+    Code    ||
+            decl _ +type +name alias func;
+            decl interface +name;
+
+            interface Testcase {
+                void f(in string input);
+                long getOptions();
+            }
+            ||
+
+    p > compiles to:
+
+    Code    ||
+            <interface name="Testcase">
+              <func type="void" name="f">
+                <parm>
+                  <in/>
+                  <string/>
+                  <input/>
+                </parm>
+              </func>
+              <func type="long" name="getOptions"/>
+            </interface>
+            ||
+
+    h2 id=quoting > Quoting Operators
+
+    p > Five different quoting operators implement different functionality:
+
+    h3 id=quote > Quote >
+
+    p > The «>» operator quotes into text nodes, doing XML escaping of text. An example:
+
+    Code | > this text will be put into a text node and these angle brackets <> will be quoted
+
+    p > Additionally, it can be used to implement an indention system, see ¬yslt YSLT¬ below.
+
+    p   >>
+        Then an integer literal can be the first part of the operator; it gives the indention
+        level. For example:
+        >>
+
+    Code    ||
+            0> this text is indented to the actual level and then output,
+             >  followed by this text.\\n
+
+            1> this text is indented one indention level\\n
+            2> two levels\\n
+            1> one level again\\n
+            ||
+
+    p   >>
+        Quote text is being output by the ¬#textfunction «text» function¬.
+        >>
+
+    h3 id=blockquote > Block Quote >>
+
+    p {
+        > To include more lines of text into a single quoted area, use double «>>». The lines 
+        > are concatenated together then. An example:
+    }
+
+    Code    ||
+            p   >>
+                This generates a text paragraph for HTML. All this text, which you can find in
+                these lines, is being concatenated together to one single text node, and then put
+                into the body of the <p> ... </p> tag.
+                >>
+            ||
+
+    p   >>
+        Block quote text is being output by the ¬#textfunction «text» function¬.
+        >>
+
+    h3 > Line Quote |
+
+    p > The «|» operator does the same as the «>» operator, adding a newline character to the text node.
+
+    p > Additionally, it can be used to implement an indention system, see ¬yslt YSLT¬ below.
+
+    p > Then it's used together with additional «>» symbols showing the grade of indention:
+
+    Code    ||
+            | not indented
+            |> single indent
+            |>> double indent
+            (...)
+            ||
+
+    p   >>
+        Line quote text is being output by the ¬#textfunction «text» function¬.
+        >>
+
+    h3 > Block Line Quote ||
+
+    p   >>
+        The «||» operator opens and closes a block of lines, which then are handled like if each of
+        them would be preceeded with a Line Operator «|».
+        >>
+
+    p > Sample:
+
+    Code {
+        | ||
+        ||
+        this is code being quoted through
+        this is the second line
+        ||
+        | ||
+    }
+     
+    p > is equivalent to:
+
+    Code {
+        ||
+        | this is code being quoted through
+        | this is the second line
+        ||
+    }
+
+    p   >>
+        Block line quote text is being output by the ¬#textfunction «text» function¬.
+        >>
+
+    h3 > Inserting Commands
+
+    p   >>
+        Just like with a ¬http://en.wikipedia.org/wiki/Shell_(computing)#Unix_shells Unix shell¬,
+        you can insert statements into text by using backticks:
+        >>
+
+    Code ] | Click `a href="http://fdik.org/yml/" "this link"`, please!
+
+    p {
+        >>
+        Being in a Block Line Quote «||», you additionally can use the Line Command operator
+        (two backquotes,
+        >>
+        ]  ``).
+    }
+
+    p > This is very interesting to have in YSLT, for example:
+
+    Code {
+        | ||
+        | some code
+        ] ``
+        > apply "myTemplate";\n
+        | some other code
+        | ||
+    }
+
+    h3 id=userop > User defined in-text Operators
+
+    p > You can define short cuts for inserting commands into text by defining operators.
+
+    p   >>
+        Therefore, you need a ¬http://en.wikipedia.org/wiki/Regular_expression regular expression¬
+        for matching text and YML text for replacing with. Here an example, how this is used by YSLT:
+        >>
+
+    Code ] define operator "«(.*?)»" as value "%1";
+
+    p > The RegEx have ¬http://docs.python.org/library/re.html Python syntax¬.
+
+    p   >>
+        In this example all matches to the RegEx will be replaced by the YML text in the «as» clause.
+        The text of the first group in the RegEx will replace the «%1» in the resulting YML text. You
+        can do that for more than one group – just use «%2» for the second group, «%3» for the third
+        one and so on.
+        >>
+
+    p > The «define» keyword can be omitted.
+
+    h3 id=quotethrough > Quote Through ]
+
+    p   >>
+        The ¬http://en.wikipedia.org/wiki/Apple_II_series Apple ][¬ prompt operator just quotes
+        through directly into XML what it gets.
+        >>
+
+    p   >>
+        If the first character of a command is a «<», then quote through is applied
+        automatically.
+        >>
+    
+    p > This is the preferred way to output XML tags directly in YML:
+
+    Code    ||
+            <output me="directly" />
+            
+            ] <!--
+            ]     add some comment, which then appears in XML
+            ] -->
+            ||
+
+    h2 id=including > Including YML files
+
+    p   >>
+        You can include a second YML script file into an existing YML script file
+        at any place using one of the following:
+        >>
+
+    Code    ||
+            include something.yml2
+            include "something else.yml2"
+            include 'anything addionally.yml2'
+            ||
+
+    a name="ymlpath";
+    p   >>
+        If you're not starting the filename with '.' or '/' as in the example above, then
+        if the «YML_PATH» environment variable is set to a colon separated list of directories,
+        these directories are being searched for the given filename. Otherwise, the local
+        directory is searched.
+        >>
+
+    p   >>
+        Filename ¬http://en.wikipedia.org/wiki/Glob_(programming) globbing¬ using «*» and «?»
+        placeholders is supported to include more than one file at a time:
+        >>
+
+    Code | include part*.yml2
+
+    p   >>
+        Filename globbing also can be used reverted; that means, the files are included in reverse
+        order:
+        >>
+
+    Code | include reverse part*.yml2
+
+    p > If there are the files part1.yml, part2.yml and part3.yml, part3.yml is included first now.
+
+    p > To include plain text as text nodes, you can use:
+
+    Code | include text some.txt
+
+    p > To include ready made XML, use:
+
+    Code | include xml some.xml
+
+    h2 id=python > Escaping into Python – the Escape Operator !
+
+    p > You can insert a Python command at any place by using the «!» operator:
+
+    Code | !class X(str): pass
+
+    h3 > Python script Operator !!
+
+    p > You can use the double «!!» to include more than one line of Python code:
+
+    Code    ||
+            !!
+            def fak(n):
+                if n == 0:
+                    return 1
+                else:
+                    return n * fak(n - 1)
+
+            def getName(id):
+                return SQL("select name from customers where id='"+str(id)+"';")[0]
+            !!
+            ||
+
+    h3 > Python generated parameters in Function Calls
+
+    p   >>
+        You may use Python expressions to generate names and/or values in Function Calls.
+        To do so, embed the Python expression in «! ... !»:
+        >>
+
+    Code    ||
+            f x=!fak(5)!;
+            customer name=!getName(42)!;
+            tag !getNextAttributeName()!=42;
+            ||
+
+    h3 > Python generated Function Calls
+
+    p   >>
+        You can generate text with a Python expression, which represents an YML Function Call.
+        The resulting YML function is then executed. Also here, embed the Python expression
+        in «! ... !»:
+        >>
+
+    Code | !getTagName() + " " + getAttrib() + "='" + getValue() + "'"!
+
+    h3 > Using Pointers as values in Python function calls
+
+    p   >>
+        Sometimes it is useful to call a generating Python function using information of a
+        YML Function Call. For that case, there is the «python» statement in YML. You can
+        call there a single Python function using YML Pointers as parameters.
+        >>
+
+    p > This is used in the YSLT specification, for example:
+
+    Code    ||
+            decl apply(select, *indent=1) alias apply-templates {
+                python withIndent(*indent);
+                content;
+            };
+            ||
+
+    h2 id=comments > Comments //, /* */
+
+    p > Comments are written like in Java or C++:
+
+    Code    ||
+            // this is a comment
+            something() { // this is a comment after a tag
+            /* this is some comment, too */
+            ||
+
+    p > After Quoting Operators, comments are not possible. Instead, they're quoted through:
+
+    Code    ||
+            // the following line you'll find in the output document
+            > this text is being output // and this too
+            ||
+
+    div id=bottom {
+        > ¬programming << Using YML 2¬ 
+        > ¬#top ^Top^¬ 
+        > ¬yslt >> show me YSLT¬ 
+        > ¬features.en.yhtml2 (source)¬
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/format.css	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,90 @@
+html {
+    background-color: lightgrey;
+}
+
+body {
+    margin-left: auto;
+    margin-right: auto;
+    margin-top: 0;
+    width: 900px;
+    min-height: 768px;
+    background-color: white;
+    font-family: Arial,Helvetica,FreeSans
+}
+
+em {
+    color: darkblue;
+    font-weight: bold;
+    font-style: normal;
+}
+
+#headline {
+    color: black;
+    font-size: x-large;
+    font-weight: normal;
+    border-bottom-width: 1px;
+    border-bottom-style: solid;
+    padding: 10px;
+}
+
+td {
+    vertical-align: top;
+}
+
+#navigation {
+    position: relative;
+    float: right;
+    width: 200px;
+    border-left-width: 1px;
+    border-left-style: dotted;
+    padding: 10px;
+    font-size: small;
+}
+
+#entries {
+    width: 569px;
+    padding: 10px;
+}
+
+.statusline {
+    width: 569px;
+    padding-left: 10px;
+    padding-right: 10px;
+    font-size: small;
+}
+
+#bottom {
+    clear: both;
+    color: grey;
+    padding: 10px;
+}
+
+h1, h2 {
+    font-size: medium;
+    color: darkblue;
+}
+
+h3 {
+    font-size: medium;
+    color: black;
+}
+
+h4 {
+    font-size: medium;
+    font-weight: normal;
+    font-style: italic;
+}
+
+.subscript {
+    font-size: small;
+    border-bottom-width: 1px;
+    border-bottom-style: dotted;
+    margin-bottom: 1em;
+    padding-bottom: 1em;
+}
+
+.small {
+    font-size: small;
+    margin-bottom: 1em;
+    padding-bottom: 1em;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gpl-2.0.txt	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed 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.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/heading.en.yhtml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,66 @@
+decl a(href);
+
+decl Code alias pre {
+    code
+        content;
+};
+
+decl ne is a {
+    content;
+    br;
+};
+
+div id=headline {
+    p > YML – Why a Markup Language?!
+    div class=small {
+        "YML 2.5.4 of We Apr 10 2013  –  Copyleft 2007-2013, "
+        a "http://blog.fdik.org", "Volker Birk";
+        " – "
+        a "http://fdik.org/yml2.tar.bz2", "Download YML 2";
+    }
+}
+
+div id=navigation {
+    h1 a "index", "Introduction";
+    ne "index#xml", "XML";
+    ne "index#motivation", "Motivation";
+    ne "index#howitworks", "How it works";
+    ne "index#ylanguages", "Y Languages";
+
+    h1 a "programming", "Using YML 2";
+    ne "programming#wiki", "A Wiki like language";
+    ne "programming#how", "How does that work?";
+    ne "programming#details", "Details, please!";
+    ne "programming#using", "Using it";
+
+    h1 a "features", "Features";
+    ne "features#text", "Text";
+    ne "features#functioncalls", "Function Calls";
+    ne "features#decl", "Declaring Functions";
+    ne "features#quoting", "Quoting Operators";
+    ne "features#including", "Including YML Files";
+    ne "features#python", "Escaping into Python";
+    ne "features#comments", "Comments";
+
+    h1 a "yslt", "YSLT";
+    ne "yslt#intro", "Introduction into YSLT";
+    ne "yslt#hello", "Hello, World";
+    ne "yslt#programming", "Programming in YSLT";
+    ne "yslt#htmlgen", "Generating HTML out of a DSL";
+    ne "yslt#codegen", "Generating Java code out of a DSL";
+    ne "yslt#ddlgen", "Generating SQL DDL out of UML in XMI";
+    ne "yslt#features", "YSLT Features";
+
+    h1 a "toolchain", "Tool Chain";
+    ne "toolchain#compiler", "YML compiler";
+    ne "toolchain#processor", "YML/YSLT processor";
+    ne "toolchain#recommended", "Recommended external tools";
+    ne "http://www.auchdieserschwachsinnmussinsinternet.de/2009-03/#s1236859037", "Windows tool chain";
+    ne "http://fdik.org/yml2.tar.bz2", "Download YML 2";
+    ne "toolchain#downloads", "Download different versions";
+
+    h1 "Misc";
+    ne "gpl-2.0.txt", "License for YML";
+    ne "http://www.pibit.ch/", "Commercial support for YML";
+    ne "http://fdik.org/pyPEG", "YML is using pyPEG";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hello.en.yhtml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,12 @@
+include homepage.en.yhtml2
+
+page "Hello, world" {
+    p   >>
+        Hello, world! I can link here, say:
+        ¬http://en.wikipedia.org to Wikipedia¬
+        >>
+
+    p   >>
+        This is ƒemphasized. And this is «code».
+        >>
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/homepage.en.yhtml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+decl pageContent alias body {
+    a name=top;
+    include heading.en.yhtml2;
+    div id=entries
+        content;
+};
+
+decl page(*title, lang="en", xml:lang="en", xmlns="http://www.w3.org/1999/xhtml") alias html {
+    head {
+        title *title;
+        meta http-equiv="Content-Type", content="text/html;charset=UTF-8";
+        link rel=stylesheet, type="text/css", href="format.css";
+    }
+
+    pageContent
+        content;
+};
+
+define operator "¬\s*(.*?)\s+(.*?)\s*¬" as a href="%1" > %2
+define operator "«(.*?)»" as code > %1
+define operator "ƒ(\S+)" as em > %1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/index.en.yhtml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,206 @@
+// the YML homepage
+
+include homepage.en.yhtml2
+
+page "YML – Why a Markup Language?!" {
+    h1 > Introduction
+
+    h2 > What is YML?
+
+    p   >>
+        Well, it's the idea not to need to define a grammar first when you want to use a
+        ¬http://en.wikipedia.org/wiki/Domain_Specific_Language Domain Specific Language¬.
+        For that purpose, YML is being translated into XML. Let's make an example.
+        >>
+
+    p   >>
+        Everything which comes close to a C like language, parses without a grammar
+        definition:
+        >>
+
+    p > This:
+
+    Code
+        ||
+        template< class T > T max(T a, T b);
+        ||
+
+    p > Parses to:
+
+    Code
+        ||
+        <?xml version='1.0' encoding='UTF-8'?>
+        <template>
+          <generic>
+            <class/>
+            <T/>
+          </generic>
+          <T>
+            <max>
+              <parm>
+                <T/>
+                <a/>
+              </parm>
+              <parm>
+                <T/>
+                <b/>
+              </parm>
+            </max>
+          </T>
+        </template>
+        ||
+
+    p   >>
+        Instead of defining grammars, you test out and play around until the
+        results are matching your needs. If the resulting tree does not fit
+        what you're expecting, change it by patching the grammar with `code > decl`:
+        >>
+
+    p > This:
+
+    Code
+        ||
+        module A {
+            interface B {
+                attribute long n;
+            };
+        };
+        ||
+
+    p > Parses to:
+
+    Code
+        ||
+        <?xml version='1.0' encoding='UTF-8'?>
+        <module>
+          <A>
+            <interface>
+              <B>
+                <attribute>
+                  <long>
+                    <n/>
+                  </long>
+                </attribute>
+              </B>
+            </interface>
+          </A>
+        </module>
+        ||
+
+    p   >>
+        This does not look like what we want. So we tell YML that
+        we have a module name after the module, an interface name after
+        the interface and type and name after the attribute:
+        >>
+
+    p > This:
+
+    Code
+        ||
+        decl module @name;
+        decl interface @name;
+        decl attribute @type @name;
+
+        module A {
+            interface B {
+                attribute long n;
+            };
+        };
+        ||
+
+    p > Parses to:
+
+    Code
+        ||
+        <?xml version='1.0' encoding='UTF-8'?>
+        <module name="A">
+          <interface name="B">
+            <attribute type="long" name="n"/>
+          </interface>
+        </module>
+        ||
+
+    h2 id=what > What can I do with YML?
+
+    p > With YML you can:
+
+    ul {
+        li p > use a C-like ¬http://en.wikipedia.org/wiki/Domain-specific_language DSL¬ without writing a grammar first
+        li p > generate code out of this ¬http://en.wikipedia.org/wiki/Domain-specific_language DSL¬ using ¬yslt YSLT¬
+        li p > generate code out of ¬http://en.wikipedia.org/wiki/Unified_Modeling_Language UML¬ using ¬yslt YSLT¬ on ¬http://en.wikipedia.org/wiki/XML_Metadata_Interchange XMI¬
+        li p > generate code out of any XML based language like ¬http://en.wikipedia.org/wiki/Scalable_Vector_Graphics SVG¬ using ¬yslt YSLT¬
+        li p > define a ¬http://en.wikipedia.org/wiki/Wiki wiki¬ like language in just a few lines like ¬http://fdik.org/yml/programming#wiki YHTML¬ does
+        li p > replace bad designed and complicated XML languages with simpler C-like ones
+        li p > ... and much more.
+    }
+
+    h2 id=howitworks > How it works: Replacing angle brackets with some Python
+
+    p > Just writing down what I wanted to have instead of XML for a sample:
+
+    Code    ||
+            <list name="List of goods">
+                <head>
+                    <columTitle>
+                        Goods
+                    </columnTitle>
+                    <columnTitle>
+                        Price
+                    </columnTitle>
+                </head>
+                <row>
+                    <value>
+                        Beer
+                    </value>
+                    <value>
+                        20
+                    </value>
+                </row>
+                <row>
+                    <value>
+                        Wine
+                    </value>
+                    <value>
+                        30
+                    </value>
+                </row>
+            </list>
+            ||
+
+    p > Something like that should be more easy, say, like this:
+
+    Code    ||
+            list "List of goods" {
+                head title "Goods", title "Price";
+                row value "Beer", value 20;
+                row value "Wine", value 30;
+            }
+            ||
+
+    h2 id=ylanguages > Y Languages
+
+    p   >>
+        The latter is what I call an Y language – a language specified in YML. How could this be
+        achieved? Well, what's to do? To have the required information, how to build XML from the
+        script above, we need:
+        >>
+
+    ul {
+        li  >>
+            the information, that “list of goods” is an attribute named «name», while «Goods» is
+            the text value of a tag
+            >>
+        li > «title» shout be written out as «columnTitle»
+    }
+
+    p > How to do that? Let's invent a simple definition language for that information:
+
+    Code    ||
+            decl list(name);
+            decl title alias columnTitle;
+            ||
+
+    p > Here you can ¬samples/list.yml2 download the complete list sample¬.
+
+    div id=bottom > ¬#top ^Top^¬ ¬programming >> Using YML 2¬ ¬index.en.yhtml2 (source)¬
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/manpage.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,1 @@
+decl manpage(xmlns="http://docbook.org/ns/docbook", version="5.0", *title) alias article { title *title; content; };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programming.en.yhtml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,413 @@
+include homepage.en.yhtml2
+
+page "Using YML 2" {
+    p   >>
+        YML 2 is a smart ¬http://en.wikipedia.org/wiki/Template_processor template language¬ and
+        ¬http://en.wikipedia.org/wiki/Domain-specific_language DSL concept¬. This guide will give
+        you a feeling, for what it's worth.
+        >>
+
+    h2 id=wiki > Creating a Wiki like language for writing documentation
+
+    p   >>
+        Let's say, we want to define a small Wiki system, which should be translated from a Wiki
+        like language into HTML. This guide is written in one using YML 2. I call it ƒYHTML. You can
+        view the ¬homepage.en.yhtml2 source code of what you're reading now¬. It's about writing
+        web pages like that:
+        >>
+
+    Code {
+        ||
+        page "Hello, world" {
+            p   ¬features#blockquote >>¬
+                Hello, world! I can link here, say:
+        ||
+        >         
+        ] ¬http://en.wikipedia.org to Wikipedia¬
+        > \n
+        ||
+                ¬features#blockquote >>¬
+
+            p   ¬features#blockquote >>¬
+        ||
+        >         
+        ] This is ƒemphasized. And this is «code».
+        > \n
+        ||
+                ¬features#blockquote >>¬
+        }
+        ||
+    }
+    p   >>
+        Prerequisite: knowing how ¬http://en.wikipedia.org/wiki/Html#Markup HTML¬ works.
+        >>
+
+    h2 id=how > How does that work?
+
+    p   >>
+        YML 2 is a template language. That means, you can define ¬http://en.wikipedia.org/wiki/Recursion recursive¬
+        templates of what's to be generated. This is ¬homepage.en.yhtml2 the code¬; just click on underlined things
+        to get an explanation:
+        >>
+
+    Code {
+        ||
+        ¬features#quotethrough <¬?xml version="1.0" encoding="UTF-8"?¬features#quotethrough >¬
+        ¬features#quotethrough <¬!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"¬features#quotethrough >¬
+
+        ¬features#decl decl¬ pageContent ¬features#alias alias¬ body ¬features#defaultbody {¬
+            a name¬features#named =¬"top";
+            ¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬;
+            div id¬features#named =¬"entries"
+                ¬features#contentfc content¬;
+        ¬features#defaultbody }¬;
+
+        ¬features#decl decl¬ page(¬features#pointer *title¬, lang¬features#defaultattr =¬"en", xml:lang¬features#defaultattr =¬"en", xmlns¬features#defaultattr =¬"http://www.w3.org/1999/xhtml")
+            ¬features#alias alias¬ html ¬features#defaultbody {¬
+            head ¬features#subtree {¬
+                title ¬features#pointer *title¬;
+                meta http-equiv¬features#named =¬"Content-Type", content¬features#named =¬"text/html;charset=UTF-8";
+                link rel¬features#named =¬"stylesheet", type¬features#named =¬"text/css", href¬features#named =¬"format.css";
+            ¬features#subtree }¬
+
+            pageContent
+                ¬features#contentfc content¬;
+        ¬features#defaultbody }¬;
+        ||
+
+        br; > ¬features#userop define operator¬ 
+        ] <a href="http://docs.python.org/library/re.html">"¬\s*(.*?)\s+(.*?)\s*¬"</a>
+        >  ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2
+
+        br; > ¬features#userop define operator¬ 
+        ] <a href="http://docs.python.org/library/re.html">"«(.*?)»"</a>
+        >  ¬features#userop as¬ code ¬features#quote >¬ %1
+
+        br; > ¬features#userop define operator¬ 
+        ] <a href="http://docs.python.org/library/re.html">"ƒ(\S+)"</a>
+        >  ¬features#userop as¬ em ¬features#quote >¬ %1
+    }
+
+    h2 id=details > Details, please!
+
+    h3 > Starting with XHTML headers
+
+    p   >>
+        Because HTML headers are boring and annoying, I'm copying them from document to document. And at last,
+        they ended here ;-) If you already have things in angle brackets, you can just add them to your YML 2
+        document “as is”, because everything which starts with an opening angle bracket will be a “give through”
+        for the YML 2 toolchain. So our first two lines are:
+        >>
+
+    Code 
+        ||
+        ¬features#quotethrough <¬?xml version="1.0" encoding="UTF-8"?¬features#quotethrough >¬
+        ¬features#quotethrough <¬!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"¬features#quotethrough >¬
+        ||
+
+    h3 > Defining the document structure
+
+    p   >>
+        A Webpage usually has a structure: it has a specific title and content. Beside that, technical things
+        have to be encoded. A Webpage in XHTML is XML text, setting xmlns to the right name space. That's how we
+        do that in YML 2:
+        >>
+    
+    Code 
+        ||
+        ¬features#decl decl¬ page(¬features#pointer *title¬, lang¬features#defaultattr =¬"en", xml:lang¬features#defaultattr =¬"en", xmlns¬features#defaultattr =¬"http://www.w3.org/1999/xhtml")
+            ¬features#alias alias¬ html ¬features#defaultbody {¬
+        ||
+
+    p   >>
+        First we ¬features#decl declare¬ the «page» function. It's ¬features#alias aliased to¬ «html», so it will
+        generate a «html» tag, not a «page» tag.
+        >>
+
+    p   >>
+        The first parameter, «*title», is a placeholder for the title of the document. The content of what we give
+        here later will be repeated at any place we're putting «*title» into our template. This technique is called
+        ¬features#pointer Pointers¬.
+        >>
+
+    p   >>
+        The two other attributes have ¬features#defaultattr Default Values¬, so they're generated each time the
+        «page» function will be called.
+        >>
+
+    h3 > The Document content
+
+    p   >>
+        The document content is what is in the «{ ... }» block:
+        >>
+
+    Code
+        ||
+        ¬features#defaultbody {¬
+            head ¬features#subtree {¬
+                title ¬features#pointer *title¬;
+                meta http-equiv¬features#named =¬"Content-Type", content¬features#named =¬"text/html;charset=UTF-8";
+                link rel¬features#named =¬"stylesheet", type¬features#named =¬"text/css", href¬features#named =¬"format.css";
+            ¬features#subtree }¬
+
+            pageContent
+                ¬features#contentfc content¬;
+        ¬features#defaultbody }¬;
+        ||
+
+    p   >>
+        This reflects, that each HTML document has a «head» and a «body» section. Of course, we insert the «*title»
+        pointer value in the «title» tag. Then some meta data and a link to a nice
+        ¬http://en.wikipedia.org/wiki/Cascading_Style_Sheets CSS¬ ;-)
+        >>
+
+    p   >>
+        For the «body» section, we have a little helper function, «pageContent». The function named «content» is
+        a ¬features#contentfc placeholder¬, where the content of the page will be placed, when our «page» function
+        will be called.
+        >>
+
+    h3 > Generating the «body» with the «pageContent» function
+
+    p   >>
+        The «pageContent» function is used for generating the «body» with standard elements; therefore, it's
+        ¬features#alias aliased¬ to «body»:
+        >>
+
+    Code
+        ||
+        ¬features#decl decl¬ pageContent ¬features#alias alias¬ body ¬features#defaultbody {¬
+            a name¬features#named =¬"top";
+            ¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬;
+            div id¬features#named =¬"entries"
+                ¬features#contentfc content¬;
+        ¬features#defaultbody }¬;
+        ||
+
+    p   >>
+        It first sets an HTML anchor, so links can reference the top of the page:
+        >>
+
+    Code | a name¬features#named =¬"top";
+       
+    p   >>
+        Then a file with heading and navigation (the menu to the right on the page here) is being
+        ¬features#including included¬:
+        >>
+
+    Code | ¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬;
+
+    p   >>
+        At last, the page content is being put in, surrounded by a «div» named «entries», so it can be referenced
+        later, too:
+        >>
+
+    Code    ||
+            div id¬features#named =¬"entries"
+                ¬features#contentfc content¬;
+            ||
+
+    p   >>
+        If you'll have a look on the included ¬heading.en.yhtml2 heading.en.yhtml2¬ file, then you'll see the 
+        the static head and navigation sections hard coded. With the ¬format.css CSS file¬ everything is brought
+        to the right place.
+        >>
+
+    h3 > Defining some operators for the Wiki like language
+
+    p   >>
+        The trick with a Wiki like language is, that one can write plain text, and adding structural things
+        to it, like links i.e.
+        >>
+
+    p   >>
+        So we need language constructs, which let us structure. In YML 2 these are called
+        ¬features#userop User defined in-text Operators¬:
+        >>
+
+    Code {
+        > ¬features#userop define operator¬ 
+        ] <a href="http://docs.python.org/library/re.html">"¬\s*(.*?)\s+(.*?)\s*¬"</a>
+        >  ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2
+
+        br; > ¬features#userop define operator¬ 
+        ] <a href="http://docs.python.org/library/re.html">"«(.*?)»"</a>
+        >  ¬features#userop as¬ code ¬features#quote >¬ %1
+
+        br; > ¬features#userop define operator¬ 
+        ] <a href="http://docs.python.org/library/re.html">"ƒ(\S+)"</a>
+        >  ¬features#userop as¬ em ¬features#quote >¬ %1
+    }
+
+    p   >>
+        They look somewhat disturbing, if you're not familiar with
+        ¬http://en.wikipedia.org/wiki/Regular_expression Regex¬, so I will explain.
+        >>
+
+    p   >>
+        First we define a link:
+        >>
+
+    Code {
+        > ¬features#userop define operator¬ 
+        ] <a href="http://docs.python.org/library/re.html">"¬\s*(.*?)\s+(.*?)\s*¬"</a>
+        >  ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2
+    }
+
+    p   >>
+        The keyword «define operator» starts the definition. Then there is the Regex:
+        >>
+
+    Code | "¬\s*(.*?)\s+(.*?)\s*¬"
+
+    p {
+        "I decided I want to have the special character " "¬" " surrounding each link like this: "
+        code ] ¬http://en.wikipedia.org go to Wikipedia¬
+        ". This is just like what ¬http://www.mediawiki.org MediaWiki¬ does with brackets; here the "
+        "same would read: «[http://en.wikipedia.org go to Wikipedia]»."
+    }
+
+    p   >>
+        I like using such special characters. This is because I'm using a
+        ¬http://www.apple.com/mac/ Mac¬ and ¬http://en.wikipedia.org/wiki/GNU/Linux GNU/Linux¬.
+        If you're using ¬http://www.microsoft.com/windows/ Windows¬, I really can recommend
+        ¬http://www.autohotkey.com/docs/Hotkeys.htm AutoHotkey¬. It's a great piece of software to expand the
+        keyboard capabilities of Windows (and much more).
+        >>
+
+    p {
+        > How does this Regex stuff work? It's a ¬http://en.wikipedia.org/wiki/Pattern_matching pattern matching¬ language consuming characters with each 
+        > command. Well, we want to have the following: The first thing between the 
+        ] ¬
+        >  markers shell be the link target URL. All other things shell be the name of the link shown. 
+        >>
+        For that case, we're first consuming whitespace with «\s*» – the «\s» means “an arbitrary whitespace
+        character” (like blank, newline, etc.). The asterisk «*» means “some of them or none”, so this
+        consumes all whitespace which is there (and gives no error if there is none).
+        >>
+    }
+
+    p   >>
+        Second, we open a group with parentheses «( )» This first group we can later reference as «%1»
+        when substituting.
+        >>
+
+    p   >>
+        Inside this group, we're telling that we want anything in it, no matter what it is. For this case,
+        we're using a dot «.» which means “any character”, followed by asterisk questionmark «*?», which is 
+        the code for “consume as much as you can, but only up to the next code in the Regex”. The total
+        «(.*?)» consumes the target URL (without checking it).
+        >>
+
+    p   >>
+        Then we're consuming some whitespace again, this time with «\s+». Using a plus «+» instead of an 
+        asterisk «*» or asterisk questionmark «*?» means: there has to be at least one whitespace character.
+        And we want whitespace between the URL and the name, right? ;-)
+        >>
+
+    p   >>
+        Now we're consuming the second group. We're consuming whatever is there – it's the name of the
+        link. We're using another «(.*?)» group for it. It will be group 2, and we can reference it with
+        this in the substitution: «%2».
+        >>
+
+    p {
+        > At last we're consuming redundant whitespace with «\s*», and our Regex is closed by another 
+        ] ¬
+        >  character. And that makes the total Regex:
+    }
+
+    Code ] "¬\s*(.*?)\s+(.*?)\s*¬"
+
+    p   >>
+        So what can we do with it? What we want are «<a href="..." />» tags. And that means, we want to
+        call a function like this: «a href="..." > ...»
+        >>
+
+    p   >>
+        As «href» we want to have the result of group 1,
+        because this is the link target. After the ¬features#quote Quote operator¬ «>» we want to have
+        what is the name of the link, that is the result of group 2. That we can write literally:
+        >>
+
+    Code | a href="%1" > %2
+
+    p   >>
+        Our first User defined in-text Operator is ready :-)
+        >>
+
+    p   >>
+        Maybe you would prefer using brackets. So just do it ;-) Change the Regex to this, and you
+        can use brackets for links like in MediaWiki; we have to escape the brackets «[ ]» with a
+        backslash «\\», because brackets are also codes in Regex, and we don't want the code, we really
+        want brackets:
+        >>
+
+    Code | "\[\s*(.*?)\s+(.*?)\s*\]"
+
+    p   >>
+        The other two operators should now be easy to understand:
+        >>
+
+    Code {
+        > ¬features#userop define operator¬ 
+        ] <a href="http://docs.python.org/library/re.html">"«(.*?)»"</a>
+        >  ¬features#userop as¬ code ¬features#quote >¬ %1
+
+        br; > ¬features#userop define operator¬ 
+        ] <a href="http://docs.python.org/library/re.html">"ƒ(\S+)"</a>
+        >  ¬features#userop as¬ em ¬features#quote >¬ %1
+    }
+
+    p   >>
+        A tip: the code with an upper case letter S «\S» means, that only non-whitespace characters shell
+        be consumed.
+        >>
+
+    h2 id=using > Using it
+
+    p   >>
+        How to write a new web page with our templates? Here's a ¬hello.en.yhtml2 hello world¬. We can use
+        ¬features#blockquote Block Quotes¬ for entering text, and our new self defined operators:
+        >>
+
+    Code {
+        ||
+        ¬features#including include¬ homepage.en.yhtml2
+
+        page "Hello, world" {
+            p   ¬features#blockquote >>¬
+                Hello, world! I can link here, say:
+        ||
+        >         
+        ] ¬http://en.wikipedia.org to Wikipedia¬
+        > \n
+        ||
+                ¬features#blockquote >>¬
+
+            p   ¬features#blockquote >>¬
+        ||
+        >         
+        ] This is ƒemphasized. And this is «code».
+        > \n
+        ||
+                ¬features#blockquote >>¬
+        }
+        ||
+    }
+
+    p   >>
+        The result you can ¬hello see here¬:
+        >>
+
+    iframe src="hello", width="100%", height=300 > ¬hello see here¬
+
+    div id=bottom {
+        > ¬index << back to Introduction¬ 
+        > ¬#top ^Top^¬ 
+        > ¬features >> The Features¬ 
+        > ¬programming.en.yhtml2 (source)¬
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyPEG.py	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,351 @@
+# YPL parser 1.5
+
+# written by VB.
+
+import re
+import sys, codecs
+import exceptions
+
+class keyword(unicode): pass
+class code(unicode): pass
+class ignore(object):
+    def __init__(self, regex_text, *args):
+        self.regex = re.compile(regex_text, *args)
+
+class _and(object):
+    def __init__(self, something):
+        self.obj = something
+
+class _not(_and): pass
+
+class Name(unicode):
+    def __init__(self, *args):
+        self.line = 0
+        self.file = u""
+
+class Symbol(list):
+    def __init__(self, name, what):
+        self.__name__ = name
+        self.append(name)
+        self.what = what
+        self.append(what)
+    def __call__(self):
+        return self.what
+    def __unicode__(self):
+        return u'Symbol(' + repr(self.__name__) + ', ' + repr(self.what) + u')'
+    def __repr__(self):
+        return unicode(self)
+
+word_regex = re.compile(ur"\w+")
+rest_regex = re.compile(ur".*")
+
+print_trace = False
+
+def u(text):
+    if isinstance(text, exceptions.BaseException):
+        text = text.args[0]
+    if type(text) is unicode:
+        return text
+    if isinstance(text, str):
+        if sys.stdin.encoding:
+            return codecs.decode(text, sys.stdin.encoding)
+        else:
+            return codecs.decode(text, "utf-8")
+    return unicode(text)
+
+def skip(skipper, text, skipWS, skipComments):
+    if skipWS:
+        t = text.lstrip()
+    else:
+        t = text
+    if skipComments:
+        try:
+            while True:
+                skip, t = skipper.parseLine(t, skipComments, [], skipWS, None)
+                if skipWS:
+                    t = t.lstrip()
+        except: pass
+    return t
+
+class parser(object):
+    def __init__(self, another = False, p = False):
+        self.restlen = -1 
+        if not(another):
+            self.skipper = parser(True, p)
+            self.skipper.packrat = p
+        else:
+            self.skipper = self
+        self.lines = None
+        self.textlen = 0
+        self.memory = {}
+        self.packrat = p
+
+    # parseLine():
+    #   textline:       text to parse
+    #   pattern:        pyPEG language description
+    #   resultSoFar:    parsing result so far (default: blank list [])
+    #   skipWS:         Flag if whitespace should be skipped (default: True)
+    #   skipComments:   Python functions returning pyPEG for matching comments
+    #   
+    #   returns:        pyAST, textrest
+    #
+    #   raises:         SyntaxError(reason) if textline is detected not being in language
+    #                   described by pattern
+    #
+    #                   SyntaxError(reason) if pattern is an illegal language description
+
+    def parseLine(self, textline, pattern, resultSoFar = [], skipWS = True, skipComments = None):
+        name = None
+        _textline = textline
+        _pattern = pattern
+
+        def R(result, text):
+            if __debug__:
+                if print_trace:
+                    try:
+                        if _pattern.__name__ != "comment":
+                            sys.stderr.write(u"match: " + _pattern.__name__ + u"\n")
+                    except: pass
+
+            if self.restlen == -1:
+                self.restlen = len(text)
+            else:
+                self.restlen = min(self.restlen, len(text))
+            res = resultSoFar
+            if name and result:
+                name.line = self.lineNo()
+                res.append(Symbol(name, result))
+            elif name:
+                name.line = self.lineNo()
+                res.append(Symbol(name, []))
+            elif result:
+                if type(result) is type([]):
+                    res.extend(result)
+                else:
+                    res.extend([result])
+            if self.packrat:
+                self.memory[(len(_textline), id(_pattern))] = (res, text)
+            return res, text
+
+        def syntaxError():
+            if self.packrat:
+                self.memory[(len(_textline), id(_pattern))] = False
+            raise SyntaxError()
+
+        if self.packrat:
+            try:
+                result = self.memory[(len(textline), id(pattern))]
+                if result:
+                    return result
+                else:
+                    raise SyntaxError()
+            except: pass
+
+        if callable(pattern):
+            if __debug__:
+                if print_trace:
+                    try:
+                        if pattern.__name__ != "comment":
+                            sys.stderr.write(u"testing with " + pattern.__name__ + u": " + textline[:40] + u"\n")
+                    except: pass
+
+            if pattern.__name__[0] != "_":
+                name = Name(pattern.__name__)
+
+            pattern = pattern()
+            if callable(pattern):
+                pattern = (pattern,)
+
+        text = skip(self.skipper, textline, skipWS, skipComments)
+
+        pattern_type = type(pattern)
+
+        if pattern_type is str or pattern_type is unicode:
+            if text[:len(pattern)] == pattern:
+                text = skip(self.skipper, text[len(pattern):], skipWS, skipComments)
+                return R(None, text)
+            else:
+                syntaxError()
+
+        elif pattern_type is keyword:
+            m = word_regex.match(text)
+            if m:
+                if m.group(0) == pattern:
+                    text = skip(self.skipper, text[len(pattern):], skipWS, skipComments)
+                    return R(None, text)
+                else:
+                    syntaxError()
+            else:
+                syntaxError()
+
+        elif pattern_type is _not:
+            try:
+                r, t = self.parseLine(text, pattern.obj, [], skipWS, skipComments)
+            except:
+                return resultSoFar, textline
+            syntaxError()
+
+        elif pattern_type is _and:
+            r, t = self.parseLine(text, pattern.obj, [], skipWS, skipComments)
+            return resultSoFar, textline
+
+        elif pattern_type is type(word_regex) or pattern_type is ignore:
+            if pattern_type is ignore:
+                pattern = pattern.regex
+            m = pattern.match(text)
+            if m:
+                text = skip(self.skipper, text[len(m.group(0)):], skipWS, skipComments)
+                if pattern_type is ignore:
+                    return R(None, text)
+                else:
+                    return R(m.group(0), text)
+            else:
+                syntaxError()
+
+        elif pattern_type is tuple:
+            result = []
+            n = 1
+            for p in pattern:
+                if type(p) is type(0):
+                    n = p
+                else:
+                    if n>0:
+                        for i in range(n):
+                            result, text = self.parseLine(text, p, result, skipWS, skipComments)
+                    elif n==0:
+                        if text == "":
+                            pass
+                        else:
+                            try:
+                                newResult, newText = self.parseLine(text, p, result, skipWS, skipComments)
+                                result, text = newResult, newText
+                            except SyntaxError:
+                                pass
+                    elif n<0:
+                        found = False
+                        while True:
+                            try:
+                                newResult, newText = self.parseLine(text, p, result, skipWS, skipComments)
+                                result, text, found = newResult, newText, True
+                            except SyntaxError:
+                                break
+                        if n == -2 and not(found):
+                            syntaxError()
+                    n = 1
+            return R(result, text)
+
+        elif pattern_type is list:
+            result = []
+            found = False
+            for p in pattern:
+                try:
+                    result, text = self.parseLine(text, p, result, skipWS, skipComments)
+                    found = True
+                except SyntaxError:
+                    pass
+                if found:
+                    break
+            if found:
+                return R(result, text)
+            else:
+                syntaxError()
+
+        else:
+            raise SyntaxError(u"illegal type in grammar: " + u(pattern_type))
+
+    def lineNo(self):
+        if not(self.lines): return u""
+        if self.restlen == -1: return u""
+        parsed = self.textlen - self.restlen
+
+        left, right = 0, len(self.lines)
+
+        while True:
+            mid = int((right + left) / 2)
+            if self.lines[mid][0] <= parsed:
+                try:
+                    if self.lines[mid + 1][0] >= parsed:
+                        try:
+                            return u(self.lines[mid + 1][1]) + u":" + u(self.lines[mid + 1][2])
+                        except:
+                            return u""
+                    else:
+                        left = mid + 1
+                except:
+                    try:
+                        return u(self.lines[mid + 1][1]) + u":" + u(self.lines[mid + 1][2])
+                    except:
+                        return u""
+            else:
+                right = mid - 1
+            if left > right:
+                return u""
+
+# plain module API
+
+def parseLine(textline, pattern, resultSoFar = [], skipWS = True, skipComments = None, packrat = False):
+    p = parser(p=packrat)
+    text = skip(p.skipper, textline, skipWS, skipComments)
+    ast, text = p.parseLine(text, pattern, resultSoFar, skipWS, skipComments)
+    return ast, text
+
+# parse():
+#   language:       pyPEG language description
+#   lineSource:     a fileinput.FileInput object
+#   skipWS:         Flag if whitespace should be skipped (default: True)
+#   skipComments:   Python function which returns pyPEG for matching comments
+#   packrat:        use memoization
+#   lineCount:      add line number information to AST
+#   
+#   returns:        pyAST
+#
+#   raises:         SyntaxError(reason), if a parsed line is not in language
+#                   SyntaxError(reason), if the language description is illegal
+
+def parse(language, lineSource, skipWS = True, skipComments = None, packrat = False, lineCount = True):
+    lines, lineNo = [], 0
+
+    while callable(language):
+        language = language()
+
+    orig, ld = u"", 0
+    for line in lineSource:
+        if lineSource.isfirstline():
+            ld = 1
+        else:
+            ld += 1
+        lines.append((len(orig), lineSource.filename(), lineSource.lineno() - 1))
+        orig += u(line)
+
+    textlen = len(orig)
+
+    try:
+        p = parser(p=packrat)
+        p.textlen = len(orig)
+        if lineCount:
+            p.lines = lines
+        else:
+            p.line = None
+        text = skip(p.skipper, orig, skipWS, skipComments)
+        result, text = p.parseLine(text, language, [], skipWS, skipComments)
+        if text:
+            raise SyntaxError()
+
+    except SyntaxError, msg:
+        parsed = textlen - p.restlen
+        textlen = 0
+        nn, lineNo, file = 0, 0, u""
+        for n, ld, l in lines:
+            if n >= parsed:
+                break
+            else:
+                lineNo = l
+                nn += 1
+                file = ld
+
+        lineNo += 1
+        nn -= 1
+        lineCont = orig.splitlines()[nn]
+        raise SyntaxError(u"syntax error in " + u(file) + u":" + u(lineNo) + u": " + lineCont)
+
+    return result
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/Customer.java	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,10 @@
+// Die Klasse Customer
+class Customer {
+    public void setName(String value) {
+        name = value;
+    }
+    public String getName() {
+        return name;
+    }
+    private String name;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/address.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,13 @@
+list {
+    address {
+        name "Meier";
+        street "Hauptstrasse";
+        city "Heidenheim";
+    }
+
+    address {
+        name "Schmid";
+        street "Wilhelmstrasse";
+        city "Gingen";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/addresslistenhtml.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,7 @@
+include yslt.yml2
+
+stylesheet {
+    template "/list" html body table apply "address";
+    template "address" tr apply "*";
+    template "*" td value ".";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/adressliste.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,12 @@
+liste {
+    adresse {
+        name "Meier";
+        strasse "Uhlmannstrasse 42";
+        ort "Laupheim";
+    }
+    adresse {
+        name "Schmidt";
+        strasse "Haupstrasse 23";
+        ort "Bad Waldsee";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/backend.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,9 @@
+include yslt.yml2
+
+textstylesheet {
+    template "/list" {
+        > CREATE TABLE 
+        value "name()";
+        > (\n
+        apply "*/*";
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/blub.svg	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,61 @@
+<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:cc="http://web.resource.org/cc/" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" sodipodi:docname="XiIrritant.svg" sodipodi:version="0.32" height="177.523" width="155.932" id="svg1" inkscape:version="0.40" viewBox="-10 -10 178 178" sodipodi:docbase="/mnt/donnees/09-Mes_images/Travaux/Travaux vectoriel/pictogrammes/s&#233;cu SVG/produits chimiques">
+  <metadata>
+    <rdf:RDF>
+      <cc:Work rdf:about="">
+        <dc:title>Irritant</dc:title>
+        <dc:description>produit chimique</dc:description>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li/>
+            <rdf:li>symbol</rdf:li>
+            <rdf:li>signs_and_symbols</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <dc:publisher>
+          <cc:Agent rdf:about="http://www.openclipart.org">
+            <dc:title>yves GUILLOU</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>yves GUILLOU</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:rights>
+          <cc:Agent>
+            <dc:title>yves GUILLOU</dc:title>
+          </cc:Agent>
+        </dc:rights>
+        <dc:date/>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+        <cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
+        <dc:language>en</dc:language>
+      </cc:Work>
+      <cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
+        <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+        <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+        <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview bordercolor="#666666" inkscape:window-x="200" inkscape:window-y="0" pagecolor="#ffffff" inkscape:zoom="6.6399849" inkscape:pageshadow="2" id="base" borderopacity="1.0" inkscape:current-layer="svg1" inkscape:cx="62.372805" inkscape:cy="34.864537" inkscape:window-width="1590" inkscape:pageopacity="0.0" inkscape:window-height="1121"/>
+  <defs id="defs2">
+    <marker refY="5" refX="0" markerUnits="strokeWidth" viewBox="0 0 10 10" orient="auto" markerWidth="4" id="ArrowEnd" markerHeight="3">
+      <path d="M 0 0 L 10 5 L 0 10 z" id="path4"/>
+    </marker>
+    <marker refY="5" refX="10" markerUnits="strokeWidth" viewBox="0 0 10 10" orient="auto" markerWidth="4" id="ArrowStart" markerHeight="3">
+      <path d="M 10 0 L 0 5 L 10 10 z" id="path6"/>
+    </marker>
+  </defs>
+  <g id="g7">
+    <g id="g8">
+      <path style="stroke:none; fill:#000000" d="M 155.932 155.932L 155.932 0L 0 0L 0 155.932L 155.932 155.932z" id="path9"/>
+      <path style="stroke:none; fill:#ff9900" d="M 150.83 150.83L 150.83 5.1011L 5.1011 5.1011L 5.1011 150.83L 150.83 150.83z" id="path10"/>
+    </g>
+    <g id="g11">
+      <path style="stroke:none; fill:#000000" d="M 140.823 111.783L 44.3677 14.0771L 15.1084 44.1489L 111.564 141.854L 140.823 111.783z" id="path12"/>
+      <path style="stroke:none; fill:#000000" d="M 111.783 15.1084L 14.0771 111.564L 44.1489 140.823L 141.855 44.3677L 111.783 15.1084z" id="path13"/>
+    </g>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/blub.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,1 @@
+Das ist ein Beispiel;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/browse.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,6 @@
+include yslt.yml2
+
+tstylesheet template "*" {
+    | «name()»
+    apply "*";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/bumens.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,9 @@
+function "fak" {
+    param "n";
+
+    choose {
+        when "n=0" value 1
+        otherwise value "$n * fak($n-1)";
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/clike.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,6 @@
+decl interface +name;
+decl _ +type +name alias func;
+
+interface Test {
+    void f(in string x, out long y);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/ctest.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,3 @@
+// dingens
+
+x;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/customer.java.target	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,27 @@
+package Bla;
+
+class Customer {
+    // attribute id
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int value) {
+        id = value;
+    }
+
+    private int id;
+
+    // attribute name
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String value) {
+        name = value;
+    }
+
+    private String name;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/customer.xml	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,10 @@
+<list>
+    <customer>
+        <id>23</id>
+        <name>Kurt Meier</name>
+    </customer>
+    <customer>
+        <id>42</id>
+        <name>Lieschen Schmidt</name>
+    </customer>
+</list>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/customer.xsl	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,1 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="xml"/><xsl:variable name="space" select="'                                                                                                                                                                                                        '"/><xsl:param name="autoindent" select="4"/><xsl:param name="x"/><xsl:template match="/"><xsl:param name="_indent" select="0"/><html><head><title>Customer List</title></head><body><xsl:apply-templates select="list"><xsl:with-param name="_indent" select="$_indent+1*$autoindent"/></xsl:apply-templates></body></html></xsl:template><xsl:template match="list"><xsl:param name="_indent" select="0"/><table><xsl:apply-templates select="customer"><xsl:with-param name="_indent" select="$_indent+1*$autoindent"/></xsl:apply-templates></table></xsl:template><xsl:template match="customer"><xsl:param name="_indent" select="0"/><tr><td><xsl:value-of select="$x"/></td><td><xsl:value-of select="id"/></td><td><xsl:value-of select="name"/></td></tr></xsl:template></xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/customer.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,15 @@
+include yslt.yml2
+
+stylesheet {
+    template "/" html {
+        head title "Customer List";
+        body apply "list";
+    }
+
+    template "list" table apply "customer[starts-with(name, 'Kurt')]";
+
+    template "customer" tr {
+        td value "id";
+        td value "name";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/ddl.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,15 @@
+include yslt.yml2
+
+tstylesheet {
+    template "/list" {
+        | CREATE TABLE «name(*)» (
+        
+        apply "*[1]/*";
+
+        | );
+    }
+
+    template "*" {
+        | «name()» VARCHAR`if "position()!=last()" ", "`
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/debug_test.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,9 @@
+include yslt.yml2
+
+tstylesheet {
+    template "/" {
+        debug "'debug output'";
+        assert 0, "'test assertion'";
+        > yes\n
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/delta.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,2 @@
+decl delta alias Δ;
+delta Δ="∂" Δ { "Δ" }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/demo.xmi	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="2.1" xmlns:uml="http://schema.omg.org/spec/UML/2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1">
+	<xmi:Documentation exporter="Bouml" exporterVersion="1.7.2"/>
+	<uml:Model xmi:type="uml:Model" xmi:id="themodel" name="demo">
+		<packagedElement xmi:type="uml:Package" xmi:id="BOUML_0x81_22" name="Demo">
+			<packagedElement xmi:type="uml:Class" name="Customer" xmi:id="BOUML_0x1f417_4" visibility="package" isAbstract="false" >
+				<ownedAttribute xmi:type="uml:Property" name="id" xmi:id="BOUML_0x1f417_1" visibility="public">
+					<type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#String"/>
+				</ownedAttribute>
+				<ownedAttribute xmi:type="uml:Property" name="name" xmi:id="BOUML_0x1f497_1" visibility="private">
+					<type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#String"/>
+				</ownedAttribute>
+			</packagedElement>
+		</packagedElement>
+	</uml:Model>
+</xmi:XMI>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/dingens.idl	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,20 @@
+module Bla {
+    struct Blub {
+        long a;
+        string b;
+    };
+
+    interface Blubber {
+        Blub getBlub();
+    };
+
+    typedef My::Complicated::Reachable::Thing Thing;
+
+    interface Irgendwas {
+        struct Bla {
+
+        };
+
+        readonly attribute Thing b;
+    };
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/dingens.sql	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,6 @@
+CREATE TABLE address (
+    name VARCHAR,
+    street VARCHAR
+    city VARCHAR
+);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/dingens.xml	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,1 @@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/dingens.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,3 @@
+decl module +name;
+decl interface +name;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/dml.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,9 @@
+include yslt.yml2
+
+tstylesheet {
+    template "/list/*"
+        | INSERT INTO «name()» (`apply "*", 0, mode="names"`) VALUES (`apply "*", mode="values"`);
+    
+    template "*", mode="names" > «name()»`if "position()!=last()" ", "`
+    template "*", mode="values" > '«.»'`if "position()!=last()" ", "`
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/double.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,3 @@
+when {
+    a;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/double.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,3 @@
+include yslt.yml2
+
+tstylesheet template "/when/*" | «name()»
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/empty.xml	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,1 @@
+<empty/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/empty.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,22 @@
+include yslt.yml2
+
+tstylesheet {
+    template "/xsl:stylesheet" {
+        > include yslt.yml2\n\ntstylesheet {\n
+        apply "xsl:template";
+        > }\n
+    }
+    template "xsl:template" choose {
+        when "@match" {
+            | template "«@match»" {
+            |
+            | }
+        }
+        when "@name" {
+            | template "«@name»" {
+            |
+            | }
+        }
+        if "position()!=last()" |
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/errortest.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,5 @@
+include yslt.yml2
+
+tstylesheet xmlns:yml2="http://fdik.org/yml" {
+    template "/$$", yml2:line=23 | hello
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/f.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,3 @@
+include i.yml2
+
+x
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/f.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,19 @@
+include yslt.yml2
+
+tstylesheet {
+    function stType {
+        param "type";
+
+        choose {
+            when "$type='long'" > DINT
+            when "$type='short'" > INT
+        }
+    }
+
+    function cType {
+        param "type";
+
+        when "$type='long'" > int32_t
+        when "$type='short'" > int16_t
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/function.xml	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,1 @@
+<f><parms><x/></parms><return>42</return></f>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/function.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,1 @@
+include yslt.yml2; tstylesheet template "/f" | «return»
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/gen_addr_html.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,13 @@
+include yslt.yml2
+
+stylesheet {
+    template "/list" html {
+        head title "address list";
+        body table style="border-style=solid;" apply "address";
+    }
+    template "address" tr {
+        td value "name";
+        td value "street";
+        td value "city";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/gen_again_java.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,33 @@
+include yslt.yml2
+
+tstylesheet {
+    template "/xmi:XMI/uml:Model" {
+        apply "Package", 0;
+    }
+
+    template 'packagedElement[xmi:type="uml:Package"]' {
+        | package «@name»;
+        | 
+        apply "packagedElement", 0;
+    }
+
+    template 'packagedElement[xmi:type="uml:Class"]' {
+        | class «@name» {
+        apply 'ownedAttribute[xmi:type="uml:Property"]';
+        | }
+    }
+
+    template "Attribute" {
+        |     // attribute «@name»
+        | 
+        |     public «type» get«@name»() {
+        |         return «@name»;
+        |     }
+        | 
+        |     public void set«@name»(«type» value) {
+        |         «@name» = value;
+        |     }
+        | 
+        |     private «type» «@name»;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/gen_java.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,60 @@
+include yslt.yml2
+
+define operator "†(\S+)" as call "printType" with "name", "%1";
+define operator "“(.*?)”" as call "ucase" with "text", "%1";
+
+decl umlstylesheet is tstylesheet (
+    xmlns:uml="http://schema.omg.org/spec/UML/2.1",
+    xmlns:xmi="http://schema.omg.org/spec/XMI/2.1"
+);
+
+umlstylesheet {
+    template "/xmi:XMI/uml:Model"
+        apply "packagedElement", 0;
+
+    template "packagedElement[@xmi:type='uml:Package']" {
+        | package «@name»;
+        |
+        apply "packagedElement", 0;
+    }
+
+    template "packagedElement[@xmi:type='uml:Class']" {
+        | class «@name» {
+        apply "ownedAttribute";
+        | }
+        if "position() != last()" |
+    }
+
+    template "ownedAttribute[@xmi:type='uml:Property' and count(@association)=0]" {
+        | // attribute «@name»
+        |      
+        | public †type get“@name”() {
+        |     return «@name»;
+        | }
+        |      
+        | public void set“@name”(†type value) {
+        |     «@name» = value;
+        | }
+        |      
+        | private †type «@name»;
+        if "position() != last()" |
+    }
+
+    function "ucase" {
+        param "text";
+
+        > «translate(substring($text, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')»
+        > «substring($text, 2)»
+    }
+
+    function "printType" {
+        param "name";
+
+        choose {
+            when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#UnlimitedNatural"'
+                > int
+            when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#String"'
+                > String
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/hello.xsl	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,2 @@
+<xsl:stylesheet xmlns:func="http://exslt.org/functions" xmlns:dyn="http://exslt.org/dynamic" xmlns:str="http://exslt.org/strings" xmlns:math="http://exslt.org/math" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" extension-element-prefixes="exsl func str dyn set math" xmlns:set="http://exslt.org/sets" version="1.0" xmlns:exsl="http://exslt.org/common"><xsl:output method="text"/><xsl:variable name="space" select="'                                                                                                                                                                                                        '"/><xsl:param name="autoindent" select="4"/><xsl:template match="/"><xsl:param name="_indent" select="0"/><xsl:value-of select="substring($space, 1, $_indent+0*$autoindent)"/>hello, world
+</xsl:template></xsl:stylesheet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/hello.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,11 @@
+decl hello(dingens) alias blub:DingensBlubber {
+    something {
+        special {
+            content;
+        }
+    }
+};
+
+hello 42 {
+    world;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/hello.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,3 @@
+include yslt.yml2
+
+tstylesheet template "/" | hello, world
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/i.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,1 @@
+decl x { y };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/idl.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,3 @@
+decl module +name;
+decl interface +name;
+decl _ +type +name alias func;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/indention.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,8 @@
+include yslt.yml2
+
+tstylesheet template "/" {
+    0> something\n
+    1> indent by 1\n
+    indent 1;
+     > also indent by 1\n
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/list.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,8 @@
+decl list(name);
+decl title alias columnTitle;
+
+list "List of goods" {
+    head title "Goods", title "Price";
+    row value "Beer", value 20;
+    row value "Wine", value 30;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/macros_test.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,4 @@
+decl blub(%macro, myAttr="something %macro for testing");
+
+testing
+    blub "nice";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/model.ymi	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,15 @@
+decl package +name;
+decl class +name;
+decl attr +type +name;
+
+package Bla {
+    class Customer {
+        attr long id;
+        attr string name;
+    }
+    class Order {
+        attr long id;
+        attr string desc;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/namespace.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,5 @@
+include yslt.yml2
+
+tstylesheet template "/" | «namespace-uri(*)»
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/opertest.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,5 @@
+include yslt.yml2
+
+define operator "π(\w+)" as value "%1", value "%1-19";
+
+tstylesheet template "/" | hello, world π42
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/rechner.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,14 @@
+include yslt.yml2
+
+decl ip(%value, name="ip", select="'%value'") alias xsl:variable;
+decl rechner(%name, *ip, test="@name = '%name'") alias xsl:when {
+    ip *ip;
+    | ip ist «$ip»
+};
+
+tstylesheet template "/rechner" {
+    choose {
+        rechner "R1", "192.168.1.10";
+        rechner "R2", "192.168.1.11";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/sample.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,7 @@
+include idl.yml2
+
+module blub {
+    interface bla {
+        int f(in long a, out long b);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/simple.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,11 @@
+include yslt.yml2
+
+tstylesheet {
+    template "/list" html body table apply "address";
+
+    template "address" tr {
+        td value "name";
+        td value "street";
+        td value "city";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/table.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,8 @@
+decl module +name;
+decl class +name;
+decl attr +type +name;
+
+class Table class Data {
+    attr long id;
+    attr string text;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/table2ddl.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,50 @@
+include yslt.yml2
+
+define operator "“(.*?)”" as call "idl2ddl" with "type", "%1";
+
+tstylesheet {
+    const "idtype", "'INTEGER'";
+
+    template "/" apply "module|class", 0;
+
+    template "module" {
+        param "namespace", "''";
+        choose {
+            when "$namespace=''"
+                apply "module|class", 0 with "namespace", "@name";
+            otherwise
+                apply "module|class", 0 with "namespace", "concat($namespace,'_', @name)";
+        }
+    }
+
+    template "class" {
+        param "namespace", "''";
+
+        choose {
+            when "$namespace=''"    | CREATE TABLE «@name» (
+            otherwise               | CREATE TABLE «$namespace»_«@name» (
+        }
+
+        if "count(attr[@name='id'])=0" |> id «$idtype»`if "count(attr)>0" > , `
+
+        const "name", "@name";
+        foreach "//class[class/@name=$name]" |> «@name»_fk «$idtype»,
+
+        apply "attr";
+
+        | );
+
+        apply "class", 0 with "namespace", "$namespace";
+    }
+
+    template "attr" | «@name» “@type”`if "position() != last()" > , `
+
+    function "idl2ddl" {
+        param "type";
+
+        choose {
+            when "$type='string'"   > VARCHAR
+            when "$type='long'"     > INTEGER
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/text_test.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,6 @@
+testing {
+    ||
+    `` dingens;
+    `dingens;`
+    ||
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/textest.xml	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,5 @@
+<testing>
+    Dingens
+    <blub />
+    Bumens
+</testing>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/types.xml	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,1 @@
+<types><type>string</type><type>int</type></types>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/types.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,4 @@
+types {
+    type "string";
+    type "int";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/uml.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,46 @@
+include yslt.yml2
+
+decl UML is textstylesheet(
+    xmlns:uml="http://schema.omg.org/spec/UML/2.1",
+    xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" 
+) {
+    output *output;
+    const "space", !"'" + " " * 200 + "'"!;
+    param "autoindent", 4;
+    template "text()";
+    content;
+};
+
+decl Root is template(match="/xmi:XMI/uml:Model/packagedElement"),
+     All  is template(%match="*", match="//[%match]");
+
+decl Package is template(
+    %match="true()",
+    match="packagedElement[@xmi:type='uml:Package' and (%match)]"
+);
+
+decl applyPackages is apply (
+    %match="true()",
+    select="packagedElement[@xmi:type='uml:Package' and (%match)]"
+);
+
+decl Class is template(
+    %match="true()",
+    match="packagedElement[@xmi:type='uml:Class' and (%match)]"
+);
+
+decl applyClasses is apply (
+    %match="true()",
+    select="packagedElement[@xmi:type='uml:Class' and (%match)]"
+);
+
+decl Attribute is template(
+    %match="true()",
+    match="ownedAttribute[@xmi:type='uml:Property' and type/@xmi:type='uml:PrimitiveType' and (%match)]"
+);
+
+decl applyAttributes is apply (
+    %match="true()",
+    select="ownedAttribute[@xmi:type='uml:Property' and type/@xmi:type='uml:PrimitiveType' and (%match)]"
+);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/uml2idl.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,22 @@
+include yslt.yml2
+
+define operator "†(\w+)" as call "printType" with "name", "%1";
+define operator "“(.*?)”" as call "ucase" with "text", "%1";
+
+function "ucase" {
+    param "text";
+
+    > «translate(substring($text, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')»
+    > «substring($text, 2)»
+}
+
+function "printType" {
+    param "name";
+
+    choose {
+        when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#UnlimitedNatural"'
+            > long
+        when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#String"'
+            > string
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/uml2sql.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,20 @@
+define operator "†(\w+)" as call "printType" with "name", "%1";
+define operator "“(.*?)”" as call "ucase" with "text", "%1";
+
+function "ucase" {
+    param "text";
+
+    > «translate(substring($text, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')»
+    > «substring($text, 2)»
+}
+
+function "printType" {
+    param "name";
+
+    choose {
+        when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#UnlimitedNatural"'
+            > INTEGER
+        when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#String"'
+            > VARCHAR
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/union.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,19 @@
+include yslt.yml2
+
+estylesheet {
+    template "/list" cities
+        apply "address[name='Meier']" with "me", ".";
+
+    template "address" {
+        param "me";
+
+        call "f" with "addresses", "$me/address[name='Schmid'] | .";
+    }
+
+    function "f" {
+        param "addresses";
+
+        foreach "$addresses"
+            city value "city";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/vorlesung.xmi	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,185 @@
+<xmi:XMI xmi:version="2.1" xmlns:uml="http://schema.omg.org/spec/UML/2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1">
+	<xmi:Documentation exporter="Bouml" exporterVersion="1.10"/>
+	<uml:Model xmi:type="uml:Model" xmi:id="themodel" name="Bla">
+		<packagedElement xmi:type="uml:Package" xmi:id="BOUML_0x81_22" name ="Bla">
+			<packagedElement xmi:type="uml:Class" name="Customer" xmi:id="BOUML_0x1f417_4" visibility="package" isAbstract="false" >
+				<ownedAttribute xmi:type="uml:Property" name="id" xmi:id="BOUML_0x1f417_1" visibility="private">
+					<type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#UnlimitedNatural"/>
+				</ownedAttribute>
+				<ownedAttribute xmi:type="uml:Property" name="orders" xmi:id="BOUML_0x1f417_0" visibility="private" association="BOUML_ASSOC_0x1f417_0" aggregation="none">
+					<type xmi:type="uml:Class" xmi:idref="BOUML_0x1f497_4"/>
+				</ownedAttribute>
+				<ownedAttribute xmi:type="uml:Property" name="name" xmi:id="BOUML_0x1f497_1" visibility="private">
+					<type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#String"/>
+				</ownedAttribute>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Class" name="Order" xmi:id="BOUML_0x1f497_4" visibility="package" isAbstract="false" >
+				<ownedAttribute xmi:type="uml:Property" name="" xmi:id="BOUML_0x1f497_0" visibility="private" association="BOUML_ASSOC_0x1f417_0" aggregation="shared">
+					<type xmi:type="uml:Class" xmi:idref="BOUML_0x1f417_4"/>
+				</ownedAttribute>
+				<ownedAttribute xmi:type="uml:Property" name="id" xmi:id="BOUML_0x1f517_1" visibility="private">
+					<type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#UnlimitedNatural"/>
+				</ownedAttribute>
+				<ownedAttribute xmi:type="uml:Property" name="desc" xmi:id="BOUML_0x1f597_1" visibility="private">
+					<type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#String"/>
+				</ownedAttribute>
+			</packagedElement>
+			<packagedElement xmi:type="uml:StateMachine" xmi:id="BOUML_0x1f417_23" name="Support">
+				<region xmi:type="uml:Region" xmi:id="BOUML_IMPLICIT_REGION_0x1f417_23" name="Bouml_Implicit_Region">
+					<subvertex xmi:type="uml:State" xmi:id="BOUML_0x1f497_23" name="Open">
+						<incoming xmi:idref="BOUML_0x1f417_24"/>
+						<region xmi:type="uml:Region" xmi:id="BOUML_IMPLICIT_REGION_0x1f497_23" name="Bouml_Implicit_Region">
+							<outgoing xmi:idref="BOUML_0x1f497_24"/>
+						</region>
+					</subvertex>
+					<subvertex xmi:type="uml:Pseudostate" xmi:id="BOUML_0x1f417_28" kind="initial">
+						<outgoing xmi:idref="BOUML_0x1f417_24"/>
+					</subvertex>
+					<subvertex xmi:type="uml:State" xmi:id="BOUML_0x1f517_23" name="Catched">
+						<incoming xmi:idref="BOUML_0x1f497_24"/>
+						<region xmi:type="uml:Region" xmi:id="BOUML_IMPLICIT_REGION_0x1f517_23" name="Bouml_Implicit_Region">
+							<outgoing xmi:idref="BOUML_0x1f517_24"/>
+							<outgoing xmi:idref="BOUML_0x1f617_24"/>
+						</region>
+					</subvertex>
+					<subvertex xmi:type="uml:State" xmi:id="BOUML_0x1f617_23" name="Terminated">
+						<incoming xmi:idref="BOUML_0x1f517_24"/>
+						<region xmi:type="uml:Region" xmi:id="BOUML_IMPLICIT_REGION_0x1f617_23" name="Bouml_Implicit_Region">
+							<outgoing xmi:idref="BOUML_0x1f597_24"/>
+						</region>
+					</subvertex>
+					<subvertex xmi:type="uml:FinalState" xmi:id="BOUML_0x1f517_30" name="Final">
+						<incoming xmi:idref="BOUML_0x1f597_24"/>
+						<incoming xmi:idref="BOUML_0x1f697_24"/>
+					</subvertex>
+					<subvertex xmi:type="uml:State" xmi:id="BOUML_0x1f697_23" name="InProgressLevel1">
+						<incoming xmi:idref="BOUML_0x1f617_24"/>
+						<region xmi:type="uml:Region" xmi:id="BOUML_IMPLICIT_REGION_0x1f697_23" name="Bouml_Implicit_Region">
+							<outgoing xmi:idref="BOUML_0x1f717_24"/>
+							<outgoing xmi:idref="BOUML_0x1f797_24"/>
+						</region>
+					</subvertex>
+					<subvertex xmi:type="uml:State" xmi:id="BOUML_0x1f717_23" name="Solved">
+						<incoming xmi:idref="BOUML_0x1f717_24"/>
+						<incoming xmi:idref="BOUML_0x1f897_24"/>
+						<region xmi:type="uml:Region" xmi:id="BOUML_IMPLICIT_REGION_0x1f717_23" name="Bouml_Implicit_Region">
+							<outgoing xmi:idref="BOUML_0x1f697_24"/>
+						</region>
+					</subvertex>
+					<subvertex xmi:type="uml:State" xmi:id="BOUML_0x1f797_23" name="EscalationLevel2">
+						<incoming xmi:idref="BOUML_0x1f797_24"/>
+						<region xmi:type="uml:Region" xmi:id="BOUML_IMPLICIT_REGION_0x1f797_23" name="Bouml_Implicit_Region">
+							<outgoing xmi:idref="BOUML_0x1f817_24"/>
+						</region>
+					</subvertex>
+					<subvertex xmi:type="uml:State" xmi:id="BOUML_0x1f817_23" name="CatchedLevel2">
+						<incoming xmi:idref="BOUML_0x1f817_24"/>
+						<region xmi:type="uml:Region" xmi:id="BOUML_IMPLICIT_REGION_0x1f817_23" name="Bouml_Implicit_Region">
+							<outgoing xmi:idref="BOUML_0x1f897_24"/>
+						</region>
+					</subvertex>
+				</region>
+				<transition xmi:type="uml:Transition" xmi:id="BOUML_0x1f497_24" source="BOUML_0x1f497_23" target="BOUML_0x1f517_23">
+				</transition>
+				<transition xmi:type="uml:Transition" xmi:id="BOUML_0x1f417_24" source="BOUML_0x1f417_28" target="BOUML_0x1f497_23">
+				</transition>
+				<transition xmi:type="uml:Transition" xmi:id="BOUML_0x1f517_24" name="Joke" source="BOUML_0x1f517_23" target="BOUML_0x1f617_23">
+				</transition>
+				<transition xmi:type="uml:Transition" xmi:id="BOUML_0x1f617_24" source="BOUML_0x1f517_23" target="BOUML_0x1f697_23">
+				</transition>
+				<transition xmi:type="uml:Transition" xmi:id="BOUML_0x1f597_24" source="BOUML_0x1f617_23" target="BOUML_0x1f517_30">
+				</transition>
+				<transition xmi:type="uml:Transition" xmi:id="BOUML_0x1f717_24" source="BOUML_0x1f697_23" target="BOUML_0x1f717_23">
+				</transition>
+				<transition xmi:type="uml:Transition" xmi:id="BOUML_0x1f797_24" source="BOUML_0x1f697_23" target="BOUML_0x1f797_23">
+				</transition>
+				<transition xmi:type="uml:Transition" xmi:id="BOUML_0x1f697_24" source="BOUML_0x1f717_23" target="BOUML_0x1f517_30">
+				</transition>
+				<transition xmi:type="uml:Transition" xmi:id="BOUML_0x1f817_24" name="Level2Catches" source="BOUML_0x1f797_23" target="BOUML_0x1f817_23">
+				</transition>
+				<transition xmi:type="uml:Transition" xmi:id="BOUML_0x1f897_24" source="BOUML_0x1f817_23" target="BOUML_0x1f717_23">
+				</transition>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Class" name="FinancialAccounting" xmi:id="BOUML_0x1fa97_4" visibility="package" isAbstract="false" >
+				<ownedAttribute xmi:type="uml:Property" name="" xmi:id="BOUML_0x1fa17_0" visibility="private" association="BOUML_ASSOC_0x1fa17_0" aggregation="none">
+					<type xmi:type="uml:Class" xmi:idref="BOUML_0x1fb17_4"/>
+				</ownedAttribute>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Class" name="Account" xmi:id="BOUML_0x1fb17_4" visibility="package" isAbstract="false" >
+				<ownedAttribute xmi:type="uml:Property" name="" xmi:id="BOUML_0x1fa97_0" visibility="private" association="BOUML_ASSOC_0x1fa17_0" aggregation="composite">
+					<type xmi:type="uml:Class" xmi:idref="BOUML_0x1fa97_4"/>
+				</ownedAttribute>
+				<ownedAttribute xmi:type="uml:Property" name="" xmi:id="BOUML_0x1fb97_0" visibility="private" association="BOUML_ASSOC_0x1fb17_0" aggregation="shared">
+					<type xmi:type="uml:Class" xmi:idref="BOUML_0x1fb97_4"/>
+				</ownedAttribute>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Class" name="FinTransaction" xmi:id="BOUML_0x1fb97_4" visibility="package" isAbstract="false" >
+				<ownedAttribute xmi:type="uml:Property" name="" xmi:id="BOUML_0x1fb17_0" visibility="private" association="BOUML_ASSOC_0x1fb17_0" aggregation="none">
+					<type xmi:type="uml:Class" xmi:idref="BOUML_0x1fb17_4"/>
+					<lowerValue xmi:type="uml:LiteralString" xmi:id="BOUML_MULTIPLICITY_L_0x1fb17_0" value="2"/>
+					<upperValue xmi:type="uml:LiteralString" xmi:id="BOUML_MULTIPLICITY_U_0x1fb17_0" value="2"/>
+				</ownedAttribute>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Class" name="SingleFinTransaction" xmi:id="BOUML_0x1fc17_4" visibility="package" isAbstract="false" >
+				<generalization xmi:type="uml:Generalization" xmi:id="BOUML_0x1fc97_0" general="BOUML_0x1fb97_4"/>
+				<ownedAttribute xmi:type="uml:Property" name="" xmi:id="BOUML_0x1fd97_0" visibility="private" association="BOUML_ASSOC_0x1fd17_0" aggregation="shared">
+					<type xmi:type="uml:Class" xmi:idref="BOUML_0x1fc97_4"/>
+				</ownedAttribute>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Class" name="FinTransactionBatch" xmi:id="BOUML_0x1fc97_4" visibility="package" isAbstract="false" >
+				<generalization xmi:type="uml:Generalization" xmi:id="BOUML_0x1fc17_0" general="BOUML_0x1fb97_4"/>
+				<ownedAttribute xmi:type="uml:Property" name="" xmi:id="BOUML_0x1fd17_0" visibility="private" association="BOUML_ASSOC_0x1fd17_0" aggregation="none">
+					<type xmi:type="uml:Class" xmi:idref="BOUML_0x1fc17_4"/>
+				</ownedAttribute>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Interface" name="Blub" xmi:id="BOUML_0x1ff17_4" visibility="package" isAbstract="true" >
+				<ownedOperation xmi:type="uml:Operation" name="bla" xmi:id="BOUML_0x1f417_2" visibility="public" isAbstract="false">
+					<ownedParameter name="return" xmi:id="BOUML_return_1" direction="return">
+						<type xmi:type="uml:PrimitiveType" href="http://schema.omg.org/spec/UML/2.1/uml.xml#Boolean"/>
+					</ownedParameter>
+				</ownedOperation>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Class" name="Class" xmi:id="BOUML_0x1f917_4" visibility="package" isAbstract="false" >
+			</packagedElement>
+			<packagedElement xmi:type="uml:Class" name="Persistant" xmi:id="BOUML_0x1f997_4" visibility="package" isAbstract="false" >
+				<generalization xmi:type="uml:Generalization" xmi:id="BOUML_0x1f917_0" general="BOUML_0x1f917_4"/>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Class" name="Document" xmi:id="BOUML_0x1fa17_4" visibility="package" isAbstract="false" >
+				<generalization xmi:type="uml:Generalization" xmi:id="BOUML_0x1f997_0" general="BOUML_0x1f997_4"/>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Class" name="LoggedTransaction" xmi:id="BOUML_0x1fd17_4" visibility="package" isAbstract="false" >
+				<generalization xmi:type="uml:Generalization" xmi:id="BOUML_0x1fe17_0" general="BOUML_0x1f997_4"/>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Actor" name="Supporter" xmi:id="BOUML_0x1fd97_4" visibility="package" isAbstract="false" >
+			</packagedElement>
+			<packagedElement xmi:type="uml:Actor" name="FirstLevel" xmi:id="BOUML_0x1fe17_4" visibility="package" isAbstract="false" >
+				<generalization xmi:type="uml:Generalization" xmi:id="BOUML_0x1fe97_0" general="BOUML_0x1fd97_4"/>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Actor" name="SecondLevel" xmi:id="BOUML_0x1fe97_4" visibility="package" isAbstract="false" >
+				<generalization xmi:type="uml:Generalization" xmi:id="BOUML_0x1ff17_0" general="BOUML_0x1fd97_4"/>
+			</packagedElement>
+			<packagedElement xmi:type="uml:UseCase" xmi:id="BOUML_0x1f417_5" name="Assigning">
+			</packagedElement>
+			<packagedElement xmi:type="uml:Association" xmi:id="BOUML_ASSOC_0x1f417_0" visibility="private">
+				<memberEnd xmi:idref="BOUML_0x1f417_0"/>
+				<memberEnd xmi:idref="BOUML_0x1f497_0"/>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Association" xmi:id="BOUML_ASSOC_0x1fa17_0" visibility="private">
+				<memberEnd xmi:idref="BOUML_0x1fa17_0"/>
+				<memberEnd xmi:idref="BOUML_0x1fa97_0"/>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Association" xmi:id="BOUML_ASSOC_0x1fb17_0" visibility="private">
+				<memberEnd xmi:idref="BOUML_0x1fb17_0"/>
+				<memberEnd xmi:idref="BOUML_0x1fb97_0"/>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Association" xmi:id="BOUML_ASSOC_0x1fd17_0" visibility="private">
+				<memberEnd xmi:idref="BOUML_0x1fd17_0"/>
+				<memberEnd xmi:idref="BOUML_0x1fd97_0"/>
+			</packagedElement>
+			<packagedElement xmi:type="uml:Association" xmi:id="BOUML_UCAC0_0x1f997_11">
+				<ownedEnd xmi:type="uml:Property" xmi:id="BOUML_AC0_0x1f997_11" type="BOUML_0x1fd97_4" association="BOUML_UCAC0_0x1f997_11"/>
+				<ownedEnd xmi:type="uml:Property" xmi:id="BOUML_UC0_0x1f997_11" type="BOUML_0x1f417_5" association="BOUML_UCAC0_0x1f997_11"/>
+			</packagedElement>
+		</packagedElement>
+	</uml:Model>
+</xmi:XMI>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/webseite.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,11 @@
+include yslt.yml2
+
+stylesheet {
+    template "/list" html body table border=1 apply "address";
+
+    template "address" tr {
+        td value "name";
+        td value "street";
+        td value "city";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/xmi2ddl.uml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,23 @@
+include uml.yml2
+
+UML {
+    include uml2sql.yml2
+
+    Root applyPackages;
+
+    Package {
+        param "name", "''";
+        if "$name=''"  apply "packagedElement", 0 { with "name", "@name"; }
+        if "$name!=''" apply "packagedElement", 0 { with "name", "concat($name, '_', @name)"; }
+    }
+
+    Class {
+        param "name";
+
+        | CREATE TABLE «$name»_«@name» (
+        applyAttributes;
+        | );
+    }
+
+    Attribute | «@name» †type`if "position()!=last()" > ,`
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/xmi2ddl.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,34 @@
+include yslt.yml2
+
+tstylesheet xmlns:uml="http://schema.omg.org/spec/UML/2.1",
+            xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" {
+
+    template "/" apply "xmi:XMI/uml:Model/packagedElement", 0;
+
+    template "packagedElement[@xmi:type='uml:Package']" {
+        param "name", "''";
+        if "$name=''"  apply "packagedElement", 0 { with "name", "@name"; }
+        if "$name!=''" apply "packagedElement", 0 { with "name", "concat($name, '_', @name)"; }
+    }
+
+    template "packagedElement[@xmi:type='uml:Class']" {
+        param "name";
+
+        | CREATE TABLE «$name»_«@name» (
+        apply "ownedAttribute";
+        | );
+    }
+
+    template "ownedAttribute[@xmi:type='uml:Property' and type/@xmi:type='uml:PrimitiveType']" {
+        0> «@name»
+        choose {
+            when "type/@href='http://schema.omg.org/spec/UML/2.1/uml.xml#String'"
+                >  VARCHAR
+
+            // [...] for other types, extend when clauses
+        }
+        if "position()!=last()" > ,
+        text "\n";
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/xmi2idl.uml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,21 @@
+include uml.yml2
+
+UML {
+    include uml2idl.yml2
+
+    Root apply "packagedElement", 0;
+
+    Package {
+        | module «@name» {
+        applyClass;
+        | };
+    }
+
+    Class("@stereotype='Struct'") {
+        | interface «@name» {
+        applyAttributes;
+        | };
+    }
+
+    Attribute | attribute †type «@name»;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/xml2.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,2 @@
+include yslt.yml2; tstylesheet template "*" { param "pre", "''"; if "text()!=''" | «$pre»/«name()»=«text()»
+apply "*", 0 with "pre", "concat($pre, '/', name())"; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/ydl2idl.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,23 @@
+include yslt.yml2
+
+tstylesheet {
+    template "module" {
+        | module «name(*)» {
+        apply "*/interface";
+        | };
+    }
+
+    template "interface" {
+        | interface «name(*)» {
+        apply "*/*", mode="func";
+        | };
+    }
+
+    template "*", mode="func"
+        | «name(.)» «name(*)»(`apply "*/*", mode="parms";`);
+
+    template "*", mode="parms" {
+        > «name(.)» «name(*)» «name(*/*)»
+        if "position() != last()" > , 
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/standardlib.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,55 @@
+function "yml:hex2dec" {
+    param "hex";
+    param "_result", 0;
+    
+    const "hd", "substring($hex, 1, 1)";
+    const "a", """translate($hd, 'ABCDEFabcdef123456789',
+        '123456123456000000000')""";
+
+    const "d" choose {
+        when "$a>0" value "$a + 9";
+        otherwise value "$hd";
+    }
+
+    choose {
+        when "string-length($hex) = 1"
+            value "$_result * 16 + $d";
+        otherwise call "yml:hex2dec"
+            with "hex", "substring($hex, 2, 8)", 
+            with "_result", "$_result * 16 + $d";
+    }
+}
+
+function "yml:dec2hex" {
+    param "dec";
+    param "bits", !16**7!;
+
+    const "v", "floor($dec div $bits)";
+    value "substring('0123456789abcdef', $v + 1, 1)";
+
+    if "$bits > 1" call "yml:dec2hex"
+        with "dec", "$dec - $bits * $v",
+        with "bits", "$bits div 16";
+}
+
+def "yml:dec2hex" {
+    param "dec";
+    param "digits", 8;
+        
+    result call "yml:dec2hex" with "dec", "$dec", with "bits", "math:power(16, $digits - 1)";
+}
+
+def "yml:hex2dec" {
+    param "hex";
+    result call "yml:hex2dec" with "hex", "$hex";
+}
+
+def "yml:lcase" {
+    param "text", "''";
+    result "translate($text, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')";
+}
+
+def "yml:ucase" {
+    param "text", "''";
+    result "translate($text, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toolchain.en.yhtml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,380 @@
+include homepage.en.yhtml2
+
+page "The YML Toolchain" {
+    h1 > The Toolchain
+
+    p   >>
+        There are to possibilities to handle YML files: the YML compiler and the YML/YSLT
+        processor.
+        >>
+
+    h2 id=compiler > The YML compiler
+
+    p   >>
+        The YML ¬http://en.wikipedia.org/wiki/Compiler compiler¬ is a small
+        ¬http://www.python.org Python script¬. It provides the
+        ¬http://en.wikipedia.org/wiki/Command-line_interface command line¬ front end «yml2c».
+        As default, it compiles your ¬http://en.wikipedia.org/wiki/Scripting_language script¬
+        and outputs to ¬http://en.wikipedia.org/wiki/Stdout#Standard_output_.28stdout.29 stdout¬,
+        that usually is the ¬http://en.wikipedia.org/wiki/Computer_terminal terminal¬.
+        Your ¬http://en.wikipedia.org/wiki/Shell_(computing) shell¬ provides options to redirect
+        the output into a ¬http://en.wikipedia.org/wiki/Pipeline_(Unix) pipe¬ or
+        a ¬http://en.wikipedia.org/wiki/Computer_file file¬.
+        >>
+
+    p > So to use it, just enter «yml2c» followed by the filename of your YML script:
+
+    Code | % yml2c myscript.yml2 > myscript.result
+
+    p > The «yml2c» command has the following options:
+
+    h3 > -h, --help
+
+    p > Show a help message and exit.
+
+    h3 > -C, --old-syntax
+
+    p > Use the syntax of YML 2 version 1.x (compatibility mode).
+
+    h3 > -D, --emit-linenumbers
+
+    p > Emit line numbers into the resulting XML for debugging purposes.
+
+    h3 > -E ENCODING, --encoding ENCODING
+
+    p > encoding of input files (default: UTF-8)
+
+    h3 > -I INCLUDE_PATH, --include=INCLUDE_PATH
+
+    p { "Precede " code > ¬features#ymlpath YML_PATH¬
+      " by a colon separated " code "INCLUDE_PATH"; " to search for include files." }
+
+    h3 > -m, --omit-empty-parm-tags
+    
+    p   >>
+        Does nothing (only there for compatibility with older versions of «yml2c»).
+        >>
+
+    h3 > -n NORMALIZATION, --normalization=NORMALIZATION
+
+    p   >>
+        Unicode normalization (none, NFD, NFKD, NFC, NFKC, FCD, default is NFC)
+        >>
+
+    h3 > -o FILE, --output=FILE
+
+    p > Don't output to stdout, instead place output in file «FILE».
+
+    h3 > -p, --parse-only
+
+    p   >>
+        ¬http://fdik.org/pyPEG Parse¬ only, then output ¬http://fdik.org/pyPEG/#pyAST pyAST¬
+        as text to stdout. The pyAST is the
+        ¬http://en.wikipedia.org/wiki/Abstract_syntax_tree Abstract Syntax Tree¬
+        of the parsed script as ¬http://docs.python.org/library/stdtypes.html Python data structure¬.
+        >>
+
+    h3 > -V, --version
+
+    p   >>
+        Show version and ¬http://en.wikipedia.org/wiki/Copyleft Copyleft¬ information of
+        the YML implementation.
+        >>
+
+    h3 > YML_PATH environment variable
+
+    p   >>
+        If «YML_PATH» is set to a colon separated ¬http://en.wikipedia.org/wiki/Path_(computing) path¬
+        list, then the `a href="features#including" code "include";` statement searches these paths.
+        If «YML_PATH» is not set, the local directory «.» is searched for files.
+        >>
+
+    h2 id=processor > The YML/YSLT processor
+
+    p   >>
+        If you're processing more complex tasks, say, executing an YSLT script over some
+        YML files, the YML/YSLT processor will possible fit better to your needs.
+        >>
+
+    p   >>
+        To use it, enter «yml2proc -y» followed by the filename of your YSLT script,
+        followed by the filenames of your YML input files:
+        >>
+
+    Code | % yml2proc -y myscript.ysl2 inputfile.yml2 > myscript.result
+
+    p > The YML/YSLT processor requires the ¬http://codespeak.net/lxml/ lxml Python library¬.
+
+    p > The YML/YSLT processor has the following options:
+
+    h3 > -h, --help
+
+    p > Show a help message and exit.
+
+    h3 > -C, --old-syntax
+
+    p > Use the syntax of YML 2 version 1.x (compatibility mode).
+
+    h3 > -D, --emit-linenumbers
+
+    p > Emit line numbers into the resulting XML for debugging purposes.
+
+    h3 id=debug > --debug
+
+    p   >>
+        switch on debug tracing to stderr; this enables the functionality
+        of the ¬yslt#debug debug(msg)¬ and ¬yslt#assert assert yml:assert(test, msg)¬ YSLT functions.
+        >>
+
+    h3 > -E ENCODING, --encoding ENCODING
+
+    p > encoding of input files (default: UTF-8)
+
+    h3 > -I INCLUDE_PATH, --include=INCLUDE_PATH
+
+    p { "Precede " code > ¬features#ymlpath YML_PATH¬
+      " by a colon separated " code "INCLUDE_PATH"; " to search for include files." }
+
+    h3 > -m, --omit-empty-parm-tags
+    
+    p   >>
+        Does nothing (only there for compatibility with older versions of «yml2proc»).
+        >>
+
+    h3 > -M, --empty-input-document
+
+    p   >>
+        Use an empty input document for YSLT or XSLT processing
+        >>
+
+    h3 > -n NORMALIZATION, --normalization=NORMALIZATION
+
+    p   >>
+        Unicode normalization (none, NFD, NFKD, NFC, NFKC, FCD, default is NFC)
+        >>
+
+    h3 > -o FILE, --output=FILE
+
+    p > Don't output to stdout, instead place output in file «FILE».
+
+    h3 > -p, --parse-only
+
+    p   >>
+        ¬http://fdik.org/pyPEG Parse¬ only, then output ¬http://fdik.org/pyPEG/#pyAST pyAST¬
+        as text to stdout. The pyAST is the
+        ¬http://en.wikipedia.org/wiki/Abstract_syntax_tree Abstract Syntax Tree¬
+        of the parsed script as ¬http://docs.python.org/library/stdtypes.html Python data structure¬.
+        >>
+
+    h3 > -e XPATH, --xpath=XPATH
+
+    p > Execute XPath expression XPATH and print result
+
+    p   >>
+        If you omit -y YSLTSCRIPT, then the result is printed. If you have an additional
+        -y YSLTSCRIPT parameter, then your YSLT script is processing the result of the
+        XPath expression only instead of processing the complete content of your input documents
+        >>
+
+    h3 > -P, --pretty
+    
+    p > Pretty print output adding whitespace
+
+    h3 > -x, --xml
+    
+    p > Input documents are XML already, don't try to convert them from YML
+
+    h3 > -y YSLTSCRIPT, --yslt=YSLTSCRIPT
+
+    p > Execute YSLT script YSLTSCRIPT
+
+    h3 > -X XSLTSCRIPT, --xslt=XSLTSCRIPT
+
+    p > Execute XSLT script XSLTSCRIPT
+
+    h3 > -d PARAMS, --paramdict=PARAMS
+
+    p   >>
+        Call XSLT or YSLT script with dictionary PARAMS as XPath parameters. PARAMS is a Python
+        expression which evaluates to a Python dictionary.
+        >>
+
+    p > Sample:
+
+    p code > yml2proc -y myscript -d 'dict(a=3, b="element[@name=2]")'
+
+    h3 > -s STRINGPARAMS, --stringparamdict=STRINGPARAMS
+
+    p   >>
+        Call XSLT or YSLT script with dictionary STRINGPARAMS as string parameters. STRINGPARAMS
+        is a Python expression which evaluates to a Python dictionary.
+        >>  
+
+    p > Sample:
+
+    p code > yml2proc -y myscript -s 'dict(forename="Hans", name="Meier")'
+
+    h3 > -Y, --xml2yml
+
+    p > Convert XML to normalized YML. Equivalent to -xy xml2yml.ysl2
+
+    p > The file xml2yml.ysl2 has to be in YML_PATH.
+
+    h3 > -V, --version
+
+    p   >>
+        Show version and ¬http://en.wikipedia.org/wiki/Copyleft Copyleft¬ information of
+        the YML implementation and exit.
+        >>
+
+    h3 > YML_PATH environment variable
+
+    p   >>
+        If «YML_PATH» is set to a colon separated ¬http://en.wikipedia.org/wiki/Path_(computing) path¬
+        list, then the `a href="features#including" code "include";` statement searches these paths.
+        If «YML_PATH» is not set, the local directory «.» is searched for files.
+        >>
+    
+    h2 id=recommended > Recommended external tools
+
+    h3 > XSLT Processor
+
+    p   >>
+        If you want to use ¬yslt YSLT¬ with «yml2c» instead of «yml2proc», you additionally need an
+        ¬http://www.w3.org/TR/xslt XSLT¬ processor.
+        >>
+
+    p > For that case, I recommend the ¬http://xmlsoft.org/XSLT/xsltproc2.html xsltproc tool¬.
+
+    p > To process YSLT, just use a pipe with the «xsltproc» command:
+
+    Code | % yml2c customer.ysl2 | xsltproc - customer.xml > customer.html
+
+    h3 > XML Renicing Tool
+
+    p   >>
+        Sometimes, you may want to have more human readable output with «yml2c». So an
+        ¬http://www.w3.org/XML/ XML¬ renicing tool can be helpful.
+        >>
+
+    p > The ¬http://xmlstar.sourceforge.net/ XMLStarlet¬ command line tool may be of interest.
+
+    p > Have a look on its «fo» command.
+
+    h3 > Windows tool chain
+
+    p   >>
+        See also the tips for a
+        ¬http://www.auchdieserschwachsinnmussinsinternet.de/2009-03/#s1236859037 Windows tool chain¬
+        for YML.
+        >>
+
+    h1 id=downloads > Downloads
+
+    p > You can here ¬http://fdik.org/yml2.tar.bz2 download the newest release of YML¬.
+
+    h2 > Older versions
+
+    p   >>
+        ¬http://fdik.org/yml-2.5.2.tar.bz2 YML 2.5.2¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.5.1.tar.bz2 YML 2.5.1¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.5.0.tar.bz2 YML 2.5.0¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.4.3.tar.bz2 YML 2.4.3¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.3.12.tar.bz2 YML 2.3.12¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.3.11.tar.bz2 YML 2.3.11¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.3.10.tar.bz2 YML 2.3.10¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.3.8.tar.bz2 YML 2.3.8¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.3.7.tar.bz2 YML 2.3.7¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.3.5.tar.bz2 YML 2.3.5¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.2.4.tar.bz2 YML 2.2.4¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.2.3.tar.bz2 YML 2.2.3¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.2.1.tar.bz2 YML 2.2.1¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.2.0.tar.bz2 YML 2.2.0¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.1.17.tar.bz2 YML 2.1.17¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.1.14.tar.bz2 YML 2.1.14¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.1.13.tar.bz2 YML 2.1.13¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.1.12.tar.bz2 YML 2.1.12¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.1.7.tar.bz2 YML 2.1.7¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.1.6.tar.bz2 YML 2.1.6¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.1.5.tar.bz2 YML 2.1.5¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.1.2.tar.bz2 YML 2.1.2¬
+        >>
+
+    p   >>
+        ¬http://fdik.org/yml-2.0.36.tar.bz2 YML 2.0.36¬
+        >>
+    p   >>
+        ¬http://fdik.org/yml-2.0.35.tar.bz2 YML 2.0.35¬
+        >>
+
+    p > ¬http://fdik.org/yml1 To the Homepage of version 1 of YML...¬
+
+    div id=bottom {
+        a href="yslt" "<< back to YSLT" " "
+        a href="#top" "^Top^" " "
+        a href="toolchain.en.yhtml2" "(source)"
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/syntax/yml2.vim	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,375 @@
+" Vim syntax file
+" Language:	YML2 generating C
+" Maintainer:	Volker Birk <vb@dingens.org>
+" Last Change:	2016 July 10
+
+" Quit when a (custom) syntax file was already loaded
+if exists("b:current_syntax")
+  finish
+endif
+
+" A bunch of useful YSLT keywords
+syn keyword	cStatement	include decl operator document def param const output value indent all text with withIndent element attrib processing number sort import message debug assert operator goto break return continue asm
+syn keyword	cLabel		stylesheet estylesheet textstylesheet tstylesheet template function case default
+syn keyword	cConditional	choose when otherwise if else switch
+syn keyword	cRepeat		for foreach apply while do
+
+syn keyword	cTodo		contained TODO FIXME XXX
+
+" It's easy to accidentally add a space after a backslash that was intended
+" for line continuation.  Some compilers allow it, which makes it
+" unpredicatable and should be avoided.
+syn match	cBadContinuation contained "\\\s\+$"
+
+" cCommentGroup allows adding matches for special things in comments
+syn cluster	cCommentGroup	contains=cTodo,cBadContinuation,ymlString
+
+" String and Character constants
+" Highlight special characters (those which have a backslash) differently
+syn match	cSpecial	display contained "\\\(x\x\+\|\o\{1,3}\|.\|$\)"
+if !exists("c_no_utf")
+  syn match	cSpecial	display contained "\\\(u\x\{4}\|U\x\{8}\)"
+endif
+syn region	ymlString		start=+L\=«+ skip=+\\\\\|\\"+ end=+»+ contains=cSpecial,@Spell
+if exists("c_no_cformat")
+  syn region	cString		start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,@Spell,ymlString
+  " cCppString: same as cString, but ends at end of line
+  syn region	cCppString	start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial,@Spell,ymlString
+else
+  if !exists("c_no_c99") " ISO C99
+    syn match	cFormat		display "%\(\d\+\$\)\=[-+' #0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlLjzt]\|ll\|hh\)\=\([aAbdiuoxXDOUfFeEgGcCsSpn]\|\[\^\=.[^]]*\]\)" contained
+  else
+    syn match	cFormat		display "%\(\d\+\$\)\=[-+' #0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlL]\|ll\)\=\([bdiuoxXDOUfeEgGcCsSpn]\|\[\^\=.[^]]*\]\)" contained
+  endif
+  syn match	cFormat		display "%%" contained
+  syn region	cString		start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,cFormat,@Spell,ymlString
+  " cCppString: same as cString, but ends at end of line
+  syn region	cCppString	start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial,cFormat,@Spell,ymlString
+endif
+
+syn match	cCharacter	"L\='[^\\]'"
+syn match	cCharacter	"L'[^']*'" contains=cSpecial
+if exists("c_gnu")
+  syn match	cSpecialError	"L\='\\[^'\"?\\abefnrtv]'"
+  syn match	cSpecialCharacter "L\='\\['\"?\\abefnrtv]'"
+else
+  syn match	cSpecialError	"L\='\\[^'\"?\\abfnrtv]'"
+  syn match	cSpecialCharacter "L\='\\['\"?\\abfnrtv]'"
+endif
+syn match	cSpecialCharacter display "L\='\\\o\{1,3}'"
+syn match	cSpecialCharacter display "'\\x\x\{1,2}'"
+syn match	cSpecialCharacter display "L'\\x\x\+'"
+
+"when wanted, highlight trailing white space
+if exists("c_space_errors")
+  if !exists("c_no_trail_space_error")
+    syn match	cSpaceError	display excludenl "\s\+$"
+  endif
+  if !exists("c_no_tab_space_error")
+    syn match	cSpaceError	display " \+\t"me=e-1
+  endif
+endif
+
+" This should be before cErrInParen to avoid problems with #define ({ xxx })
+if exists("c_curly_error")
+  syntax match cCurlyError "}"
+  syntax region	cBlock		start="{" end="}" contains=ALLBUT,cCurlyError,@cParenGroup,cErrInParen,cCppParen,cErrInBracket,cCppBracket,cCppString,@Spell fold
+else
+  syntax region	cBlock		start="{" end="}" transparent fold
+endif
+
+"catch errors caused by wrong parenthesis and brackets
+" also accept <% for {, %> for }, <: for [ and :> for ] (C99)
+" But avoid matching <::.
+syn cluster	cParenGroup	contains=cParenError,cIncluded,cSpecial,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cUserCont,cUserLabel,cBitField,cOctalZero,cCppOut,cCppOut2,cCppSkip,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom
+if exists("c_no_curly_error")
+  syn region	cParen		transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cCppString,@Spell
+  " cCppParen: same as cParen but ends at end-of-line; used in cDefine
+  syn region	cCppParen	transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cParen,cString,@Spell
+  syn match	cParenError	display ")"
+  syn match	cErrInParen	display contained "^[{}]\|^<%\|^%>"
+elseif exists("c_no_bracket_error")
+  syn region	cParen		transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cCppString,@Spell
+  " cCppParen: same as cParen but ends at end-of-line; used in cDefine
+  syn region	cCppParen	transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cParen,cString,@Spell
+  syn match	cParenError	display ")"
+  syn match	cErrInParen	display contained "[{}]\|<%\|%>"
+else
+  syn region	cParen		transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cErrInBracket,cCppBracket,cCppString,@Spell
+  " cCppParen: same as cParen but ends at end-of-line; used in cDefine
+  syn region	cCppParen	transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cErrInBracket,cParen,cBracket,cString,@Spell
+  syn match	cParenError	display "[\])]"
+  syn match	cErrInParen	display contained "[\]{}]\|<%\|%>"
+  syn region	cBracket	transparent start='\[\|<::\@!' end=']\|:>' contains=ALLBUT,@cParenGroup,cErrInParen,cCppParen,cCppBracket,cCppString,@Spell
+  " cCppBracket: same as cParen but ends at end-of-line; used in cDefine
+  syn region	cCppBracket	transparent start='\[\|<::\@!' skip='\\$' excludenl end=']\|:>' end='$' contained contains=ALLBUT,@cParenGroup,cErrInParen,cParen,cBracket,cString,@Spell
+  syn match	cErrInBracket	display contained "[);{}]\|<%\|%>"
+endif
+
+"integer number, or floating point number without a dot and with "f".
+syn case ignore
+syn match	cNumbers	display transparent "\<\d\|\.\d" contains=cNumber,cFloat,cOctalError,cOctal
+" Same, but without octal error (for comments)
+syn match	cNumbersCom	display contained transparent "\<\d\|\.\d" contains=cNumber,cFloat,cOctal
+syn match	cNumber		display contained "\d\+\(u\=l\{0,2}\|ll\=u\)\>"
+"hex number
+syn match	cNumber		display contained "0x\x\+\(u\=l\{0,2}\|ll\=u\)\>"
+" Flag the first zero of an octal number as something special
+syn match	cOctal		display contained "0\o\+\(u\=l\{0,2}\|ll\=u\)\>" contains=cOctalZero
+syn match	cOctalZero	display contained "\<0"
+syn match	cFloat		display contained "\d\+f"
+"floating point number, with dot, optional exponent
+syn match	cFloat		display contained "\d\+\.\d*\(e[-+]\=\d\+\)\=[fl]\="
+"floating point number, starting with a dot, optional exponent
+syn match	cFloat		display contained "\.\d\+\(e[-+]\=\d\+\)\=[fl]\=\>"
+"floating point number, without dot, with exponent
+syn match	cFloat		display contained "\d\+e[-+]\=\d\+[fl]\=\>"
+if !exists("c_no_c99")
+  "hexadecimal floating point number, optional leading digits, with dot, with exponent
+  syn match	cFloat		display contained "0x\x*\.\x\+p[-+]\=\d\+[fl]\=\>"
+  "hexadecimal floating point number, with leading digits, optional dot, with exponent
+  syn match	cFloat		display contained "0x\x\+\.\=p[-+]\=\d\+[fl]\=\>"
+endif
+
+" flag an octal number with wrong digits
+syn match	cOctalError	display contained "0\o*[89]\d*"
+syn case match
+
+if exists("c_comment_strings")
+  " A comment can contain cString, cCharacter and cNumber.
+  " But a "*/" inside a cString in a cComment DOES end the comment!  So we
+  " need to use a special type of cString: cCommentString, which also ends on
+  " "*/", and sees a "*" at the start of the line as comment again.
+  " Unfortunately this doesn't very well work for // type of comments :-(
+  syntax match	cCommentSkip	contained "^\s*\*\($\|\s\+\)"
+  syntax region cCommentString	contained start=+L\=\\\@<!"+ skip=+\\\\\|\\"+ end=+"+ end=+\*/+me=s-1 contains=cSpecial,cCommentSkip
+  syntax region cComment2String	contained start=+L\=\\\@<!"+ skip=+\\\\\|\\"+ end=+"+ end="$" contains=cSpecial
+  syntax region  cCommentL	start="//" skip="\\$" end="$" keepend contains=@cCommentGroup,cComment2String,cCharacter,cNumbersCom,cSpaceError,@Spell
+  if exists("c_no_comment_fold")
+    " Use "extend" here to have preprocessor lines not terminate halfway a
+    " comment.
+    syntax region cComment	matchgroup=cCommentStart start="/\*" end="\*/" contains=@cCommentGroup,cCommentStartError,cCommentString,cCharacter,cNumbersCom,cSpaceError,@Spell extend
+  else
+    syntax region cComment	matchgroup=cCommentStart start="/\*" end="\*/" contains=@cCommentGroup,cCommentStartError,cCommentString,cCharacter,cNumbersCom,cSpaceError,@Spell fold extend
+  endif
+else
+  syn region	cCommentL	start="//" skip="\\$" end="$" keepend contains=@cCommentGroup,cSpaceError,@Spell
+  if exists("c_no_comment_fold")
+    syn region	cComment	matchgroup=cCommentStart start="/\*" end="\*/" contains=@cCommentGroup,cCommentStartError,cSpaceError,@Spell extend
+  else
+    syn region	cComment	matchgroup=cCommentStart start="/\*" end="\*/" contains=@cCommentGroup,cCommentStartError,cSpaceError,@Spell fold extend
+  endif
+endif
+" keep a // comment separately, it terminates a preproc. conditional
+syntax match	cCommentError	display "\*/"
+syntax match	cCommentStartError display "/\*"me=e-1 contained
+
+syn keyword	cOperator	sizeof
+if exists("c_gnu")
+  syn keyword	cStatement	__asm__
+  syn keyword	cOperator	typeof __real__ __imag__
+endif
+syn keyword	cType		int long short char void
+syn keyword	cType		signed unsigned float double
+if !exists("c_no_ansi") || exists("c_ansi_typedefs")
+  syn keyword   cType		size_t ssize_t off_t wchar_t ptrdiff_t sig_atomic_t fpos_t
+  syn keyword   cType		clock_t time_t va_list jmp_buf FILE DIR div_t ldiv_t
+  syn keyword   cType		mbstate_t wctrans_t wint_t wctype_t
+endif
+if !exists("c_no_c99") " ISO C99
+  syn keyword	cType		bool complex
+  syn keyword	cType		int8_t int16_t int32_t int64_t
+  syn keyword	cType		uint8_t uint16_t uint32_t uint64_t
+  syn keyword	cType		int_least8_t int_least16_t int_least32_t int_least64_t
+  syn keyword	cType		uint_least8_t uint_least16_t uint_least32_t uint_least64_t
+  syn keyword	cType		int_fast8_t int_fast16_t int_fast32_t int_fast64_t
+  syn keyword	cType		uint_fast8_t uint_fast16_t uint_fast32_t uint_fast64_t
+  syn keyword	cType		intptr_t uintptr_t
+  syn keyword	cType		intmax_t uintmax_t
+endif
+if exists("c_gnu")
+  syn keyword	cType		__label__ __complex__ __volatile__
+endif
+
+syn keyword	cStructure	struct union enum typedef
+syn keyword	cStorageClass	static register auto volatile extern const
+if exists("c_gnu")
+  syn keyword	cStorageClass	inline __attribute__
+endif
+if !exists("c_no_c99")
+  syn keyword	cStorageClass	inline restrict
+endif
+
+if !exists("c_no_ansi") || exists("c_ansi_constants") || exists("c_gnu")
+  if exists("c_gnu")
+    syn keyword cConstant __GNUC__ __FUNCTION__ __PRETTY_FUNCTION__ __func__
+  endif
+  syn keyword cConstant __LINE__ __FILE__ __DATE__ __TIME__ __STDC__
+  syn keyword cConstant __STDC_VERSION__
+  syn keyword cConstant CHAR_BIT MB_LEN_MAX MB_CUR_MAX
+  syn keyword cConstant UCHAR_MAX UINT_MAX ULONG_MAX USHRT_MAX
+  syn keyword cConstant CHAR_MIN INT_MIN LONG_MIN SHRT_MIN
+  syn keyword cConstant CHAR_MAX INT_MAX LONG_MAX SHRT_MAX
+  syn keyword cConstant SCHAR_MIN SINT_MIN SLONG_MIN SSHRT_MIN
+  syn keyword cConstant SCHAR_MAX SINT_MAX SLONG_MAX SSHRT_MAX
+  if !exists("c_no_c99")
+    syn keyword cConstant __func__
+    syn keyword cConstant LLONG_MIN LLONG_MAX ULLONG_MAX
+    syn keyword cConstant INT8_MIN INT16_MIN INT32_MIN INT64_MIN
+    syn keyword cConstant INT8_MAX INT16_MAX INT32_MAX INT64_MAX
+    syn keyword cConstant UINT8_MAX UINT16_MAX UINT32_MAX UINT64_MAX
+    syn keyword cConstant INT_LEAST8_MIN INT_LEAST16_MIN INT_LEAST32_MIN INT_LEAST64_MIN
+    syn keyword cConstant INT_LEAST8_MAX INT_LEAST16_MAX INT_LEAST32_MAX INT_LEAST64_MAX
+    syn keyword cConstant UINT_LEAST8_MAX UINT_LEAST16_MAX UINT_LEAST32_MAX UINT_LEAST64_MAX
+    syn keyword cConstant INT_FAST8_MIN INT_FAST16_MIN INT_FAST32_MIN INT_FAST64_MIN
+    syn keyword cConstant INT_FAST8_MAX INT_FAST16_MAX INT_FAST32_MAX INT_FAST64_MAX
+    syn keyword cConstant UINT_FAST8_MAX UINT_FAST16_MAX UINT_FAST32_MAX UINT_FAST64_MAX
+    syn keyword cConstant INTPTR_MIN INTPTR_MAX UINTPTR_MAX
+    syn keyword cConstant INTMAX_MIN INTMAX_MAX UINTMAX_MAX
+    syn keyword cConstant PTRDIFF_MIN PTRDIFF_MAX SIG_ATOMIC_MIN SIG_ATOMIC_MAX
+    syn keyword cConstant SIZE_MAX WCHAR_MIN WCHAR_MAX WINT_MIN WINT_MAX
+  endif
+  syn keyword cConstant FLT_RADIX FLT_ROUNDS
+  syn keyword cConstant FLT_DIG FLT_MANT_DIG FLT_EPSILON
+  syn keyword cConstant DBL_DIG DBL_MANT_DIG DBL_EPSILON
+  syn keyword cConstant LDBL_DIG LDBL_MANT_DIG LDBL_EPSILON
+  syn keyword cConstant FLT_MIN FLT_MAX FLT_MIN_EXP FLT_MAX_EXP
+  syn keyword cConstant FLT_MIN_10_EXP FLT_MAX_10_EXP
+  syn keyword cConstant DBL_MIN DBL_MAX DBL_MIN_EXP DBL_MAX_EXP
+  syn keyword cConstant DBL_MIN_10_EXP DBL_MAX_10_EXP
+  syn keyword cConstant LDBL_MIN LDBL_MAX LDBL_MIN_EXP LDBL_MAX_EXP
+  syn keyword cConstant LDBL_MIN_10_EXP LDBL_MAX_10_EXP
+  syn keyword cConstant HUGE_VAL CLOCKS_PER_SEC NULL
+  syn keyword cConstant LC_ALL LC_COLLATE LC_CTYPE LC_MONETARY
+  syn keyword cConstant LC_NUMERIC LC_TIME
+  syn keyword cConstant SIG_DFL SIG_ERR SIG_IGN
+  syn keyword cConstant SIGABRT SIGFPE SIGILL SIGHUP SIGINT SIGSEGV SIGTERM
+  " Add POSIX signals as well...
+  syn keyword cConstant SIGABRT SIGALRM SIGCHLD SIGCONT SIGFPE SIGHUP
+  syn keyword cConstant SIGILL SIGINT SIGKILL SIGPIPE SIGQUIT SIGSEGV
+  syn keyword cConstant SIGSTOP SIGTERM SIGTRAP SIGTSTP SIGTTIN SIGTTOU
+  syn keyword cConstant SIGUSR1 SIGUSR2
+  syn keyword cConstant _IOFBF _IOLBF _IONBF BUFSIZ EOF WEOF
+  syn keyword cConstant FOPEN_MAX FILENAME_MAX L_tmpnam
+  syn keyword cConstant SEEK_CUR SEEK_END SEEK_SET
+  syn keyword cConstant TMP_MAX stderr stdin stdout
+  syn keyword cConstant EXIT_FAILURE EXIT_SUCCESS RAND_MAX
+  " Add POSIX errors as well
+  syn keyword cConstant E2BIG EACCES EAGAIN EBADF EBADMSG EBUSY
+  syn keyword cConstant ECANCELED ECHILD EDEADLK EDOM EEXIST EFAULT
+  syn keyword cConstant EFBIG EILSEQ EINPROGRESS EINTR EINVAL EIO EISDIR
+  syn keyword cConstant EMFILE EMLINK EMSGSIZE ENAMETOOLONG ENFILE ENODEV
+  syn keyword cConstant ENOENT ENOEXEC ENOLCK ENOMEM ENOSPC ENOSYS
+  syn keyword cConstant ENOTDIR ENOTEMPTY ENOTSUP ENOTTY ENXIO EPERM
+  syn keyword cConstant EPIPE ERANGE EROFS ESPIPE ESRCH ETIMEDOUT EXDEV
+  " math.h
+  syn keyword cConstant M_E M_LOG2E M_LOG10E M_LN2 M_LN10 M_PI M_PI_2 M_PI_4
+  syn keyword cConstant M_1_PI M_2_PI M_2_SQRTPI M_SQRT2 M_SQRT1_2
+endif
+if !exists("c_no_c99") " ISO C99
+  syn keyword cConstant true false
+endif
+
+" Accept %: for # (C99)
+syn region      cPreCondit      start="^\s*\(%:\|#\)\s*\(if\|ifdef\|ifndef\|elif\)\>" skip="\\$" end="$"  keepend contains=cComment,cCommentL,cCppString,cCharacter,cCppParen,cParenError,cNumbers,cCommentError,cSpaceError
+syn match	cPreCondit	display "^\s*\(%:\|#\)\s*\(else\|endif\)\>"
+if !exists("c_no_if0")
+  if !exists("c_no_if0_fold")
+    syn region	cCppOut		start="^\s*\(%:\|#\)\s*if\s\+0\+\>" end=".\@=\|$" contains=cCppOut2 fold
+  else
+    syn region	cCppOut		start="^\s*\(%:\|#\)\s*if\s\+0\+\>" end=".\@=\|$" contains=cCppOut2
+  endif
+  syn region	cCppOut2	contained start="0" end="^\s*\(%:\|#\)\s*\(endif\>\|else\>\|elif\>\)" contains=cSpaceError,cCppSkip
+  syn region	cCppSkip	contained start="^\s*\(%:\|#\)\s*\(if\>\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*\(%:\|#\)\s*endif\>" contains=cSpaceError,cCppSkip
+endif
+syn region	cIncluded	display contained start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=ymlString
+syn match	cIncluded	display contained "<[^>]*>" contains=ymlString
+syn match	cInclude	display "^\s*\(%:\|#\)\s*include\>\s*["<]" contains=cIncluded
+"syn match cLineSkip	"\\$"
+syn cluster	cPreProcGroup	contains=cPreCondit,cIncluded,cInclude,cDefine,cErrInParen,cErrInBracket,cUserLabel,cSpecial,cOctalZero,cCppOut,cCppOut2,cCppSkip,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom,cString,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cParen,cBracket,cMulti
+syn region	cDefine		start="^\s*\(%:\|#\)\s*\(define\|undef\)\>" skip="\\$" end="$" keepend contains=ALLBUT,@cPreProcGroup,@Spell
+syn region	cPreProc	start="^\s*\(%:\|#\)\s*\(pragma\>\|line\>\|warning\>\|warn\>\|error\>\)" skip="\\$" end="$" keepend contains=ALLBUT,@cPreProcGroup,@Spell
+
+" Highlight User Labels
+syn cluster	cMultiGroup	contains=cIncluded,cSpecial,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cUserCont,cUserLabel,cBitField,cOctalZero,cCppOut,cCppOut2,cCppSkip,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom,cCppParen,cCppBracket,cCppString
+syn region	cMulti		transparent start='?' skip='::' end=':' contains=ALLBUT,@cMultiGroup,@Spell
+" Avoid matching foo::bar() in C++ by requiring that the next char is not ':'
+syn cluster	cLabelGroup	contains=cUserLabel
+syn match	cUserCont	display "^\s*\I\i*\s*:$" contains=@cLabelGroup
+syn match	cUserCont	display ";\s*\I\i*\s*:$" contains=@cLabelGroup
+syn match	cUserCont	display "^\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup
+syn match	cUserCont	display ";\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup
+
+syn match	cUserLabel	display "\I\i*" contained
+
+" Avoid recognizing most bitfields as labels
+syn match	cBitField	display "^\s*\I\i*\s*:\s*[1-9]"me=e-1 contains=cType
+syn match	cBitField	display ";\s*\I\i*\s*:\s*[1-9]"me=e-1 contains=cType
+
+if exists("c_minlines")
+  let b:c_minlines = c_minlines
+else
+  if !exists("c_no_if0")
+    let b:c_minlines = 50	" #if 0 constructs can be long
+  else
+    let b:c_minlines = 15	" mostly for () constructs
+  endif
+endif
+if exists("c_curly_error")
+  syn sync fromstart
+else
+  exec "syn sync ccomment cComment minlines=" . b:c_minlines
+endif
+
+" Define the default highlighting.
+" Only used when an item doesn't have highlighting yet
+hi def link cFormat		cSpecial
+hi def link cCppString		cString
+hi def link cCommentL		cComment
+hi def link cCommentStart	cComment
+hi def link cLabel		Label
+hi def link cUserLabel		Label
+hi def link cConditional	Conditional
+hi def link cRepeat		Repeat
+hi def link cCharacter		Character
+hi def link cSpecialCharacter	cSpecial
+hi def link cNumber		Number
+hi def link cOctal		Number
+hi def link cOctalZero		PreProc	 " link this to Error if you want
+hi def link cFloat		Float
+hi def link cOctalError		cError
+hi def link cParenError		cError
+hi def link cErrInParen		cError
+hi def link cErrInBracket	cError
+hi def link cCommentError	cError
+hi def link cCommentStartError	cError
+hi def link cSpaceError		cError
+hi def link cSpecialError	cError
+hi def link cCurlyError		cError
+hi def link cOperator		Operator
+hi def link cStructure		Structure
+hi def link cStorageClass	StorageClass
+hi def link cInclude		Include
+hi def link cPreProc		PreProc
+hi def link cDefine		Macro
+hi def link cIncluded		cString
+hi def link cError		Error
+hi def link cStatement		Statement
+hi def link cPreCondit		PreCondit
+hi def link cType		Type
+hi def link cConstant		Constant
+hi def link cCommentString	cString
+hi def link cComment2String	cString
+hi def link cCommentSkip	cComment
+hi def link cString		String
+hi def link cComment		Comment
+hi def link cSpecial		SpecialChar
+hi def link cTodo		Todo
+hi def link cBadContinuation	Error
+hi def link cCppSkip		cCppOut
+hi def link cCppOut2		cCppOut
+hi def link cCppOut		Comment
+hi def link ymlString   Operator
+let b:current_syntax = "yml2"
+
+" vim: ts=8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xml2yml.ysl2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,87 @@
+// xml2yml2.ysl2 version 2.4.4
+
+include yslt.yml2
+
+decl textstylesheet is estylesheet(*output="text") {
+    output *output;
+    const "space", !"'" + " " * 200 + "'"!;
+    param "autoindent", 4;
+    content;
+}, tstylesheet is textstylesheet;
+
+define operator "†" as call "convert" with "tag", "name()";
+
+tstylesheet {
+    function "printNS"
+        for "*/namespace::*[local-name()!='xml']" {
+            > xmlns
+            if "not(local-name()='')"
+                > :«local-name()»
+            > ="«.»"
+            if "position()<last()" > , 
+        }
+    
+    template "/" {
+        if "count(*/namespace::*)>1" {
+            | decl «name(*)»(`call "printNS"`);
+            |
+        }
+        apply "*", 0;
+    }
+
+    template "text()" {
+        param "text", "normalize-space()";
+
+        if "string-length($text)>0" choose {
+            when "contains($text,'\\n')" choose {
+                when "string-length(substring-before($text,'\\n'))<string-length($text)-1" choose {
+                    when "substring($text,string-length($text),1)='\\n'"
+                        > \n||\n«$text»||\n\n
+                    otherwise > > «str:replace($text,'\\n','\\\\n')»\n
+                }
+                otherwise > | «$text»\n
+            }
+            otherwise > > `copy "."`\n
+        }
+    }
+
+    template "*" {
+        0>
+        call "convert" with "tag", "name()";
+        apply "@*";
+
+        choose {
+            when "count(*)=0 and string-length(normalize-space())=0"
+                > ;\n
+            when "count(*)=1 and string-length(normalize-space())=0" {
+                > \n
+                apply "*";
+            }
+            when "count(*)=0 and string-length(normalize-space())>0" {
+                >  
+                apply "text()";
+            }
+            otherwise {
+                >  {\n
+                for "*|text()" {
+                    if "local-name()=''"
+                        if "string-length(normalize-space())>0"
+                            1>
+                    apply ".";
+                }
+                | }
+            }
+        }
+    }
+
+    template "@*" {
+        >  «name()»="«.»"
+        if "position()<last()" > ,
+    }
+
+    function "convert" {
+        param "tag";
+
+        > «translate($tag, '-', '_')»
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yml2.py	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,108 @@
+# YML 2.5.3 language definition
+
+# written by VB.
+
+import re
+from pyPEG import keyword, _and, _not
+
+# pyPEG:
+#
+#   basestring:     terminal symbol (characters)
+#   keyword:        terminal symbol (keyword)
+#   matchobj:       terminal symbols (regex, use for scanning symbols)
+#   function:       named non-terminal symbol, recursive definition
+#                   if you don't want naming in output, precede name with an underscore
+#   tuple:          production sequence
+#   integer:        count in production sequence:
+#                    0: following element is optional
+#                   -1: following element can be omitted or repeated endless
+#                   -2: following element is required and can be repeated endless
+#   list:           options, choose one of them
+#   _not:           next element in production sequence is matched only if this would not
+#   _and:           next element in production sequence is matched only if this would, too
+
+newSyntax = True
+
+def oldSyntax():
+    global newSyntax
+    newSyntax = False
+
+def _if(cond, val):
+    if cond:
+        return val
+    else:
+        return ()
+
+def listing(x):     return x, -1, (",", x)
+r = re.compile
+
+comment = [r(r"//.*"), r(r"/\*.*?\*/", re.S)]
+_symbol = r"(?=\D)\w(\w|:)*"
+symbol = r(_symbol, re.U)
+pointer = r(r"\*" + _symbol, re.U)
+ppointer = r(r"\*\*" + _symbol, re.U)
+macro = r(r"\%" + _symbol, re.U)
+reference = r(r"\&" + _symbol, re.U)
+
+NameStartChar = ur''':|[A-Z]|_|[a-z]|[\u00C0-\u00D6]|[\u00D8-\u00F6]|[\u00F8-\u02FF]|[\u0370-\u037D]|[\u037F-\u1FFF]|[\u200C-\u200D]|[\u2070-\u218F]|[\u2C00-\u2FEF]|[\u3001-\uD7FF]|[\uF900-\uFDCF]|[\uFDF0-\uFFFD]'''
+NameChar = NameStartChar + ur'''|-|\.|[0-9]|\u00B7|[\u0300-\u036F]|[\u203F-\u2040]'''
+
+_xmlSymbol = u"(" + NameStartChar + u")(" + NameChar + u")*"
+xmlSymbol = r(_xmlSymbol)
+aliasSymbol = r(ur"-|(" + _xmlSymbol + ur")")
+
+literal = [r(r'""".*?"""', re.S), r(r"'''.*?'''", re.S), r(r"""-?\d+\.\d*|-?\.\d+|-?\d+|".*?"|'.*?'""")]
+filename = [("'", r(r"[^']*"), "'"), ('"', r(r'[^"]*'), '"'), r(r"[^\s;]+")]
+ws = r(r"\s+", re.U)
+
+def pyExp():        return "!", r(r"(!=|\\!|[^!])+"), "!"
+value = [literal, pyExp]
+
+def tagQuote():     return r(r"\].*|\<.*?\>")
+def lineQuote():    return r(r"\|.*")
+def quote():        return [r(r"\d*>.*"), (literal, 0, [";", "."])]
+def parm():         return [([xmlSymbol, pyExp, pointer, macro], "=", [value, pointer, symbol]), value, pointer]
+def parm_eq():      return [xmlSymbol, pyExp, pointer, macro], "=", [value, pointer, symbol]
+parm_eq.__name__ = "parm"
+_func = [symbol, ppointer, pointer, reference], _if(newSyntax, (-1, ("[", listing(parm), "]"))), 0, ("(", listing(parm), ")"), 0, listing(parm), -1, parm_eq
+def pythonCall():   return keyword("python"), _func, [";", "."]
+def declParm():     return [pointer, macro, xmlSymbol], 0, ("=", literal)
+def alias():        return keyword("alias"), aliasSymbol
+def descend():      return r(r"[+@*]" + _symbol, re.U)
+def base():         return keyword("is"), symbol
+def shape():        return symbol
+def decl():         return symbol, 0, base, 0, ("<", listing(shape), ">"), -1, descend, _if(newSyntax, (-1, ("[", 0, listing(declParm), "]"))), 0, ("(", 0, listing(declParm), ")"), 0, alias, 0, content
+def python():       return [r(r"!!.*?!!", re.S), r(r"!.*")]
+def operator():     return 0, keyword("define"), keyword("operator"), literal, keyword("as"), r(r".*")
+def constant():     return 0, keyword("define"), [pointer, symbol], "=", literal, 0, [";", "."]
+def in_ns():        return keyword("in"), xmlSymbol, [_decl, ("{", -2, _decl, "}")]
+_decl = keyword("decl"), listing(decl), [";", "."]
+def textsection():  return r(r'(\|\|(\>*).*?\|\|(\>*))|(\>\>.*?\>\>)', re.S)
+def include():      return keyword("include"), 0, reverse, 0, [ktext, kxml], filename, 0, [";", "."]
+def func():         return _func, 0, content
+def funclist():     return listing(func)
+_cmd = funclist, 0, [";", "."]
+_inner = [include, textsection, pythonCall, _cmd, quote, lineQuote, tagQuote, pyExp]
+_cc = "{", -1, _inner, "}"
+def content_plain(): return [ (_l, 0, _p, 0, _b, 0, _cc), (_p, 0, _b, 0, _cc), (_b, 0, _cc), _cc ]
+content_plain.__name__ = "content"
+def func_plain():   return _func, 0, content_plain
+func_plain.__name__ = "func"
+def flist_plain():  return -2, func_plain
+flist_plain.__name__ = "funclist"
+def xbase():        return flist_plain
+def generic():      return flist_plain
+def subscript():    return flist_plain
+def parentheses():  return "(", 0, funclist, ")"
+def fparm():        return flist_plain
+
+_l = _if(newSyntax, ("<", listing(generic), ">"))
+_p = _if(not newSyntax, parentheses), _if(newSyntax, ("(", 0, listing(fparm), ")"))
+_b = (":", listing(xbase))
+_c = [_inner, _cc]
+
+def content():      return [ (_l, 0, _p, 0, _b, 0, _c), (_p, 0, _b, 0, _c), (_b, 0, _c), _c ]
+def reverse():      return keyword("reverse")
+def ktext():        return keyword("text")
+def kxml():         return keyword("xml")
+def ymlCStyle():    return -1, [_decl, in_ns, include, python, operator, constant, tagQuote, lineQuote, quote, _cmd]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yml2c	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+# vim: set fileencoding=utf-8 :
+
+"""\
+YML 2 compiler version 5.4
+Copyleft (c), 2009-2011, Volker Birk  http://fdik.org/yml/
+
+"""
+
+import sys, os, codecs, locale
+import fileinput, unicodedata
+from optparse import OptionParser
+
+from pyPEG import parse, u
+from yml2 import ymlCStyle, comment, oldSyntax
+import backend
+
+def printInfo(option, opt_str, value, parser):
+    sys.stdout.write(__doc__)
+
+def w(msg):
+    if isinstance(msg, BaseException):
+        try:
+            msg = str(msg) + "\n"
+        except:
+            msg = u(msg) + u"\n"
+    if type(msg) is unicode:
+        msg = codecs.encode(msg, sys.stderr.encoding)
+    sys.stderr.write(msg)
+
+optParser = OptionParser()
+optParser.add_option("-C", "--old-syntax", action="store_true", dest="old_syntax",
+        help="syntax of YML 2 version 1.x (compatibility mode)", default=False)
+optParser.add_option("-D", "--emit-linenumbers", action="store_true", dest="emitlinenumbers",
+        help="emit line numbers into the resulting XML for debugging purposes", default=False)
+optParser.add_option("-E", "--encoding", dest="encoding", metavar="ENCODING", default=locale.getdefaultlocale()[1],
+        help="encoding of input files (default to locale)")
+optParser.add_option("-I", "--include", dest="includePathText", metavar="INCLUDE_PATH",
+        help="precede YML_PATH by a colon separated INCLUDE_PATH to search for include files")
+optParser.add_option("-m", "--omit-empty-parm-tags", action="store_true", dest="omitemptyparm",
+        help="does nothing (only there for compatibility reasons)", default=False)
+optParser.add_option("-n", "--normalization", dest="normalization", metavar="NORMALIZATION", default="NFC",
+        help="Unicode normalization (none, NFD, NFKD, NFC, NFKC, FCD, default is NFC)")
+optParser.add_option("-o", "--output", dest="outputFile", metavar="FILE",
+        help="place output in file FILE")
+optParser.add_option("-p", "--parse-only", action="store_true", dest="parseonly",
+        help="parse only, then output pyAST as text to stdout", default=False)
+optParser.add_option("-V", "--version", action="callback", callback=printInfo, help="show version info")
+(options, args) = optParser.parse_args()
+
+if options.old_syntax:
+    oldSyntax()
+
+if options.emitlinenumbers:
+    backend.emitlinenumbers = True
+
+backend.encoding = options.encoding
+
+try:
+    if options.includePathText:
+        backend.includePath = options.includePathText.split(':')
+
+    dirs = os.environ.get('YML_PATH', '.').split(':')
+    backend.includePath.extend(dirs)
+
+    files = fileinput.input(args, mode="rU", openhook=fileinput.hook_encoded(options.encoding))
+    # fileinput suffer from two nasty bugs :
+    # - ignoring open hook with stdin
+    # - iterator requires ctrl-D to be pressed twice on some platform
+    if args in [[],['-']] :
+        files._files=[]
+        files._buffer=[unicode(line, options.encoding) for line in sys.stdin.readlines()]
+
+    ymlC = ymlCStyle()
+    result = parse(ymlC, files, True, comment, packrat=True)
+
+    if options.parseonly:
+        print result
+    else:
+        result = backend.finish(result)
+        if options.normalization != "none":
+            result = unicodedata.normalize(options.normalization, result)
+
+        if options.outputFile and options.outputFile != "-":
+            outfile = open(options.outputFile, "w")
+            outfile.write(codecs.encode(result, options.encoding))
+            outfile.close()
+        else:
+            print codecs.encode(result, options.encoding)
+
+except KeyboardInterrupt:
+    w("\n")
+    sys.exit(1)
+except KeyError, msg:
+    w(u"not found: " + u(msg) + u"\n")
+    sys.exit(4)
+except LookupError, msg:
+    w(u"not found: " + u(msg) + u"\n")
+    sys.exit(4)
+except Exception, msg:
+    w(msg)
+    sys.exit(5)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yml2proc	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,248 @@
+#!/usr/bin/env python
+# vim: set fileencoding=utf-8 :
+
+"""\
+YML/YSLT 2 processor version 5.4
+Copyleft (c), 2009-2011 Volker Birk  http://fdik.org/yml/
+
+"""
+
+import sys, os, codecs, locale
+import fileinput, unicodedata
+from optparse import OptionParser
+
+try:
+    from lxml import etree
+except:
+    sys.stderr.write("This program needs lxml, see http://codespeak.net/lxml/\n")
+    sys.exit(1)
+
+from yml2 import ymlCStyle, comment, oldSyntax
+from pyPEG import parse, u
+import backend
+
+def printInfo(option, opt_str, value, parser):
+    sys.stdout.write(__doc__)
+    sys.exit(0)
+
+class YMLAssert(Exception): pass
+
+def w(msg):
+    if isinstance(msg, BaseException):
+        try:
+            msg = str(msg) + "\n"
+        except:
+            msg = u(msg) + u"\n"
+    if type(msg) is unicode:
+        msg = codecs.encode(msg, sys.stderr.encoding)
+    sys.stderr.write(msg)
+
+optParser = OptionParser()
+optParser.add_option("-C", "--old-syntax", action="store_true", dest="old_syntax",
+        help="syntax of YML 2 version 1.x (compatibility mode)", default=False)
+optParser.add_option("-D", "--emit-linenumbers", action="store_true", dest="emitlinenumbers",
+        help="emit line numbers into the resulting XML for debugging purposes", default=False)
+optParser.add_option("--debug", action="store_true", dest="trace",
+        help="switch on tracing to stderr", default=False)
+optParser.add_option("-d", "--paramdict", dest="params", metavar="PARAMS",
+        help="call X/YSLT script with dictionary PARAMS as parameters")
+optParser.add_option("-e", "--xpath", dest="xpath", metavar="XPATH",
+        help="execute XPath expression XPATH and print result")
+optParser.add_option("-E", "--encoding", dest="encoding", metavar="ENCODING", default=locale.getdefaultlocale()[1],
+        help="encoding of input files (default to locale)")
+optParser.add_option("-I", "--include", dest="includePathText", metavar="INCLUDE_PATH",
+        help="precede YML_PATH by a colon separated INCLUDE_PATH to search for include files")
+optParser.add_option("-m", "--omit-empty-parm-tags", action="store_true", dest="omitemptyparm",
+        help="does nothing (only there for compatibility reasons)", default=False)
+optParser.add_option("-M", "--empty-input-document", action="store_true", dest="emptyinput",
+        help="use an empty input document", default=False)
+optParser.add_option("-n", "--normalization", dest="normalization", metavar="NORMALIZATION", default="NFC",
+        help="Unicode normalization (none, NFD, NFKD, NFC, NFKC, FCD, default is NFC)")
+optParser.add_option("-o", "--output", dest="outputFile", metavar="FILE",
+        help="place output in file FILE")
+optParser.add_option("-p", "--parse-only", action="store_true", dest="parseonly",
+        help="parse only, then output pyAST as text to stdout", default=False)
+optParser.add_option("-P", "--pretty", action="store_true", default=False,
+        help="pretty print output adding whitespace")
+optParser.add_option("-s", "--stringparamdict", dest="stringparams", metavar="STRINGPARAMS",
+        help="call X/YSLT script with dictionary STRINGPARAMS as string parameters")
+optParser.add_option("-x", "--xml", action="store_true", default=False,
+        help="input document is XML already")
+optParser.add_option("-X", "--xslt", dest="xslt", metavar="XSLTSCRIPT",
+        help="execute XSLT script XSLTSCRIPT")
+optParser.add_option("-y", "--yslt", dest="yslt", metavar="YSLTSCRIPT",
+        help="execute YSLT script YSLTSCRIPT")
+optParser.add_option("-Y", "--xml2yml", action="store_true", default=False,
+        help="convert XML to normalized YML code")
+optParser.add_option("-V", "--version", action="callback", callback=printInfo, help="show version info and exit")
+(options, args) = optParser.parse_args()
+
+if options.old_syntax:
+    oldSyntax()
+
+if options.trace:
+    backend.enable_tracing = True
+
+if options.emitlinenumbers:
+    backend.emitlinenumbers = True
+
+if options.includePathText:
+    backend.includePath = options.includePathText.split(':')
+
+backend.encoding = options.encoding
+
+dirs = os.environ.get('YML_PATH', '.').split(':')
+backend.includePath.extend(dirs)
+
+if options.xml2yml:
+    for directory in backend.includePath:
+        try:
+            name = directory + "/xml2yml.ysl2"
+            f = open(name, "r")
+            f.close()
+            break
+        except:
+            pass
+
+    options.yslt = name
+    options.xml = True
+
+if  (options.xslt and options.yslt) or (options.xslt and options.xpath) or (options.yslt and options.xpath):
+    sys.stderr.write("Cannot combine --xpath, --xslt and --yslt params\n")
+    sys.exit(1)
+
+try:
+    ymlC = ymlCStyle()
+
+    rtext = u""
+
+    if not options.emptyinput:
+        files = fileinput.input(args, mode="rU", openhook=fileinput.hook_encoded(options.encoding))
+        # fileinput suffer from two nasty bugs :
+        # - ignoring open hook with stdin
+        # - iterator requires ctrl-D to be pressed twice on siome platform
+        if args in [[],['-']] :
+            files._files=[]
+            files._buffer=[unicode(line, options.encoding) for line in sys.stdin.readlines()]
+
+        if options.xml:
+            rtext = ""
+            for line in files:
+                rtext += line
+        else:
+            result = parse(ymlC, files, True, comment)
+            if options.parseonly:
+                print result
+                sys.exit(0)
+            else:
+                rtext = backend.finish(result)
+
+    if not rtext:
+        rtext = u"<empty/>"
+
+    def ymldebug(context, text):
+        if options.trace:
+            sys.stderr.write("Debug: " + codecs.encode(u(text), options.encoding) + "\n")
+        return ""
+
+    def ymlassert(context, value, msg):
+        if options.trace:
+            if not value:
+                raise YMLAssert(msg)
+        return ""
+
+    ymlns = etree.FunctionNamespace("http://fdik.org/yml")
+    ymlns.prefix = "yml"
+    ymlns['debug'] = ymldebug
+    ymlns['assert'] = ymlassert
+
+    if options.xpath:
+        tree = etree.fromstring(rtext)
+        ltree = tree.xpath(codecs.decode(options.xpath, options.encoding))
+        rtext = u""
+        try:
+            for rtree in ltree:
+                rtext += etree.tostring(rtree, pretty_print=options.pretty, encoding=unicode)
+        except:
+            rtext = ltree
+
+    elif options.yslt or options.xslt:
+        params = {}
+
+        if options.yslt:
+            backend.clearAll()
+            yscript = fileinput.input(options.yslt, mode="rU", openhook=fileinput.hook_encoded(options.encoding))
+            yresult = parse(ymlC, yscript, True, comment)
+            ytext = backend.finish(yresult)
+        else:
+            yscript = fileinput.input(options.xslt, mode="rU")
+            ytext = ""
+            for line in yscript:
+                ytext += line
+
+        doc = etree.fromstring(rtext)
+
+        xsltree = etree.XML(ytext, base_url=os.path.abspath(yscript.filename()))
+        transform = etree.XSLT(xsltree)
+        
+        if options.params:
+            params = eval(options.params)
+            for key, value in params.iteritems():
+                if type(value) != unicode:
+                    params[key] = u(value)
+        if options.stringparams:
+            for key, value in eval(options.stringparams).iteritems():
+                params[key] = u"'" + u(value) + u"'"
+
+        rresult = transform(doc, **params)
+        # lxml is somewhat buggy
+        try:
+            rtext = u(rresult)
+        except:
+            rtext = etree.tostring(rresult, encoding=unicode)
+            if not rtext:
+                rtext = codecs.decode(str(rresult), "utf-8")
+
+    if options.normalization != "none":
+        rtext = unicodedata.normalize(options.normalization, rtext)
+
+    if options.pretty:
+        plaintext = etree.tostring(etree.fromstring(rtext), pretty_print=True, xml_declaration=True, encoding=options.encoding)
+    else:
+        if isinstance(rtext, unicode):
+            plaintext = codecs.encode(rtext, options.encoding)
+        else:
+            plaintext = str(rtext)
+
+    try:
+        if plaintext[-1] == "\n":
+            plaintext = plaintext[:-1]
+    except: pass
+
+    if options.outputFile and options.outputFile != "-":
+        outfile = open(options.outputFile, "w")
+        outfile.write(plaintext)
+        outfile.close()
+    else:
+        print plaintext
+
+except KeyboardInterrupt:
+    w("\n")
+    sys.exit(1)
+except YMLAssert, msg:
+    w(u"YML Assertion failed: " + u(msg) + u"\n")
+    sys.exit(2)
+except KeyError, msg:
+    w(u"not found: " + u(msg) + u"\n")
+    sys.exit(4)
+except LookupError, msg:
+    w(u"not found: " + u(msg) + u"\n")
+    sys.exit(4)
+except etree.XMLSyntaxError, e:
+    log = e.error_log.filter_from_level(etree.ErrorLevels.FATAL)
+    for entry in log:
+        w(u"XML error: " + u(entry.message) + u"\n")
+    sys.exit(5)
+except Exception, msg:
+    w(msg)
+    sys.exit(5)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yslt.en.yhtml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,1069 @@
+include homepage.en.yhtml2
+
+page "YSLT – XSLT C style" {
+    h1 id=intro > YSLT – an introduction
+
+    p   >>
+        Especially the ¬http://www.w3.org/TR/xslt XSLT¬ programmer can benefit from YML.
+        Usually many attributes of XSLT are annoying in programming praxis:
+        >>
+
+    ul {
+        li  >>
+            the missing separation of ¬http://en.wikipedia.org/wiki/Indent_style indention¬
+            of the XSLT program and indention of the output text
+            >>
+
+        li > the complicated syntax
+
+        li > the lack of good text escaping mechanisms (< and > are not seldom)
+
+        li > ...
+    }
+
+    p > In short, it's ugly ;-)
+
+    p   >>
+        Usually the result is, that many programmers are avoiding XSLT as a programming language.
+        It's a pity, because for processing XML data, it can do much more than “formatting” as
+        “stylesheets”.
+        >>
+
+    p   >>
+        The idea of YSLT now is to supply a simple language, which programmers want to use, to
+        make the features of XSLT accessible to a broader base of people.
+        >>
+
+    p   >>
+        YSLT can be used much simpler; it's just a ¬http://fdik.org/yml/index#ylanguages Y Language¬
+        for XSLT. I'm using it for my blog, here you can ¬http://fdik.org/yblog2.tar.bz2 download YBlog2¬,
+        a simple blogging software in YSLT.
+        >>
+
+    p > Here you can find the ¬yslt.yml2 YSLT specification¬.
+
+    h2 id=hello > Hello, World
+
+    p > In YSLT, the hello world program reads like this:
+
+    Code    ||
+            include yslt.yml2
+            textstylesheet template "/" | hello, world
+            ||
+
+    p   >>
+        The `a href="http://fdik.org/yml/features#including" code > include` line includes the
+        YSLT Y Language declarations. The second line generates an XSLT hello world program.
+        You can generate it using:
+        >>
+
+    Code | % yml2c -o hello.xsl hello.ysl2
+
+    p > This results in the following program:
+
+    Code    ||
+            <xsl:stylesheet xmlns:func="http://exslt.org/functions"
+            xmlns:dyn="http://exslt.org/dynamic" xmlns:str="http://exslt.org/strings"
+            xmlns:math="http://exslt.org/math"
+            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+            extension-element-prefixes="exsl func str dyn set math"
+            xmlns:set="http://exslt.org/sets" version="1.0"
+            xmlns:exsl="http://exslt.org/common"><xsl:output method="text"/>
+            <xsl:variable name="space" select="'                                 '"/>
+            <xsl:param name="autoindent" select="4"/><xsl:template match="/">
+            <xsl:param name="_indent" select="0"/><xsl:value-of
+            select="substring($space, 1, $_indent+0*$autoindent)"/>hello, world
+            </xsl:template></xsl:stylesheet>
+            ||
+
+    p   >>
+        You can execute this program with any
+        ¬http://en.wikipedia.org/wiki/XML_template_engine XSL processor¬, for example the Free Software
+        ¬http://xmlsoft.org/XSLT/xsltproc2.html xsltproc¬.
+        >>
+    
+    Code    ||
+            % yml2c -o hello.xsl hello.ysl2
+            % echo '<empty/>' > empty.xml          
+            % xsltproc hello.xsl empty.xml 
+            hello, world
+            % _
+            ||
+
+    p   >>
+        Or you can just use ¬toolchain#processor yml2proc¬:
+        >>
+
+    Code    ||
+            % yml2proc -My hello.ysl2
+            hello, world
+            % _
+            ||
+
+    h2 id=programming > Programming in YSLT
+
+    p   >>
+        Because YSLT is just a ¬index#ylanguages Y Language¬ for XSLT, you can do anything with YSLT
+        you can do with XSLT in just nicer syntax ;-) To read what XSLT is all about, I recommend 
+        ¬http://www.w3.org/TR/xslt the official W3C documentation for XSLT¬.
+        >>
+
+    p   >>
+        So this document is just an beginners guide, if you want to understand XSLT completely,
+        better read the ¬http://www.w3.org W3C¬ stuff.
+        >>
+
+    h3 > Programming YSLT means programming with a pure functional language.
+
+    p   >>
+        Lovers of ¬http://en.wikipedia.org/wiki/Lisp_(programming_language) Lisp¬ or
+        ¬http://www.haskell.org/ Haskell¬ will not see any problems. But many programmers are used to
+        have a programming language with a
+        ¬http://en.wikipedia.org/wiki/Procedural_programming procedural imperative paradigma¬ like
+        ¬http://java.sun.com Java¬,
+        ¬http://en.wikipedia.org/wiki/C_(programming_language) C¬/¬http://en.wikipedia.org/wiki/C++ C++¬
+        or ¬http://www.python.org Python¬. Why should they use a
+        ¬http://en.wikipedia.org/wiki/Functional_programming functional¬ language?
+        >>
+
+    p   >>
+        Actually, if a functional language is practical or not, depends of what's to do – “the
+        right tool for the task”, one could say.
+        >>
+
+    p   >>
+        Because processing XML data means traversing a (document) tree,
+        ¬http://en.wikipedia.org/wiki/Recursion recursive¬ algorithms are a clear advantage.
+        And this is the reason, why choosing a functional language is a good choice for that job.
+        >>
+
+    p   >>
+        It's a little bit like with ¬http://en.wikipedia.org/wiki/SQL SQL¬ – for it's job, it's
+        excellent, but no-one wants to write a complete application in SQL (and also not in one
+        of the Turing-complete SQL extension languages like
+        ¬http://www.oracle.com/technology/tech/pl_sql/index.html PL/SQL¬).
+        >>
+
+    h3 id=htmlgen > Generating HTML out of a DSL
+
+    p   >>
+        Of course, you can use YSLT as you would use XSLT. Let's say, you have data in XML
+        documents, and you want to have an excerpt out of this data. This is a common task,
+        comparable to «SELECT» data out of an SQL database. But we have no database, we have
+        something like this file customers.yml2:
+        >>
+
+    Code    ||
+            decl customer(*id, *name) { id *id, name *name };
+
+            list {
+                customer 23, "Kurt Meier";
+                customer 42, "Lieschen Schmidt";
+            }
+            ||
+
+    p   >>
+        Let's say, we want to output this into an ¬http://en.wikipedia.org/wiki/XHTML XHTML¬ document,
+        where the list is showed as a table. Then we would do the following:
+        >>
+
+    p > The XHTML document should be like the following and include the list in the body:
+
+    Code    ||
+            include yslt.yml2
+
+            stylesheet {
+                template "/" html {
+                    head title "Customer List";
+                    body apply "list";
+                }
+            ||
+
+    p   >>
+        In the example above, stylesheet declares the main program. Then we define a template, which
+        is executed automatically starting reading the root «'/'» of the document tree of the XML
+        document we're processing.
+        >>
+
+    p > Using the XML document as input, we're creating this HTML tree:
+
+    Code    ||
+            <html>
+                <head>
+                    <title>Customer List</title>
+                </head>
+                <body>
+
+                <!-- ... ->
+
+                </body>
+            </html>
+            ||
+
+    p > How do we create the list? Well, let's use a table with customers:
+
+    Code |     template "list" table apply "customer";
+
+    p   >>
+        What to do per customer? Well, generate a table row with two columns, one for «id» and one
+        for «name»:
+        >>
+
+    Code    ||
+                template "customer" tr {
+                    td value "id";
+                    td value "name";
+                }
+            }
+            ||
+
+    p > That was it. We now can run our small program:
+
+    Code | % yml2proc -y customer.ysl2 -x customer.xml -o customer.html -P
+
+    p > The result looks like this:
+
+    Code    ||
+            % cat customer.html 
+            <?xml version="1.0"?>
+            <html>
+              <head>
+                <title>Customer List</title>
+              </head>
+              <body>
+                <table>
+                  <tr>
+                    <td>23</td>
+                    <td>Kurt Meier</td>
+                  </tr>
+                  <tr>
+                    <td>42</td>
+                    <td>Lieschen Schmidt</td>
+                  </tr>
+                </table>
+              </body>
+            </html>
+            % _
+            ||
+
+    p > Here you can download ¬samples/customer.ysl2 the complete program¬.
+
+    h3 id=codegen > How to generate code with YSLT
+
+    p > Generating code is easy with YSLT, if you follow these steps:
+
+    ol {
+        li > design the software you want to generate using patterns and write that in a DSL
+        li > write target code once for each pattern
+        li > deconstruct a compiler for the target code for each pattern
+        li > fine tune until the diff is empty
+    }
+
+    p   >>
+        Let's test by example. First let's say, we have a pattern of entities we want
+        to implement as Java beans. The enities in our DSL are:
+        >>
+
+    Code    ||
+            decl entity +name;
+            decl attr +type +name;
+            decl aggregates +entity;
+
+            structure {
+                entity Customer {
+                    attr String name;
+                    attr int creditLimit;
+                    aggregates Order;
+                }
+
+                entity Order {
+                    attr String no;
+                    attr String description;
+                    attr int amount;
+                }
+            }
+            ||
+
+    p   >>
+        How to write that in a Java Program? Well, following the second step, we're
+        writing our target code manually; for this simple sample, let's be naive and
+        save the following into a file named Customer.java.target:
+        >>
+
+    Code    ||
+            import java.util.Vector;
+            import java.util.Collections;
+            import base.Entity;
+
+            class Customer extends Entity {
+                Customer {
+                    id = genId();
+                }
+
+                // attribute name
+                
+                private String name;
+                public String getName() {
+                    return name;   
+                }
+                public void setName(String value) {
+                    name = value;
+                }
+ 
+                // attribute creditLimit
+
+                private int creditLimit;
+                public int getCreditLimit() {
+                    return creditLimit;   
+                }
+                public void setCreditLimit(int value) {
+                    creditLimit = value;
+                }
+
+                // Order aggregation
+
+                protected Vector orderList = new Vector();
+                void addOrder(Order entity) {
+                    orderList.add(entity);
+                }
+                void removeOrder(Order entity) {
+                    orderList.remove(entity);
+                }
+                Iterator orderIterator() {
+                    return orderList.iterator();
+                }
+            }
+            ||
+
+    p   >>
+        The third step does most of the work. First we cite this code
+        into gen_entity.ysl2 and create the basic form of an YSLT script:
+        >>
+
+    Code    ||
+            include yslt.yml2
+
+            tstylesheet {
+                template "/" {
+                    | import java.util.Vector;
+                    | import java.util.Collections;
+                    | import base.Entity;
+                    | 
+                    | class Customer extends Entity {
+                    |     Customer {
+                    |         id = genId();
+                    |     }
+                    | 
+                    |     // attribute name
+                    |     
+                    |     private String name;
+                    |     public String getName() {
+                    |         return name;   
+                    |     }
+                    |     public void setName(String value) {
+                    |         name = value;
+                    |     }
+                    | 
+                    |     // attribute creditLimit
+                    | 
+                    |     private int creditLimit;
+                    |     public int getCreditLimit() {
+                    |         return creditLimit;   
+                    |     }
+                    |     public void setCreditLimit(int value) {
+                    |         creditLimit = value;
+                    |     }
+                    | 
+                    |     // Order aggregation
+                    | 
+                    |     protected Vector orderList = new Vector();
+                    |     void addOrder(Order entity) {
+                    |         orderList.add(entity);
+                    |     }
+                    |     void removeOrder(Order entity) {
+                    |         orderList.remove(entity);
+                    |     }
+                    |     Iterator orderIterator() {
+                    |         return orderList.iterator();
+                    |     }
+                    | }
+                }
+            }
+            ||
+
+    p   >>
+        Now for the deconstruction. I think, it'll be best, if we
+        ¬#edocument create a .java file for each entity¬.
+        So we're moving the whole thing into a template for each entity
+        creating a file, and we're applying this for each entity using the name of each
+        Entity as parameter. We're adding some distinction of cases, too.
+        >>
+
+    p   >>
+        When we apply, the indention system of YSLT will add an indention level, so we can
+        take out rendundant whitespace; for the first apply we don't want this, so we're
+        giving the number 0 as the indention level.
+        >>
+
+    p   >>
+        In attributes, braces «{…}» let us insert the value of an XPath expression into our
+        DSL, while inside quoted text the same is done by the ¬#angledouble angle double quotes¬
+        `] <code>&#xab…&#xbb</code>`:
+        >>
+
+    Code    ||
+            include yslt.yml2
+
+            tstylesheet {
+                template "/structure" apply "Entity", 0;
+
+                template "Entity" document "{@name}.java" {
+                    if "aggregates" {
+                        | import java.util.Vector;
+                        | import java.util.Collections;
+                    }
+
+                    | import base.Entity;
+                    | 
+                    | class `] &#xab`@name`] &#xbb` extends Entity {
+                    |     `] &#xab`@name`] &#xbb` {
+                    |         id = genId();
+                    |     }
+                    | 
+            [...]
+                    |         orderList.remove(entity);
+                    |     }
+                    |     Iterator orderIterator() {
+                    |         return orderList.iterator();
+                    |     }
+                    | }
+                }
+            }
+            ||
+
+    p   >>
+        Well, not bad. Now for the pattern of an attribute and an aggregation, respectively.
+        >>
+
+    Code    ||
+            include yslt.yml2
+
+            tstylesheet {
+                template "/structure" apply "Entity";
+
+                template "Entity" document "{@name}.java" {
+                    if "aggregates" {
+                        | import java.util.Vector;
+                        | import java.util.Collections;
+                    }
+
+                    | import base.Entity;
+                    | 
+                    | class `] &#xab`@name`] &#xbb` extends Entity {
+                    |     `] &#xab`@name`] &#xbb` {
+                    |         id = genId();
+                    |     }
+                    | 
+
+                    apply "attr|aggregates";
+
+                    | }
+                }
+
+                template "attr" {
+                    |
+                    | // attribute `] &#xab`@name`] &#xbb`
+                    |
+                    | private `] &#xab`@type`] &#xbb` `] &#xab`@name`] &#xbb`;
+                    | public `] &#xab`@type`] &#xbb` get`] &#xab`@name`] &#xbb`() {
+                    |     return `] &#xab`@name`] &#xbb`;
+                    | }
+                    | public void set`] &#xab`@name`] &#xbb`(`] &#xab`@type`] &#xbb` value) {
+                    |     `] &#xab`@name`] &#xbb` = value;
+                    | }
+                }
+                
+                template "aggregates" {
+                    |
+                    | // `] &#xab`@entity`] &#xbb` aggregation
+                    | 
+                    | protected Vector `] &#xab`@entity`] &#xbb`List = new Vector();
+                    | void add`] &#xab`@entity`] &#xbb`(`] &#xab`@entity`] &#xbb` entity) {
+                    |     `] &#xab`@entity`] &#xbb`List.add(entity);
+                    | }
+                    | void remove`] &#xab`@entity`] &#xbb`(`] &#xab`@entity`] &#xbb` entity) {
+                    |     `] &#xab`@entity`] &#xbb`List.remove(entity);
+                    | }
+                    | Iterator `] &#xab`@entity`] &#xbb`Iterator() {
+                    |     return `] &#xab`@entity`] &#xbb`List.iterator();
+                    | }
+                }
+            }
+            ||
+
+    p   >>
+        As you can see, we're deconstructing step by step. This is a good idea to get
+        into code generation with YSLT, but it remains a good idea even for the advanced
+        programmer: it keeps a clear view on what's happening.
+        >>
+
+    p   >>
+        In the last step, test it out and make a diff to your target code. You will see
+        that our example needs some beautifying: in Java, camel case is important and
+        makes you some work to revert characters to uppercase or lowercase, respectively.
+        For that work you'll see that ¬http://www.w3.org/TR/xpath/#function-translate XPath's translate() function¬ is a little bit ugly ;-)
+        So we're defining an ¬features#userop operator¬ for that at the top of the file:
+        >>
+
+    Code    ||
+            define operator "“(.*?)”" as call "ucase" with "text", "%1";
+            ||
+
+    p   >>
+        Inside the template, we're defining the ucase function:
+        >>
+
+    Code    ||
+                function "ucase" {
+                    param "text";
+
+                    value "translate(substring($text,1,1),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')";
+                    value "substring($text, 2)";
+                }
+            }
+            ||
+
+    p   >>
+        Now we can replace one quoting with another; have a look at the getter and setter 
+        methods:
+        >>
+
+    Code    ||
+            include yslt.yml2
+
+            define operator "“(.*?)”" as call "ucase" with "text", "%1";
+
+            tstylesheet {
+                template "/structure" apply "Entity";
+
+            [...]
+
+                template "attr" {
+                    |
+                    | // attribute `] &#xab`@name`] &#xbb`
+                    |
+                    | private `] &#xab`@type`] &#xbb` `] &#xab`@name`] &#xbb`;
+                    | public `] &#xab`@type`] &#xbb` get“@name”() {
+                    |     return `] &#xab`@name`] &#xbb`;
+                    | }
+                    | public void set“@name”(`] &#xab`@type`] &#xbb` value) {
+                    |     `] &#xab`@name`] &#xbb` = value;
+                    | }
+                }
+
+            [...]
+
+                function "ucase" {
+                    param "text";
+
+                    value "translate(substring($text,1,1),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')";
+                    value "substring($text, 2)";
+                }
+            }
+            ||
+
+    p   >>
+        Well, the rest is a pure laborious task ;-) Feel free to complete. And: use diff!
+        >>
+
+    h3 id=ddlgen > A more advanced example: generating SQL DDL out of an UML diagram
+
+    p   >>
+        Well, now for something real ;-) This is a very common task: somebody models
+        with an ¬http://en.wikipedia.org/wiki/Class_diagram UML class diagram¬, and you want
+        to have SQL ¬http://en.wikipedia.org/wiki/Data_Definition_Language DDL¬, which generates
+        a matching database structure.
+        >>
+
+    p > Let's go:
+
+    p   >>
+        First, lets use a stylesheet, which declares the needed
+        ¬http://www.w3.org/TR/REC-xml-names/ XMI namespaces¬:
+        >>
+
+    Code    ||
+            include yslt.yml2
+
+            tstylesheet xmlns:uml="http://schema.omg.org/spec/UML/2.1",
+                        xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" {
+            ||
+
+    p > Now, search the Model for all content:
+
+    Code |    template "/" apply "xmi:XMI/uml:Model/packagedElement", 0;
+
+    p   >>
+        We're translating ¬http://en.wikipedia.org/wiki/Package_(UML) UML Packages¬ into
+        underscore separated prefixes:
+        >>
+
+    Code    ||
+                template "packagedElement[@xmi:type='uml:Package']" {
+                    param "name", "''";
+                    if "$name=''"  apply "packagedElement", 0 { with "name", "@name"; }
+                    if "$name!=''" apply "packagedElement", 0 { with "name", "concat($name, '_', @name)"; }
+                }
+
+            ||
+
+    p > Each Class is represented by a table in the database:
+
+    Code    ||
+                template "packagedElement[@xmi:type='uml:Class']" {
+                    param "name";
+
+                    | CREATE TABLE «$name»_«@name» (
+                    apply "ownedAttribute";
+                    | );
+                }
+            ||
+
+    p   >>
+        Finally, for each different data type for an attribute we're outputting different fields
+        with different types:
+        >>
+
+    Code    ||
+                template "ownedAttribute[@xmi:type='uml:Property' and type/@xmi:type='uml:PrimitiveType']" {
+                    0> «@name»
+                    choose {
+                        when "type/@href='http://schema.omg.org/spec/UML/2.1/uml.xml#String'"
+                            >  VARCHAR
+
+                        // [...] for other types, extend when clauses
+                    }
+                    if "position()!=last()" > ,
+                    text "\\n";
+                }
+            }
+            ||
+
+    p > Our little sample only supports «VARCHAR», but it is an easy game to play to complete that.
+
+    p   >>
+        Here you can download the ¬samples/xmi2ddl.ysl2 XMI 2 DDL compiler sample¬. I used
+        ¬http://bouml.free.fr/ BOUML¬ to create a small ¬samples/demo.xmi UML sample file¬
+        as ¬http://www.omg.org/spec/XMI/ XMI 2.1¬.
+        >>
+
+    p > To compile that, use:
+
+    Code    ||
+            % yml2proc -y xmi2ddl.ysl2 -x demo.xmi 
+            CREATE TABLE demo_Customer (
+                id VARCHAR,
+                name VARCHAR
+            );
+            % _
+            ||
+
+    p   >>
+        In the samples directory you'll find
+        ¬samples/xmi2ddl.uml2 a prettier solution¬ using ¬samples/uml.yml2 some declares to prettify¬.
+        >>
+
+    h1 id=features > Features of YSLT
+
+    p   >>
+        Because YSLT just generates XSLT programs, it will be a good idea to read the
+        ¬http://www.w3.org/TR/xslt XSLT Documentation¬ as well as the
+        ¬http://www.w3.org/TR/xpath XPath Documentation¬.
+        >>
+
+    p   >>
+        In the following, you find a ¬#functionlist List of YSLT Functions¬ and a
+        ¬#operatorlist List of YSLT Operators¬.
+        >>
+
+    h2 id=functionlist > List of YSLT Functions
+
+    h3 > apply(select, *indent=1)
+
+    p   >>
+        Generates the «<xsl:apply-templates />»
+        ¬http://www.w3.org/TR/xslt#section-Applying-Template-Rules tag¬. The «*indent» pointer gives
+        the number of indention levels to add (default: 1) for the Indention System.
+        >>
+
+    p i > Example:
+
+    Code | apply "attr|aggregation", mode=define;
+
+    h3 id=assert > assert(test, msg)
+
+    p   >>
+        Generates «<xsl:value-of select="yml:assert(test, msg)"». See the ¬#ymlassert yml:assert() XPath extension¬.
+        This function does not generate anything when not being called by ¬toolchain#processor ysltproc¬
+        with the --debug switch.
+        >>
+
+    h3 > attrib(name, namespace)
+
+    p > Generates the «<xsl:attribute />» ¬http://www.w3.org/TR/xslt#creating-attributes tag¬.
+
+    h3 > call(name)
+
+    p   >>
+        Generates the «<call-template />» ¬http://www.w3.org/TR/xslt#named-templates tag¬.
+        Used to call a «function()».
+        >>
+
+    p i > Example:
+
+    Code | call "ucase" with "text", "$name";
+
+    h3 > choose()
+
+    p   >>
+        Generates the «<xsl:choose />»
+        ¬http://www.w3.org/TR/xslt#section-Conditional-Processing-with-xsl:choose tag¬.
+        Use in a «choose() ... when()... otherwise()...» structure.
+        >>
+
+    p i > Example:
+
+    Code    ||
+            choose {
+                when "$id=1"
+                    > yes
+                when "$id=2"
+                    > no
+                otherwise
+                    error "invalid id";
+            }
+            ||
+
+    h3 > comment()
+
+    p > Generates the «<xsl:comment />» ¬http://www.w3.org/TR/xslt#section-Creating-Comments tag¬.
+
+    p i > Example:
+
+    Code | comment "this comment will remain in XML";
+
+    h3 > const(name, select)
+
+    p > Generates the «<xsl:variable />» ¬http://www.w3.org/TR/xslt#variables tag¬.
+
+    p i > Example:
+
+    Code | const "pi", 3.14;
+
+    h3 > copy(select)
+
+    p > Generates the «<xsl:copy-of />» ¬http://www.w3.org/TR/xslt#copy-of tag¬.
+
+    p i > Example:
+
+    Code | copy ".";
+
+    h3 id=debug > debug(msg)
+
+    p   >>
+        Generates «<xsl:value-of select="yml:debug(msg)"». See the ¬#ymldebug yml:debug() XPath extension¬.
+        This function does not generate anything when not being called by ¬toolchain#processor ysltproc¬
+        with the --debug switch.
+        >>
+
+    h3 > def(name)
+
+    p   >>
+        Generates the ¬http://www.exslt.org EXSLT¬ «<func:funcion />»
+        ¬http://www.exslt.org/func/elements/function/ tag¬.
+        >>
+
+    h3 id=edocument > document(href, method)
+
+    p   >>
+        Generates the ¬http://www.exslt.org EXSLT¬ «<exsl:document />»
+        ¬http://www.exslt.org/exsl/elements/document/ tag¬.
+        >>
+
+    p i > Example:
+
+    Code    ||
+            template "entity" document "{@name}.java" {
+                […]
+            }
+            ||
+
+    h3 > element(name, namespace)
+
+    p   >>
+        Generates the «<xsl:element />»
+        ¬http://www.w3.org/TR/xslt#section-Creating-Elements-with-xsl:element tag¬.
+        >>
+
+    h3 > error()
+
+    p   >>
+        Generates the «<xsl:message />» ¬http://www.w3.org/TR/xslt#message tag¬
+        with attribute «terminate» set to "yes".
+        >>
+
+    h3 > estylesheet(*output="xml")
+
+    p   >>
+        Does the same as «stylesheet()», but additionally declares the ¬http://www.exslt.org/ EXSLT¬
+        functions of the groups «exsl», «func», «str», «dyn», «set» and «math» and declares the
+        corresponding name spaces.
+        >>
+
+    h3 > for(select)
+
+    p > Generates the «<xsl:for-each />» ¬http://www.w3.org/TR/xslt#for-each tag¬.
+
+    p i > Example:
+
+    Code | for "../structure[@name='hello'" > «@type»
+
+    h3 > foreach(select)
+
+    p > Same as «for()».
+
+    h3 > function(name)
+
+    p   >>
+        Generates the «<xsl:template />» ¬http://www.w3.org/TR/xslt#named-templates tag¬.
+        Used by calling with «call()».
+        >>
+
+    p i > Example:
+
+    Code    ||
+            function "ucase" {
+                param "text";
+
+                value "translate(substring($text,1,1),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')";
+                value "substring($text, 2)";
+            }
+            ||
+
+    h3 > if(test)
+
+    p   >>
+        Generates the «<xsl:if />»
+        ¬http://www.w3.org/TR/xslt#section-Conditional-Processing-with-xsl:if tag¬.
+        >>
+
+    p i > Example:
+
+    Code | if "position()<last()" > , 
+
+    h3 > import(href)
+
+    p > Generates the «<xsl:import />» ¬http://www.w3.org/TR/xslt#import tag¬.
+
+    h3 > key(name, match, use)
+
+    p > Generates the «<xsl:key />» ¬http://www.w3.org/TR/xslt#key tag¬.
+
+    h3 > message()
+
+    p > Generates the «<xsl:message />» ¬http://www.w3.org/TR/xslt#message tag¬.
+
+    h3 > otherwise()
+
+    p   >>
+        Generates the «<xsl:otherwise />»
+        ¬http://www.w3.org/TR/xslt#section-Conditional-Processing-with-xsl:choose tag¬.
+        Use in a «choose() ... when()... otherwise()...» structure.
+        >>
+
+    h3 > output(method)
+
+    p > Generates the «<xsl:output />» ¬http://www.w3.org/TR/xslt#output tag¬.
+
+    h3 > param(name, select)
+
+    p > Generates the «<xsl:param />» ¬http://www.w3.org/TR/xslt#variables tag¬.
+
+    p i > Example:
+
+    Code | param "x", 42;
+
+    h3 > processing(name)
+
+    p   >>
+        Generates the «<xsl:processing-instruction />»
+        ¬http://www.w3.org/TR/xslt#section-Creating-Processing-Instructions tag¬.
+        >>
+
+    h3 > raw()
+
+    p   >>
+        Generates the «<xsl:text />» ¬http://www.w3.org/TR/xslt#section-Creating-Text tag¬.
+        Sets the attribute «disable-output-escaping» to "yes".
+        >>
+
+    h3 > result(select)
+
+    p   >>
+        Generates the ¬http://www.exslt.org EXSLT¬ «<func:result />»
+        ¬http://www.exslt.org/func/elements/result/ tag¬.
+        >>
+
+    h3 > stylesheet(*output="xml")
+
+    p   >>
+        Generates the XSLT «<stylesheet />» ¬http://www.w3.org/TR/xslt#stylesheet-element tag¬.
+        Additionally generates an «<output />» ¬http://www.w3.org/TR/xslt#output tag¬
+        in the body, with attribute «method» set to the value of the pointer «*output» (default: "xml").
+        >>
+
+    p > The content you're giving is placed in the body after the «<output />» tag.
+
+    p > The «version» attribute is set to "1.0" and XML namespace «xsl» is correctly defined.
+
+    p   >>
+        In short: use for a stylesheet, just give the output type as parameter, if you don't want to
+        to generate XML but HTML ("html") oder plain text ("text").
+        >>
+
+    p > «stylesheet()» additionally generates tags for the Indention System.
+
+    h3 > template(match)
+
+    p   >>
+        Generates the «<xsl:template />» ¬http://www.w3.org/TR/xslt#section-Defining-Template-Rules tag¬.
+        Additionally generates tags for the Indention System.
+        >>
+
+    p i > Example:
+
+    Code    ||
+            template "attr", mode=declare
+                | attribute `] &#xab@type&#xbb` `] &#xab@name&#xbb`;
+            ||
+
+    h3 > text()
+
+    p > Generate the «<xsl:text />» ¬http://www.w3.org/TR/xslt#section-Creating-Text tag¬.
+
+    h3 > textstylesheet()
+
+    p > Same as «estylesheet()», but «*output» is now "text", that means the stylesheet outputs plain text.
+
+    h3 > tstylesheet()
+
+    p > Same as «textstylesheet()».
+
+    h3 > value(select)
+
+    p > Generates the «<xsl:value-of />» ¬http://www.w3.org/TR/xslt#value-of tag¬.
+
+    p i > Example:
+
+    Code | value "@name";
+
+    h3 > warning()
+
+    p   >>
+        Generates the «<xsl:message />» ¬http://www.w3.org/TR/xslt#message tag¬
+        with attribute «terminate» set to "no".
+        >>
+
+    h3 > when()
+
+    p   >>
+        Generates the «<xsl:when />»
+        ¬http://www.w3.org/TR/xslt#section-Conditional-Processing-with-xsl:choose tag¬.
+        Use in a «choose() ... when()... otherwise()...» structure.
+        >>
+
+    h3 > with(name, select)
+
+    p   >>
+        Generates the «<xsl:with-param />»
+        ¬http://www.w3.org/TR/xslt#section-Passing-Parameters-to-Templates tag¬.
+        >>
+
+    p i > Example:
+
+    Code | call "ucase" with "text", "$name";
+
+    h2 id=operatorlist > List of YSLT Text Operators
+
+    h3 id="angledouble" > Operator `] <code>&#xab…&#xbb</code>`
+
+    p > Generate YSLT Function Call «value('…')».
+
+    h2 id=xpathext > Debugging Functions
+
+    p   >>
+        YML defines two functions in namespace http://fdik.org/yml, which are enabled if the command line
+        option --debug is given in ¬yslt#processor yml2proc¬.
+        >>
+
+    h3 id=ymlassert > yml:assert(test, msg)
+
+    p   >>
+        If XPath expression «test» evaluates to «false()» or to an empty set, XPath expression «msg» is
+        printed to stderr; the compilation then aborts with an error.
+        >>
+
+    p   >>
+        Better don't use it directly, use the ¬#assert assert() YSLT function¬.
+        >>
+
+    h3 id=ymldebug > yml:debug(msg)
+
+    p   >>
+        Prints XPath expression «msg» to stderr.
+        >>
+
+    p   >>
+        Better don't use it directly, use the ¬#debug debug() YSLT function¬.
+        >>
+
+    h2 id=stdlib > Standard Function Library
+
+    p   >>
+        Additionally, you can «include standardlib.ysl2» in the body of your stylesheet.
+        Then you'll have these extra functions:
+        >>
+
+    h3 id=dec2hex > yml:dec2hex(dec, digits=8)
+
+    p   >>
+        Converts number «dec» into a string with a hexadecimal representation filled up to
+        «digits» digits. If you're omitting the second parameter, it is set to 8.
+        >>
+
+    h3 id=hex2dec > yml:hex2dec(hex)
+
+    p   >>
+        Converts the string «hex» consisting of hexadecimal digits into a number.
+        >>
+
+    h3 id=lcase > yml:lcase(text)
+
+    p   >>
+        Converts all uppercase letters of string «text» into lowercase ones.
+        >>
+
+    h3 id=ucase > yml:ucase(text)
+
+    p   >>
+        Converts all lowercase letters of string «text» into uppercase ones.
+        >>
+
+    div id=bottom {
+        a href="features" "<< back to YML Features" " "
+        a href="#top" "^Top^" " "
+        a href="toolchain" "> > explain the Tool Chain" " "
+        a href="yslt.en.yhtml2" "(source)"
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yslt.yml2	Mon Jul 11 23:15:28 2016 +0200
@@ -0,0 +1,99 @@
+// YSLT version 2.5.4
+
+!!
+def indent(level):
+    return "value 'substring($space, 1, $_indent+" + str(level) + "*$autoindent)';"
+!!
+
+in exsl decl document(href, method) alias document;
+in func decl def(name) alias function, result(select);
+
+decl debug_off(exclude-result-prefixes="yml");
+
+in xsl {
+    decl _trace_param(%text, name="yml:trace", select='yml:debug("* %text")') alias param;
+    decl _trace_with is _trace_param alias with-param;
+
+    decl param(name, select);
+    decl const(name, select) alias variable, variable is const;
+    decl output(method), key(name, match, use);
+    decl value(select) alias value-of, copy(select) alias copy-of;
+
+    decl indent is value(%level, select='substring($space, 1, $_indent + (%level) * $autoindent)');
+
+    decl stylesheet(
+        *output="xml",
+        version="1.0",
+        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    ) {
+        output *output;
+        const "space", !"'" + " " * 200 + "'"!;
+        param "autoindent", 4;
+        content;
+    };
+
+    decl estylesheet is stylesheet (
+        xmlns:exsl='http://exslt.org/common',
+        xmlns:math='http://exslt.org/math',
+        xmlns:func='http://exslt.org/functions',
+        xmlns:str='http://exslt.org/strings',
+        xmlns:dyn='http://exslt.org/dynamic',
+        xmlns:set='http://exslt.org/sets',
+        xmlns:date='http://exslt.org/dates-and-times',
+        extension-element-prefixes='exsl func str dyn set math date'
+    );
+
+    decl textstylesheet is estylesheet(*output="text") {
+        output *output;
+        const "space", !"'" + " " * 200 + "'"!;
+        param "autoindent", 4;
+        xsl:template "text()";
+        content;
+    }, tstylesheet is textstylesheet;
+
+    decl template(match) {
+        _trace_param *_trace_info;
+        param "_indent", 0;
+        content;
+    };
+
+    decl function(name) alias template {
+        _trace_param *_trace_info;
+        param "_indent", 0;
+        content;
+    };
+   
+    decl call(name) alias call-template {
+        _trace_with *_trace_info;
+        content;
+    };
+
+    decl namespace_alias(stylesheet-prefix, result-prefix);
+    decl text, raw(disable-output-escaping='yes') alias text;
+
+    decl with(name, select) alias with-param;
+    decl withIndent(%level, name="_indent", select='$_indent + (%level) * $autoindent') alias with-param;
+
+    decl apply(select, *indent=1) alias apply-templates {
+        _trace_with *_trace_info;
+        withIndent *indent;
+        content;
+    };
+
+    decl choose, when(test), otherwise;
+    decl if(test);
+    decl for(select) alias for-each, foreach is for;
+    decl element(name, namespace);
+    decl attrib(name, namespace) alias attribute, attrib_set(name) alias attribute-set;
+    decl processing(name) alias processing-instruction;
+    decl comment;
+    decl number(value), sort(select), decimal_format(name, decimal-separator=".", grouping-separator=",");
+    decl import(href), fallback;
+    decl message, error is message(terminate='yes'), warning is message(terminate='no');
+
+    decl debug(%text, select='yml:debug(%text)') alias value-of;
+    decl assert(%test, %msg="''", select='yml:assert(%test,%msg)') alias value-of;
+}
+
+define operator "«(.*?)»" as value "%1";
+