move python code into new package dir
authorClaudio Luck <claudio.luck@pep.foundation>
Tue, 04 Sep 2018 16:48:59 +0200
changeset 52 b4a9a3122abb
parent 22 3a2bd70c01df
child 53 b94d4c5b9496
move python code into new package dir
Makefile
backend.py
manpage.yml2
pyPEG.py
standardlib.ysl2
xml2yml.ysl2
yml2.py
yml2/__init__.py
yml2/backend.py
yml2/manpage.yml2
yml2/pyPEG.py
yml2/standardlib.ysl2
yml2/xml2yml.ysl2
yml2/yml2.py
yml2/yml2c
yml2/yml2proc
yml2/yslt.yml2
yml2c
yml2proc
yslt.yml2
--- a/Makefile	Wed Aug 29 23:57:58 2018 +0200
+++ b/Makefile	Tue Sep 04 16:48:59 2018 +0200
@@ -1,5 +1,5 @@
 YML_PATH=
-YML2C=yml2c
+YML2C=yml2/yml2c
 
 all: homepage
 
--- a/backend.py	Wed Aug 29 23:57:58 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,840 +0,0 @@
-# 2.5.8 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:
-            if value[0] != "'" and value[0] != '"':
-                self.values[parm] = u(value)
-            else:
-                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 == "textsectionu":
-        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:
-                if result != u'': result += u' '
-                result += codegen(Symbol(u'quote', [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 = sorted(glob(filemask))
-        else:
-            files = []
-            for directory in includePath:
-                path = os.path.join(directory, filemask)
-                files.extend(sorted(glob(path)))
-
-        if files and 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")
--- a/manpage.yml2	Wed Aug 29 23:57:58 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-decl manpage(xmlns="http://docbook.org/ns/docbook", version="5.0", *title) alias article { title *title; content; };
--- a/pyPEG.py	Wed Aug 29 23:57:58 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,351 +0,0 @@
-# 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
--- a/standardlib.ysl2	Wed Aug 29 23:57:58 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-// YML2 standardlib version 2.5.8
-
-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')";
-}
-
-def "yml:mixedCase" {
-    param "text", "''";
-    result "concat(yml:lcase(substring($text,1,1)),substring($text,2))";
-}
-
-def "yml:capit" {
-    param "text", "''";
-    result "concat(yml:ucase(substring($text,1,1)),substring($text,2))";
-}
-
--- a/xml2yml.ysl2	Wed Aug 29 23:57:58 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-// 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, '-', '_')»
-    }
-}
--- a/yml2.py	Wed Aug 29 23:57:58 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-# YML 2.5.8 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, symbol])
-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 textsectionu(): 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, textsectionu, 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/yml2/backend.py	Tue Sep 04 16:48:59 2018 +0200
@@ -0,0 +1,840 @@
+# 2.5.8 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:
+            if value[0] != "'" and value[0] != '"':
+                self.values[parm] = u(value)
+            else:
+                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 == "textsectionu":
+        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:
+                if result != u'': result += u' '
+                result += codegen(Symbol(u'quote', [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 = sorted(glob(filemask))
+        else:
+            files = []
+            for directory in includePath:
+                path = os.path.join(directory, filemask)
+                files.extend(sorted(glob(path)))
+
+        if files and 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/yml2/manpage.yml2	Tue Sep 04 16:48:59 2018 +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/yml2/pyPEG.py	Tue Sep 04 16:48:59 2018 +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/yml2/standardlib.ysl2	Tue Sep 04 16:48:59 2018 +0200
@@ -0,0 +1,68 @@
+// YML2 standardlib version 2.5.8
+
+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')";
+}
+
+def "yml:mixedCase" {
+    param "text", "''";
+    result "concat(yml:lcase(substring($text,1,1)),substring($text,2))";
+}
+
+def "yml:capit" {
+    param "text", "''";
+    result "concat(yml:ucase(substring($text,1,1)),substring($text,2))";
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yml2/xml2yml.ysl2	Tue Sep 04 16:48:59 2018 +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/yml2.py	Tue Sep 04 16:48:59 2018 +0200
@@ -0,0 +1,109 @@
+# YML 2.5.8 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, symbol])
+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 textsectionu(): 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, textsectionu, 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/yml2/yml2c	Tue Sep 04 16:48:59 2018 +0200
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+# vim: set fileencoding=utf-8 :
+
+"""\
+YML 2 compiler version 5.8
+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))
+
+    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 as msg:
+    w(u"not found: " + u(msg) + u"\n")
+    sys.exit(4)
+except LookupError as msg:
+    w(u"not found: " + u(msg) + u"\n")
+    sys.exit(4)
+except Exception as msg:
+    w(msg)
+    sys.exit(5)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yml2/yml2proc	Tue Sep 04 16:48:59 2018 +0200
@@ -0,0 +1,242 @@
+#!/usr/bin/env python
+# vim: set fileencoding=utf-8 :
+
+"""\
+YML/YSLT 2 processor version 5.8
+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))
+
+        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 as msg:
+    w(u"YML Assertion failed: " + u(msg) + u"\n")
+    sys.exit(2)
+except KeyError as msg:
+    w(u"not found: " + u(msg) + u"\n")
+    sys.exit(4)
+except LookupError as msg:
+    w(u"not found: " + u(msg) + u"\n")
+    sys.exit(4)
+except etree.XMLSyntaxError as 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 as msg:
+    w(msg)
+    sys.exit(5)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yml2/yslt.yml2	Tue Sep 04 16:48:59 2018 +0200
@@ -0,0 +1,101 @@
+// YSLT version 2.5.5
+
+!!
+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:sets='http://exslt.org/sets',
+        xmlns:date='http://exslt.org/dates-and-times',
+        xmlns:yml='http://fdik.org/yml',
+        extension-element-prefixes='exsl func str dyn set sets math date yml'
+    );
+
+    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";
+
--- a/yml2c	Wed Aug 29 23:57:58 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-
-"""\
-YML 2 compiler version 5.8
-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))
-
-    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 as msg:
-    w(u"not found: " + u(msg) + u"\n")
-    sys.exit(4)
-except LookupError as msg:
-    w(u"not found: " + u(msg) + u"\n")
-    sys.exit(4)
-except Exception as msg:
-    w(msg)
-    sys.exit(5)
--- a/yml2proc	Wed Aug 29 23:57:58 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,242 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-
-"""\
-YML/YSLT 2 processor version 5.8
-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))
-
-        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 as msg:
-    w(u"YML Assertion failed: " + u(msg) + u"\n")
-    sys.exit(2)
-except KeyError as msg:
-    w(u"not found: " + u(msg) + u"\n")
-    sys.exit(4)
-except LookupError as msg:
-    w(u"not found: " + u(msg) + u"\n")
-    sys.exit(4)
-except etree.XMLSyntaxError as 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 as msg:
-    w(msg)
-    sys.exit(5)
--- a/yslt.yml2	Wed Aug 29 23:57:58 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-// YSLT version 2.5.5
-
-!!
-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:sets='http://exslt.org/sets',
-        xmlns:date='http://exslt.org/dates-and-times',
-        xmlns:yml='http://fdik.org/yml',
-        extension-element-prefixes='exsl func str dyn set sets math date yml'
-    );
-
-    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";
-