adapting to Python 3
authorVolker Birk <vb@pep-project.org>
Mon, 23 Sep 2019 19:25:58 +0200
changeset 31 d3dddb80d1f5
parent 30 a1ecf17c60eb
child 32 2b7b48758eaa
adapting to Python 3
backend.py
heading.en.yhtml2
pyPEG.py
yml2.py
yml2c
yml2proc
--- a/backend.py	Fri Feb 15 10:45:57 2019 +0100
+++ b/backend.py	Mon Sep 23 19:25:58 2019 +0200
@@ -1,10 +1,10 @@
-# 2.5.10 backend
+# 2.6.0 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 copy, deepcopy
 from glob import glob
@@ -12,9 +12,9 @@
 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,7 +241,7 @@
 
     def xml(self, callParms, callValues, hasContent, avoidTag = False):
         global pointers
-        extraContent = u""
+        extraContent = ""
         if self.content:
             hasContent = True
         resultParms = self.values.copy()
@@ -250,7 +250,7 @@
         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))
@@ -497,7 +497,7 @@
             ymlFunc[name]
         except KeyError:
             try:
-                if ymlFunc["_"].alias != u"-":
+                if ymlFunc["_"].alias != "-":
                     return codegen(('func', ['_', ('content', [('funclist', [obj])])]))
                 else:
                     ymlFunc[name] = copy(ymlFunc["_"])
@@ -512,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:
@@ -563,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
@@ -575,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
@@ -606,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]:
@@ -626,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''
+    elif ctype == "textsection":
+        result = ''
         ll = obj[1].splitlines()
         space = len(ll[-1]) - 2
         for l in ll[1:-1]:
@@ -647,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]
@@ -674,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:
@@ -701,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]
@@ -715,7 +715,7 @@
             name = name[1:]
         value = obj[1][1]
         pointers[name] = value
-        return code(u"")
+        return code("")
 
     elif ctype == "include":
         reverse = False
@@ -728,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] == '.':
@@ -744,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:
@@ -780,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]
@@ -790,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)
@@ -802,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/heading.en.yhtml2	Fri Feb 15 10:45:57 2019 +0100
+++ b/heading.en.yhtml2	Mon Sep 23 19:25:58 2019 +0200
@@ -13,7 +13,7 @@
 div id=headline {
     p > YML – Why a Markup Language?!
     div class=small {
-        "YML 2.5.10 of Tu 15 Feb 2019  –  Copyleft 2007-2019, "
+        "YML 2.6.0 of Mo 23 Sep 2019  –  Copyleft 2007-2019, "
         a "http://blog.fdik.org", "Volker Birk";
         " – "
         a "http://fdik.org/yml2.tar.bz2", "Download YML 2";
--- a/pyPEG.py	Fri Feb 15 10:45:57 2019 +0100
+++ b/pyPEG.py	Mon Sep 23 19:25:58 2019 +0200
@@ -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.py	Fri Feb 15 10:45:57 2019 +0100
+++ b/yml2.py	Mon Sep 23 19:25:58 2019 +0200
@@ -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/yml2c	Fri Feb 15 10:45:57 2019 +0100
+++ b/yml2c	Mon Sep 23 19:25:58 2019 +0200
@@ -1,9 +1,9 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # vim: set fileencoding=utf-8 :
 
 """\
-YML 2 compiler version 5.10
-Copyleft (c), 2009-2018, Volker Birk  http://fdik.org/yml/
+YML 2 compiler version 6.0
+Copyleft (c), 2009-2019, Volker Birk  http://fdik.org/yml/
 
 """
 
@@ -24,7 +24,7 @@
             msg = str(msg) + "\n"
         except:
             msg = u(msg) + u"\n"
-    if type(msg) is unicode:
+    if type(msg) is bytes:
         msg = codecs.encode(msg, sys.stderr.encoding)
     sys.stderr.write(msg)
 
@@ -76,11 +76,12 @@
             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")
--- a/yml2proc	Fri Feb 15 10:45:57 2019 +0100
+++ b/yml2proc	Mon Sep 23 19:25:58 2019 +0200
@@ -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.0
+Copyleft (c), 2009-2019 Volker Birk  http://fdik.org/yml/
 
 """
 
@@ -33,7 +33,7 @@
             msg = str(msg) + "\n"
         except:
             msg = u(msg) + u"\n"
-    if type(msg) is unicode:
+    if type(msg) is str:
         msg = codecs.encode(msg, sys.stderr.encoding)
     sys.stderr.write(msg)
 
@@ -182,7 +182,7 @@
         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():
@@ -203,10 +203,10 @@
     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":
@@ -214,11 +214,13 @@
     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")