# HG changeset patch # User Volker Birk # Date 1468271728 -7200 # Node ID 76005e62091d417f6193d960fc0810b21c829fc9 initial commit diff -r 000000000000 -r 76005e62091d .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,2 @@ +syntax: glob +*.pyc diff -r 000000000000 -r 76005e62091d Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,20 @@ +YML_PATH= +YML2C=yml2c + +all: homepage + +homepage: index.html features.html yslt.html toolchain.html programming.html hello.html + +update: homepage format.css gpl-2.0.txt + rsync -avC *.html *.yml2 format.css *.yhtml2 gpl-2.0.txt samples dragon:fdik.org/yml2/ + +update-all: update yml2c yml2.py pyPEG.py backend.py yml2proc + if test -z $(VERSION) ; then echo VERSION not set ; exit 1 ; fi + rsync -avC *.py yml2c Makefile yml2proc xml2yml.ysl2 standardlib.ysl2 samples dragon:fdik.org/yml2/ + ssh dragon bash -c "cd ; cd fdik.org/; tar cvjf yml-$(VERSION).tar.bz2 yml2/{*.py,*.yml2,*.yhtml2,format.css,gpl-2.0.txt,yml2c,Makefile,yml2proc,xml2yml.ysl2,standardlib.ysl2,samples} ; rm yml2.tar.bz2 ; ln -s yml-$(VERSION).tar.bz2 yml2.tar.bz2" + +%.html: %.en.yhtml2 heading.en.yhtml2 homepage.en.yhtml2 + $(YML2C) $< -o $@ + +clean: + rm -f *.html *.pyc *.pyo diff -r 000000000000 -r 76005e62091d backend.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/backend.py Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,815 @@ +# 2.5.0 backend + +# written by VB. + +import re, codecs +import fileinput +import sys, traceback, exceptions, os +from xml.sax.saxutils import escape, quoteattr +from copy import deepcopy +from glob import glob +from pyPEG import code, parse, parseLine, u, Symbol +from yml2 import ymlCStyle, comment, _inner + +ymlFunc, pointers, pythonFunc = {}, {}, {} +in_ns = u"" +operator = [] +included = u"" +includePath = [] +emitlinenumbers = False +encoding = "utf-8" + +first = True +enable_tracing = False + +ymlFunc["decl"] = "#error" +ymlFunc["define"] = "#error" +ymlFunc["operator"] = "#error" + +def clearAll(): + global ymlFunc, pointers, pythonFunc, in_ns, operator, included + ymlFunc, pointers, pythonFunc = {}, {}, {} + in_ns = u"" + operator = [] + included = u"" + +lq = re.compile(r"\|(\>*)(.*)") +sq = re.compile(r"(\d*)\>(.*)") +ts = re.compile(r'(\|\|(?P\>*)\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: + 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 == "lineQuote" or ctype == "quote": + m, text, base, inds = None, u"", 0, 0 + + if ctype == "lineQuote": + text = obj[1] + m = lq.match(text) + if m: + inds = len(m.group(1)) + text = m.group(2)[1:] + else: inds = 0 + elif ctype == "quote": + inds = -1 + text = obj[1][0] + m = sq.match(text) + if m: + if m.group(1): + inds = int(m.group(1)) + text = m.group(2)[1:] + else: + if type(text) is unicode or type(text) is str: + text = u(evalPython(text)) + + ind = u"" + if inds > -1: + try: + cmd = evalPython(u"indent(" + u(inds) + u")") + result, rest = parseLine(u(cmd), _inner, [], True, comment) + if rest: + raise SyntaxError() + ind = _finish(result) + except: pass + + if ctype == "lineQuote": text += u"\n" + + hasTextFunc = False + try: + ymlFunc["text"] + hasTextFunc = True + except: pass + + text = executeCmd(text) + return code(ind + text) + + elif ctype == "tagQuote": + m = tq.match(obj[1]) + if m.group(1) == "<": + return code(u"<" + m.group(2)) + else: + return code(m.group(2)) + + elif ctype == "operator": + operator.append((re.compile(evalPython(obj[1][0])), obj[1][1])) + return code(u"") + + elif ctype == "constant": + name = obj[1][0] + if name[0] == "*": + name = name[1:] + value = obj[1][1] + pointers[name] = value + return code(u"") + + elif ctype == "include": + reverse = False + ktext, kxml = False, False + for arg in obj[1]: + if type(arg) is tuple or type(arg) is Symbol: + if arg[0] == "reverse": + reverse = True + elif arg[0] == "ktext": + ktext = True + elif arg[0] == "kxml": + kxml = True + elif type(arg) is unicode or type(arg) is str: + filemask = arg + + if filemask[0] == '/' or filemask[0] == '.': + files = glob(filemask) + else: + files = [] + for directory in includePath: + path = os.path.join(directory, filemask) + files.extend(glob(path)) + + if reverse: + files = files[-1::-1] + + if not(files): + if included: + raise IOError(u"in " + included + ":" + u(line) + u": include file(s) '" + filemask + u"' not found") + else: + raise IOError(u"in " + u(line) + u": include file(s) '" + filemask + u"' not found") + + includeFile = fileinput.input(files, mode="rU", openhook=fileinput.hook_encoded(encoding)) + _included = included + if ktext or kxml: + text = u"" + for line in includeFile: + included = includeFile.filename() + if kxml: + if (not line[:6] == ' Text + + p >> + To output text nodes (¬http://www.w3.org/TR/2008/REC-xml-20081126/#syntax character data¬), + write literals. There are integer literals, floating point literals and text literals. + >> + + p >> + Literals are written + ¬http://docs.python.org/reference/lexical_analysis.html#id7 like in Python¬, + that means, text literals are in single or double quotes, or multiline + in triple double quotes: + >> + + Code || + "text" 'also text' """some more text""" + 42 "an integer and" 42.23 "a floating point literal" + || + + p >> + Literals are being output by the ¬#textfunction text function¬. + >> + + h2 id=functioncalls > Function Calls + + p >> + The main idea of YML scripts is calling functions which then generate + XML tags (¬http://www.w3.org/TR/2008/REC-xml-20081126/#syntax Markup¬). + Functions are generating single tags, lists or trees of tags. + >> + + p >> + To call a function, write the name of the function, followed by a comma separated list + of function parameters (C like syntax) or just «attribute=value» pairs. Unlike C, you don't + need to insert the parameter list into parentheses. A simple function call can be terminated + by a semicolon «;» or by a period «.» + >> + + p >> + It does not matter, if you're calling your function using parentheses or brackets or without. + So these statements are equal: + >> + + Code || + foo "hello, world"; + foo "hello, world". + foo("hello, world"); + foo["hello, world"]; + || + + h3 id=subtree > Subtrees + + p >> + If you omit the tailing semicolon, you're creating a Subtree; YML Subtrees can also be + opened and closed with braces: + >> + + Code || + foo { + bar { + something; + } + } + || + + p > If a Subtree only consists of one single subelement, then you may omit the braces: + + Code || + foo + bar; + || + + h3 id=named > Named Parameters + + p >> + To generate ¬http://www.w3.org/TR/2008/REC-xml-20081126/#attdecls attributes¬ by calling + a function, you can use Named Parameters. + >> + + p >> + For that case, assign literals or symbols to attribute names like the following. + The name of the parameter then will be used as the name of the generated attribute. + An example: + >> + + Code || + div id=sample { + "this is a " a href="#sample" "link sample" + } + || + + p > This generates: + + Code |
this is a link sample
+ + h3 > Unnamed Parameters + + p >> + Unnamed Parameters prepare values for predefined attributes. The following example is + equivalent to the sample above: + >> + + Code || + decl a(href); + decl div(id); + + div "sample" { + "this is a " a "#sample" "link sample" + } + || + + p > If no predefined attribute can be allocated, the value of the parameter is added to the body. + + h3 > Calling with & + + p >> + Especially if you have a ¬#defaultbody default body¬ for your function, calling with + a leading «&» can be sensible: then the tag itself is omitted and only the body is being output: + >> + + Code || + decl something { tag1; tag2; }; + + list { + &something; + } + || + + p > results in: + + Code || + + + + + || + + p >> + This has the same result as ¬#alias aliasing¬ «something» to «-». + >> + + h3 id=funclist > Function Lists + + p >> + Function Lists are a feature of YML to simulate a more C like syntax. Let's have some + examples. You can have a list of functions whereever you can have a function. Function + Lists are comma separated: + >> + + Code || + x i, j, k + || + + p > compiles to: + + Code || + + + + + + || + + h3 id=paramlists > Parameter Lists + + p >> + A sample together with ¬#descending Descending Attributes¬: + >> + + Code || + decl Interface @name; + decl attr @type @name; + decl func @type @name; + + Interface Icecream { + attr color flavour; + attr long number; + func int getPrice(); + func void addFlavour(in color flavour, in long number); + } + || + + p > compiles to: + + Code || + + + + + + + + + + + + + + + + + + || + + p >> + Note the «parm» tags – they're generated by default, if you write a Parameter List + behind a Function Call. That differs from calling the function with parameters – + ¬#functioncalls calling¬ means using ¬#text text¬ values. + >> + + p >> + The «parm» tags are emitted, because the «_parm» function is called each time + such a parameter will be emitted. + >> + + p >> + If you want to have the «_parm» function doing other things, just ¬#decl declare¬ + it in another way. + >> + + h3 id=generics > Generic Declarations + + p >> + Using Generic Declarations is just like using ¬#paramlists Parameter Lists¬ – use angle brackets + instead of parentheses. For Generic Declarations, the «_generic» function is called each + time such a Generic Declaration will be emitted, generating «generic» tags as the default: + >> + + Code | max(x, y) + + p > compiles to: + + Code || + + + + + + + + + + + + || + + h3 id=contentfc > The «content» function + + p >> + The «content;» Function Call has a special meaning (only in a ¬#defaultbody default body¬): + it does not generate a tag, but instead + the tags of a supplied body in a call will be inserted at each place where the «content;» + function call is existing in the ¬#defaultbody default body¬. + >> + + h3 id=textfunction > The «text» function + + p >> + There is a special YML function named «text». Usually, it's just ¬#alias aliased¬ to «-» (and + therefore outputting nothing). The «text» function is called each time a text literal will be + output. + >> + + p >> + If you ¬#decl declare¬ the «text» function, you can overload that behaviour. For example, + ¬yslt YSLT¬ is declaring «text» like this: + >> + + Code || + decl text alias xsl:text; + + "test" + || + + p > generates: + + Code | test + + p >> + The «text» function is not called, if you give text as a value for an attribute: + >> + + Code || + decl text alias xsl:text; + + a "test" + || + + p > generates: + + Code | test + + p >> + But it is called using the quoting operators: + >> + + Code || + decl text alias xsl:text; + + a > test + || + + p > generates: + + Code | test + + h3 id=declfunction > The «decl», «define» and «operator» functions + + p >> + The «decl», «define» and «operator» functions are not defined, so they cannot be used + accidentally by having a syntax error i.e. in a «decl» statement. If you want to use such + a function, i.e. «decl()», you have to ¬#decl declare it explicitely¬: + >> + + Code || + decl decl; + decl(); + || + + p > will result in: + + Code | + + h2 id=decl > Declaring Functions: decl + + p >> + As default, each Function Call generates one XML tag, which has the same name. To be exact, + the XML tag has dashes in it's name where the YML function has underscores. + >> + + p >> + To define, how tags and attributes look like, which are created by a Function Call, you + can use the «decl» statement. + >> + + h3 > Trivial Declarations + + p > In a trivial declaration, you're just declaring the Function Name and so the XML tag name: + + Code | decl html, head, title, body, p, a; + + p > As seen in the example, multiple declarations can be done in a comma separated list. + + p >> + Because trivial declarations are done automatically, if you're using a function for the + first time, you usually don't need to declare this way. + >> + + h3 > Specifying Unnamed Parameters + + p >> + To specifiy Unnamed Parameters, give the parameter list comma separated in parentheses + or provide one or more brackets with parameter lists in them: + >> + + Code | decl a(href), img[src]; + + p >> + If you're using the corresponding functions a() and img() together with an unnamed parameter + in a call, then these attributes are used for applying the values, respectively: + >> + + Code | a "http://www.ccc.de" "The Club Homepage" img "logo.png"; + + p > These Function Calls generate: + + Code | The Club Homepage + + h3 id=defaultattr > Giving Default Values for parameters + + p >> + To give default values for generating XML attributes, assign a literal to each named parameter + in the declaration parentheses or brackets. Two examples, which do the same: + >> + + Code + || + decl img(src, alt="picture"); + decl img[src][alt="picture"]; + || + + h3 id=alias > Aliasing: using different YML functions for the same XML tag for different tasks + + p >> + Sometimes tags are used in different ways to do different things. For this case, you can + use aliasing. Aliasing means, the YML function name and the XML tag name differ. For example: + >> + + Code | decl a(href), target(name) alias a; + + p > Both defined YML functions then generate «» tags – but the Unnamed Parameter differs. + + p >> + The alias name «-» has a special meaning: it omits the tag in the output. That is especially + sensible if you have a ¬#defaultbody default body¬. Then an alias to «-» has the same meaning + as starting the function call with the «&» character: only the body is emitted. + >> + + h3 id=descending > Specifying Descending Attributes + + p >> + Maybe you want to write something like this: + >> + + Code || + Module ERP { + Interface Customer { + // ... + } + } + || + + p > Without any extras, this compiles to: + + Code || + + + + + + + + || + + p >> + For this case, it would be practical, if «ERP» would not be interpreted as extra tag + but as value for an attribute «name». This you can achive with Descending Attributes: + >> + + Code | decl Module @name, Interface @name; + + p > With this declaration, the code sample above is compiling to: + + Code || + + + + || + + p >> + Descending attributes can also be used this way: + >> + + Code || + decl module +name; + decl element +name; + + module Some { + element { + one; + two; + three; + } + element { + four; five; six + } + } + || + + p >> + The above generates: + >> + + Code || + + + + + + + + + + || + + h3 id=descending_pointer > Specifying Descending Pointers + + p >> + Like with descending attributes, you can use descending ¬#pointer pointers¬. Instead of preceding the + name of an attribute with a «+» sign (like with ¬#descending descending attributes¬), precede it with an asterisk «*». + >> + + p >> + Like with ¬#pointer pointers¬ in general, it's a good idea to combine that with a ¬#defaultbody default body¬: + >> + + Code || + decl f *p { some tags with *p }; + + f value; + || + + p >> + This generates: + >> + + Code || + + + + + value + + + + || + + h3 id=defaultbody > Supplying a Default Body + + p >> + Additionally, you can supply a Default Body for each tag. For that case, add a YML function + block in braces to your declaration: + >> + + Code || + decl pageContent alias body { + a name=top; + include heading.en.yhtml2; + div id=entries + content; + }; + || + + p > The sample above is used for generating this homepage, for example. + + p > See the ¬#contentfc content function¬. + + h3 id=inheritance > Inheritance + + p >> + Declarations can ¬http://en.wikipedia.org/wiki/Inheritance_(computer_science) inherit¬ + information from previous declarations. For that case, there is the + possibility to use an «is» clause to give a function name to inherit from. + >> + + p > The following is an example from the YSLT specification: + + Code || + decl stylesheet(version="1.0", xmlns:xsl="http://www.w3.org/1999/XSL/Transform"); + + decl estylesheet is stylesheet ( + xmlns:exsl='http://exslt.org/common', + xmlns:math='http://exslt.org/math', + xmlns:func='http://exslt.org/functions', + xmlns:str='http://exslt.org/strings', + xmlns:dyn='http://exslt.org/dynamic', + xmlns:set='http://exslt.org/sets', + extension-element-prefixes='exsl func str dyn set math' + ); + + decl textstylesheet is estylesheet { + output "text"; + const "space", !"'" + " " * 200 + "'"!; + param "autoindent", 4; + content; + }, tstylesheet is textstylesheet; + || + + p >> + Here «estylesheet» inherits the tag name and the Default Values from «stylesheet», + while «textstylesheet» inherits all from «estylesheet» again. «estylesheet» then adds + a Default Body, and «tstylesheet» does exactly the same as «textstylesheet». + >> + + p > All of these YML functions output «stylesheet» XML tags, but with different defaults. + + h3 id=shapes > Shapes + + p >> + Shapes are comparable to ¬#inheritance inheritance¬. Declaring a shape inherits + every property beside the name. + >> + + Code || + decl coords(x=0, y=0); + decl point (name); + + point "origin"; + || + + p > compiles to: + + Code | + + p >> + It's possible to have more than one shape, too. Multiple shapes + are patching each other in the sequence they're listed: + >> + + Code || + decl coords(x=0, y=0); + decl named +name; + decl point ; + + point origin; + || + + p > compiles to: + + Code | + + h3 > Namespaces + + p >> + ¬http://www.w3.org/TR/xml-names/ XML namespaces¬ can be used just by providing an + «alias» clause. Additionally, they can be used by an «in» clause; these two lines + are equivalent: + >> + + Code || + decl apply(select) alias xsl:apply-templates; + in xsl decl apply(select) alias apply-templates; + || + + p > «in» clauses also can be used with a block of declarations in braces: + + Code || + in xsl { + decl template(match); + decl apply(select) alias apply-templates; + + decl function(name) alias template; + decl call(name) alias call-template; + } + || + + h3 id=pointer > Pointers + + p >> + In some situations, it is good to have information in a Function Call, which then + changes the way XML tags are generated. For this case, there are Pointers. + >> + + p >> + The name should not mislead you; I took it because I chose the «*» symbol to declare them, + and that is the meaning of this symbol in the programming language C. The concept behind + is very easy. + >> + + p >> + For example, it could be a good idea to generate a small HTML document containing some + content. For this case, the title of the page is a good case for using pointers: + >> + + Code || + decl page(*title) alias html { + head { + title *title; + } + body { + h1 *title; + content; + } + }; + || + + p >> + In the example above, calling «page('My Page') { p 'hello, world'; }» will result in + this XML output: + >> + + Code || + + + My Page + + +

My Page

+

hello, world

+ + + || + + p >> + Pointers can be referenced in any place in the Default Body of a «decl» statement, also for + generating extra tags. Then the value for a Pointer will be the tag name. + >> + + p >> + Additionally, you can insert the value of a pointer as text by calling it with two leading + asterisks, i.e. if the pointer is defined as «*x», you can insert its value as text using: «**x». + >> + + h4 id=pwt > Pointers without tags + + p >> + To give a literal a name, you can define pointers to literals. + >> + + Code || + define *answer = 42; + something *answer; + || + + p > will compile to: + + Code | 42 + + p >> + The «define» keyword as well as the asterisk «*» can be omitted. So this is + equivalent to the statements above: + >> + + Code || + answer = 42; + something *answer; + || + + h4 > The pointer *_debug_trace + + p >> + If you're calling ¬toolchain#processor yml2proc¬ with ¬toolchain#debug --debug¬, then this pointer is filled + with tracing info text, otherwise it's an empty string. + >> + + h3 id=macros, "Macros"; + + p >> + Macros are a way to generate values for attributes with variable content. Macros can be set + like any other parameters; they're used for a text search & replace in the values of attributes + when attributes are generated. + >> + + p >> + Parameters, which represent macros, are determined with a preceding «%» sign. They're + accounted for before any other parameter is accounted for in a function call, even if + they were defined after other parameters. + >> + + p > An example: + + Code || + decl foo(%macro, myAttr="something %macro for testing"); + + testing + foo "nice"; + || + + p > This generates: + + Code || + + + + || + + h3 id=nullfunction > The Null Function + + p >> + The function with the name «_» (underscore) is called Null Function. If you define this + function, then you're switching off the default behaviour, that trivial declares are done + automatically. + >> + + p >> + Instead, unknown functions now call the Null Function. This can be very sensible together + with ¬#descending Descending Attributes¬: + >> + + Code || + decl _ +type +name alias func; + decl interface +name; + + interface Testcase { + void f(in string input); + long getOptions(); + } + || + + p > compiles to: + + Code || + + + + + + + + + + + || + + h2 id=quoting > Quoting Operators + + p > Five different quoting operators implement different functionality: + + h3 id=quote > Quote > + + p > The «>» operator quotes into text nodes, doing XML escaping of text. An example: + + Code | > this text will be put into a text node and these angle brackets <> will be quoted + + p > Additionally, it can be used to implement an indention system, see ¬yslt YSLT¬ below. + + p >> + Then an integer literal can be the first part of the operator; it gives the indention + level. For example: + >> + + Code || + 0> this text is indented to the actual level and then output, + > followed by this text.\\n + + 1> this text is indented one indention level\\n + 2> two levels\\n + 1> one level again\\n + || + + p >> + Quote text is being output by the ¬#textfunction «text» function¬. + >> + + h3 id=blockquote > Block Quote >> + + p { + > To include more lines of text into a single quoted area, use double «>>». The lines + > are concatenated together then. An example: + } + + Code || + p >> + This generates a text paragraph for HTML. All this text, which you can find in + these lines, is being concatenated together to one single text node, and then put + into the body of the

...

tag. + >> + || + + p >> + Block quote text is being output by the ¬#textfunction «text» function¬. + >> + + h3 > Line Quote | + + p > The «|» operator does the same as the «>» operator, adding a newline character to the text node. + + p > Additionally, it can be used to implement an indention system, see ¬yslt YSLT¬ below. + + p > Then it's used together with additional «>» symbols showing the grade of indention: + + Code || + | not indented + |> single indent + |>> double indent + (...) + || + + p >> + Line quote text is being output by the ¬#textfunction «text» function¬. + >> + + h3 > Block Line Quote || + + p >> + The «||» operator opens and closes a block of lines, which then are handled like if each of + them would be preceeded with a Line Operator «|». + >> + + p > Sample: + + Code { + | || + || + this is code being quoted through + this is the second line + || + | || + } + + p > is equivalent to: + + Code { + || + | this is code being quoted through + | this is the second line + || + } + + p >> + Block line quote text is being output by the ¬#textfunction «text» function¬. + >> + + h3 > Inserting Commands + + p >> + Just like with a ¬http://en.wikipedia.org/wiki/Shell_(computing)#Unix_shells Unix shell¬, + you can insert statements into text by using backticks: + >> + + Code ] | Click `a href="http://fdik.org/yml/" "this link"`, please! + + p { + >> + Being in a Block Line Quote «||», you additionally can use the Line Command operator + (two backquotes, + >> + ] ``). + } + + p > This is very interesting to have in YSLT, for example: + + Code { + | || + | some code + ] `` + > apply "myTemplate";\n + | some other code + | || + } + + h3 id=userop > User defined in-text Operators + + p > You can define short cuts for inserting commands into text by defining operators. + + p >> + Therefore, you need a ¬http://en.wikipedia.org/wiki/Regular_expression regular expression¬ + for matching text and YML text for replacing with. Here an example, how this is used by YSLT: + >> + + Code ] define operator "«(.*?)»" as value "%1"; + + p > The RegEx have ¬http://docs.python.org/library/re.html Python syntax¬. + + p >> + In this example all matches to the RegEx will be replaced by the YML text in the «as» clause. + The text of the first group in the RegEx will replace the «%1» in the resulting YML text. You + can do that for more than one group – just use «%2» for the second group, «%3» for the third + one and so on. + >> + + p > The «define» keyword can be omitted. + + h3 id=quotethrough > Quote Through ] + + p >> + The ¬http://en.wikipedia.org/wiki/Apple_II_series Apple ][¬ prompt operator just quotes + through directly into XML what it gets. + >> + + p >> + If the first character of a command is a «<», then quote through is applied + automatically. + >> + + p > This is the preferred way to output XML tags directly in YML: + + Code || + + + ] + || + + h2 id=including > Including YML files + + p >> + You can include a second YML script file into an existing YML script file + at any place using one of the following: + >> + + Code || + include something.yml2 + include "something else.yml2" + include 'anything addionally.yml2' + || + + a name="ymlpath"; + p >> + If you're not starting the filename with '.' or '/' as in the example above, then + if the «YML_PATH» environment variable is set to a colon separated list of directories, + these directories are being searched for the given filename. Otherwise, the local + directory is searched. + >> + + p >> + Filename ¬http://en.wikipedia.org/wiki/Glob_(programming) globbing¬ using «*» and «?» + placeholders is supported to include more than one file at a time: + >> + + Code | include part*.yml2 + + p >> + Filename globbing also can be used reverted; that means, the files are included in reverse + order: + >> + + Code | include reverse part*.yml2 + + p > If there are the files part1.yml, part2.yml and part3.yml, part3.yml is included first now. + + p > To include plain text as text nodes, you can use: + + Code | include text some.txt + + p > To include ready made XML, use: + + Code | include xml some.xml + + h2 id=python > Escaping into Python – the Escape Operator ! + + p > You can insert a Python command at any place by using the «!» operator: + + Code | !class X(str): pass + + h3 > Python script Operator !! + + p > You can use the double «!!» to include more than one line of Python code: + + Code || + !! + def fak(n): + if n == 0: + return 1 + else: + return n * fak(n - 1) + + def getName(id): + return SQL("select name from customers where id='"+str(id)+"';")[0] + !! + || + + h3 > Python generated parameters in Function Calls + + p >> + You may use Python expressions to generate names and/or values in Function Calls. + To do so, embed the Python expression in «! ... !»: + >> + + Code || + f x=!fak(5)!; + customer name=!getName(42)!; + tag !getNextAttributeName()!=42; + || + + h3 > Python generated Function Calls + + p >> + You can generate text with a Python expression, which represents an YML Function Call. + The resulting YML function is then executed. Also here, embed the Python expression + in «! ... !»: + >> + + Code | !getTagName() + " " + getAttrib() + "='" + getValue() + "'"! + + h3 > Using Pointers as values in Python function calls + + p >> + Sometimes it is useful to call a generating Python function using information of a + YML Function Call. For that case, there is the «python» statement in YML. You can + call there a single Python function using YML Pointers as parameters. + >> + + p > This is used in the YSLT specification, for example: + + Code || + decl apply(select, *indent=1) alias apply-templates { + python withIndent(*indent); + content; + }; + || + + h2 id=comments > Comments //, /* */ + + p > Comments are written like in Java or C++: + + Code || + // this is a comment + something() { // this is a comment after a tag + /* this is some comment, too */ + || + + p > After Quoting Operators, comments are not possible. Instead, they're quoted through: + + Code || + // the following line you'll find in the output document + > this text is being output // and this too + || + + div id=bottom { + > ¬programming << Using YML 2¬ + > ¬#top ^Top^¬ + > ¬yslt >> show me YSLT¬ + > ¬features.en.yhtml2 (source)¬ + } +} diff -r 000000000000 -r 76005e62091d format.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/format.css Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,90 @@ +html { + background-color: lightgrey; +} + +body { + margin-left: auto; + margin-right: auto; + margin-top: 0; + width: 900px; + min-height: 768px; + background-color: white; + font-family: Arial,Helvetica,FreeSans +} + +em { + color: darkblue; + font-weight: bold; + font-style: normal; +} + +#headline { + color: black; + font-size: x-large; + font-weight: normal; + border-bottom-width: 1px; + border-bottom-style: solid; + padding: 10px; +} + +td { + vertical-align: top; +} + +#navigation { + position: relative; + float: right; + width: 200px; + border-left-width: 1px; + border-left-style: dotted; + padding: 10px; + font-size: small; +} + +#entries { + width: 569px; + padding: 10px; +} + +.statusline { + width: 569px; + padding-left: 10px; + padding-right: 10px; + font-size: small; +} + +#bottom { + clear: both; + color: grey; + padding: 10px; +} + +h1, h2 { + font-size: medium; + color: darkblue; +} + +h3 { + font-size: medium; + color: black; +} + +h4 { + font-size: medium; + font-weight: normal; + font-style: italic; +} + +.subscript { + font-size: small; + border-bottom-width: 1px; + border-bottom-style: dotted; + margin-bottom: 1em; + padding-bottom: 1em; +} + +.small { + font-size: small; + margin-bottom: 1em; + padding-bottom: 1em; +} diff -r 000000000000 -r 76005e62091d gpl-2.0.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gpl-2.0.txt Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff -r 000000000000 -r 76005e62091d heading.en.yhtml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/heading.en.yhtml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,66 @@ +decl a(href); + +decl Code alias pre { + code + content; +}; + +decl ne is a { + content; + br; +}; + +div id=headline { + p > YML – Why a Markup Language?! + div class=small { + "YML 2.5.4 of We Apr 10 2013 – Copyleft 2007-2013, " + a "http://blog.fdik.org", "Volker Birk"; + " – " + a "http://fdik.org/yml2.tar.bz2", "Download YML 2"; + } +} + +div id=navigation { + h1 a "index", "Introduction"; + ne "index#xml", "XML"; + ne "index#motivation", "Motivation"; + ne "index#howitworks", "How it works"; + ne "index#ylanguages", "Y Languages"; + + h1 a "programming", "Using YML 2"; + ne "programming#wiki", "A Wiki like language"; + ne "programming#how", "How does that work?"; + ne "programming#details", "Details, please!"; + ne "programming#using", "Using it"; + + h1 a "features", "Features"; + ne "features#text", "Text"; + ne "features#functioncalls", "Function Calls"; + ne "features#decl", "Declaring Functions"; + ne "features#quoting", "Quoting Operators"; + ne "features#including", "Including YML Files"; + ne "features#python", "Escaping into Python"; + ne "features#comments", "Comments"; + + h1 a "yslt", "YSLT"; + ne "yslt#intro", "Introduction into YSLT"; + ne "yslt#hello", "Hello, World"; + ne "yslt#programming", "Programming in YSLT"; + ne "yslt#htmlgen", "Generating HTML out of a DSL"; + ne "yslt#codegen", "Generating Java code out of a DSL"; + ne "yslt#ddlgen", "Generating SQL DDL out of UML in XMI"; + ne "yslt#features", "YSLT Features"; + + h1 a "toolchain", "Tool Chain"; + ne "toolchain#compiler", "YML compiler"; + ne "toolchain#processor", "YML/YSLT processor"; + ne "toolchain#recommended", "Recommended external tools"; + ne "http://www.auchdieserschwachsinnmussinsinternet.de/2009-03/#s1236859037", "Windows tool chain"; + ne "http://fdik.org/yml2.tar.bz2", "Download YML 2"; + ne "toolchain#downloads", "Download different versions"; + + h1 "Misc"; + ne "gpl-2.0.txt", "License for YML"; + ne "http://www.pibit.ch/", "Commercial support for YML"; + ne "http://fdik.org/pyPEG", "YML is using pyPEG"; +} diff -r 000000000000 -r 76005e62091d hello.en.yhtml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hello.en.yhtml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,12 @@ +include homepage.en.yhtml2 + +page "Hello, world" { + p >> + Hello, world! I can link here, say: + ¬http://en.wikipedia.org to Wikipedia¬ + >> + + p >> + This is ƒemphasized. And this is «code». + >> +} diff -r 000000000000 -r 76005e62091d homepage.en.yhtml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/homepage.en.yhtml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,24 @@ + + + +decl pageContent alias body { + a name=top; + include heading.en.yhtml2; + div id=entries + content; +}; + +decl page(*title, lang="en", xml:lang="en", xmlns="http://www.w3.org/1999/xhtml") alias html { + head { + title *title; + meta http-equiv="Content-Type", content="text/html;charset=UTF-8"; + link rel=stylesheet, type="text/css", href="format.css"; + } + + pageContent + content; +}; + +define operator "¬\s*(.*?)\s+(.*?)\s*¬" as a href="%1" > %2 +define operator "«(.*?)»" as code > %1 +define operator "ƒ(\S+)" as em > %1 diff -r 000000000000 -r 76005e62091d index.en.yhtml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/index.en.yhtml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,206 @@ +// the YML homepage + +include homepage.en.yhtml2 + +page "YML – Why a Markup Language?!" { + h1 > Introduction + + h2 > What is YML? + + p >> + Well, it's the idea not to need to define a grammar first when you want to use a + ¬http://en.wikipedia.org/wiki/Domain_Specific_Language Domain Specific Language¬. + For that purpose, YML is being translated into XML. Let's make an example. + >> + + p >> + Everything which comes close to a C like language, parses without a grammar + definition: + >> + + p > This: + + Code + || + template< class T > T max(T a, T b); + || + + p > Parses to: + + Code + || + + + || + + p >> + Instead of defining grammars, you test out and play around until the + results are matching your needs. If the resulting tree does not fit + what you're expecting, change it by patching the grammar with `code > decl`: + >> + + p > This: + + Code + || + module A { + interface B { + attribute long n; + }; + }; + || + + p > Parses to: + + Code + || + + +
+ + + + + + + + + + + + || + + p >> + This does not look like what we want. So we tell YML that + we have a module name after the module, an interface name after + the interface and type and name after the attribute: + >> + + p > This: + + Code + || + decl module @name; + decl interface @name; + decl attribute @type @name; + + module A { + interface B { + attribute long n; + }; + }; + || + + p > Parses to: + + Code + || + + + + + + + || + + h2 id=what > What can I do with YML? + + p > With YML you can: + + ul { + li p > use a C-like ¬http://en.wikipedia.org/wiki/Domain-specific_language DSL¬ without writing a grammar first + li p > generate code out of this ¬http://en.wikipedia.org/wiki/Domain-specific_language DSL¬ using ¬yslt YSLT¬ + li p > generate code out of ¬http://en.wikipedia.org/wiki/Unified_Modeling_Language UML¬ using ¬yslt YSLT¬ on ¬http://en.wikipedia.org/wiki/XML_Metadata_Interchange XMI¬ + li p > generate code out of any XML based language like ¬http://en.wikipedia.org/wiki/Scalable_Vector_Graphics SVG¬ using ¬yslt YSLT¬ + li p > define a ¬http://en.wikipedia.org/wiki/Wiki wiki¬ like language in just a few lines like ¬http://fdik.org/yml/programming#wiki YHTML¬ does + li p > replace bad designed and complicated XML languages with simpler C-like ones + li p > ... and much more. + } + + h2 id=howitworks > How it works: Replacing angle brackets with some Python + + p > Just writing down what I wanted to have instead of XML for a sample: + + Code || + + + + Goods + + + Price + + + + + Beer + + + 20 + + + + + Wine + + + 30 + + + + || + + p > Something like that should be more easy, say, like this: + + Code || + list "List of goods" { + head title "Goods", title "Price"; + row value "Beer", value 20; + row value "Wine", value 30; + } + || + + h2 id=ylanguages > Y Languages + + p >> + The latter is what I call an Y language – a language specified in YML. How could this be + achieved? Well, what's to do? To have the required information, how to build XML from the + script above, we need: + >> + + ul { + li >> + the information, that “list of goods” is an attribute named «name», while «Goods» is + the text value of a tag + >> + li > «title» shout be written out as «columnTitle» + } + + p > How to do that? Let's invent a simple definition language for that information: + + Code || + decl list(name); + decl title alias columnTitle; + || + + p > Here you can ¬samples/list.yml2 download the complete list sample¬. + + div id=bottom > ¬#top ^Top^¬ ¬programming >> Using YML 2¬ ¬index.en.yhtml2 (source)¬ +} diff -r 000000000000 -r 76005e62091d manpage.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/manpage.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,1 @@ +decl manpage(xmlns="http://docbook.org/ns/docbook", version="5.0", *title) alias article { title *title; content; }; diff -r 000000000000 -r 76005e62091d programming.en.yhtml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/programming.en.yhtml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,413 @@ +include homepage.en.yhtml2 + +page "Using YML 2" { + p >> + YML 2 is a smart ¬http://en.wikipedia.org/wiki/Template_processor template language¬ and + ¬http://en.wikipedia.org/wiki/Domain-specific_language DSL concept¬. This guide will give + you a feeling, for what it's worth. + >> + + h2 id=wiki > Creating a Wiki like language for writing documentation + + p >> + Let's say, we want to define a small Wiki system, which should be translated from a Wiki + like language into HTML. This guide is written in one using YML 2. I call it ƒYHTML. You can + view the ¬homepage.en.yhtml2 source code of what you're reading now¬. It's about writing + web pages like that: + >> + + Code { + || + page "Hello, world" { + p ¬features#blockquote >>¬ + Hello, world! I can link here, say: + || + > + ] ¬http://en.wikipedia.org to Wikipedia¬ + > \n + || + ¬features#blockquote >>¬ + + p ¬features#blockquote >>¬ + || + > + ] This is ƒemphasized. And this is «code». + > \n + || + ¬features#blockquote >>¬ + } + || + } + p >> + Prerequisite: knowing how ¬http://en.wikipedia.org/wiki/Html#Markup HTML¬ works. + >> + + h2 id=how > How does that work? + + p >> + YML 2 is a template language. That means, you can define ¬http://en.wikipedia.org/wiki/Recursion recursive¬ + templates of what's to be generated. This is ¬homepage.en.yhtml2 the code¬; just click on underlined things + to get an explanation: + >> + + Code { + || + ¬features#quotethrough <¬?xml version="1.0" encoding="UTF-8"?¬features#quotethrough >¬ + ¬features#quotethrough <¬!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"¬features#quotethrough >¬ + + ¬features#decl decl¬ pageContent ¬features#alias alias¬ body ¬features#defaultbody {¬ + a name¬features#named =¬"top"; + ¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬; + div id¬features#named =¬"entries" + ¬features#contentfc content¬; + ¬features#defaultbody }¬; + + ¬features#decl decl¬ page(¬features#pointer *title¬, lang¬features#defaultattr =¬"en", xml:lang¬features#defaultattr =¬"en", xmlns¬features#defaultattr =¬"http://www.w3.org/1999/xhtml") + ¬features#alias alias¬ html ¬features#defaultbody {¬ + head ¬features#subtree {¬ + title ¬features#pointer *title¬; + meta http-equiv¬features#named =¬"Content-Type", content¬features#named =¬"text/html;charset=UTF-8"; + link rel¬features#named =¬"stylesheet", type¬features#named =¬"text/css", href¬features#named =¬"format.css"; + ¬features#subtree }¬ + + pageContent + ¬features#contentfc content¬; + ¬features#defaultbody }¬; + || + + br; > ¬features#userop define operator¬ + ] "¬\s*(.*?)\s+(.*?)\s*¬" + > ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2 + + br; > ¬features#userop define operator¬ + ] "«(.*?)»" + > ¬features#userop as¬ code ¬features#quote >¬ %1 + + br; > ¬features#userop define operator¬ + ] "ƒ(\S+)" + > ¬features#userop as¬ em ¬features#quote >¬ %1 + } + + h2 id=details > Details, please! + + h3 > Starting with XHTML headers + + p >> + Because HTML headers are boring and annoying, I'm copying them from document to document. And at last, + they ended here ;-) If you already have things in angle brackets, you can just add them to your YML 2 + document “as is”, because everything which starts with an opening angle bracket will be a “give through” + for the YML 2 toolchain. So our first two lines are: + >> + + Code + || + ¬features#quotethrough <¬?xml version="1.0" encoding="UTF-8"?¬features#quotethrough >¬ + ¬features#quotethrough <¬!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"¬features#quotethrough >¬ + || + + h3 > Defining the document structure + + p >> + A Webpage usually has a structure: it has a specific title and content. Beside that, technical things + have to be encoded. A Webpage in XHTML is XML text, setting xmlns to the right name space. That's how we + do that in YML 2: + >> + + Code + || + ¬features#decl decl¬ page(¬features#pointer *title¬, lang¬features#defaultattr =¬"en", xml:lang¬features#defaultattr =¬"en", xmlns¬features#defaultattr =¬"http://www.w3.org/1999/xhtml") + ¬features#alias alias¬ html ¬features#defaultbody {¬ + || + + p >> + First we ¬features#decl declare¬ the «page» function. It's ¬features#alias aliased to¬ «html», so it will + generate a «html» tag, not a «page» tag. + >> + + p >> + The first parameter, «*title», is a placeholder for the title of the document. The content of what we give + here later will be repeated at any place we're putting «*title» into our template. This technique is called + ¬features#pointer Pointers¬. + >> + + p >> + The two other attributes have ¬features#defaultattr Default Values¬, so they're generated each time the + «page» function will be called. + >> + + h3 > The Document content + + p >> + The document content is what is in the «{ ... }» block: + >> + + Code + || + ¬features#defaultbody {¬ + head ¬features#subtree {¬ + title ¬features#pointer *title¬; + meta http-equiv¬features#named =¬"Content-Type", content¬features#named =¬"text/html;charset=UTF-8"; + link rel¬features#named =¬"stylesheet", type¬features#named =¬"text/css", href¬features#named =¬"format.css"; + ¬features#subtree }¬ + + pageContent + ¬features#contentfc content¬; + ¬features#defaultbody }¬; + || + + p >> + This reflects, that each HTML document has a «head» and a «body» section. Of course, we insert the «*title» + pointer value in the «title» tag. Then some meta data and a link to a nice + ¬http://en.wikipedia.org/wiki/Cascading_Style_Sheets CSS¬ ;-) + >> + + p >> + For the «body» section, we have a little helper function, «pageContent». The function named «content» is + a ¬features#contentfc placeholder¬, where the content of the page will be placed, when our «page» function + will be called. + >> + + h3 > Generating the «body» with the «pageContent» function + + p >> + The «pageContent» function is used for generating the «body» with standard elements; therefore, it's + ¬features#alias aliased¬ to «body»: + >> + + Code + || + ¬features#decl decl¬ pageContent ¬features#alias alias¬ body ¬features#defaultbody {¬ + a name¬features#named =¬"top"; + ¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬; + div id¬features#named =¬"entries" + ¬features#contentfc content¬; + ¬features#defaultbody }¬; + || + + p >> + It first sets an HTML anchor, so links can reference the top of the page: + >> + + Code | a name¬features#named =¬"top"; + + p >> + Then a file with heading and navigation (the menu to the right on the page here) is being + ¬features#including included¬: + >> + + Code | ¬features#including include¬ ¬heading.en.yhtml2 heading.en.yhtml2¬; + + p >> + At last, the page content is being put in, surrounded by a «div» named «entries», so it can be referenced + later, too: + >> + + Code || + div id¬features#named =¬"entries" + ¬features#contentfc content¬; + || + + p >> + If you'll have a look on the included ¬heading.en.yhtml2 heading.en.yhtml2¬ file, then you'll see the + the static head and navigation sections hard coded. With the ¬format.css CSS file¬ everything is brought + to the right place. + >> + + h3 > Defining some operators for the Wiki like language + + p >> + The trick with a Wiki like language is, that one can write plain text, and adding structural things + to it, like links i.e. + >> + + p >> + So we need language constructs, which let us structure. In YML 2 these are called + ¬features#userop User defined in-text Operators¬: + >> + + Code { + > ¬features#userop define operator¬ + ] "¬\s*(.*?)\s+(.*?)\s*¬" + > ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2 + + br; > ¬features#userop define operator¬ + ] "«(.*?)»" + > ¬features#userop as¬ code ¬features#quote >¬ %1 + + br; > ¬features#userop define operator¬ + ] "ƒ(\S+)" + > ¬features#userop as¬ em ¬features#quote >¬ %1 + } + + p >> + They look somewhat disturbing, if you're not familiar with + ¬http://en.wikipedia.org/wiki/Regular_expression Regex¬, so I will explain. + >> + + p >> + First we define a link: + >> + + Code { + > ¬features#userop define operator¬ + ] "¬\s*(.*?)\s+(.*?)\s*¬" + > ¬features#userop as¬ a href¬features#named =¬"%1" ¬features#quote >¬ %2 + } + + p >> + The keyword «define operator» starts the definition. Then there is the Regex: + >> + + Code | "¬\s*(.*?)\s+(.*?)\s*¬" + + p { + "I decided I want to have the special character " "¬" " surrounding each link like this: " + code ] ¬http://en.wikipedia.org go to Wikipedia¬ + ". This is just like what ¬http://www.mediawiki.org MediaWiki¬ does with brackets; here the " + "same would read: «[http://en.wikipedia.org go to Wikipedia]»." + } + + p >> + I like using such special characters. This is because I'm using a + ¬http://www.apple.com/mac/ Mac¬ and ¬http://en.wikipedia.org/wiki/GNU/Linux GNU/Linux¬. + If you're using ¬http://www.microsoft.com/windows/ Windows¬, I really can recommend + ¬http://www.autohotkey.com/docs/Hotkeys.htm AutoHotkey¬. It's a great piece of software to expand the + keyboard capabilities of Windows (and much more). + >> + + p { + > How does this Regex stuff work? It's a ¬http://en.wikipedia.org/wiki/Pattern_matching pattern matching¬ language consuming characters with each + > command. Well, we want to have the following: The first thing between the + ] ¬ + > markers shell be the link target URL. All other things shell be the name of the link shown. + >> + For that case, we're first consuming whitespace with «\s*» – the «\s» means “an arbitrary whitespace + character” (like blank, newline, etc.). The asterisk «*» means “some of them or none”, so this + consumes all whitespace which is there (and gives no error if there is none). + >> + } + + p >> + Second, we open a group with parentheses «( )» This first group we can later reference as «%1» + when substituting. + >> + + p >> + Inside this group, we're telling that we want anything in it, no matter what it is. For this case, + we're using a dot «.» which means “any character”, followed by asterisk questionmark «*?», which is + the code for “consume as much as you can, but only up to the next code in the Regex”. The total + «(.*?)» consumes the target URL (without checking it). + >> + + p >> + Then we're consuming some whitespace again, this time with «\s+». Using a plus «+» instead of an + asterisk «*» or asterisk questionmark «*?» means: there has to be at least one whitespace character. + And we want whitespace between the URL and the name, right? ;-) + >> + + p >> + Now we're consuming the second group. We're consuming whatever is there – it's the name of the + link. We're using another «(.*?)» group for it. It will be group 2, and we can reference it with + this in the substitution: «%2». + >> + + p { + > At last we're consuming redundant whitespace with «\s*», and our Regex is closed by another + ] ¬ + > character. And that makes the total Regex: + } + + Code ] "¬\s*(.*?)\s+(.*?)\s*¬" + + p >> + So what can we do with it? What we want are «» tags. And that means, we want to + call a function like this: «a href="..." > ...» + >> + + p >> + As «href» we want to have the result of group 1, + because this is the link target. After the ¬features#quote Quote operator¬ «>» we want to have + what is the name of the link, that is the result of group 2. That we can write literally: + >> + + Code | a href="%1" > %2 + + p >> + Our first User defined in-text Operator is ready :-) + >> + + p >> + Maybe you would prefer using brackets. So just do it ;-) Change the Regex to this, and you + can use brackets for links like in MediaWiki; we have to escape the brackets «[ ]» with a + backslash «\\», because brackets are also codes in Regex, and we don't want the code, we really + want brackets: + >> + + Code | "\[\s*(.*?)\s+(.*?)\s*\]" + + p >> + The other two operators should now be easy to understand: + >> + + Code { + > ¬features#userop define operator¬ + ] "«(.*?)»" + > ¬features#userop as¬ code ¬features#quote >¬ %1 + + br; > ¬features#userop define operator¬ + ] "ƒ(\S+)" + > ¬features#userop as¬ em ¬features#quote >¬ %1 + } + + p >> + A tip: the code with an upper case letter S «\S» means, that only non-whitespace characters shell + be consumed. + >> + + h2 id=using > Using it + + p >> + How to write a new web page with our templates? Here's a ¬hello.en.yhtml2 hello world¬. We can use + ¬features#blockquote Block Quotes¬ for entering text, and our new self defined operators: + >> + + Code { + || + ¬features#including include¬ homepage.en.yhtml2 + + page "Hello, world" { + p ¬features#blockquote >>¬ + Hello, world! I can link here, say: + || + > + ] ¬http://en.wikipedia.org to Wikipedia¬ + > \n + || + ¬features#blockquote >>¬ + + p ¬features#blockquote >>¬ + || + > + ] This is ƒemphasized. And this is «code». + > \n + || + ¬features#blockquote >>¬ + } + || + } + + p >> + The result you can ¬hello see here¬: + >> + + iframe src="hello", width="100%", height=300 > ¬hello see here¬ + + div id=bottom { + > ¬index << back to Introduction¬ + > ¬#top ^Top^¬ + > ¬features >> The Features¬ + > ¬programming.en.yhtml2 (source)¬ + } +} diff -r 000000000000 -r 76005e62091d pyPEG.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyPEG.py Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,351 @@ +# YPL parser 1.5 + +# written by VB. + +import re +import sys, codecs +import exceptions + +class keyword(unicode): pass +class code(unicode): pass +class ignore(object): + def __init__(self, regex_text, *args): + self.regex = re.compile(regex_text, *args) + +class _and(object): + def __init__(self, something): + self.obj = something + +class _not(_and): pass + +class Name(unicode): + def __init__(self, *args): + self.line = 0 + self.file = u"" + +class Symbol(list): + def __init__(self, name, what): + self.__name__ = name + self.append(name) + self.what = what + self.append(what) + def __call__(self): + return self.what + def __unicode__(self): + return u'Symbol(' + repr(self.__name__) + ', ' + repr(self.what) + u')' + def __repr__(self): + return unicode(self) + +word_regex = re.compile(ur"\w+") +rest_regex = re.compile(ur".*") + +print_trace = False + +def u(text): + if isinstance(text, exceptions.BaseException): + text = text.args[0] + if type(text) is unicode: + return text + if isinstance(text, str): + if sys.stdin.encoding: + return codecs.decode(text, sys.stdin.encoding) + else: + return codecs.decode(text, "utf-8") + return unicode(text) + +def skip(skipper, text, skipWS, skipComments): + if skipWS: + t = text.lstrip() + else: + t = text + if skipComments: + try: + while True: + skip, t = skipper.parseLine(t, skipComments, [], skipWS, None) + if skipWS: + t = t.lstrip() + except: pass + return t + +class parser(object): + def __init__(self, another = False, p = False): + self.restlen = -1 + if not(another): + self.skipper = parser(True, p) + self.skipper.packrat = p + else: + self.skipper = self + self.lines = None + self.textlen = 0 + self.memory = {} + self.packrat = p + + # parseLine(): + # textline: text to parse + # pattern: pyPEG language description + # resultSoFar: parsing result so far (default: blank list []) + # skipWS: Flag if whitespace should be skipped (default: True) + # skipComments: Python functions returning pyPEG for matching comments + # + # returns: pyAST, textrest + # + # raises: SyntaxError(reason) if textline is detected not being in language + # described by pattern + # + # SyntaxError(reason) if pattern is an illegal language description + + def parseLine(self, textline, pattern, resultSoFar = [], skipWS = True, skipComments = None): + name = None + _textline = textline + _pattern = pattern + + def R(result, text): + if __debug__: + if print_trace: + try: + if _pattern.__name__ != "comment": + sys.stderr.write(u"match: " + _pattern.__name__ + u"\n") + except: pass + + if self.restlen == -1: + self.restlen = len(text) + else: + self.restlen = min(self.restlen, len(text)) + res = resultSoFar + if name and result: + name.line = self.lineNo() + res.append(Symbol(name, result)) + elif name: + name.line = self.lineNo() + res.append(Symbol(name, [])) + elif result: + if type(result) is type([]): + res.extend(result) + else: + res.extend([result]) + if self.packrat: + self.memory[(len(_textline), id(_pattern))] = (res, text) + return res, text + + def syntaxError(): + if self.packrat: + self.memory[(len(_textline), id(_pattern))] = False + raise SyntaxError() + + if self.packrat: + try: + result = self.memory[(len(textline), id(pattern))] + if result: + return result + else: + raise SyntaxError() + except: pass + + if callable(pattern): + if __debug__: + if print_trace: + try: + if pattern.__name__ != "comment": + sys.stderr.write(u"testing with " + pattern.__name__ + u": " + textline[:40] + u"\n") + except: pass + + if pattern.__name__[0] != "_": + name = Name(pattern.__name__) + + pattern = pattern() + if callable(pattern): + pattern = (pattern,) + + text = skip(self.skipper, textline, skipWS, skipComments) + + pattern_type = type(pattern) + + if pattern_type is str or pattern_type is unicode: + if text[:len(pattern)] == pattern: + text = skip(self.skipper, text[len(pattern):], skipWS, skipComments) + return R(None, text) + else: + syntaxError() + + elif pattern_type is keyword: + m = word_regex.match(text) + if m: + if m.group(0) == pattern: + text = skip(self.skipper, text[len(pattern):], skipWS, skipComments) + return R(None, text) + else: + syntaxError() + else: + syntaxError() + + elif pattern_type is _not: + try: + r, t = self.parseLine(text, pattern.obj, [], skipWS, skipComments) + except: + return resultSoFar, textline + syntaxError() + + elif pattern_type is _and: + r, t = self.parseLine(text, pattern.obj, [], skipWS, skipComments) + return resultSoFar, textline + + elif pattern_type is type(word_regex) or pattern_type is ignore: + if pattern_type is ignore: + pattern = pattern.regex + m = pattern.match(text) + if m: + text = skip(self.skipper, text[len(m.group(0)):], skipWS, skipComments) + if pattern_type is ignore: + return R(None, text) + else: + return R(m.group(0), text) + else: + syntaxError() + + elif pattern_type is tuple: + result = [] + n = 1 + for p in pattern: + if type(p) is type(0): + n = p + else: + if n>0: + for i in range(n): + result, text = self.parseLine(text, p, result, skipWS, skipComments) + elif n==0: + if text == "": + pass + else: + try: + newResult, newText = self.parseLine(text, p, result, skipWS, skipComments) + result, text = newResult, newText + except SyntaxError: + pass + elif n<0: + found = False + while True: + try: + newResult, newText = self.parseLine(text, p, result, skipWS, skipComments) + result, text, found = newResult, newText, True + except SyntaxError: + break + if n == -2 and not(found): + syntaxError() + n = 1 + return R(result, text) + + elif pattern_type is list: + result = [] + found = False + for p in pattern: + try: + result, text = self.parseLine(text, p, result, skipWS, skipComments) + found = True + except SyntaxError: + pass + if found: + break + if found: + return R(result, text) + else: + syntaxError() + + else: + raise SyntaxError(u"illegal type in grammar: " + u(pattern_type)) + + def lineNo(self): + if not(self.lines): return u"" + if self.restlen == -1: return u"" + parsed = self.textlen - self.restlen + + left, right = 0, len(self.lines) + + while True: + mid = int((right + left) / 2) + if self.lines[mid][0] <= parsed: + try: + if self.lines[mid + 1][0] >= parsed: + try: + return u(self.lines[mid + 1][1]) + u":" + u(self.lines[mid + 1][2]) + except: + return u"" + else: + left = mid + 1 + except: + try: + return u(self.lines[mid + 1][1]) + u":" + u(self.lines[mid + 1][2]) + except: + return u"" + else: + right = mid - 1 + if left > right: + return u"" + +# plain module API + +def parseLine(textline, pattern, resultSoFar = [], skipWS = True, skipComments = None, packrat = False): + p = parser(p=packrat) + text = skip(p.skipper, textline, skipWS, skipComments) + ast, text = p.parseLine(text, pattern, resultSoFar, skipWS, skipComments) + return ast, text + +# parse(): +# language: pyPEG language description +# lineSource: a fileinput.FileInput object +# skipWS: Flag if whitespace should be skipped (default: True) +# skipComments: Python function which returns pyPEG for matching comments +# packrat: use memoization +# lineCount: add line number information to AST +# +# returns: pyAST +# +# raises: SyntaxError(reason), if a parsed line is not in language +# SyntaxError(reason), if the language description is illegal + +def parse(language, lineSource, skipWS = True, skipComments = None, packrat = False, lineCount = True): + lines, lineNo = [], 0 + + while callable(language): + language = language() + + orig, ld = u"", 0 + for line in lineSource: + if lineSource.isfirstline(): + ld = 1 + else: + ld += 1 + lines.append((len(orig), lineSource.filename(), lineSource.lineno() - 1)) + orig += u(line) + + textlen = len(orig) + + try: + p = parser(p=packrat) + p.textlen = len(orig) + if lineCount: + p.lines = lines + else: + p.line = None + text = skip(p.skipper, orig, skipWS, skipComments) + result, text = p.parseLine(text, language, [], skipWS, skipComments) + if text: + raise SyntaxError() + + except SyntaxError, msg: + parsed = textlen - p.restlen + textlen = 0 + nn, lineNo, file = 0, 0, u"" + for n, ld, l in lines: + if n >= parsed: + break + else: + lineNo = l + nn += 1 + file = ld + + lineNo += 1 + nn -= 1 + lineCont = orig.splitlines()[nn] + raise SyntaxError(u"syntax error in " + u(file) + u":" + u(lineNo) + u": " + lineCont) + + return result diff -r 000000000000 -r 76005e62091d samples/Customer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/Customer.java Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,10 @@ +// Die Klasse Customer +class Customer { + public void setName(String value) { + name = value; + } + public String getName() { + return name; + } + private String name; +} diff -r 000000000000 -r 76005e62091d samples/address.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/address.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,13 @@ +list { + address { + name "Meier"; + street "Hauptstrasse"; + city "Heidenheim"; + } + + address { + name "Schmid"; + street "Wilhelmstrasse"; + city "Gingen"; + } +} diff -r 000000000000 -r 76005e62091d samples/addresslistenhtml.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/addresslistenhtml.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,7 @@ +include yslt.yml2 + +stylesheet { + template "/list" html body table apply "address"; + template "address" tr apply "*"; + template "*" td value "."; +} diff -r 000000000000 -r 76005e62091d samples/adressliste.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/adressliste.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,12 @@ +liste { + adresse { + name "Meier"; + strasse "Uhlmannstrasse 42"; + ort "Laupheim"; + } + adresse { + name "Schmidt"; + strasse "Haupstrasse 23"; + ort "Bad Waldsee"; + } +} diff -r 000000000000 -r 76005e62091d samples/backend.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/backend.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,9 @@ +include yslt.yml2 + +textstylesheet { + template "/list" { + > CREATE TABLE + value "name()"; + > (\n + apply "*/*"; + diff -r 000000000000 -r 76005e62091d samples/blub.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/blub.svg Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,61 @@ + + + + + Irritant + produit chimique + + + + symbol + signs_and_symbols + + + + + yves GUILLOU + + + + + yves GUILLOU + + + + + yves GUILLOU + + + + image/svg+xml + + + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 000000000000 -r 76005e62091d samples/blub.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/blub.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,1 @@ +Das ist ein Beispiel; diff -r 000000000000 -r 76005e62091d samples/browse.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/browse.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,6 @@ +include yslt.yml2 + +tstylesheet template "*" { + | «name()» + apply "*"; +} diff -r 000000000000 -r 76005e62091d samples/bumens.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/bumens.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,9 @@ +function "fak" { + param "n"; + + choose { + when "n=0" value 1 + otherwise value "$n * fak($n-1)"; + } +} + diff -r 000000000000 -r 76005e62091d samples/clike.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/clike.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,6 @@ +decl interface +name; +decl _ +type +name alias func; + +interface Test { + void f(in string x, out long y); +} diff -r 000000000000 -r 76005e62091d samples/ctest.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/ctest.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,3 @@ +// dingens + +x; diff -r 000000000000 -r 76005e62091d samples/customer.java.target --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/customer.java.target Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,27 @@ +package Bla; + +class Customer { + // attribute id + + public int getId() { + return id; + } + + public void setId(int value) { + id = value; + } + + private int id; + + // attribute name + + public String getName() { + return name; + } + + public void setName(String value) { + name = value; + } + + private String name; +} diff -r 000000000000 -r 76005e62091d samples/customer.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/customer.xml Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,10 @@ + + + 23 + Kurt Meier + + + 42 + Lieschen Schmidt + + diff -r 000000000000 -r 76005e62091d samples/customer.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/customer.xsl Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,1 @@ +Customer List
diff -r 000000000000 -r 76005e62091d samples/customer.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/customer.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,15 @@ +include yslt.yml2 + +stylesheet { + template "/" html { + head title "Customer List"; + body apply "list"; + } + + template "list" table apply "customer[starts-with(name, 'Kurt')]"; + + template "customer" tr { + td value "id"; + td value "name"; + } +} diff -r 000000000000 -r 76005e62091d samples/ddl.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/ddl.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,15 @@ +include yslt.yml2 + +tstylesheet { + template "/list" { + | CREATE TABLE «name(*)» ( + + apply "*[1]/*"; + + | ); + } + + template "*" { + | «name()» VARCHAR`if "position()!=last()" ", "` + } +} diff -r 000000000000 -r 76005e62091d samples/debug_test.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/debug_test.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,9 @@ +include yslt.yml2 + +tstylesheet { + template "/" { + debug "'debug output'"; + assert 0, "'test assertion'"; + > yes\n + } +} diff -r 000000000000 -r 76005e62091d samples/delta.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/delta.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,2 @@ +decl delta alias Δ; +delta Δ="∂" Δ { "Δ" } diff -r 000000000000 -r 76005e62091d samples/demo.xmi --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/demo.xmi Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff -r 000000000000 -r 76005e62091d samples/dingens.idl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/dingens.idl Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,20 @@ +module Bla { + struct Blub { + long a; + string b; + }; + + interface Blubber { + Blub getBlub(); + }; + + typedef My::Complicated::Reachable::Thing Thing; + + interface Irgendwas { + struct Bla { + + }; + + readonly attribute Thing b; + }; +}; diff -r 000000000000 -r 76005e62091d samples/dingens.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/dingens.sql Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,6 @@ +CREATE TABLE address ( + name VARCHAR, + street VARCHAR + city VARCHAR +); + diff -r 000000000000 -r 76005e62091d samples/dingens.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/dingens.xml Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,1 @@ + diff -r 000000000000 -r 76005e62091d samples/dingens.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/dingens.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,3 @@ +decl module +name; +decl interface +name; + diff -r 000000000000 -r 76005e62091d samples/dml.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/dml.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,9 @@ +include yslt.yml2 + +tstylesheet { + template "/list/*" + | INSERT INTO «name()» (`apply "*", 0, mode="names"`) VALUES (`apply "*", mode="values"`); + + template "*", mode="names" > «name()»`if "position()!=last()" ", "` + template "*", mode="values" > '«.»'`if "position()!=last()" ", "` +} diff -r 000000000000 -r 76005e62091d samples/double.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/double.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,3 @@ +when { + a; +} diff -r 000000000000 -r 76005e62091d samples/double.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/double.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,3 @@ +include yslt.yml2 + +tstylesheet template "/when/*" | «name()» diff -r 000000000000 -r 76005e62091d samples/empty.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/empty.xml Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,1 @@ + diff -r 000000000000 -r 76005e62091d samples/empty.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/empty.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,22 @@ +include yslt.yml2 + +tstylesheet { + template "/xsl:stylesheet" { + > include yslt.yml2\n\ntstylesheet {\n + apply "xsl:template"; + > }\n + } + template "xsl:template" choose { + when "@match" { + | template "«@match»" { + | + | } + } + when "@name" { + | template "«@name»" { + | + | } + } + if "position()!=last()" | + } +} diff -r 000000000000 -r 76005e62091d samples/errortest.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/errortest.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,5 @@ +include yslt.yml2 + +tstylesheet xmlns:yml2="http://fdik.org/yml" { + template "/$$", yml2:line=23 | hello +} diff -r 000000000000 -r 76005e62091d samples/f.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/f.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,3 @@ +include i.yml2 + +x diff -r 000000000000 -r 76005e62091d samples/f.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/f.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,19 @@ +include yslt.yml2 + +tstylesheet { + function stType { + param "type"; + + choose { + when "$type='long'" > DINT + when "$type='short'" > INT + } + } + + function cType { + param "type"; + + when "$type='long'" > int32_t + when "$type='short'" > int16_t + } +} diff -r 000000000000 -r 76005e62091d samples/function.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/function.xml Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,1 @@ +42 \ No newline at end of file diff -r 000000000000 -r 76005e62091d samples/function.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/function.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,1 @@ +include yslt.yml2; tstylesheet template "/f" | «return» diff -r 000000000000 -r 76005e62091d samples/gen_addr_html.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/gen_addr_html.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,13 @@ +include yslt.yml2 + +stylesheet { + template "/list" html { + head title "address list"; + body table style="border-style=solid;" apply "address"; + } + template "address" tr { + td value "name"; + td value "street"; + td value "city"; + } +} diff -r 000000000000 -r 76005e62091d samples/gen_again_java.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/gen_again_java.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,33 @@ +include yslt.yml2 + +tstylesheet { + template "/xmi:XMI/uml:Model" { + apply "Package", 0; + } + + template 'packagedElement[xmi:type="uml:Package"]' { + | package «@name»; + | + apply "packagedElement", 0; + } + + template 'packagedElement[xmi:type="uml:Class"]' { + | class «@name» { + apply 'ownedAttribute[xmi:type="uml:Property"]'; + | } + } + + template "Attribute" { + | // attribute «@name» + | + | public «type» get«@name»() { + | return «@name»; + | } + | + | public void set«@name»(«type» value) { + | «@name» = value; + | } + | + | private «type» «@name»; + } +} diff -r 000000000000 -r 76005e62091d samples/gen_java.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/gen_java.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,60 @@ +include yslt.yml2 + +define operator "†(\S+)" as call "printType" with "name", "%1"; +define operator "“(.*?)”" as call "ucase" with "text", "%1"; + +decl umlstylesheet is tstylesheet ( + xmlns:uml="http://schema.omg.org/spec/UML/2.1", + xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" +); + +umlstylesheet { + template "/xmi:XMI/uml:Model" + apply "packagedElement", 0; + + template "packagedElement[@xmi:type='uml:Package']" { + | package «@name»; + | + apply "packagedElement", 0; + } + + template "packagedElement[@xmi:type='uml:Class']" { + | class «@name» { + apply "ownedAttribute"; + | } + if "position() != last()" | + } + + template "ownedAttribute[@xmi:type='uml:Property' and count(@association)=0]" { + | // attribute «@name» + | + | public †type get“@name”() { + | return «@name»; + | } + | + | public void set“@name”(†type value) { + | «@name» = value; + | } + | + | private †type «@name»; + if "position() != last()" | + } + + function "ucase" { + param "text"; + + > «translate(substring($text, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')» + > «substring($text, 2)» + } + + function "printType" { + param "name"; + + choose { + when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#UnlimitedNatural"' + > int + when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#String"' + > String + } + } +} diff -r 000000000000 -r 76005e62091d samples/hello.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/hello.xsl Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,2 @@ +hello, world + diff -r 000000000000 -r 76005e62091d samples/hello.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/hello.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,11 @@ +decl hello(dingens) alias blub:DingensBlubber { + something { + special { + content; + } + } +}; + +hello 42 { + world; +} diff -r 000000000000 -r 76005e62091d samples/hello.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/hello.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,3 @@ +include yslt.yml2 + +tstylesheet template "/" | hello, world diff -r 000000000000 -r 76005e62091d samples/i.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/i.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,1 @@ +decl x { y }; diff -r 000000000000 -r 76005e62091d samples/idl.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/idl.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,3 @@ +decl module +name; +decl interface +name; +decl _ +type +name alias func; diff -r 000000000000 -r 76005e62091d samples/indention.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/indention.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,8 @@ +include yslt.yml2 + +tstylesheet template "/" { + 0> something\n + 1> indent by 1\n + indent 1; + > also indent by 1\n +} diff -r 000000000000 -r 76005e62091d samples/list.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/list.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,8 @@ +decl list(name); +decl title alias columnTitle; + +list "List of goods" { + head title "Goods", title "Price"; + row value "Beer", value 20; + row value "Wine", value 30; +} diff -r 000000000000 -r 76005e62091d samples/macros_test.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/macros_test.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,4 @@ +decl blub(%macro, myAttr="something %macro for testing"); + +testing + blub "nice"; diff -r 000000000000 -r 76005e62091d samples/model.ymi --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/model.ymi Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,15 @@ +decl package +name; +decl class +name; +decl attr +type +name; + +package Bla { + class Customer { + attr long id; + attr string name; + } + class Order { + attr long id; + attr string desc; + } +} + diff -r 000000000000 -r 76005e62091d samples/namespace.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/namespace.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,5 @@ +include yslt.yml2 + +tstylesheet template "/" | «namespace-uri(*)» + + diff -r 000000000000 -r 76005e62091d samples/opertest.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/opertest.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,5 @@ +include yslt.yml2 + +define operator "π(\w+)" as value "%1", value "%1-19"; + +tstylesheet template "/" | hello, world π42 diff -r 000000000000 -r 76005e62091d samples/rechner.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/rechner.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,14 @@ +include yslt.yml2 + +decl ip(%value, name="ip", select="'%value'") alias xsl:variable; +decl rechner(%name, *ip, test="@name = '%name'") alias xsl:when { + ip *ip; + | ip ist «$ip» +}; + +tstylesheet template "/rechner" { + choose { + rechner "R1", "192.168.1.10"; + rechner "R2", "192.168.1.11"; + } +} diff -r 000000000000 -r 76005e62091d samples/sample.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/sample.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,7 @@ +include idl.yml2 + +module blub { + interface bla { + int f(in long a, out long b); + } +} diff -r 000000000000 -r 76005e62091d samples/simple.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/simple.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,11 @@ +include yslt.yml2 + +tstylesheet { + template "/list" html body table apply "address"; + + template "address" tr { + td value "name"; + td value "street"; + td value "city"; + } +} diff -r 000000000000 -r 76005e62091d samples/table.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/table.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,8 @@ +decl module +name; +decl class +name; +decl attr +type +name; + +class Table class Data { + attr long id; + attr string text; +} diff -r 000000000000 -r 76005e62091d samples/table2ddl.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/table2ddl.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,50 @@ +include yslt.yml2 + +define operator "“(.*?)”" as call "idl2ddl" with "type", "%1"; + +tstylesheet { + const "idtype", "'INTEGER'"; + + template "/" apply "module|class", 0; + + template "module" { + param "namespace", "''"; + choose { + when "$namespace=''" + apply "module|class", 0 with "namespace", "@name"; + otherwise + apply "module|class", 0 with "namespace", "concat($namespace,'_', @name)"; + } + } + + template "class" { + param "namespace", "''"; + + choose { + when "$namespace=''" | CREATE TABLE «@name» ( + otherwise | CREATE TABLE «$namespace»_«@name» ( + } + + if "count(attr[@name='id'])=0" |> id «$idtype»`if "count(attr)>0" > , ` + + const "name", "@name"; + foreach "//class[class/@name=$name]" |> «@name»_fk «$idtype», + + apply "attr"; + + | ); + + apply "class", 0 with "namespace", "$namespace"; + } + + template "attr" | «@name» “@type”`if "position() != last()" > , ` + + function "idl2ddl" { + param "type"; + + choose { + when "$type='string'" > VARCHAR + when "$type='long'" > INTEGER + } + } +} diff -r 000000000000 -r 76005e62091d samples/text_test.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/text_test.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,6 @@ +testing { + || + `` dingens; + `dingens;` + || +} diff -r 000000000000 -r 76005e62091d samples/textest.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/textest.xml Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,5 @@ + + Dingens + + Bumens + diff -r 000000000000 -r 76005e62091d samples/types.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/types.xml Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,1 @@ +stringint diff -r 000000000000 -r 76005e62091d samples/types.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/types.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,4 @@ +types { + type "string"; + type "int"; +} diff -r 000000000000 -r 76005e62091d samples/uml.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/uml.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,46 @@ +include yslt.yml2 + +decl UML is textstylesheet( + xmlns:uml="http://schema.omg.org/spec/UML/2.1", + xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" +) { + output *output; + const "space", !"'" + " " * 200 + "'"!; + param "autoindent", 4; + template "text()"; + content; +}; + +decl Root is template(match="/xmi:XMI/uml:Model/packagedElement"), + All is template(%match="*", match="//[%match]"); + +decl Package is template( + %match="true()", + match="packagedElement[@xmi:type='uml:Package' and (%match)]" +); + +decl applyPackages is apply ( + %match="true()", + select="packagedElement[@xmi:type='uml:Package' and (%match)]" +); + +decl Class is template( + %match="true()", + match="packagedElement[@xmi:type='uml:Class' and (%match)]" +); + +decl applyClasses is apply ( + %match="true()", + select="packagedElement[@xmi:type='uml:Class' and (%match)]" +); + +decl Attribute is template( + %match="true()", + match="ownedAttribute[@xmi:type='uml:Property' and type/@xmi:type='uml:PrimitiveType' and (%match)]" +); + +decl applyAttributes is apply ( + %match="true()", + select="ownedAttribute[@xmi:type='uml:Property' and type/@xmi:type='uml:PrimitiveType' and (%match)]" +); + diff -r 000000000000 -r 76005e62091d samples/uml2idl.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/uml2idl.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,22 @@ +include yslt.yml2 + +define operator "†(\w+)" as call "printType" with "name", "%1"; +define operator "“(.*?)”" as call "ucase" with "text", "%1"; + +function "ucase" { + param "text"; + + > «translate(substring($text, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')» + > «substring($text, 2)» +} + +function "printType" { + param "name"; + + choose { + when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#UnlimitedNatural"' + > long + when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#String"' + > string + } +} diff -r 000000000000 -r 76005e62091d samples/uml2sql.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/uml2sql.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,20 @@ +define operator "†(\w+)" as call "printType" with "name", "%1"; +define operator "“(.*?)”" as call "ucase" with "text", "%1"; + +function "ucase" { + param "text"; + + > «translate(substring($text, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')» + > «substring($text, 2)» +} + +function "printType" { + param "name"; + + choose { + when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#UnlimitedNatural"' + > INTEGER + when '$name/@href = "http://schema.omg.org/spec/UML/2.1/uml.xml#String"' + > VARCHAR + } +} diff -r 000000000000 -r 76005e62091d samples/union.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/union.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,19 @@ +include yslt.yml2 + +estylesheet { + template "/list" cities + apply "address[name='Meier']" with "me", "."; + + template "address" { + param "me"; + + call "f" with "addresses", "$me/address[name='Schmid'] | ."; + } + + function "f" { + param "addresses"; + + foreach "$addresses" + city value "city"; + } +} diff -r 000000000000 -r 76005e62091d samples/vorlesung.xmi --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/vorlesung.xmi Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 000000000000 -r 76005e62091d samples/webseite.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/webseite.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,11 @@ +include yslt.yml2 + +stylesheet { + template "/list" html body table border=1 apply "address"; + + template "address" tr { + td value "name"; + td value "street"; + td value "city"; + } +} diff -r 000000000000 -r 76005e62091d samples/xmi2ddl.uml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/xmi2ddl.uml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,23 @@ +include uml.yml2 + +UML { + include uml2sql.yml2 + + Root applyPackages; + + Package { + param "name", "''"; + if "$name=''" apply "packagedElement", 0 { with "name", "@name"; } + if "$name!=''" apply "packagedElement", 0 { with "name", "concat($name, '_', @name)"; } + } + + Class { + param "name"; + + | CREATE TABLE «$name»_«@name» ( + applyAttributes; + | ); + } + + Attribute | «@name» †type`if "position()!=last()" > ,` +} diff -r 000000000000 -r 76005e62091d samples/xmi2ddl.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/xmi2ddl.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,34 @@ +include yslt.yml2 + +tstylesheet xmlns:uml="http://schema.omg.org/spec/UML/2.1", + xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" { + + template "/" apply "xmi:XMI/uml:Model/packagedElement", 0; + + template "packagedElement[@xmi:type='uml:Package']" { + param "name", "''"; + if "$name=''" apply "packagedElement", 0 { with "name", "@name"; } + if "$name!=''" apply "packagedElement", 0 { with "name", "concat($name, '_', @name)"; } + } + + template "packagedElement[@xmi:type='uml:Class']" { + param "name"; + + | CREATE TABLE «$name»_«@name» ( + apply "ownedAttribute"; + | ); + } + + template "ownedAttribute[@xmi:type='uml:Property' and type/@xmi:type='uml:PrimitiveType']" { + 0> «@name» + choose { + when "type/@href='http://schema.omg.org/spec/UML/2.1/uml.xml#String'" + > VARCHAR + + // [...] for other types, extend when clauses + } + if "position()!=last()" > , + text "\n"; + } +} + diff -r 000000000000 -r 76005e62091d samples/xmi2idl.uml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/xmi2idl.uml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,21 @@ +include uml.yml2 + +UML { + include uml2idl.yml2 + + Root apply "packagedElement", 0; + + Package { + | module «@name» { + applyClass; + | }; + } + + Class("@stereotype='Struct'") { + | interface «@name» { + applyAttributes; + | }; + } + + Attribute | attribute †type «@name»; +} diff -r 000000000000 -r 76005e62091d samples/xml2.yml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/xml2.yml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,2 @@ +include yslt.yml2; tstylesheet template "*" { param "pre", "''"; if "text()!=''" | «$pre»/«name()»=«text()» +apply "*", 0 with "pre", "concat($pre, '/', name())"; } diff -r 000000000000 -r 76005e62091d samples/ydl2idl.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/ydl2idl.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,23 @@ +include yslt.yml2 + +tstylesheet { + template "module" { + | module «name(*)» { + apply "*/interface"; + | }; + } + + template "interface" { + | interface «name(*)» { + apply "*/*", mode="func"; + | }; + } + + template "*", mode="func" + | «name(.)» «name(*)»(`apply "*/*", mode="parms";`); + + template "*", mode="parms" { + > «name(.)» «name(*)» «name(*/*)» + if "position() != last()" > , + } +} diff -r 000000000000 -r 76005e62091d standardlib.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/standardlib.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,55 @@ +function "yml:hex2dec" { + param "hex"; + param "_result", 0; + + const "hd", "substring($hex, 1, 1)"; + const "a", """translate($hd, 'ABCDEFabcdef123456789', + '123456123456000000000')"""; + + const "d" choose { + when "$a>0" value "$a + 9"; + otherwise value "$hd"; + } + + choose { + when "string-length($hex) = 1" + value "$_result * 16 + $d"; + otherwise call "yml:hex2dec" + with "hex", "substring($hex, 2, 8)", + with "_result", "$_result * 16 + $d"; + } +} + +function "yml:dec2hex" { + param "dec"; + param "bits", !16**7!; + + const "v", "floor($dec div $bits)"; + value "substring('0123456789abcdef', $v + 1, 1)"; + + if "$bits > 1" call "yml:dec2hex" + with "dec", "$dec - $bits * $v", + with "bits", "$bits div 16"; +} + +def "yml:dec2hex" { + param "dec"; + param "digits", 8; + + result call "yml:dec2hex" with "dec", "$dec", with "bits", "math:power(16, $digits - 1)"; +} + +def "yml:hex2dec" { + param "hex"; + result call "yml:hex2dec" with "hex", "$hex"; +} + +def "yml:lcase" { + param "text", "''"; + result "translate($text, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"; +} + +def "yml:ucase" { + param "text", "''"; + result "translate($text, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"; +} diff -r 000000000000 -r 76005e62091d toolchain.en.yhtml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolchain.en.yhtml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,380 @@ +include homepage.en.yhtml2 + +page "The YML Toolchain" { + h1 > The Toolchain + + p >> + There are to possibilities to handle YML files: the YML compiler and the YML/YSLT + processor. + >> + + h2 id=compiler > The YML compiler + + p >> + The YML ¬http://en.wikipedia.org/wiki/Compiler compiler¬ is a small + ¬http://www.python.org Python script¬. It provides the + ¬http://en.wikipedia.org/wiki/Command-line_interface command line¬ front end «yml2c». + As default, it compiles your ¬http://en.wikipedia.org/wiki/Scripting_language script¬ + and outputs to ¬http://en.wikipedia.org/wiki/Stdout#Standard_output_.28stdout.29 stdout¬, + that usually is the ¬http://en.wikipedia.org/wiki/Computer_terminal terminal¬. + Your ¬http://en.wikipedia.org/wiki/Shell_(computing) shell¬ provides options to redirect + the output into a ¬http://en.wikipedia.org/wiki/Pipeline_(Unix) pipe¬ or + a ¬http://en.wikipedia.org/wiki/Computer_file file¬. + >> + + p > So to use it, just enter «yml2c» followed by the filename of your YML script: + + Code | % yml2c myscript.yml2 > myscript.result + + p > The «yml2c» command has the following options: + + h3 > -h, --help + + p > Show a help message and exit. + + h3 > -C, --old-syntax + + p > Use the syntax of YML 2 version 1.x (compatibility mode). + + h3 > -D, --emit-linenumbers + + p > Emit line numbers into the resulting XML for debugging purposes. + + h3 > -E ENCODING, --encoding ENCODING + + p > encoding of input files (default: UTF-8) + + h3 > -I INCLUDE_PATH, --include=INCLUDE_PATH + + p { "Precede " code > ¬features#ymlpath YML_PATH¬ + " by a colon separated " code "INCLUDE_PATH"; " to search for include files." } + + h3 > -m, --omit-empty-parm-tags + + p >> + Does nothing (only there for compatibility with older versions of «yml2c»). + >> + + h3 > -n NORMALIZATION, --normalization=NORMALIZATION + + p >> + Unicode normalization (none, NFD, NFKD, NFC, NFKC, FCD, default is NFC) + >> + + h3 > -o FILE, --output=FILE + + p > Don't output to stdout, instead place output in file «FILE». + + h3 > -p, --parse-only + + p >> + ¬http://fdik.org/pyPEG Parse¬ only, then output ¬http://fdik.org/pyPEG/#pyAST pyAST¬ + as text to stdout. The pyAST is the + ¬http://en.wikipedia.org/wiki/Abstract_syntax_tree Abstract Syntax Tree¬ + of the parsed script as ¬http://docs.python.org/library/stdtypes.html Python data structure¬. + >> + + h3 > -V, --version + + p >> + Show version and ¬http://en.wikipedia.org/wiki/Copyleft Copyleft¬ information of + the YML implementation. + >> + + h3 > YML_PATH environment variable + + p >> + If «YML_PATH» is set to a colon separated ¬http://en.wikipedia.org/wiki/Path_(computing) path¬ + list, then the `a href="features#including" code "include";` statement searches these paths. + If «YML_PATH» is not set, the local directory «.» is searched for files. + >> + + h2 id=processor > The YML/YSLT processor + + p >> + If you're processing more complex tasks, say, executing an YSLT script over some + YML files, the YML/YSLT processor will possible fit better to your needs. + >> + + p >> + To use it, enter «yml2proc -y» followed by the filename of your YSLT script, + followed by the filenames of your YML input files: + >> + + Code | % yml2proc -y myscript.ysl2 inputfile.yml2 > myscript.result + + p > The YML/YSLT processor requires the ¬http://codespeak.net/lxml/ lxml Python library¬. + + p > The YML/YSLT processor has the following options: + + h3 > -h, --help + + p > Show a help message and exit. + + h3 > -C, --old-syntax + + p > Use the syntax of YML 2 version 1.x (compatibility mode). + + h3 > -D, --emit-linenumbers + + p > Emit line numbers into the resulting XML for debugging purposes. + + h3 id=debug > --debug + + p >> + switch on debug tracing to stderr; this enables the functionality + of the ¬yslt#debug debug(msg)¬ and ¬yslt#assert assert yml:assert(test, msg)¬ YSLT functions. + >> + + h3 > -E ENCODING, --encoding ENCODING + + p > encoding of input files (default: UTF-8) + + h3 > -I INCLUDE_PATH, --include=INCLUDE_PATH + + p { "Precede " code > ¬features#ymlpath YML_PATH¬ + " by a colon separated " code "INCLUDE_PATH"; " to search for include files." } + + h3 > -m, --omit-empty-parm-tags + + p >> + Does nothing (only there for compatibility with older versions of «yml2proc»). + >> + + h3 > -M, --empty-input-document + + p >> + Use an empty input document for YSLT or XSLT processing + >> + + h3 > -n NORMALIZATION, --normalization=NORMALIZATION + + p >> + Unicode normalization (none, NFD, NFKD, NFC, NFKC, FCD, default is NFC) + >> + + h3 > -o FILE, --output=FILE + + p > Don't output to stdout, instead place output in file «FILE». + + h3 > -p, --parse-only + + p >> + ¬http://fdik.org/pyPEG Parse¬ only, then output ¬http://fdik.org/pyPEG/#pyAST pyAST¬ + as text to stdout. The pyAST is the + ¬http://en.wikipedia.org/wiki/Abstract_syntax_tree Abstract Syntax Tree¬ + of the parsed script as ¬http://docs.python.org/library/stdtypes.html Python data structure¬. + >> + + h3 > -e XPATH, --xpath=XPATH + + p > Execute XPath expression XPATH and print result + + p >> + If you omit -y YSLTSCRIPT, then the result is printed. If you have an additional + -y YSLTSCRIPT parameter, then your YSLT script is processing the result of the + XPath expression only instead of processing the complete content of your input documents + >> + + h3 > -P, --pretty + + p > Pretty print output adding whitespace + + h3 > -x, --xml + + p > Input documents are XML already, don't try to convert them from YML + + h3 > -y YSLTSCRIPT, --yslt=YSLTSCRIPT + + p > Execute YSLT script YSLTSCRIPT + + h3 > -X XSLTSCRIPT, --xslt=XSLTSCRIPT + + p > Execute XSLT script XSLTSCRIPT + + h3 > -d PARAMS, --paramdict=PARAMS + + p >> + Call XSLT or YSLT script with dictionary PARAMS as XPath parameters. PARAMS is a Python + expression which evaluates to a Python dictionary. + >> + + p > Sample: + + p code > yml2proc -y myscript -d 'dict(a=3, b="element[@name=2]")' + + h3 > -s STRINGPARAMS, --stringparamdict=STRINGPARAMS + + p >> + Call XSLT or YSLT script with dictionary STRINGPARAMS as string parameters. STRINGPARAMS + is a Python expression which evaluates to a Python dictionary. + >> + + p > Sample: + + p code > yml2proc -y myscript -s 'dict(forename="Hans", name="Meier")' + + h3 > -Y, --xml2yml + + p > Convert XML to normalized YML. Equivalent to -xy xml2yml.ysl2 + + p > The file xml2yml.ysl2 has to be in YML_PATH. + + h3 > -V, --version + + p >> + Show version and ¬http://en.wikipedia.org/wiki/Copyleft Copyleft¬ information of + the YML implementation and exit. + >> + + h3 > YML_PATH environment variable + + p >> + If «YML_PATH» is set to a colon separated ¬http://en.wikipedia.org/wiki/Path_(computing) path¬ + list, then the `a href="features#including" code "include";` statement searches these paths. + If «YML_PATH» is not set, the local directory «.» is searched for files. + >> + + h2 id=recommended > Recommended external tools + + h3 > XSLT Processor + + p >> + If you want to use ¬yslt YSLT¬ with «yml2c» instead of «yml2proc», you additionally need an + ¬http://www.w3.org/TR/xslt XSLT¬ processor. + >> + + p > For that case, I recommend the ¬http://xmlsoft.org/XSLT/xsltproc2.html xsltproc tool¬. + + p > To process YSLT, just use a pipe with the «xsltproc» command: + + Code | % yml2c customer.ysl2 | xsltproc - customer.xml > customer.html + + h3 > XML Renicing Tool + + p >> + Sometimes, you may want to have more human readable output with «yml2c». So an + ¬http://www.w3.org/XML/ XML¬ renicing tool can be helpful. + >> + + p > The ¬http://xmlstar.sourceforge.net/ XMLStarlet¬ command line tool may be of interest. + + p > Have a look on its «fo» command. + + h3 > Windows tool chain + + p >> + See also the tips for a + ¬http://www.auchdieserschwachsinnmussinsinternet.de/2009-03/#s1236859037 Windows tool chain¬ + for YML. + >> + + h1 id=downloads > Downloads + + p > You can here ¬http://fdik.org/yml2.tar.bz2 download the newest release of YML¬. + + h2 > Older versions + + p >> + ¬http://fdik.org/yml-2.5.2.tar.bz2 YML 2.5.2¬ + >> + + p >> + ¬http://fdik.org/yml-2.5.1.tar.bz2 YML 2.5.1¬ + >> + + p >> + ¬http://fdik.org/yml-2.5.0.tar.bz2 YML 2.5.0¬ + >> + + p >> + ¬http://fdik.org/yml-2.4.3.tar.bz2 YML 2.4.3¬ + >> + + p >> + ¬http://fdik.org/yml-2.3.12.tar.bz2 YML 2.3.12¬ + >> + + p >> + ¬http://fdik.org/yml-2.3.11.tar.bz2 YML 2.3.11¬ + >> + + p >> + ¬http://fdik.org/yml-2.3.10.tar.bz2 YML 2.3.10¬ + >> + + p >> + ¬http://fdik.org/yml-2.3.8.tar.bz2 YML 2.3.8¬ + >> + + p >> + ¬http://fdik.org/yml-2.3.7.tar.bz2 YML 2.3.7¬ + >> + + p >> + ¬http://fdik.org/yml-2.3.5.tar.bz2 YML 2.3.5¬ + >> + + p >> + ¬http://fdik.org/yml-2.2.4.tar.bz2 YML 2.2.4¬ + >> + + p >> + ¬http://fdik.org/yml-2.2.3.tar.bz2 YML 2.2.3¬ + >> + + p >> + ¬http://fdik.org/yml-2.2.1.tar.bz2 YML 2.2.1¬ + >> + + p >> + ¬http://fdik.org/yml-2.2.0.tar.bz2 YML 2.2.0¬ + >> + + p >> + ¬http://fdik.org/yml-2.1.17.tar.bz2 YML 2.1.17¬ + >> + + p >> + ¬http://fdik.org/yml-2.1.14.tar.bz2 YML 2.1.14¬ + >> + + p >> + ¬http://fdik.org/yml-2.1.13.tar.bz2 YML 2.1.13¬ + >> + + p >> + ¬http://fdik.org/yml-2.1.12.tar.bz2 YML 2.1.12¬ + >> + + p >> + ¬http://fdik.org/yml-2.1.7.tar.bz2 YML 2.1.7¬ + >> + + p >> + ¬http://fdik.org/yml-2.1.6.tar.bz2 YML 2.1.6¬ + >> + + p >> + ¬http://fdik.org/yml-2.1.5.tar.bz2 YML 2.1.5¬ + >> + + p >> + ¬http://fdik.org/yml-2.1.2.tar.bz2 YML 2.1.2¬ + >> + + p >> + ¬http://fdik.org/yml-2.0.36.tar.bz2 YML 2.0.36¬ + >> + p >> + ¬http://fdik.org/yml-2.0.35.tar.bz2 YML 2.0.35¬ + >> + + p > ¬http://fdik.org/yml1 To the Homepage of version 1 of YML...¬ + + div id=bottom { + a href="yslt" "<< back to YSLT" " " + a href="#top" "^Top^" " " + a href="toolchain.en.yhtml2" "(source)" + } +} diff -r 000000000000 -r 76005e62091d vim/syntax/yml2.vim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vim/syntax/yml2.vim Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,375 @@ +" Vim syntax file +" Language: YML2 generating C +" Maintainer: Volker Birk +" Last Change: 2016 July 10 + +" Quit when a (custom) syntax file was already loaded +if exists("b:current_syntax") + finish +endif + +" A bunch of useful YSLT keywords +syn keyword cStatement include decl operator document def param const output value indent all text with withIndent element attrib processing number sort import message debug assert operator goto break return continue asm +syn keyword cLabel stylesheet estylesheet textstylesheet tstylesheet template function case default +syn keyword cConditional choose when otherwise if else switch +syn keyword cRepeat for foreach apply while do + +syn keyword cTodo contained TODO FIXME XXX + +" It's easy to accidentally add a space after a backslash that was intended +" for line continuation. Some compilers allow it, which makes it +" unpredicatable and should be avoided. +syn match cBadContinuation contained "\\\s\+$" + +" cCommentGroup allows adding matches for special things in comments +syn cluster cCommentGroup contains=cTodo,cBadContinuation,ymlString + +" String and Character constants +" Highlight special characters (those which have a backslash) differently +syn match cSpecial display contained "\\\(x\x\+\|\o\{1,3}\|.\|$\)" +if !exists("c_no_utf") + syn match cSpecial display contained "\\\(u\x\{4}\|U\x\{8}\)" +endif +syn region ymlString start=+L\=«+ skip=+\\\\\|\\"+ end=+»+ contains=cSpecial,@Spell +if exists("c_no_cformat") + syn region cString start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,@Spell,ymlString + " cCppString: same as cString, but ends at end of line + syn region cCppString start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial,@Spell,ymlString +else + if !exists("c_no_c99") " ISO C99 + syn match cFormat display "%\(\d\+\$\)\=[-+' #0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlLjzt]\|ll\|hh\)\=\([aAbdiuoxXDOUfFeEgGcCsSpn]\|\[\^\=.[^]]*\]\)" contained + else + syn match cFormat display "%\(\d\+\$\)\=[-+' #0*]*\(\d*\|\*\|\*\d\+\$\)\(\.\(\d*\|\*\|\*\d\+\$\)\)\=\([hlL]\|ll\)\=\([bdiuoxXDOUfeEgGcCsSpn]\|\[\^\=.[^]]*\]\)" contained + endif + syn match cFormat display "%%" contained + syn region cString start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,cFormat,@Spell,ymlString + " cCppString: same as cString, but ends at end of line + syn region cCppString start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial,cFormat,@Spell,ymlString +endif + +syn match cCharacter "L\='[^\\]'" +syn match cCharacter "L'[^']*'" contains=cSpecial +if exists("c_gnu") + syn match cSpecialError "L\='\\[^'\"?\\abefnrtv]'" + syn match cSpecialCharacter "L\='\\['\"?\\abefnrtv]'" +else + syn match cSpecialError "L\='\\[^'\"?\\abfnrtv]'" + syn match cSpecialCharacter "L\='\\['\"?\\abfnrtv]'" +endif +syn match cSpecialCharacter display "L\='\\\o\{1,3}'" +syn match cSpecialCharacter display "'\\x\x\{1,2}'" +syn match cSpecialCharacter display "L'\\x\x\+'" + +"when wanted, highlight trailing white space +if exists("c_space_errors") + if !exists("c_no_trail_space_error") + syn match cSpaceError display excludenl "\s\+$" + endif + if !exists("c_no_tab_space_error") + syn match cSpaceError display " \+\t"me=e-1 + endif +endif + +" This should be before cErrInParen to avoid problems with #define ({ xxx }) +if exists("c_curly_error") + syntax match cCurlyError "}" + syntax region cBlock start="{" end="}" contains=ALLBUT,cCurlyError,@cParenGroup,cErrInParen,cCppParen,cErrInBracket,cCppBracket,cCppString,@Spell fold +else + syntax region cBlock start="{" end="}" transparent fold +endif + +"catch errors caused by wrong parenthesis and brackets +" also accept <% for {, %> for }, <: for [ and :> for ] (C99) +" But avoid matching <::. +syn cluster cParenGroup contains=cParenError,cIncluded,cSpecial,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cUserCont,cUserLabel,cBitField,cOctalZero,cCppOut,cCppOut2,cCppSkip,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom +if exists("c_no_curly_error") + syn region cParen transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cCppString,@Spell + " cCppParen: same as cParen but ends at end-of-line; used in cDefine + syn region cCppParen transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cParen,cString,@Spell + syn match cParenError display ")" + syn match cErrInParen display contained "^[{}]\|^<%\|^%>" +elseif exists("c_no_bracket_error") + syn region cParen transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cCppString,@Spell + " cCppParen: same as cParen but ends at end-of-line; used in cDefine + syn region cCppParen transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cParen,cString,@Spell + syn match cParenError display ")" + syn match cErrInParen display contained "[{}]\|<%\|%>" +else + syn region cParen transparent start='(' end=')' contains=ALLBUT,@cParenGroup,cCppParen,cErrInBracket,cCppBracket,cCppString,@Spell + " cCppParen: same as cParen but ends at end-of-line; used in cDefine + syn region cCppParen transparent start='(' skip='\\$' excludenl end=')' end='$' contained contains=ALLBUT,@cParenGroup,cErrInBracket,cParen,cBracket,cString,@Spell + syn match cParenError display "[\])]" + syn match cErrInParen display contained "[\]{}]\|<%\|%>" + syn region cBracket transparent start='\[\|<::\@!' end=']\|:>' contains=ALLBUT,@cParenGroup,cErrInParen,cCppParen,cCppBracket,cCppString,@Spell + " cCppBracket: same as cParen but ends at end-of-line; used in cDefine + syn region cCppBracket transparent start='\[\|<::\@!' skip='\\$' excludenl end=']\|:>' end='$' contained contains=ALLBUT,@cParenGroup,cErrInParen,cParen,cBracket,cString,@Spell + syn match cErrInBracket display contained "[);{}]\|<%\|%>" +endif + +"integer number, or floating point number without a dot and with "f". +syn case ignore +syn match cNumbers display transparent "\<\d\|\.\d" contains=cNumber,cFloat,cOctalError,cOctal +" Same, but without octal error (for comments) +syn match cNumbersCom display contained transparent "\<\d\|\.\d" contains=cNumber,cFloat,cOctal +syn match cNumber display contained "\d\+\(u\=l\{0,2}\|ll\=u\)\>" +"hex number +syn match cNumber display contained "0x\x\+\(u\=l\{0,2}\|ll\=u\)\>" +" Flag the first zero of an octal number as something special +syn match cOctal display contained "0\o\+\(u\=l\{0,2}\|ll\=u\)\>" contains=cOctalZero +syn match cOctalZero display contained "\<0" +syn match cFloat display contained "\d\+f" +"floating point number, with dot, optional exponent +syn match cFloat display contained "\d\+\.\d*\(e[-+]\=\d\+\)\=[fl]\=" +"floating point number, starting with a dot, optional exponent +syn match cFloat display contained "\.\d\+\(e[-+]\=\d\+\)\=[fl]\=\>" +"floating point number, without dot, with exponent +syn match cFloat display contained "\d\+e[-+]\=\d\+[fl]\=\>" +if !exists("c_no_c99") + "hexadecimal floating point number, optional leading digits, with dot, with exponent + syn match cFloat display contained "0x\x*\.\x\+p[-+]\=\d\+[fl]\=\>" + "hexadecimal floating point number, with leading digits, optional dot, with exponent + syn match cFloat display contained "0x\x\+\.\=p[-+]\=\d\+[fl]\=\>" +endif + +" flag an octal number with wrong digits +syn match cOctalError display contained "0\o*[89]\d*" +syn case match + +if exists("c_comment_strings") + " A comment can contain cString, cCharacter and cNumber. + " But a "*/" inside a cString in a cComment DOES end the comment! So we + " need to use a special type of cString: cCommentString, which also ends on + " "*/", and sees a "*" at the start of the line as comment again. + " Unfortunately this doesn't very well work for // type of comments :-( + syntax match cCommentSkip contained "^\s*\*\($\|\s\+\)" + syntax region cCommentString contained start=+L\=\\\@" skip="\\$" end="$" keepend contains=cComment,cCommentL,cCppString,cCharacter,cCppParen,cParenError,cNumbers,cCommentError,cSpaceError +syn match cPreCondit display "^\s*\(%:\|#\)\s*\(else\|endif\)\>" +if !exists("c_no_if0") + if !exists("c_no_if0_fold") + syn region cCppOut start="^\s*\(%:\|#\)\s*if\s\+0\+\>" end=".\@=\|$" contains=cCppOut2 fold + else + syn region cCppOut start="^\s*\(%:\|#\)\s*if\s\+0\+\>" end=".\@=\|$" contains=cCppOut2 + endif + syn region cCppOut2 contained start="0" end="^\s*\(%:\|#\)\s*\(endif\>\|else\>\|elif\>\)" contains=cSpaceError,cCppSkip + syn region cCppSkip contained start="^\s*\(%:\|#\)\s*\(if\>\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*\(%:\|#\)\s*endif\>" contains=cSpaceError,cCppSkip +endif +syn region cIncluded display contained start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=ymlString +syn match cIncluded display contained "<[^>]*>" contains=ymlString +syn match cInclude display "^\s*\(%:\|#\)\s*include\>\s*["<]" contains=cIncluded +"syn match cLineSkip "\\$" +syn cluster cPreProcGroup contains=cPreCondit,cIncluded,cInclude,cDefine,cErrInParen,cErrInBracket,cUserLabel,cSpecial,cOctalZero,cCppOut,cCppOut2,cCppSkip,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom,cString,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cParen,cBracket,cMulti +syn region cDefine start="^\s*\(%:\|#\)\s*\(define\|undef\)\>" skip="\\$" end="$" keepend contains=ALLBUT,@cPreProcGroup,@Spell +syn region cPreProc start="^\s*\(%:\|#\)\s*\(pragma\>\|line\>\|warning\>\|warn\>\|error\>\)" skip="\\$" end="$" keepend contains=ALLBUT,@cPreProcGroup,@Spell + +" Highlight User Labels +syn cluster cMultiGroup contains=cIncluded,cSpecial,cCommentSkip,cCommentString,cComment2String,@cCommentGroup,cCommentStartError,cUserCont,cUserLabel,cBitField,cOctalZero,cCppOut,cCppOut2,cCppSkip,cFormat,cNumber,cFloat,cOctal,cOctalError,cNumbersCom,cCppParen,cCppBracket,cCppString +syn region cMulti transparent start='?' skip='::' end=':' contains=ALLBUT,@cMultiGroup,@Spell +" Avoid matching foo::bar() in C++ by requiring that the next char is not ':' +syn cluster cLabelGroup contains=cUserLabel +syn match cUserCont display "^\s*\I\i*\s*:$" contains=@cLabelGroup +syn match cUserCont display ";\s*\I\i*\s*:$" contains=@cLabelGroup +syn match cUserCont display "^\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup +syn match cUserCont display ";\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup + +syn match cUserLabel display "\I\i*" contained + +" Avoid recognizing most bitfields as labels +syn match cBitField display "^\s*\I\i*\s*:\s*[1-9]"me=e-1 contains=cType +syn match cBitField display ";\s*\I\i*\s*:\s*[1-9]"me=e-1 contains=cType + +if exists("c_minlines") + let b:c_minlines = c_minlines +else + if !exists("c_no_if0") + let b:c_minlines = 50 " #if 0 constructs can be long + else + let b:c_minlines = 15 " mostly for () constructs + endif +endif +if exists("c_curly_error") + syn sync fromstart +else + exec "syn sync ccomment cComment minlines=" . b:c_minlines +endif + +" Define the default highlighting. +" Only used when an item doesn't have highlighting yet +hi def link cFormat cSpecial +hi def link cCppString cString +hi def link cCommentL cComment +hi def link cCommentStart cComment +hi def link cLabel Label +hi def link cUserLabel Label +hi def link cConditional Conditional +hi def link cRepeat Repeat +hi def link cCharacter Character +hi def link cSpecialCharacter cSpecial +hi def link cNumber Number +hi def link cOctal Number +hi def link cOctalZero PreProc " link this to Error if you want +hi def link cFloat Float +hi def link cOctalError cError +hi def link cParenError cError +hi def link cErrInParen cError +hi def link cErrInBracket cError +hi def link cCommentError cError +hi def link cCommentStartError cError +hi def link cSpaceError cError +hi def link cSpecialError cError +hi def link cCurlyError cError +hi def link cOperator Operator +hi def link cStructure Structure +hi def link cStorageClass StorageClass +hi def link cInclude Include +hi def link cPreProc PreProc +hi def link cDefine Macro +hi def link cIncluded cString +hi def link cError Error +hi def link cStatement Statement +hi def link cPreCondit PreCondit +hi def link cType Type +hi def link cConstant Constant +hi def link cCommentString cString +hi def link cComment2String cString +hi def link cCommentSkip cComment +hi def link cString String +hi def link cComment Comment +hi def link cSpecial SpecialChar +hi def link cTodo Todo +hi def link cBadContinuation Error +hi def link cCppSkip cCppOut +hi def link cCppOut2 cCppOut +hi def link cCppOut Comment +hi def link ymlString Operator +let b:current_syntax = "yml2" + +" vim: ts=8 diff -r 000000000000 -r 76005e62091d xml2yml.ysl2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xml2yml.ysl2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,87 @@ +// xml2yml2.ysl2 version 2.4.4 + +include yslt.yml2 + +decl textstylesheet is estylesheet(*output="text") { + output *output; + const "space", !"'" + " " * 200 + "'"!; + param "autoindent", 4; + content; +}, tstylesheet is textstylesheet; + +define operator "†" as call "convert" with "tag", "name()"; + +tstylesheet { + function "printNS" + for "*/namespace::*[local-name()!='xml']" { + > xmlns + if "not(local-name()='')" + > :«local-name()» + > ="«.»" + if "position() , + } + + 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 000000000000 -r 76005e62091d yml2.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/yml2.py Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,108 @@ +# YML 2.5.3 language definition + +# written by VB. + +import re +from pyPEG import keyword, _and, _not + +# pyPEG: +# +# basestring: terminal symbol (characters) +# keyword: terminal symbol (keyword) +# matchobj: terminal symbols (regex, use for scanning symbols) +# function: named non-terminal symbol, recursive definition +# if you don't want naming in output, precede name with an underscore +# tuple: production sequence +# integer: count in production sequence: +# 0: following element is optional +# -1: following element can be omitted or repeated endless +# -2: following element is required and can be repeated endless +# list: options, choose one of them +# _not: next element in production sequence is matched only if this would not +# _and: next element in production sequence is matched only if this would, too + +newSyntax = True + +def oldSyntax(): + global newSyntax + newSyntax = False + +def _if(cond, val): + if cond: + return val + else: + return () + +def listing(x): return x, -1, (",", x) +r = re.compile + +comment = [r(r"//.*"), r(r"/\*.*?\*/", re.S)] +_symbol = r"(?=\D)\w(\w|:)*" +symbol = r(_symbol, re.U) +pointer = r(r"\*" + _symbol, re.U) +ppointer = r(r"\*\*" + _symbol, re.U) +macro = r(r"\%" + _symbol, re.U) +reference = r(r"\&" + _symbol, re.U) + +NameStartChar = ur''':|[A-Z]|_|[a-z]|[\u00C0-\u00D6]|[\u00D8-\u00F6]|[\u00F8-\u02FF]|[\u0370-\u037D]|[\u037F-\u1FFF]|[\u200C-\u200D]|[\u2070-\u218F]|[\u2C00-\u2FEF]|[\u3001-\uD7FF]|[\uF900-\uFDCF]|[\uFDF0-\uFFFD]''' +NameChar = NameStartChar + ur'''|-|\.|[0-9]|\u00B7|[\u0300-\u036F]|[\u203F-\u2040]''' + +_xmlSymbol = u"(" + NameStartChar + u")(" + NameChar + u")*" +xmlSymbol = r(_xmlSymbol) +aliasSymbol = r(ur"-|(" + _xmlSymbol + ur")") + +literal = [r(r'""".*?"""', re.S), r(r"'''.*?'''", re.S), r(r"""-?\d+\.\d*|-?\.\d+|-?\d+|".*?"|'.*?'""")] +filename = [("'", r(r"[^']*"), "'"), ('"', r(r'[^"]*'), '"'), r(r"[^\s;]+")] +ws = r(r"\s+", re.U) + +def pyExp(): return "!", r(r"(!=|\\!|[^!])+"), "!" +value = [literal, pyExp] + +def tagQuote(): return r(r"\].*|\<.*?\>") +def lineQuote(): return r(r"\|.*") +def quote(): return [r(r"\d*>.*"), (literal, 0, [";", "."])] +def parm(): return [([xmlSymbol, pyExp, pointer, macro], "=", [value, pointer, symbol]), value, pointer] +def parm_eq(): return [xmlSymbol, pyExp, pointer, macro], "=", [value, pointer, symbol] +parm_eq.__name__ = "parm" +_func = [symbol, ppointer, pointer, reference], _if(newSyntax, (-1, ("[", listing(parm), "]"))), 0, ("(", listing(parm), ")"), 0, listing(parm), -1, parm_eq +def pythonCall(): return keyword("python"), _func, [";", "."] +def declParm(): return [pointer, macro, xmlSymbol], 0, ("=", literal) +def alias(): return keyword("alias"), aliasSymbol +def descend(): return r(r"[+@*]" + _symbol, re.U) +def base(): return keyword("is"), symbol +def shape(): return symbol +def decl(): return symbol, 0, base, 0, ("<", listing(shape), ">"), -1, descend, _if(newSyntax, (-1, ("[", 0, listing(declParm), "]"))), 0, ("(", 0, listing(declParm), ")"), 0, alias, 0, content +def python(): return [r(r"!!.*?!!", re.S), r(r"!.*")] +def operator(): return 0, keyword("define"), keyword("operator"), literal, keyword("as"), r(r".*") +def constant(): return 0, keyword("define"), [pointer, symbol], "=", literal, 0, [";", "."] +def in_ns(): return keyword("in"), xmlSymbol, [_decl, ("{", -2, _decl, "}")] +_decl = keyword("decl"), listing(decl), [";", "."] +def textsection(): return r(r'(\|\|(\>*).*?\|\|(\>*))|(\>\>.*?\>\>)', re.S) +def include(): return keyword("include"), 0, reverse, 0, [ktext, kxml], filename, 0, [";", "."] +def func(): return _func, 0, content +def funclist(): return listing(func) +_cmd = funclist, 0, [";", "."] +_inner = [include, textsection, pythonCall, _cmd, quote, lineQuote, tagQuote, pyExp] +_cc = "{", -1, _inner, "}" +def content_plain(): return [ (_l, 0, _p, 0, _b, 0, _cc), (_p, 0, _b, 0, _cc), (_b, 0, _cc), _cc ] +content_plain.__name__ = "content" +def func_plain(): return _func, 0, content_plain +func_plain.__name__ = "func" +def flist_plain(): return -2, func_plain +flist_plain.__name__ = "funclist" +def xbase(): return flist_plain +def generic(): return flist_plain +def subscript(): return flist_plain +def parentheses(): return "(", 0, funclist, ")" +def fparm(): return flist_plain + +_l = _if(newSyntax, ("<", listing(generic), ">")) +_p = _if(not newSyntax, parentheses), _if(newSyntax, ("(", 0, listing(fparm), ")")) +_b = (":", listing(xbase)) +_c = [_inner, _cc] + +def content(): return [ (_l, 0, _p, 0, _b, 0, _c), (_p, 0, _b, 0, _c), (_b, 0, _c), _c ] +def reverse(): return keyword("reverse") +def ktext(): return keyword("text") +def kxml(): return keyword("xml") +def ymlCStyle(): return -1, [_decl, in_ns, include, python, operator, constant, tagQuote, lineQuote, quote, _cmd] diff -r 000000000000 -r 76005e62091d yml2c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/yml2c Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# vim: set fileencoding=utf-8 : + +"""\ +YML 2 compiler version 5.4 +Copyleft (c), 2009-2011, Volker Birk http://fdik.org/yml/ + +""" + +import sys, os, codecs, locale +import fileinput, unicodedata +from optparse import OptionParser + +from pyPEG import parse, u +from yml2 import ymlCStyle, comment, oldSyntax +import backend + +def printInfo(option, opt_str, value, parser): + sys.stdout.write(__doc__) + +def w(msg): + if isinstance(msg, BaseException): + try: + msg = str(msg) + "\n" + except: + msg = u(msg) + u"\n" + if type(msg) is unicode: + msg = codecs.encode(msg, sys.stderr.encoding) + sys.stderr.write(msg) + +optParser = OptionParser() +optParser.add_option("-C", "--old-syntax", action="store_true", dest="old_syntax", + help="syntax of YML 2 version 1.x (compatibility mode)", default=False) +optParser.add_option("-D", "--emit-linenumbers", action="store_true", dest="emitlinenumbers", + help="emit line numbers into the resulting XML for debugging purposes", default=False) +optParser.add_option("-E", "--encoding", dest="encoding", metavar="ENCODING", default=locale.getdefaultlocale()[1], + help="encoding of input files (default to locale)") +optParser.add_option("-I", "--include", dest="includePathText", metavar="INCLUDE_PATH", + help="precede YML_PATH by a colon separated INCLUDE_PATH to search for include files") +optParser.add_option("-m", "--omit-empty-parm-tags", action="store_true", dest="omitemptyparm", + help="does nothing (only there for compatibility reasons)", default=False) +optParser.add_option("-n", "--normalization", dest="normalization", metavar="NORMALIZATION", default="NFC", + help="Unicode normalization (none, NFD, NFKD, NFC, NFKC, FCD, default is NFC)") +optParser.add_option("-o", "--output", dest="outputFile", metavar="FILE", + help="place output in file FILE") +optParser.add_option("-p", "--parse-only", action="store_true", dest="parseonly", + help="parse only, then output pyAST as text to stdout", default=False) +optParser.add_option("-V", "--version", action="callback", callback=printInfo, help="show version info") +(options, args) = optParser.parse_args() + +if options.old_syntax: + oldSyntax() + +if options.emitlinenumbers: + backend.emitlinenumbers = True + +backend.encoding = options.encoding + +try: + if options.includePathText: + backend.includePath = options.includePathText.split(':') + + dirs = os.environ.get('YML_PATH', '.').split(':') + backend.includePath.extend(dirs) + + files = fileinput.input(args, mode="rU", openhook=fileinput.hook_encoded(options.encoding)) + # fileinput suffer from two nasty bugs : + # - ignoring open hook with stdin + # - iterator requires ctrl-D to be pressed twice on some platform + if args in [[],['-']] : + files._files=[] + files._buffer=[unicode(line, options.encoding) for line in sys.stdin.readlines()] + + ymlC = ymlCStyle() + result = parse(ymlC, files, True, comment, packrat=True) + + if options.parseonly: + print result + else: + result = backend.finish(result) + if options.normalization != "none": + result = unicodedata.normalize(options.normalization, result) + + if options.outputFile and options.outputFile != "-": + outfile = open(options.outputFile, "w") + outfile.write(codecs.encode(result, options.encoding)) + outfile.close() + else: + print codecs.encode(result, options.encoding) + +except KeyboardInterrupt: + w("\n") + sys.exit(1) +except KeyError, msg: + w(u"not found: " + u(msg) + u"\n") + sys.exit(4) +except LookupError, msg: + w(u"not found: " + u(msg) + u"\n") + sys.exit(4) +except Exception, msg: + w(msg) + sys.exit(5) diff -r 000000000000 -r 76005e62091d yml2proc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/yml2proc Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,248 @@ +#!/usr/bin/env python +# vim: set fileencoding=utf-8 : + +"""\ +YML/YSLT 2 processor version 5.4 +Copyleft (c), 2009-2011 Volker Birk http://fdik.org/yml/ + +""" + +import sys, os, codecs, locale +import fileinput, unicodedata +from optparse import OptionParser + +try: + from lxml import etree +except: + sys.stderr.write("This program needs lxml, see http://codespeak.net/lxml/\n") + sys.exit(1) + +from yml2 import ymlCStyle, comment, oldSyntax +from pyPEG import parse, u +import backend + +def printInfo(option, opt_str, value, parser): + sys.stdout.write(__doc__) + sys.exit(0) + +class YMLAssert(Exception): pass + +def w(msg): + if isinstance(msg, BaseException): + try: + msg = str(msg) + "\n" + except: + msg = u(msg) + u"\n" + if type(msg) is unicode: + msg = codecs.encode(msg, sys.stderr.encoding) + sys.stderr.write(msg) + +optParser = OptionParser() +optParser.add_option("-C", "--old-syntax", action="store_true", dest="old_syntax", + help="syntax of YML 2 version 1.x (compatibility mode)", default=False) +optParser.add_option("-D", "--emit-linenumbers", action="store_true", dest="emitlinenumbers", + help="emit line numbers into the resulting XML for debugging purposes", default=False) +optParser.add_option("--debug", action="store_true", dest="trace", + help="switch on tracing to stderr", default=False) +optParser.add_option("-d", "--paramdict", dest="params", metavar="PARAMS", + help="call X/YSLT script with dictionary PARAMS as parameters") +optParser.add_option("-e", "--xpath", dest="xpath", metavar="XPATH", + help="execute XPath expression XPATH and print result") +optParser.add_option("-E", "--encoding", dest="encoding", metavar="ENCODING", default=locale.getdefaultlocale()[1], + help="encoding of input files (default to locale)") +optParser.add_option("-I", "--include", dest="includePathText", metavar="INCLUDE_PATH", + help="precede YML_PATH by a colon separated INCLUDE_PATH to search for include files") +optParser.add_option("-m", "--omit-empty-parm-tags", action="store_true", dest="omitemptyparm", + help="does nothing (only there for compatibility reasons)", default=False) +optParser.add_option("-M", "--empty-input-document", action="store_true", dest="emptyinput", + help="use an empty input document", default=False) +optParser.add_option("-n", "--normalization", dest="normalization", metavar="NORMALIZATION", default="NFC", + help="Unicode normalization (none, NFD, NFKD, NFC, NFKC, FCD, default is NFC)") +optParser.add_option("-o", "--output", dest="outputFile", metavar="FILE", + help="place output in file FILE") +optParser.add_option("-p", "--parse-only", action="store_true", dest="parseonly", + help="parse only, then output pyAST as text to stdout", default=False) +optParser.add_option("-P", "--pretty", action="store_true", default=False, + help="pretty print output adding whitespace") +optParser.add_option("-s", "--stringparamdict", dest="stringparams", metavar="STRINGPARAMS", + help="call X/YSLT script with dictionary STRINGPARAMS as string parameters") +optParser.add_option("-x", "--xml", action="store_true", default=False, + help="input document is XML already") +optParser.add_option("-X", "--xslt", dest="xslt", metavar="XSLTSCRIPT", + help="execute XSLT script XSLTSCRIPT") +optParser.add_option("-y", "--yslt", dest="yslt", metavar="YSLTSCRIPT", + help="execute YSLT script YSLTSCRIPT") +optParser.add_option("-Y", "--xml2yml", action="store_true", default=False, + help="convert XML to normalized YML code") +optParser.add_option("-V", "--version", action="callback", callback=printInfo, help="show version info and exit") +(options, args) = optParser.parse_args() + +if options.old_syntax: + oldSyntax() + +if options.trace: + backend.enable_tracing = True + +if options.emitlinenumbers: + backend.emitlinenumbers = True + +if options.includePathText: + backend.includePath = options.includePathText.split(':') + +backend.encoding = options.encoding + +dirs = os.environ.get('YML_PATH', '.').split(':') +backend.includePath.extend(dirs) + +if options.xml2yml: + for directory in backend.includePath: + try: + name = directory + "/xml2yml.ysl2" + f = open(name, "r") + f.close() + break + except: + pass + + options.yslt = name + options.xml = True + +if (options.xslt and options.yslt) or (options.xslt and options.xpath) or (options.yslt and options.xpath): + sys.stderr.write("Cannot combine --xpath, --xslt and --yslt params\n") + sys.exit(1) + +try: + ymlC = ymlCStyle() + + rtext = u"" + + if not options.emptyinput: + files = fileinput.input(args, mode="rU", openhook=fileinput.hook_encoded(options.encoding)) + # fileinput suffer from two nasty bugs : + # - ignoring open hook with stdin + # - iterator requires ctrl-D to be pressed twice on siome platform + if args in [[],['-']] : + files._files=[] + files._buffer=[unicode(line, options.encoding) for line in sys.stdin.readlines()] + + if options.xml: + rtext = "" + for line in files: + rtext += line + else: + result = parse(ymlC, files, True, comment) + if options.parseonly: + print result + sys.exit(0) + else: + rtext = backend.finish(result) + + if not rtext: + rtext = u"" + + def ymldebug(context, text): + if options.trace: + sys.stderr.write("Debug: " + codecs.encode(u(text), options.encoding) + "\n") + return "" + + def ymlassert(context, value, msg): + if options.trace: + if not value: + raise YMLAssert(msg) + return "" + + ymlns = etree.FunctionNamespace("http://fdik.org/yml") + ymlns.prefix = "yml" + ymlns['debug'] = ymldebug + ymlns['assert'] = ymlassert + + if options.xpath: + tree = etree.fromstring(rtext) + ltree = tree.xpath(codecs.decode(options.xpath, options.encoding)) + rtext = u"" + try: + for rtree in ltree: + rtext += etree.tostring(rtree, pretty_print=options.pretty, encoding=unicode) + except: + rtext = ltree + + elif options.yslt or options.xslt: + params = {} + + if options.yslt: + backend.clearAll() + yscript = fileinput.input(options.yslt, mode="rU", openhook=fileinput.hook_encoded(options.encoding)) + yresult = parse(ymlC, yscript, True, comment) + ytext = backend.finish(yresult) + else: + yscript = fileinput.input(options.xslt, mode="rU") + ytext = "" + for line in yscript: + ytext += line + + doc = etree.fromstring(rtext) + + xsltree = etree.XML(ytext, base_url=os.path.abspath(yscript.filename())) + transform = etree.XSLT(xsltree) + + if options.params: + params = eval(options.params) + for key, value in params.iteritems(): + if type(value) != unicode: + params[key] = u(value) + if options.stringparams: + for key, value in eval(options.stringparams).iteritems(): + params[key] = u"'" + u(value) + u"'" + + rresult = transform(doc, **params) + # lxml is somewhat buggy + try: + rtext = u(rresult) + except: + rtext = etree.tostring(rresult, encoding=unicode) + if not rtext: + rtext = codecs.decode(str(rresult), "utf-8") + + if options.normalization != "none": + rtext = unicodedata.normalize(options.normalization, rtext) + + if options.pretty: + plaintext = etree.tostring(etree.fromstring(rtext), pretty_print=True, xml_declaration=True, encoding=options.encoding) + else: + if isinstance(rtext, unicode): + plaintext = codecs.encode(rtext, options.encoding) + else: + plaintext = str(rtext) + + try: + if plaintext[-1] == "\n": + plaintext = plaintext[:-1] + except: pass + + if options.outputFile and options.outputFile != "-": + outfile = open(options.outputFile, "w") + outfile.write(plaintext) + outfile.close() + else: + print plaintext + +except KeyboardInterrupt: + w("\n") + sys.exit(1) +except YMLAssert, msg: + w(u"YML Assertion failed: " + u(msg) + u"\n") + sys.exit(2) +except KeyError, msg: + w(u"not found: " + u(msg) + u"\n") + sys.exit(4) +except LookupError, msg: + w(u"not found: " + u(msg) + u"\n") + sys.exit(4) +except etree.XMLSyntaxError, e: + log = e.error_log.filter_from_level(etree.ErrorLevels.FATAL) + for entry in log: + w(u"XML error: " + u(entry.message) + u"\n") + sys.exit(5) +except Exception, msg: + w(msg) + sys.exit(5) diff -r 000000000000 -r 76005e62091d yslt.en.yhtml2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/yslt.en.yhtml2 Mon Jul 11 23:15:28 2016 +0200 @@ -0,0 +1,1069 @@ +include homepage.en.yhtml2 + +page "YSLT – XSLT C style" { + h1 id=intro > YSLT – an introduction + + p >> + Especially the ¬http://www.w3.org/TR/xslt XSLT¬ programmer can benefit from YML. + Usually many attributes of XSLT are annoying in programming praxis: + >> + + ul { + li >> + the missing separation of ¬http://en.wikipedia.org/wiki/Indent_style indention¬ + of the XSLT program and indention of the output text + >> + + li > the complicated syntax + + li > the lack of good text escaping mechanisms (< and > are not seldom) + + li > ... + } + + p > In short, it's ugly ;-) + + p >> + Usually the result is, that many programmers are avoiding XSLT as a programming language. + It's a pity, because for processing XML data, it can do much more than “formatting” as + “stylesheets”. + >> + + p >> + The idea of YSLT now is to supply a simple language, which programmers want to use, to + make the features of XSLT accessible to a broader base of people. + >> + + p >> + YSLT can be used much simpler; it's just a ¬http://fdik.org/yml/index#ylanguages Y Language¬ + for XSLT. I'm using it for my blog, here you can ¬http://fdik.org/yblog2.tar.bz2 download YBlog2¬, + a simple blogging software in YSLT. + >> + + p > Here you can find the ¬yslt.yml2 YSLT specification¬. + + h2 id=hello > Hello, World + + p > In YSLT, the hello world program reads like this: + + Code || + include yslt.yml2 + textstylesheet template "/" | hello, world + || + + p >> + The `a href="http://fdik.org/yml/features#including" code > include` line includes the + YSLT Y Language declarations. The second line generates an XSLT hello world program. + You can generate it using: + >> + + Code | % yml2c -o hello.xsl hello.ysl2 + + p > This results in the following program: + + Code || + + + + hello, world + + || + + p >> + You can execute this program with any + ¬http://en.wikipedia.org/wiki/XML_template_engine XSL processor¬, for example the Free Software + ¬http://xmlsoft.org/XSLT/xsltproc2.html xsltproc¬. + >> + + Code || + % yml2c -o hello.xsl hello.ysl2 + % echo '' > empty.xml + % xsltproc hello.xsl empty.xml + hello, world + % _ + || + + p >> + Or you can just use ¬toolchain#processor yml2proc¬: + >> + + Code || + % yml2proc -My hello.ysl2 + hello, world + % _ + || + + h2 id=programming > Programming in YSLT + + p >> + Because YSLT is just a ¬index#ylanguages Y Language¬ for XSLT, you can do anything with YSLT + you can do with XSLT in just nicer syntax ;-) To read what XSLT is all about, I recommend + ¬http://www.w3.org/TR/xslt the official W3C documentation for XSLT¬. + >> + + p >> + So this document is just an beginners guide, if you want to understand XSLT completely, + better read the ¬http://www.w3.org W3C¬ stuff. + >> + + h3 > Programming YSLT means programming with a pure functional language. + + p >> + Lovers of ¬http://en.wikipedia.org/wiki/Lisp_(programming_language) Lisp¬ or + ¬http://www.haskell.org/ Haskell¬ will not see any problems. But many programmers are used to + have a programming language with a + ¬http://en.wikipedia.org/wiki/Procedural_programming procedural imperative paradigma¬ like + ¬http://java.sun.com Java¬, + ¬http://en.wikipedia.org/wiki/C_(programming_language) C¬/¬http://en.wikipedia.org/wiki/C++ C++¬ + or ¬http://www.python.org Python¬. Why should they use a + ¬http://en.wikipedia.org/wiki/Functional_programming functional¬ language? + >> + + p >> + Actually, if a functional language is practical or not, depends of what's to do – “the + right tool for the task”, one could say. + >> + + p >> + Because processing XML data means traversing a (document) tree, + ¬http://en.wikipedia.org/wiki/Recursion recursive¬ algorithms are a clear advantage. + And this is the reason, why choosing a functional language is a good choice for that job. + >> + + p >> + It's a little bit like with ¬http://en.wikipedia.org/wiki/SQL SQL¬ – for it's job, it's + excellent, but no-one wants to write a complete application in SQL (and also not in one + of the Turing-complete SQL extension languages like + ¬http://www.oracle.com/technology/tech/pl_sql/index.html PL/SQL¬). + >> + + h3 id=htmlgen > Generating HTML out of a DSL + + p >> + Of course, you can use YSLT as you would use XSLT. Let's say, you have data in XML + documents, and you want to have an excerpt out of this data. This is a common task, + comparable to «SELECT» data out of an SQL database. But we have no database, we have + something like this file customers.yml2: + >> + + Code || + decl customer(*id, *name) { id *id, name *name }; + + list { + customer 23, "Kurt Meier"; + customer 42, "Lieschen Schmidt"; + } + || + + p >> + Let's say, we want to output this into an ¬http://en.wikipedia.org/wiki/XHTML XHTML¬ document, + where the list is showed as a table. Then we would do the following: + >> + + p > The XHTML document should be like the following and include the list in the body: + + Code || + include yslt.yml2 + + stylesheet { + template "/" html { + head title "Customer List"; + body apply "list"; + } + || + + p >> + In the example above, stylesheet declares the main program. Then we define a template, which + is executed automatically starting reading the root «'/'» of the document tree of the XML + document we're processing. + >> + + p > Using the XML document as input, we're creating this HTML tree: + + Code || + + + Customer List + + + +