# HG changeset patch # User Claudio Luck # Date 1536072539 -7200 # Node ID b4a9a3122abb1ae277bae3031bf81aded1c2bca1 # Parent 3a2bd70c01dfa6941b8e37dbc27673a1f9713fe4 move python code into new package dir diff -r 3a2bd70c01df -r b4a9a3122abb Makefile --- 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 diff -r 3a2bd70c01df -r b4a9a3122abb backend.py --- 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\>*)\s*\n(?P.*?)\n(?P\s*)\|\|)|("""(?P.*?)""")|(\>\>(?P.*?)\>\>)', 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"" - else: - result += 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"" - - 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] == '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 diff -r 3a2bd70c01df -r b4a9a3122abb standardlib.ysl2 --- 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))"; -} - diff -r 3a2bd70c01df -r b4a9a3122abb xml2yml.ysl2 --- 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() , - } - - 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')) \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() , - } - - function "convert" { - param "tag"; - - > «translate($tag, '-', '_')» - } -} diff -r 3a2bd70c01df -r b4a9a3122abb yml2.py --- 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] diff -r 3a2bd70c01df -r b4a9a3122abb yml2/backend.py --- /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\>*)\s*\n(?P.*?)\n(?P\s*)\|\|)|("""(?P.*?)""")|(\>\>(?P.*?)\>\>)', 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"" + else: + result += 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"" + + 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] == '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 diff -r 3a2bd70c01df -r b4a9a3122abb yml2/standardlib.ysl2 --- /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))"; +} + diff -r 3a2bd70c01df -r b4a9a3122abb yml2/xml2yml.ysl2 --- /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() , + } + + 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')) \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() , + } + + function "convert" { + param "tag"; + + > «translate($tag, '-', '_')» + } +} diff -r 3a2bd70c01df -r b4a9a3122abb yml2/yml2.py --- /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] diff -r 3a2bd70c01df -r b4a9a3122abb yml2/yml2c --- /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) diff -r 3a2bd70c01df -r b4a9a3122abb yml2/yml2proc --- /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"" + + 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) diff -r 3a2bd70c01df -r b4a9a3122abb yml2/yslt.yml2 --- /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"; + diff -r 3a2bd70c01df -r b4a9a3122abb yml2c --- 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) diff -r 3a2bd70c01df -r b4a9a3122abb yml2proc --- 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"" - - 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) diff -r 3a2bd70c01df -r b4a9a3122abb yslt.yml2 --- 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"; -