pypackage: Merge 2.6.2
authorClaudio Luck <claudio.luck@pep.foundation>
Wed, 18 Mar 2020 19:20:01 +0100
changeset 58 a218553807ab
parent 57 2f4ad3800a3f (current diff)
parent 40 432ab62b2537 (diff)
child 59 ca8b9c6eb602
pypackage: Merge 2.6.2
yml2/backend.py
yml2/pyPEG.py
yml2/yml2.py
yml2/yml2c.py
yml2/yml2proc.py
yml2/yslt.yml2
yml2c
yml2proc
--- a/heading.en.yhtml2	Wed Feb 27 14:43:35 2019 +0100
+++ b/heading.en.yhtml2	Wed Mar 18 19:20:01 2020 +0100
@@ -13,10 +13,12 @@
 div id=headline {
     p > YML – Why a Markup Language?!
     div class=small {
-        "YML 2.5.8 of We 29 Aug 2018  –  Copyleft 2007-2018, "
+        "YML 2.6.2 of Mo 02 Nov 2019  –  Copyleft 2007-2019, "
         a "http://blog.fdik.org", "Volker Birk";
         " – "
         a "http://fdik.org/yml2.tar.bz2", "Download YML 2";
+        " – "
+        a "https://pep.foundation/dev/repos/yml2/", "Mercurial repository";
     }
 }
 
--- a/yml2/backend.py	Wed Feb 27 14:43:35 2019 +0100
+++ b/yml2/backend.py	Wed Mar 18 19:20:01 2020 +0100
@@ -1,20 +1,20 @@
-# 2.5.10 backend
+# 2.6.1 backend
 
 # written by VB.
 
 import re, codecs
 import fileinput
-import sys, traceback, exceptions, os
+import sys, traceback, os
 from xml.sax.saxutils import escape, quoteattr
-from copy import deepcopy
+from copy import copy, 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""
+in_ns = ""
 operator = []
-included = u""
+included = ""
 includePath = []
 emitlinenumbers = False
 encoding = "utf-8"
@@ -29,9 +29,9 @@
 def clearAll():
     global ymlFunc, pointers, pythonFunc, in_ns, operator, included
     ymlFunc, pointers, pythonFunc = {}, {}, {}
-    in_ns = u""
+    in_ns = ""
     operator = []
-    included = u""
+    included = ""
 
 lq = re.compile(r"\|(\>*)(.*)")
 sq = re.compile(r"(\d*)\>(.*)")
@@ -48,84 +48,84 @@
         return u(pointers[name[1:]])
     except:
         if name == "*_trace_info":
-            return u'""'
+            return '""'
         if included:
-            raise LookupError(u"in " + included + u":" + u(line) + u": pointer " + name)
-        else:
-            raise LookupError(u"in " + u(line) + u": pointer " + name)
+            raise LookupError("in " + included + ":" + u(line) + ": pointer " + name)
+        else:
+            raise LookupError("in " + u(line) + ": pointer " + name)
 
 def evalPython(expr):
     try:
         result = eval(u(expr), pythonFunc)
-        if type(result) is str:
+        if type(result) is bytes:
             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:
+        msg = "in python expression: " + u(parm)
+        if name is SyntaxError:
             tbl = traceback.format_exception(name, parm, tb)
-            msg += u"\n" + tbl[-3] + tbl[-2]
-        else:
-            msg += u": " + expr + u"\n"
+            msg += "\n" + tbl[-3] + tbl[-2]
+        else:
+            msg += ": " + expr + "\n"
         if included:
-            raise name(u"in " + included + u":" + u(line) + u": " + msg)
-        else:
-            raise name(u"in " + u(line) + u": " + msg)
+            raise name("in " + included + ":" + u(line) + ": " + msg)
+        else:
+            raise name("in " + u(line) + ": " + msg)
     
 def execPython(script):
     try:
-        if type(script) is unicode:
-            exec script in pythonFunc
-        else:
-            exec codecs.decode(script, encoding) in pythonFunc
+        if type(script) is str:
+            exec(script, pythonFunc)
+        else:
+            exec(codecs.decode(script, encoding), pythonFunc)
     except:
         name, parm, tb = sys.exc_info()
-        msg = u"in python script: " + u(parm)
-        if name is exceptions.SyntaxError:
+        msg = "in python script: " + u(parm)
+        if name is SyntaxError:
             tbl = traceback.format_exception(name, parm, tb)
-            msg += u"\n" + tbl[-3] + tbl[-2]
-        else:
-            msg += u": " + expr + u"\n"
+            msg += "\n" + tbl[-3] + tbl[-2]
+        else:
+            msg += ": " + expr + "\n"
         if included:
-            raise name(u"in " + included + u":" + u(line) + u": " + msg)
-        else:
-            raise name(u"in " + u(line) + u": " + msg)
+            raise name("in " + included + ":" + u(line) + ": " + msg)
+        else:
+            raise name("in " + u(line) + ": " + msg)
 
 def textOut(text):
     if not text:
-        return u""
-    if type(text) is not unicode:
+        return ""
+    if type(text) is not str:
         text = codecs.decode(text, encoding)
     text = text.replace(r'\"', r'\\"')
-    text = u'u"""' + text.replace('"', r'\"') + u'"""'
+    text = '"""' + text.replace('"', r'\"') + '"""'
     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">"
+            if type(textFunc.alias) is str:
+                result += "</" + textFunc.alias + ">"
+            else:
+                result += "</" + codecs.decode(textFunc.alias, encoding) + ">"
         return result
     except:
         return escape(eval(text))
 
 def strRepl(text):
     if not text:
-        return u""
-    if type(text) is not unicode:
+        return ""
+    if type(text) is not str:
         text = codecs.decode(text, encoding)
     text = text.replace(r'\"', r'\\"')
-    text = u'u"""' + text.replace('"', r'\"') + u'"""'
-    if type(text) is unicode:
+    text = '"""' + text.replace('"', r'\"') + '"""'
+    if type(text) is str:
         return escape(eval(text))
 
 def applyMacros(macros, text):
     result = text
-    for key, value in macros.iteritems():
+    for key, value in macros.items():
         result = result.replace(key, value)
     return result
 
@@ -139,7 +139,7 @@
         self.pointers = {}
         self.macros = {}
         if in_ns:
-            self.alias = in_ns + u":" + name.replace("_", "-")
+            self.alias = in_ns + ":" + name.replace("_", "-")
         else:
             self.alias = name.replace("_", "-")
         pythonFunc["yml_" + name] = self
@@ -205,13 +205,13 @@
                     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'"'
+            text = u(parms) + ", " + u(vals)
+            pointers["_trace_info"] = '"' + u(line) + ": " + u(self.name) + " " + text.replace('"', '#') + '"'
 
         if emitlinenumbers:
             global first
             if first:
-                vals["xmlns:yml"] = u"http://fdik.org/yml"
+                vals["xmlns:yml"] = "http://fdik.org/yml"
                 first = False
             vals["yml:called"] = u(line)
         return self.xml(parms, vals, hasContent, avoidTag)
@@ -231,7 +231,7 @@
             self.descends.append(desc)
 
     def addValue(self, parm, value):
-        if type(value) is str or type(value) is unicode:
+        if type(value) is str or type(value) is str:
             if value[0] != "'" and value[0] != '"':
                 self.values[parm] = u(value)
             else:
@@ -241,16 +241,16 @@
 
     def xml(self, callParms, callValues, hasContent, avoidTag = False):
         global pointers
-        extraContent = u""
+        extraContent = ""
         if self.content:
             hasContent = True
         resultParms = self.values.copy()
         macros = self.macros.copy()
-        toDelete = resultParms.keys()
+        toDelete = [ key for key in resultParms.keys() ]
         for key in toDelete:
             if key[0] == "*":
                 del resultParms[key]
-        for key, value in callValues.iteritems():
+        for key, value in callValues.items():
             if key[0] == "%":
                 macros[key] = value
             else:
@@ -261,9 +261,9 @@
                 if self.parms[i][0] == "*":
                     cp = u(cp)
                     if "'" in cp:
-                        pointers[self.parms[i][1:]] = u'"' + cp + u'"'
+                        pointers[self.parms[i][1:]] = '"' + cp + '"'
                     else:
-                        pointers[self.parms[i][1:]] = u"'" + cp + u"'"
+                        pointers[self.parms[i][1:]] = "'" + cp + "'"
                 elif self.parms[i][0] == "%":
                     macros[self.parms[i]] = u(cp)
                 else:
@@ -272,21 +272,21 @@
                 extraContent += u(cp)
                 hasContent = True
             i += 1
-        result = u""
-        for p, v in resultParms.iteritems():
+        result = ""
+        for p, v in resultParms.items():
             if p[0] == "'" or p[0] == '"':
                 p = eval(p)
-            result += u" "+ p + u"=" + quoteattr(applyMacros(macros, u(v)))
+            result += " "+ p + "=" + quoteattr(applyMacros(macros, u(v)))
         if hasContent:
             if avoidTag:
                 return True, strRepl(extraContent)
             else:
-                return True, u"<" + self.alias + result + u">" + strRepl(extraContent)
+                return True, "<" + self.alias + result + ">" + strRepl(extraContent)
         else:
             if avoidTag:
-                return False, u""
-            else:
-                return False, u"<" + self.alias + result + u"/>"
+                return False, ""
+            else:
+                return False, "<" + self.alias + result + "/>"
 
 def replaceContent(tree, subtree):
     n = 0
@@ -313,7 +313,7 @@
     return tree
 
 def executeCmd(text):
-    if type(text) is not unicode:
+    if type(text) is not str:
         text = codecs.decode(text, encoding)
     for (regex, pattern) in operator:
         match = re.search(regex, text)
@@ -321,11 +321,11 @@
             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():]
+                cmd = cmd.replace("%" + u(i+1), opt[i])
+            text = text[:match.start()] + "`" + cmd + "`"+ text[match.end():]
             match = re.search(regex, text)
 
-    result = u""
+    result = ""
     m = re.search(bq, text)
     while text and m:
         cmd  = m.group(1)
@@ -336,9 +336,9 @@
             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())
+                raise SyntaxError("in " + included + ":" + u(line) + ": syntax error in executing command: " + cmd.strip())
+            else:
+                raise SyntaxError("in " + u(line) + ": syntax error in executing command: " + cmd.strip())
         inner = _finish(r)
         result += head + inner
         m = re.search(bq, text)
@@ -358,20 +358,20 @@
     except: pass
 
     if ctype == "empty":
-        return code(u"")
+        return code("")
 
     if ctype == "in_ns":
         in_ns = obj[1][0]
         subtree = obj[1]
         for sel in subtree:
             codegen(sel)
-        in_ns = u""
-        return code(u"")
+        in_ns = ""
+        return code("")
 
     elif ctype == "decl":
-        name = u""
+        name = ""
         for data in obj[1]:
-            if type(data) is unicode or type(data) is str:
+            if type(data) is str:
                 name = data
                 try:
                     yf = ymlFunc[name]
@@ -380,7 +380,7 @@
                     ymlFunc[name] = YF(name)
                     yf = ymlFunc[name]
                     if in_ns:
-                        yf.alias = in_ns + u":" + name
+                        yf.alias = in_ns + ":" + name
                         if not enable_tracing:
                             if in_ns == "xsl" and (name == "debug" or name=="assert" or name[:7]=="_trace_"):
                                 yf.alias = "-"
@@ -394,9 +394,9 @@
                         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)
+                            raise KeyError("in " + included + ":" + u(line) + ": " + base + " as base for " + name)
                         else:
-                            raise KeyError(u"in " + u(line) + u": " + base + u" as base for " + name)
+                            raise KeyError("in " + u(line) + ": " + base + " as base for " + name)
                 elif data[0] == "shape":
                     shape = ymlFunc[data[1]]
                     try:
@@ -404,9 +404,9 @@
                         yf.patch(shape)
                     except KeyError:
                         if included:
-                            raise KeyError(u"in " + included + u":" + u(line) + u": " + base + u" as shape for " + name)
+                            raise KeyError("in " + included + ":" + u(line) + ": " + base + " as shape for " + name)
                         else:
-                            raise KeyError(u"in " + u(line) + u": " + base + u" as shape for " + name)
+                            raise KeyError("in " + u(line) + ": " + base + " as shape for " + name)
                 elif data[0] == "descend":
                     yf.addDescend(data[1])
                 elif data[0] == "declParm":
@@ -422,23 +422,23 @@
                             yf.pointers[parmName[1:]] = value
                             yf.addParm(parmName)
                         elif parmName[0] == "%":
-                            if type(value) is unicode or type(value) is str:
+                            if 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]
+                        yf.alias = in_ns + ":" + data[1][0]
                     else:
                         yf.alias = data[1][0]
                 elif data[0] == "content":
                     yf.content = data[1]
 
-        return code(u"")
+        return code("")
 
     elif ctype == "funclist":
-        result = u""
+        result = ""
         for f in obj[1]:
             result += codegen(f)
         return code(result)
@@ -447,13 +447,13 @@
         if len(obj[1]):
             return codegen(('func', ['_parentheses', ('content', [obj[1][0]])]))
         else:
-            return u""
+            return ""
 
     elif ctype == "fparm":
         if len(obj[1]):
             return codegen(('func', ['_parm', ('content', [obj[1][0]])]))
         else:
-            return u""
+            return ""
 
     elif ctype == "generic":
         return codegen(('func', ['_generic', ('content', [obj[1][0]])]))
@@ -468,15 +468,15 @@
         if name == "decl":
             if ymlFunc[name] == "#error":
                 if included:
-                    raise SyntaxError(u"in " + included + u":" + u(line) + u": syntax error in decl statement")
+                    raise SyntaxError("in " + included + ":" + u(line) + ": syntax error in decl statement")
                 else:
-                    raise SyntaxError(u"in " + u(line) + u": syntax error in decl statement")
+                    raise SyntaxError("in " + u(line) + ": 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")
+                    raise SyntaxError("in " + included + ":" + u(line) + ": syntax error in define statement")
                 else:
-                    raise SyntaxError(u"in " + u(line) + u": syntax error in define statement")
+                    raise SyntaxError("in " + u(line) + ": syntax error in define statement")
 
         if name[0] == "&":
             avoidTag = True
@@ -485,7 +485,7 @@
 
         if len(name) > 2:
             if name[0:2] == "**":
-                return code(eval('u'+pointer(name[1:])))
+                return code(eval(''+pointer(name[1:])))
 
         if name[0] == "*":
             name = eval(pointer(name))
@@ -495,11 +495,15 @@
 
         try:
             ymlFunc[name]
-        except:
+        except KeyError:
             try:
-                ymlFunc["_"]
-                return codegen(('func', ['_', ('content', [('funclist', [obj])])]))
-            except:
+                if ymlFunc["_"].alias != "-":
+                    return codegen(('func', ['_', ('content', [('funclist', [obj])])]))
+                else:
+                    ymlFunc[name] = copy(ymlFunc["_"])
+                    ymlFunc[name].alias = name.replace("_", "-")
+                    return codegen(obj)
+            except KeyError:
                 ymlFunc[name] = YF(name)
         
         if ymlFunc[name].alias == "-": avoidTag = True
@@ -508,9 +512,9 @@
         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")
+                    raise KeyError("in " + included + ":" + u(line) + ": " + name + " 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")
+                    raise KeyError("in " + u(line) + ": " + name + " has descending attributes, but no descendants are following")
 
             def first_func(obj):
                 if type(obj) is tuple or type(obj) is Symbol:
@@ -559,7 +563,7 @@
                         if dname[0] == "*":
                             pointers[dname[1:]] = "'" + f[1][0] + "'"
                         else:
-                            add_params.append( ('parm', [dname, u"'" + f[1][0] + u"'"]) )
+                            add_params.append( ('parm', [dname, "'" + f[1][0] + "'"]) )
                         try:
                             add_params.extend( get_parms(f) )
                         except: pass
@@ -571,14 +575,14 @@
                     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")
+                    raise KeyError("in " + included + ":" + u(line) + ": " + name + " 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")
+                    raise KeyError("in " + u(line) + ": " + name + " has descending attributes, and too less descendants are following")
 
         if not to_add:
             to_add = ( obj, )
 
-        complete = u""
+        complete = ""
 
         for obj in to_add:
             subtree = None
@@ -602,14 +606,14 @@
                     result += codegen(sel)
 
             if hasContent and not(avoidTag):
-                result += u"</" + ymlFunc[name].alias + u">"
+                result += "</" + ymlFunc[name].alias + ">"
 
             complete += result
 
         return code(complete)
 
     elif ctype == "textsection":
-        result = u''
+        result = ''
         ll = obj[1].splitlines()
         space = len(ll[-1]) - 2
         for l in ll[1:-1]:
@@ -622,15 +626,15 @@
                     result += _finish(r)
                 except SyntaxError:
                     if included:
-                        raise SyntaxError(u"in " + included + u":" + u(line) + u": syntax error in executing command: " + cmd.strip())
+                        raise SyntaxError("in " + included + ":" + u(line) + ": 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:]))
+                        raise SyntaxError("in " + u(line) + ": syntax error in executing command: " + cmd.strip())
+            else:
+                result += codegen(Symbol('lineQuote', '| ' + l[space:]))
         return code(result)
 
     elif ctype == "textsectionu":
-        result = u''
+        result = ''
         ll = obj[1].splitlines()
         space = len(ll[-1]) - 2
         for l in ll[1:-1]:
@@ -643,16 +647,16 @@
                     result += _finish(r)
                 except SyntaxError:
                     if included:
-                        raise SyntaxError(u"in " + included + u":" + u(line) + u": syntax error in executing command: " + cmd.strip())
+                        raise SyntaxError("in " + included + ":" + u(line) + ": 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:]]))
+                        raise SyntaxError("in " + u(line) + ": syntax error in executing command: " + cmd.strip())
+            else:
+                if result != '': result += ' '
+                result += codegen(Symbol('quote', ['> ' + l[space:]]))
         return code(result)
 
     elif ctype == "lineQuote" or ctype == "quote":
-        m, text, base, inds = None, u"", 0, 0
+        m, text, base, inds = None, "", 0, 0
 
         if ctype == "lineQuote":
             text = obj[1]
@@ -670,20 +674,20 @@
                     inds = int(m.group(1))
                 text = m.group(2)[1:]
             else:
-                if type(text) is unicode or type(text) is str:
+                if type(text) is str:
                     text = u(evalPython(text))
 
-        ind = u""
+        ind = ""
         if inds > -1:
             try:
-                cmd = evalPython(u"indent(" + u(inds) + u")")
+                cmd = evalPython("indent(" + u(inds) + ")")
                 result, rest = parseLine(u(cmd), _inner, [], True, comment)
                 if rest:
                     raise SyntaxError()
                 ind = _finish(result)
             except: pass
         
-        if ctype == "lineQuote": text += u"\n"
+        if ctype == "lineQuote": text += "\n"
 
         hasTextFunc = False
         try:
@@ -697,13 +701,13 @@
     elif ctype == "tagQuote":
         m = tq.match(obj[1])
         if m.group(1) == "<":
-            return code(u"<" + m.group(2))
+            return code("<" + 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"")
+        return code("")
 
     elif ctype == "constant":
         name = obj[1][0]
@@ -711,7 +715,7 @@
             name = name[1:]
         value = obj[1][1]
         pointers[name] = value
-        return code(u"")
+        return code("")
 
     elif ctype == "include":
         reverse = False
@@ -724,7 +728,7 @@
                     ktext = True
                 elif arg[0] == "kxml":
                     kxml = True
-            elif type(arg) is unicode or type(arg) is str:
+            elif type(arg) is str:
                 filemask = arg
 
         if filemask[0] == '/' or filemask[0] == '.':
@@ -740,14 +744,14 @@
 
         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")
+                raise IOError("in " + included + ":" + u(line) + ": include file(s) '" + filemask + "' not found")
+            else:
+                raise IOError("in " + u(line) + ": include file(s) '" + filemask + "' not found")
 
         includeFile = fileinput.input(files, mode="rU", openhook=fileinput.hook_encoded(encoding))
         _included = included
         if ktext or kxml:
-            text = u""
+            text = ""
             for line in includeFile:
                 included = includeFile.filename()
                 if kxml:
@@ -776,7 +780,7 @@
         parms = []
         data = obj[1]
         for p in data:
-            if type(p) is unicode or type(p) is str:
+            if type(p) is str:
                 name = p
             elif type(p) is tuple or type(p) is Symbol:
                 ptype = p[0]
@@ -786,9 +790,9 @@
                     else:
                         parms.append(p[1][0])
         if len(parms) == 0:
-            exp = name + u"()"
+            exp = name + "()"
         elif len(parms) == 1:
-            exp = name + u"(" + u(parms[0]) + u")"
+            exp = name + "(" + u(parms[0]) + ")"
         else:
             exp = name + u(tuple(parms))
         cmd = evalPython(exp)
@@ -798,31 +802,31 @@
         return code(_finish(result))
 
     else:
-        return code(u"")
+        return code("")
 
 def _finish(tree):
-    result = u""
-    python = u""
+    result = ""
+    python = ""
 
     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"
+                python += el[1][0][1:] + "\n"
             continue
         else:
             if python:
                 execPython(python)
-                python = u""
+                python = ""
 
         try:
             result += codegen(el)
         except RuntimeError:
             if included:
-                raise RuntimeError(u"in " + included + u":" + u(line))
-            else:
-                raise RuntimeError(u"in " + u(line))
+                raise RuntimeError("in " + included + ":" + u(line))
+            else:
+                raise RuntimeError("in " + u(line))
 
     if python:
         execPython(python)
--- a/yml2/pyPEG.py	Wed Feb 27 14:43:35 2019 +0100
+++ b/yml2/pyPEG.py	Wed Mar 18 19:20:01 2020 +0100
@@ -1,13 +1,13 @@
-# YPL parser 1.5
+# YPL parser 1.6
+# adapted for Python 3.x
 
 # written by VB.
 
 import re
 import sys, codecs
-import exceptions
-
-class keyword(unicode): pass
-class code(unicode): pass
+
+class keyword(str): pass
+class code(str): pass
 class ignore(object):
     def __init__(self, regex_text, *args):
         self.regex = re.compile(regex_text, *args)
@@ -18,10 +18,10 @@
 
 class _not(_and): pass
 
-class Name(unicode):
+class Name(str):
     def __init__(self, *args):
         self.line = 0
-        self.file = u""
+        self.file = ""
 
 class Symbol(list):
     def __init__(self, name, what):
@@ -31,27 +31,27 @@
         self.append(what)
     def __call__(self):
         return self.what
-    def __unicode__(self):
-        return u'Symbol(' + repr(self.__name__) + ', ' + repr(self.what) + u')'
+    def __str__(self):
+        return 'Symbol(' + repr(self.__name__) + ', ' + repr(self.what) + ')'
     def __repr__(self):
-        return unicode(self)
-
-word_regex = re.compile(ur"\w+")
-rest_regex = re.compile(ur".*")
+        return str(self)
+
+word_regex = re.compile(r"\w+")
+rest_regex = re.compile(r".*")
 
 print_trace = False
 
 def u(text):
-    if isinstance(text, exceptions.BaseException):
+    if isinstance(text, BaseException):
         text = text.args[0]
-    if type(text) is unicode:
+    if type(text) is str:
         return text
-    if isinstance(text, str):
+    if isinstance(text, bytes):
         if sys.stdin.encoding:
             return codecs.decode(text, sys.stdin.encoding)
         else:
             return codecs.decode(text, "utf-8")
-    return unicode(text)
+    return str(text)
 
 def skip(skipper, text, skipWS, skipComments):
     if skipWS:
@@ -104,7 +104,7 @@
                 if print_trace:
                     try:
                         if _pattern.__name__ != "comment":
-                            sys.stderr.write(u"match: " + _pattern.__name__ + u"\n")
+                            sys.stderr.write("match: " + _pattern.__name__ + "\n")
                     except: pass
 
             if self.restlen == -1:
@@ -146,7 +146,7 @@
                 if print_trace:
                     try:
                         if pattern.__name__ != "comment":
-                            sys.stderr.write(u"testing with " + pattern.__name__ + u": " + textline[:40] + u"\n")
+                            sys.stderr.write("testing with " + pattern.__name__ + ": " + textline[:40] + "\n")
                     except: pass
 
             if pattern.__name__[0] != "_":
@@ -160,7 +160,7 @@
 
         pattern_type = type(pattern)
 
-        if pattern_type is str or pattern_type is unicode:
+        if pattern_type is str:
             if text[:len(pattern)] == pattern:
                 text = skip(self.skipper, text[len(pattern):], skipWS, skipComments)
                 return R(None, text)
@@ -251,11 +251,11 @@
                 syntaxError()
 
         else:
-            raise SyntaxError(u"illegal type in grammar: " + u(pattern_type))
+            raise SyntaxError("illegal type in grammar: " + u(pattern_type))
 
     def lineNo(self):
-        if not(self.lines): return u""
-        if self.restlen == -1: return u""
+        if not(self.lines): return ""
+        if self.restlen == -1: return ""
         parsed = self.textlen - self.restlen
 
         left, right = 0, len(self.lines)
@@ -266,20 +266,20 @@
                 try:
                     if self.lines[mid + 1][0] >= parsed:
                         try:
-                            return u(self.lines[mid + 1][1]) + u":" + u(self.lines[mid + 1][2])
+                            return u(self.lines[mid + 1][1]) + ":" + u(self.lines[mid + 1][2])
                         except:
-                            return u""
+                            return ""
                     else:
                         left = mid + 1
                 except:
                     try:
-                        return u(self.lines[mid + 1][1]) + u":" + u(self.lines[mid + 1][2])
+                        return u(self.lines[mid + 1][1]) + ":" + u(self.lines[mid + 1][2])
                     except:
-                        return u""
+                        return ""
             else:
                 right = mid - 1
             if left > right:
-                return u""
+                return ""
 
 # plain module API
 
@@ -308,7 +308,7 @@
     while callable(language):
         language = language()
 
-    orig, ld = u"", 0
+    orig, ld = "", 0
     for line in lineSource:
         if lineSource.isfirstline():
             ld = 1
@@ -331,10 +331,10 @@
         if text:
             raise SyntaxError()
 
-    except SyntaxError, msg:
+    except SyntaxError as msg:
         parsed = textlen - p.restlen
         textlen = 0
-        nn, lineNo, file = 0, 0, u""
+        nn, lineNo, file = 0, 0, ""
         for n, ld, l in lines:
             if n >= parsed:
                 break
@@ -346,6 +346,6 @@
         lineNo += 1
         nn -= 1
         lineCont = orig.splitlines()[nn]
-        raise SyntaxError(u"syntax error in " + u(file) + u":" + u(lineNo) + u": " + lineCont)
+        raise SyntaxError("syntax error in " + u(file) + ":" + u(lineNo) + ": " + lineCont)
 
     return result
--- a/yml2/yml2.py	Wed Feb 27 14:43:35 2019 +0100
+++ b/yml2/yml2.py	Wed Mar 18 19:20:01 2020 +0100
@@ -1,4 +1,4 @@
-# YML 2.5.10 language definition
+# YML 2.6.0 language definition
 
 # written by VB.
 
@@ -44,12 +44,12 @@
 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]'''
+NameStartChar = r''':|[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 + r'''|-|\.|[0-9]|\u00B7|[\u0300-\u036F]|[\u203F-\u2040]'''
 
-_xmlSymbol = u"(" + NameStartChar + u")(" + NameChar + u")*"
+_xmlSymbol = "(" + NameStartChar + ")(" + NameChar + ")*"
 xmlSymbol = r(_xmlSymbol)
-aliasSymbol = r(ur"-|(" + _xmlSymbol + ur")")
+aliasSymbol = r(r"-|(" + _xmlSymbol + r")")
 
 literal = [r(r'""".*?"""', re.S), r(r"'''.*?'''", re.S), r(r"""0x[a-f0-9]+|-?\d+\.\d*|-?\.\d+|-?\d+|".*?"|'.*?'""")]
 filename = [("'", r(r"[^']*"), "'"), ('"', r(r'[^"]*'), '"'), r(r"[^\s;]+")]
--- a/yml2/yml2c.py	Wed Feb 27 14:43:35 2019 +0100
+++ b/yml2/yml2c.py	Wed Mar 18 19:20:01 2020 +0100
@@ -1,9 +1,9 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # vim: set fileencoding=utf-8 :
 
 """\
-YML 2 compiler version 5.8
-Copyleft (c), 2009-2011, Volker Birk  http://fdik.org/yml/
+YML 2 compiler version 6.2
+Copyleft (c), 2009-2019, Volker Birk  http://fdik.org/yml/
 
 """
 
@@ -17,18 +17,15 @@
 
 def printInfo(option, opt_str, value, parser):
     sys.stdout.write(__doc__)
+    sys.exit(0)
 
 def w(msg):
     if isinstance(msg, BaseException):
-        try:
-            msg = str(msg) + "\n"
-        except:
-            msg = u(msg) + u"\n"
-    if type(msg) is unicode:
+        msg = str(msg) + "\n"
+    if type(msg) is bytes:
         msg = codecs.encode(msg, sys.stderr.encoding)
     sys.stderr.write(msg)
 
-
 def main():
     optParser = OptionParser()
     optParser.add_option("-C", "--old-syntax", action="store_true", dest="old_syntax",
@@ -78,20 +75,21 @@
                 result = unicodedata.normalize(options.normalization, result)
 
             if options.outputFile and options.outputFile != "-":
-                outfile = open(options.outputFile, "w")
+                outfile = open(options.outputFile, "wb")
                 outfile.write(codecs.encode(result, options.encoding))
                 outfile.close()
             else:
-                print(codecs.encode(result, options.encoding))
+                sys.stdout.buffer.write(codecs.encode(result, options.encoding))
+                print()
 
     except KeyboardInterrupt:
         w("\n")
         sys.exit(1)
     except KeyError as msg:
-        w(u"not found: " + u(msg) + u"\n")
+        w("not found: " + u(msg) + "\n")
         sys.exit(4)
     except LookupError as msg:
-        w(u"not found: " + u(msg) + u"\n")
+        w("not found: " + u(msg) + "\n")
         sys.exit(4)
     except Exception as msg:
         w(msg)
@@ -100,3 +98,4 @@
 
 if __name__ == "__main__":
     sys.exit(main())
+
--- a/yml2/yml2proc.py	Wed Feb 27 14:43:35 2019 +0100
+++ b/yml2/yml2proc.py	Wed Mar 18 19:20:01 2020 +0100
@@ -1,9 +1,9 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # vim: set fileencoding=utf-8 :
 
 """\
-YML/YSLT 2 processor version 5.10
-Copyleft (c), 2009-2018 Volker Birk  http://fdik.org/yml/
+YML/YSLT 2 processor version 6.2
+Copyleft (c), 2009-2019 Volker Birk  http://fdik.org/yml/
 
 """
 
@@ -32,12 +32,9 @@
         try:
             msg = str(msg) + "\n"
         except:
-            msg = u(msg) + u"\n"
-    if type(msg) is unicode:
-        msg = codecs.encode(msg, sys.stderr.encoding)
+            msg = u(msg) + "\n"
     sys.stderr.write(msg)
 
-
 def main():
     optParser = OptionParser()
     optParser.add_option("-C", "--old-syntax", action="store_true", dest="old_syntax",
@@ -78,24 +75,24 @@
             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:
@@ -105,22 +102,22 @@
                 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""
-
+    
+        rtext = ""
+    
         if not options.emptyinput:
             files = fileinput.input(args, mode="rU", openhook=fileinput.hook_encoded(options.encoding))
-
+    
             if options.xml:
                 rtext = ""
                 for line in files:
@@ -132,39 +129,39 @@
                     sys.exit(0)
                 else:
                     rtext = backend.finish(result)
-
+    
         if not rtext:
-            rtext = u"<empty/>"
-
+            rtext = "<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""
+            rtext = ""
             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))
@@ -175,21 +172,21 @@
                 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:
+                    if type(value) is not str:
                         params[key] = u(value)
             if options.stringparams:
                 for key, value in eval(options.stringparams).iteritems():
-                    params[key] = u"'" + u(value) + u"'"
-
+                    params[key] = "'" + u(value) + "'"
+    
             rresult = transform(doc, **params)
             # lxml is somewhat buggy
             try:
@@ -198,46 +195,48 @@
                 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):
+            if isinstance(rtext, str):
                 plaintext = codecs.encode(rtext, options.encoding)
             else:
-                plaintext = str(rtext)
-
+                plaintext = rtext
+    
         try:
             if plaintext[-1] == "\n":
                 plaintext = plaintext[:-1]
         except: pass
-
+    
         if options.outputFile and options.outputFile != "-":
-            outfile = open(options.outputFile, "w")
+            outfile = open(options.outputFile, "wb")
             outfile.write(plaintext)
             outfile.close()
         else:
-            print(plaintext)
-
+            sys.stdout.buffer.write(plaintext)
+            if not options.pretty:
+                print()
+    
     except KeyboardInterrupt:
         w("\n")
         sys.exit(1)
     except YMLAssert as msg:
-        w(u"YML Assertion failed: " + u(msg) + u"\n")
+        w("YML Assertion failed: " + u(msg) + "\n")
         sys.exit(2)
     except KeyError as msg:
-        w(u"not found: " + u(msg) + u"\n")
+        w("not found: " + u(msg) + "\n")
         sys.exit(4)
     except LookupError as msg:
-        w(u"not found: " + u(msg) + u"\n")
+        w("not found: " + u(msg) + "\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")
+            w("XML error: " + u(entry.message) + "\n")
         sys.exit(5)
     except Exception as msg:
         w(msg)
--- a/yml2/yslt.yml2	Wed Feb 27 14:43:35 2019 +0100
+++ b/yml2/yslt.yml2	Wed Mar 18 19:20:01 2020 +0100
@@ -1,4 +1,4 @@
-// YSLT version 2.5.5
+// YSLT version 2.6.2
 
 !!
 def indent(level):
@@ -49,7 +49,7 @@
         output *output;
         const "space", !"'" + " " * 200 + "'"!;
         param "autoindent", 4;
-        xsl:template "text()";
+        xsl:template match="text()";
         content;
     }, tstylesheet is textstylesheet;