1 # 2.5.10 backend |
1 # 2.6.0 backend |
2 |
2 |
3 # written by VB. |
3 # written by VB. |
4 |
4 |
5 import re, codecs |
5 import re, codecs |
6 import fileinput |
6 import fileinput |
7 import sys, traceback, exceptions, os |
7 import sys, traceback, os |
8 from xml.sax.saxutils import escape, quoteattr |
8 from xml.sax.saxutils import escape, quoteattr |
9 from copy import copy, deepcopy |
9 from copy import copy, deepcopy |
10 from glob import glob |
10 from glob import glob |
11 from pyPEG import code, parse, parseLine, u, Symbol |
11 from pyPEG import code, parse, parseLine, u, Symbol |
12 from yml2 import ymlCStyle, comment, _inner |
12 from yml2 import ymlCStyle, comment, _inner |
13 |
13 |
14 ymlFunc, pointers, pythonFunc = {}, {}, {} |
14 ymlFunc, pointers, pythonFunc = {}, {}, {} |
15 in_ns = u"" |
15 in_ns = "" |
16 operator = [] |
16 operator = [] |
17 included = u"" |
17 included = "" |
18 includePath = [] |
18 includePath = [] |
19 emitlinenumbers = False |
19 emitlinenumbers = False |
20 encoding = "utf-8" |
20 encoding = "utf-8" |
21 |
21 |
22 first = True |
22 first = True |
27 ymlFunc["operator"] = "#error" |
27 ymlFunc["operator"] = "#error" |
28 |
28 |
29 def clearAll(): |
29 def clearAll(): |
30 global ymlFunc, pointers, pythonFunc, in_ns, operator, included |
30 global ymlFunc, pointers, pythonFunc, in_ns, operator, included |
31 ymlFunc, pointers, pythonFunc = {}, {}, {} |
31 ymlFunc, pointers, pythonFunc = {}, {}, {} |
32 in_ns = u"" |
32 in_ns = "" |
33 operator = [] |
33 operator = [] |
34 included = u"" |
34 included = "" |
35 |
35 |
36 lq = re.compile(r"\|(\>*)(.*)") |
36 lq = re.compile(r"\|(\>*)(.*)") |
37 sq = re.compile(r"(\d*)\>(.*)") |
37 sq = re.compile(r"(\d*)\>(.*)") |
38 ts = re.compile(r'(\|\|(?P<inds>\>*)\s*\n(?P<text1>.*?)\n(?P<base>\s*)\|\|)|("""(?P<text2>.*?)""")|(\>\>(?P<text3>.*?)\>\>)', re.S) |
38 ts = re.compile(r'(\|\|(?P<inds>\>*)\s*\n(?P<text1>.*?)\n(?P<base>\s*)\|\|)|("""(?P<text2>.*?)""")|(\>\>(?P<text3>.*?)\>\>)', re.S) |
39 tq = re.compile(r"(\]|\<)\s*(.*)") |
39 tq = re.compile(r"(\]|\<)\s*(.*)") |
46 def pointer(name): |
46 def pointer(name): |
47 try: |
47 try: |
48 return u(pointers[name[1:]]) |
48 return u(pointers[name[1:]]) |
49 except: |
49 except: |
50 if name == "*_trace_info": |
50 if name == "*_trace_info": |
51 return u'""' |
51 return '""' |
52 if included: |
52 if included: |
53 raise LookupError(u"in " + included + u":" + u(line) + u": pointer " + name) |
53 raise LookupError("in " + included + ":" + u(line) + ": pointer " + name) |
54 else: |
54 else: |
55 raise LookupError(u"in " + u(line) + u": pointer " + name) |
55 raise LookupError("in " + u(line) + ": pointer " + name) |
56 |
56 |
57 def evalPython(expr): |
57 def evalPython(expr): |
58 try: |
58 try: |
59 result = eval(u(expr), pythonFunc) |
59 result = eval(u(expr), pythonFunc) |
60 if type(result) is str: |
60 if type(result) is bytes: |
61 return codecs.decode(result, encoding) |
61 return codecs.decode(result, encoding) |
62 else: |
62 else: |
63 return result |
63 return result |
64 except: |
64 except: |
65 name, parm, tb = sys.exc_info() |
65 name, parm, tb = sys.exc_info() |
66 msg = u"in python expression: " + u(parm) |
66 msg = "in python expression: " + u(parm) |
67 if name is exceptions.SyntaxError: |
67 if name is SyntaxError: |
68 tbl = traceback.format_exception(name, parm, tb) |
68 tbl = traceback.format_exception(name, parm, tb) |
69 msg += u"\n" + tbl[-3] + tbl[-2] |
69 msg += "\n" + tbl[-3] + tbl[-2] |
70 else: |
70 else: |
71 msg += u": " + expr + u"\n" |
71 msg += ": " + expr + "\n" |
72 if included: |
72 if included: |
73 raise name(u"in " + included + u":" + u(line) + u": " + msg) |
73 raise name("in " + included + ":" + u(line) + ": " + msg) |
74 else: |
74 else: |
75 raise name(u"in " + u(line) + u": " + msg) |
75 raise name("in " + u(line) + ": " + msg) |
76 |
76 |
77 def execPython(script): |
77 def execPython(script): |
78 try: |
78 try: |
79 if type(script) is unicode: |
79 if type(script) is str: |
80 exec script in pythonFunc |
80 exec(script, pythonFunc) |
81 else: |
81 else: |
82 exec codecs.decode(script, encoding) in pythonFunc |
82 exec(codecs.decode(script, encoding), pythonFunc) |
83 except: |
83 except: |
84 name, parm, tb = sys.exc_info() |
84 name, parm, tb = sys.exc_info() |
85 msg = u"in python script: " + u(parm) |
85 msg = "in python script: " + u(parm) |
86 if name is exceptions.SyntaxError: |
86 if name is SyntaxError: |
87 tbl = traceback.format_exception(name, parm, tb) |
87 tbl = traceback.format_exception(name, parm, tb) |
88 msg += u"\n" + tbl[-3] + tbl[-2] |
88 msg += "\n" + tbl[-3] + tbl[-2] |
89 else: |
89 else: |
90 msg += u": " + expr + u"\n" |
90 msg += ": " + expr + "\n" |
91 if included: |
91 if included: |
92 raise name(u"in " + included + u":" + u(line) + u": " + msg) |
92 raise name("in " + included + ":" + u(line) + ": " + msg) |
93 else: |
93 else: |
94 raise name(u"in " + u(line) + u": " + msg) |
94 raise name("in " + u(line) + ": " + msg) |
95 |
95 |
96 def textOut(text): |
96 def textOut(text): |
97 if not text: |
97 if not text: |
98 return u"" |
98 return "" |
99 if type(text) is not unicode: |
99 if type(text) is not str: |
100 text = codecs.decode(text, encoding) |
100 text = codecs.decode(text, encoding) |
101 text = text.replace(r'\"', r'\\"') |
101 text = text.replace(r'\"', r'\\"') |
102 text = u'u"""' + text.replace('"', r'\"') + u'"""' |
102 text = '"""' + text.replace('"', r'\"') + '"""' |
103 try: |
103 try: |
104 textFunc = ymlFunc["text"] |
104 textFunc = ymlFunc["text"] |
105 parms = ['text', ('parm', [text])] |
105 parms = ['text', ('parm', [text])] |
106 c, result = textFunc(parms) |
106 c, result = textFunc(parms) |
107 if c: |
107 if c: |
108 if type(textFunc.alias) is unicode: |
108 if type(textFunc.alias) is str: |
109 result += u"</" + textFunc.alias + u">" |
109 result += "</" + textFunc.alias + ">" |
110 else: |
110 else: |
111 result += u"</" + codecs.decode(textFunc.alias, encoding) + u">" |
111 result += "</" + codecs.decode(textFunc.alias, encoding) + ">" |
112 return result |
112 return result |
113 except: |
113 except: |
114 return escape(eval(text)) |
114 return escape(eval(text)) |
115 |
115 |
116 def strRepl(text): |
116 def strRepl(text): |
117 if not text: |
117 if not text: |
118 return u"" |
118 return "" |
119 if type(text) is not unicode: |
119 if type(text) is not str: |
120 text = codecs.decode(text, encoding) |
120 text = codecs.decode(text, encoding) |
121 text = text.replace(r'\"', r'\\"') |
121 text = text.replace(r'\"', r'\\"') |
122 text = u'u"""' + text.replace('"', r'\"') + u'"""' |
122 text = '"""' + text.replace('"', r'\"') + '"""' |
123 if type(text) is unicode: |
123 if type(text) is str: |
124 return escape(eval(text)) |
124 return escape(eval(text)) |
125 |
125 |
126 def applyMacros(macros, text): |
126 def applyMacros(macros, text): |
127 result = text |
127 result = text |
128 for key, value in macros.iteritems(): |
128 for key, value in macros.items(): |
129 result = result.replace(key, value) |
129 result = result.replace(key, value) |
130 return result |
130 return result |
131 |
131 |
132 class YF: |
132 class YF: |
133 def __init__(self, name): |
133 def __init__(self, name): |
229 self.descends.append(desc[1:]) |
229 self.descends.append(desc[1:]) |
230 else: |
230 else: |
231 self.descends.append(desc) |
231 self.descends.append(desc) |
232 |
232 |
233 def addValue(self, parm, value): |
233 def addValue(self, parm, value): |
234 if type(value) is str or type(value) is unicode: |
234 if type(value) is str or type(value) is str: |
235 if value[0] != "'" and value[0] != '"': |
235 if value[0] != "'" and value[0] != '"': |
236 self.values[parm] = u(value) |
236 self.values[parm] = u(value) |
237 else: |
237 else: |
238 self.values[parm] = u(evalPython(value)) |
238 self.values[parm] = u(evalPython(value)) |
239 else: |
239 else: |
240 self.values[parm] = u(evalPython(u(value))) |
240 self.values[parm] = u(evalPython(u(value))) |
241 |
241 |
242 def xml(self, callParms, callValues, hasContent, avoidTag = False): |
242 def xml(self, callParms, callValues, hasContent, avoidTag = False): |
243 global pointers |
243 global pointers |
244 extraContent = u"" |
244 extraContent = "" |
245 if self.content: |
245 if self.content: |
246 hasContent = True |
246 hasContent = True |
247 resultParms = self.values.copy() |
247 resultParms = self.values.copy() |
248 macros = self.macros.copy() |
248 macros = self.macros.copy() |
249 toDelete = resultParms.keys() |
249 toDelete = resultParms.keys() |
250 for key in toDelete: |
250 for key in toDelete: |
251 if key[0] == "*": |
251 if key[0] == "*": |
252 del resultParms[key] |
252 del resultParms[key] |
253 for key, value in callValues.iteritems(): |
253 for key, value in callValues.items(): |
254 if key[0] == "%": |
254 if key[0] == "%": |
255 macros[key] = value |
255 macros[key] = value |
256 else: |
256 else: |
257 resultParms[key] = value |
257 resultParms[key] = value |
258 i = 0 |
258 i = 0 |
259 for cp in callParms: |
259 for cp in callParms: |
260 if i < len(self.parms): |
260 if i < len(self.parms): |
261 if self.parms[i][0] == "*": |
261 if self.parms[i][0] == "*": |
262 cp = u(cp) |
262 cp = u(cp) |
263 if "'" in cp: |
263 if "'" in cp: |
264 pointers[self.parms[i][1:]] = u'"' + cp + u'"' |
264 pointers[self.parms[i][1:]] = '"' + cp + '"' |
265 else: |
265 else: |
266 pointers[self.parms[i][1:]] = u"'" + cp + u"'" |
266 pointers[self.parms[i][1:]] = "'" + cp + "'" |
267 elif self.parms[i][0] == "%": |
267 elif self.parms[i][0] == "%": |
268 macros[self.parms[i]] = u(cp) |
268 macros[self.parms[i]] = u(cp) |
269 else: |
269 else: |
270 resultParms[self.parms[i]] = cp |
270 resultParms[self.parms[i]] = cp |
271 else: |
271 else: |
272 extraContent += u(cp) |
272 extraContent += u(cp) |
273 hasContent = True |
273 hasContent = True |
274 i += 1 |
274 i += 1 |
275 result = u"" |
275 result = "" |
276 for p, v in resultParms.iteritems(): |
276 for p, v in resultParms.items(): |
277 if p[0] == "'" or p[0] == '"': |
277 if p[0] == "'" or p[0] == '"': |
278 p = eval(p) |
278 p = eval(p) |
279 result += u" "+ p + u"=" + quoteattr(applyMacros(macros, u(v))) |
279 result += " "+ p + "=" + quoteattr(applyMacros(macros, u(v))) |
280 if hasContent: |
280 if hasContent: |
281 if avoidTag: |
281 if avoidTag: |
282 return True, strRepl(extraContent) |
282 return True, strRepl(extraContent) |
283 else: |
283 else: |
284 return True, u"<" + self.alias + result + u">" + strRepl(extraContent) |
284 return True, "<" + self.alias + result + ">" + strRepl(extraContent) |
285 else: |
285 else: |
286 if avoidTag: |
286 if avoidTag: |
287 return False, u"" |
287 return False, "" |
288 else: |
288 else: |
289 return False, u"<" + self.alias + result + u"/>" |
289 return False, "<" + self.alias + result + "/>" |
290 |
290 |
291 def replaceContent(tree, subtree): |
291 def replaceContent(tree, subtree): |
292 n = 0 |
292 n = 0 |
293 while n < len(tree): |
293 while n < len(tree): |
294 obj = tree[n] |
294 obj = tree[n] |
311 replaceContent(obj[1], subtree) |
311 replaceContent(obj[1], subtree) |
312 n += 1 |
312 n += 1 |
313 return tree |
313 return tree |
314 |
314 |
315 def executeCmd(text): |
315 def executeCmd(text): |
316 if type(text) is not unicode: |
316 if type(text) is not str: |
317 text = codecs.decode(text, encoding) |
317 text = codecs.decode(text, encoding) |
318 for (regex, pattern) in operator: |
318 for (regex, pattern) in operator: |
319 match = re.search(regex, text) |
319 match = re.search(regex, text) |
320 while match: |
320 while match: |
321 cmd = pattern |
321 cmd = pattern |
322 opt = match.groups() |
322 opt = match.groups() |
323 for i in range(len(opt)): |
323 for i in range(len(opt)): |
324 cmd = cmd.replace(u"%" + u(i+1), opt[i]) |
324 cmd = cmd.replace("%" + u(i+1), opt[i]) |
325 text = text[:match.start()] + u"`" + cmd + u"`"+ text[match.end():] |
325 text = text[:match.start()] + "`" + cmd + "`"+ text[match.end():] |
326 match = re.search(regex, text) |
326 match = re.search(regex, text) |
327 |
327 |
328 result = u"" |
328 result = "" |
329 m = re.search(bq, text) |
329 m = re.search(bq, text) |
330 while text and m: |
330 while text and m: |
331 cmd = m.group(1) |
331 cmd = m.group(1) |
332 head = textOut(text[:m.start()]) |
332 head = textOut(text[:m.start()]) |
333 text = text[m.end():] |
333 text = text[m.end():] |
334 try: |
334 try: |
335 r, rest = parseLine(cmd, _inner, [], True, comment) |
335 r, rest = parseLine(cmd, _inner, [], True, comment) |
336 if rest: raise SyntaxError(cmd) |
336 if rest: raise SyntaxError(cmd) |
337 except SyntaxError: |
337 except SyntaxError: |
338 if included: |
338 if included: |
339 raise SyntaxError(u"in " + included + u":" + u(line) + u": syntax error in executing command: " + cmd.strip()) |
339 raise SyntaxError("in " + included + ":" + u(line) + ": syntax error in executing command: " + cmd.strip()) |
340 else: |
340 else: |
341 raise SyntaxError(u"in " + u(line) + u": syntax error in executing command: " + cmd.strip()) |
341 raise SyntaxError("in " + u(line) + ": syntax error in executing command: " + cmd.strip()) |
342 inner = _finish(r) |
342 inner = _finish(r) |
343 result += head + inner |
343 result += head + inner |
344 m = re.search(bq, text) |
344 m = re.search(bq, text) |
345 result += textOut(text) |
345 result += textOut(text) |
346 |
346 |
420 yf.addValue(parmName, value) |
420 yf.addValue(parmName, value) |
421 if parmName[0] == "*": |
421 if parmName[0] == "*": |
422 yf.pointers[parmName[1:]] = value |
422 yf.pointers[parmName[1:]] = value |
423 yf.addParm(parmName) |
423 yf.addParm(parmName) |
424 elif parmName[0] == "%": |
424 elif parmName[0] == "%": |
425 if type(value) is unicode or type(value) is str: |
425 if type(value) is str: |
426 yf.macros[parmName] = u(evalPython(value)) |
426 yf.macros[parmName] = u(evalPython(value)) |
427 else: |
427 else: |
428 yf.macros[parmName] = u(evalPython(u(value))) |
428 yf.macros[parmName] = u(evalPython(u(value))) |
429 yf.addParm(parmName) |
429 yf.addParm(parmName) |
430 elif data[0] == "alias": |
430 elif data[0] == "alias": |
431 if in_ns: |
431 if in_ns: |
432 yf.alias = in_ns + u":" + data[1][0] |
432 yf.alias = in_ns + ":" + data[1][0] |
433 else: |
433 else: |
434 yf.alias = data[1][0] |
434 yf.alias = data[1][0] |
435 elif data[0] == "content": |
435 elif data[0] == "content": |
436 yf.content = data[1] |
436 yf.content = data[1] |
437 |
437 |
438 return code(u"") |
438 return code("") |
439 |
439 |
440 elif ctype == "funclist": |
440 elif ctype == "funclist": |
441 result = u"" |
441 result = "" |
442 for f in obj[1]: |
442 for f in obj[1]: |
443 result += codegen(f) |
443 result += codegen(f) |
444 return code(result) |
444 return code(result) |
445 |
445 |
446 elif ctype == "parentheses": |
446 elif ctype == "parentheses": |
447 if len(obj[1]): |
447 if len(obj[1]): |
448 return codegen(('func', ['_parentheses', ('content', [obj[1][0]])])) |
448 return codegen(('func', ['_parentheses', ('content', [obj[1][0]])])) |
449 else: |
449 else: |
450 return u"" |
450 return "" |
451 |
451 |
452 elif ctype == "fparm": |
452 elif ctype == "fparm": |
453 if len(obj[1]): |
453 if len(obj[1]): |
454 return codegen(('func', ['_parm', ('content', [obj[1][0]])])) |
454 return codegen(('func', ['_parm', ('content', [obj[1][0]])])) |
455 else: |
455 else: |
456 return u"" |
456 return "" |
457 |
457 |
458 elif ctype == "generic": |
458 elif ctype == "generic": |
459 return codegen(('func', ['_generic', ('content', [obj[1][0]])])) |
459 return codegen(('func', ['_generic', ('content', [obj[1][0]])])) |
460 |
460 |
461 elif ctype == "xbase": |
461 elif ctype == "xbase": |
645 r, x = parseLine(cmd, _inner, [], True, comment) |
645 r, x = parseLine(cmd, _inner, [], True, comment) |
646 if x: raise SyntaxError(cmd) |
646 if x: raise SyntaxError(cmd) |
647 result += _finish(r) |
647 result += _finish(r) |
648 except SyntaxError: |
648 except SyntaxError: |
649 if included: |
649 if included: |
650 raise SyntaxError(u"in " + included + u":" + u(line) + u": syntax error in executing command: " + cmd.strip()) |
650 raise SyntaxError("in " + included + ":" + u(line) + ": syntax error in executing command: " + cmd.strip()) |
651 else: |
651 else: |
652 raise SyntaxError(u"in " + u(line) + u": syntax error in executing command: " + cmd.strip()) |
652 raise SyntaxError("in " + u(line) + ": syntax error in executing command: " + cmd.strip()) |
653 else: |
653 else: |
654 if result != u'': result += u' ' |
654 if result != '': result += ' ' |
655 result += codegen(Symbol(u'quote', [u'> ' + l[space:]])) |
655 result += codegen(Symbol('quote', ['> ' + l[space:]])) |
656 return code(result) |
656 return code(result) |
657 |
657 |
658 elif ctype == "lineQuote" or ctype == "quote": |
658 elif ctype == "lineQuote" or ctype == "quote": |
659 m, text, base, inds = None, u"", 0, 0 |
659 m, text, base, inds = None, "", 0, 0 |
660 |
660 |
661 if ctype == "lineQuote": |
661 if ctype == "lineQuote": |
662 text = obj[1] |
662 text = obj[1] |
663 m = lq.match(text) |
663 m = lq.match(text) |
664 if m: |
664 if m: |
778 |
778 |
779 elif ctype == "pythonCall": |
779 elif ctype == "pythonCall": |
780 parms = [] |
780 parms = [] |
781 data = obj[1] |
781 data = obj[1] |
782 for p in data: |
782 for p in data: |
783 if type(p) is unicode or type(p) is str: |
783 if type(p) is str: |
784 name = p |
784 name = p |
785 elif type(p) is tuple or type(p) is Symbol: |
785 elif type(p) is tuple or type(p) is Symbol: |
786 ptype = p[0] |
786 ptype = p[0] |
787 if ptype == "parm": |
787 if ptype == "parm": |
788 if p[1][0][0] == "*": |
788 if p[1][0][0] == "*": |
789 parms.append(pointer(p[1][0])) |
789 parms.append(pointer(p[1][0])) |
790 else: |
790 else: |
791 parms.append(p[1][0]) |
791 parms.append(p[1][0]) |
792 if len(parms) == 0: |
792 if len(parms) == 0: |
793 exp = name + u"()" |
793 exp = name + "()" |
794 elif len(parms) == 1: |
794 elif len(parms) == 1: |
795 exp = name + u"(" + u(parms[0]) + u")" |
795 exp = name + "(" + u(parms[0]) + ")" |
796 else: |
796 else: |
797 exp = name + u(tuple(parms)) |
797 exp = name + u(tuple(parms)) |
798 cmd = evalPython(exp) |
798 cmd = evalPython(exp) |
799 result, rest = parseLine(u(cmd), _inner, [], True, comment) |
799 result, rest = parseLine(u(cmd), _inner, [], True, comment) |
800 if rest: |
800 if rest: |
801 raise SyntaxError() |
801 raise SyntaxError() |
802 return code(_finish(result)) |
802 return code(_finish(result)) |
803 |
803 |
804 else: |
804 else: |
805 return code(u"") |
805 return code("") |
806 |
806 |
807 def _finish(tree): |
807 def _finish(tree): |
808 result = u"" |
808 result = "" |
809 python = u"" |
809 python = "" |
810 |
810 |
811 for el in tree: |
811 for el in tree: |
812 if el[0] == "python": |
812 if el[0] == "python": |
813 if el[1][0][:2] == "!!": |
813 if el[1][0][:2] == "!!": |
814 python += el[1][0][2:-2] |
814 python += el[1][0][2:-2] |
815 else: |
815 else: |
816 python += el[1][0][1:] + u"\n" |
816 python += el[1][0][1:] + "\n" |
817 continue |
817 continue |
818 else: |
818 else: |
819 if python: |
819 if python: |
820 execPython(python) |
820 execPython(python) |
821 python = u"" |
821 python = "" |
822 |
822 |
823 try: |
823 try: |
824 result += codegen(el) |
824 result += codegen(el) |
825 except RuntimeError: |
825 except RuntimeError: |
826 if included: |
826 if included: |
827 raise RuntimeError(u"in " + included + u":" + u(line)) |
827 raise RuntimeError("in " + included + ":" + u(line)) |
828 else: |
828 else: |
829 raise RuntimeError(u"in " + u(line)) |
829 raise RuntimeError("in " + u(line)) |
830 |
830 |
831 if python: |
831 if python: |
832 execPython(python) |
832 execPython(python) |
833 |
833 |
834 return result |
834 return result |