>b's YML 2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

849 lines
28 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
3 years ago
5 years ago
5 years ago
2 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. # 2.7.0 backend
  2. # written by VB.
  3. import re, codecs
  4. import fileinput
  5. import sys, traceback, os
  6. from xml.sax.saxutils import escape, quoteattr
  7. from copy import copy, deepcopy
  8. from glob import glob
  9. from .pyPEG import code, parse, parseLine, u, Symbol
  10. from .grammar import ymlCStyle, comment, _inner
  11. ymlFunc, pointers, pythonFunc = {}, {}, {}
  12. in_ns = ""
  13. operator = []
  14. included = ""
  15. includePath = []
  16. emitlinenumbers = False
  17. encoding = "utf-8"
  18. first = True
  19. enable_tracing = False
  20. ymlFunc["decl"] = "#error"
  21. ymlFunc["define"] = "#error"
  22. ymlFunc["operator"] = "#error"
  23. def clearAll():
  24. global ymlFunc, pointers, pythonFunc, in_ns, operator, included
  25. ymlFunc, pointers, pythonFunc = {}, {}, {}
  26. in_ns = ""
  27. operator = []
  28. included = ""
  29. lq = re.compile(r"\|(\>*)(.*)")
  30. sq = re.compile(r"(\d*)\>(.*)")
  31. ts = re.compile(r'(\|\|(?P<inds>\>*)\s*\n(?P<text1>.*?)\n(?P<base>\s*)\|\|)|("""(?P<text2>.*?)""")|(\>\>(?P<text3>.*?)\>\>)', re.S)
  32. tq = re.compile(r"(\]|\<)\s*(.*)")
  33. bq = re.compile(r"\`(.*?)\`", re.S)
  34. bqq = re.compile(r"\s*\`\`(.*)")
  35. all = re.compile(r".*", re.S)
  36. line = 1
  37. def pointer(name):
  38. try:
  39. return u(pointers[name[1:]])
  40. except:
  41. if name == "*_trace_info":
  42. return '""'
  43. if included:
  44. raise LookupError("in " + included + ":" + u(line) + ": pointer " + name)
  45. else:
  46. raise LookupError("in " + u(line) + ": pointer " + name)
  47. def evalPython(expr):
  48. try:
  49. result = eval(u(expr), pythonFunc)
  50. if type(result) is bytes:
  51. return codecs.decode(result, encoding)
  52. else:
  53. return result
  54. except:
  55. name, parm, tb = sys.exc_info()
  56. msg = "in python expression: " + u(parm)
  57. if name is SyntaxError:
  58. tbl = traceback.format_exception(name, parm, tb)
  59. msg += "\n" + tbl[-3] + tbl[-2]
  60. else:
  61. msg += ": " + expr + "\n"
  62. if included:
  63. raise name("in " + included + ":" + u(line) + ": " + msg)
  64. else:
  65. raise name("in " + u(line) + ": " + msg)
  66. def execPython(script):
  67. try:
  68. if type(script) is str:
  69. exec(script, pythonFunc)
  70. else:
  71. exec(codecs.decode(script, encoding), pythonFunc)
  72. except:
  73. name, parm, tb = sys.exc_info()
  74. msg = "in python script: " + u(parm)
  75. if name is SyntaxError:
  76. tbl = traceback.format_exception(name, parm, tb)
  77. msg += "\n" + tbl[-3] + tbl[-2]
  78. else:
  79. msg += ": " + expr + "\n"
  80. if included:
  81. raise name("in " + included + ":" + u(line) + ": " + msg)
  82. else:
  83. raise name("in " + u(line) + ": " + msg)
  84. def textOut(text):
  85. if not text:
  86. return ""
  87. if type(text) is not str:
  88. text = codecs.decode(text, encoding)
  89. text = text.replace(r'\"', r'\\"')
  90. text = '"""' + text.replace('"', r'\"') + '"""'
  91. try:
  92. textFunc = ymlFunc["text"]
  93. parms = ['text', ('parm', [text])]
  94. c, result = textFunc(parms)
  95. if c:
  96. if type(textFunc.alias) is str:
  97. result += "</" + textFunc.alias + ">"
  98. else:
  99. result += "</" + codecs.decode(textFunc.alias, encoding) + ">"
  100. return result
  101. except:
  102. return escape(eval(text))
  103. def strRepl(text):
  104. if not text:
  105. return ""
  106. if type(text) is not str:
  107. text = codecs.decode(text, encoding)
  108. text = text.replace(r'\"', r'\\"')
  109. text = '"""' + text.replace('"', r'\"') + '"""'
  110. if type(text) is str:
  111. return escape(eval(text))
  112. def applyMacros(macros, text):
  113. result = text
  114. for key, value in macros.items():
  115. result = result.replace(key, value)
  116. return result
  117. class YF:
  118. def __init__(self, name):
  119. self.name = name
  120. self.parms = []
  121. self.descends = []
  122. self.values = {}
  123. self.content = None
  124. self.pointers = {}
  125. self.macros = {}
  126. if in_ns:
  127. self.alias = in_ns + ":" + name.replace("_", "-")
  128. else:
  129. self.alias = name.replace("_", "-")
  130. pythonFunc["yml_" + name] = self
  131. if emitlinenumbers:
  132. self.values["yml:declared"] = u(line)
  133. def copy(self, newName):
  134. yf = YF(newName)
  135. yf.parms.extend(self.parms)
  136. yf.descends.extend(self.descends)
  137. yf.values = self.values.copy()
  138. yf.content = self.content
  139. yf.pointers = self.pointers.copy()
  140. yf.macros = self.macros.copy()
  141. yf.alias = self.alias
  142. return yf
  143. def patch(self, second):
  144. self.parms.extend(second.parms)
  145. self.descends.extend(second.descends)
  146. self.values.update(second.values)
  147. if second.content:
  148. self.content = second.content
  149. self.pointers.update(second.pointers)
  150. self.macros.update(second.macros)
  151. def __call__(self, called_with, hasContent = False, avoidTag = False):
  152. global pointers
  153. parms = []
  154. vals = {}
  155. if self.pointers:
  156. pointers.update(self.pointers)
  157. for data in called_with:
  158. if type(data) is tuple or type(data) is Symbol:
  159. if data[0] == "parm":
  160. l = data[1]
  161. parm = l[0]
  162. if parm[0] == "*":
  163. parm = pointer(parm)
  164. if len(l) == 1:
  165. if type(parm) is tuple or type(parm) is Symbol:
  166. if parm[0] == "pyExp":
  167. val = evalPython(parm[1][0])
  168. parms.append(val)
  169. else:
  170. parms.append(evalPython((parm)))
  171. else:
  172. if type(parm) is tuple or type(parm) is Symbol:
  173. if parm[0] == "pyExp":
  174. parm = evalPython(parm[1][0])
  175. val = l[1]
  176. if type(val) is tuple or type(val) is Symbol:
  177. if val[0] == "pyExp":
  178. val = evalPython(val[1][0])
  179. if val[0] == "*":
  180. val = pointer(val)
  181. if u(val)[0] == '"' or u(val)[0] == "'":
  182. vals[parm] = evalPython(u(val))
  183. else:
  184. vals[parm] = u(val)
  185. elif data[0] == "content":
  186. hasContent = True
  187. if enable_tracing:
  188. text = u(parms) + ", " + u(vals)
  189. pointers["_trace_info"] = '"' + u(line) + ": " + u(self.name) + " " + text.replace('"', '#') + '"'
  190. if emitlinenumbers:
  191. global first
  192. if first:
  193. vals["xmlns:yml"] = "http://fdik.org/yml"
  194. first = False
  195. vals["yml:called"] = u(line)
  196. return self.xml(parms, vals, hasContent, avoidTag)
  197. def addParm(self, parm):
  198. if parm[0] == "%":
  199. for i in range(len(self.parms)):
  200. if self.parms[i][0] != "%":
  201. self.parms.insert(i, parm)
  202. return
  203. self.parms.append(parm)
  204. def addDescend(self, desc):
  205. if desc[0] == "+" or desc[0] == "@":
  206. self.descends.append(desc[1:])
  207. else:
  208. self.descends.append(desc)
  209. def addValue(self, parm, value):
  210. if type(value) is str or type(value) is str:
  211. if value[0] != "'" and value[0] != '"':
  212. self.values[parm] = u(value)
  213. else:
  214. self.values[parm] = u(evalPython(value))
  215. else:
  216. self.values[parm] = u(evalPython(u(value)))
  217. def xml(self, callParms, callValues, hasContent, avoidTag = False):
  218. global pointers
  219. extraContent = ""
  220. if self.content:
  221. hasContent = True
  222. resultParms = self.values.copy()
  223. macros = self.macros.copy()
  224. toDelete = [ key for key in resultParms.keys() ]
  225. for key in toDelete:
  226. if key[0] == "*":
  227. del resultParms[key]
  228. for key, value in callValues.items():
  229. if key[0] == "%":
  230. macros[key] = value
  231. else:
  232. resultParms[key] = value
  233. i = 0
  234. for cp in callParms:
  235. if i < len(self.parms):
  236. if self.parms[i][0] == "*":
  237. cp = u(cp)
  238. if "'" in cp:
  239. pointers[self.parms[i][1:]] = '"' + cp + '"'
  240. else:
  241. pointers[self.parms[i][1:]] = "'" + cp + "'"
  242. elif self.parms[i][0] == "%":
  243. macros[self.parms[i]] = u(cp)
  244. else:
  245. resultParms[self.parms[i]] = cp
  246. else:
  247. extraContent += u(cp)
  248. hasContent = True
  249. i += 1
  250. result = ""
  251. for p, v in resultParms.items():
  252. if p[0] == "'" or p[0] == '"':
  253. p = eval(p)
  254. result += " "+ p + "=" + quoteattr(applyMacros(macros, u(v)))
  255. if hasContent:
  256. if avoidTag:
  257. return True, strRepl(extraContent)
  258. else:
  259. return True, "<" + self.alias + result + ">" + strRepl(extraContent)
  260. else:
  261. if avoidTag:
  262. return False, ""
  263. else:
  264. return False, "<" + self.alias + result + "/>"
  265. def replaceContent(tree, subtree):
  266. n = 0
  267. while n < len(tree):
  268. obj = tree[n]
  269. if obj[0] == "func":
  270. l = obj[1]
  271. if l[0] == "content":
  272. d = 1
  273. if subtree:
  274. for el in subtree:
  275. tree.insert(n+d, el)
  276. d += 1
  277. del tree[n]
  278. n += d
  279. else:
  280. try:
  281. if l[-1][0] == "content":
  282. replaceContent(l[-1][1], subtree)
  283. except: pass
  284. elif obj[0] == "funclist":
  285. replaceContent(obj[1], subtree)
  286. n += 1
  287. return tree
  288. def executeCmd(text):
  289. if type(text) is not str:
  290. text = codecs.decode(text, encoding)
  291. for (regex, pattern) in operator:
  292. match = re.search(regex, text)
  293. while match:
  294. cmd = pattern
  295. opt = match.groups()
  296. for i in range(len(opt)):
  297. cmd = cmd.replace("%" + u(i+1), opt[i])
  298. text = text[:match.start()] + "`" + cmd + "`"+ text[match.end():]
  299. match = re.search(regex, text)
  300. result = ""
  301. m = re.search(bq, text)
  302. while text and m:
  303. cmd = m.group(1)
  304. head = textOut(text[:m.start()])
  305. text = text[m.end():]
  306. try:
  307. r, rest = parseLine(cmd, _inner, [], True, comment)
  308. if rest: raise SyntaxError(cmd)
  309. except SyntaxError:
  310. if included:
  311. raise SyntaxError("in " + included + ":" + u(line) + ": syntax error in executing command: " + cmd.strip())
  312. else:
  313. raise SyntaxError("in " + u(line) + ": syntax error in executing command: " + cmd.strip())
  314. inner = _finish(r)
  315. result += head + inner
  316. m = re.search(bq, text)
  317. result += textOut(text)
  318. return result
  319. def codegen(obj):
  320. global in_ns, pointers, line, included
  321. ctype = obj[0]
  322. if type(obj) is code:
  323. return obj
  324. try:
  325. if ctype.line: line = ctype.line
  326. except: pass
  327. if ctype == "empty":
  328. return code("")
  329. if ctype == "in_ns":
  330. in_ns = obj[1][0]
  331. subtree = obj[1]
  332. for sel in subtree:
  333. codegen(sel)
  334. in_ns = ""
  335. return code("")
  336. elif ctype == "decl":
  337. name = ""
  338. for data in obj[1]:
  339. if type(data) is str:
  340. name = data
  341. try:
  342. yf = ymlFunc[name]
  343. yf.alias
  344. except:
  345. ymlFunc[name] = YF(name)
  346. yf = ymlFunc[name]
  347. if in_ns:
  348. yf.alias = in_ns + ":" + name
  349. if not enable_tracing:
  350. if in_ns == "xsl" and (name == "debug" or name=="assert" or name[:7]=="_trace_"):
  351. yf.alias = "-"
  352. yf.addParm("skip1")
  353. yf.addParm("skip2")
  354. break
  355. elif type(data) is tuple or type(data) is Symbol:
  356. if data[0] == "base":
  357. base = data[1][0]
  358. try:
  359. yf = ymlFunc[name] = ymlFunc[base].copy(name)
  360. except KeyError:
  361. if included:
  362. raise KeyError("in " + included + ":" + u(line) + ": " + base + " as base for " + name)
  363. else:
  364. raise KeyError("in " + u(line) + ": " + base + " as base for " + name)
  365. elif data[0] == "shape":
  366. shape = ymlFunc[data[1]]
  367. try:
  368. yf = ymlFunc[name]
  369. yf.patch(shape)
  370. except KeyError:
  371. if included:
  372. raise KeyError("in " + included + ":" + u(line) + ": " + base + " as shape for " + name)
  373. else:
  374. raise KeyError("in " + u(line) + ": " + base + " as shape for " + name)
  375. elif data[0] == "descend":
  376. yf.addDescend(data[1])
  377. elif data[0] == "declParm":
  378. l = data[1]
  379. parmName = l[0]
  380. if len(l)==1:
  381. yf.addParm(parmName)
  382. else:
  383. value = l[1]
  384. if parmName[0] != "%":
  385. yf.addValue(parmName, value)
  386. if parmName[0] == "*":
  387. yf.pointers[parmName[1:]] = value
  388. yf.addParm(parmName)
  389. elif parmName[0] == "%":
  390. if type(value) is str:
  391. yf.macros[parmName] = u(evalPython(value))
  392. else:
  393. yf.macros[parmName] = u(evalPython(u(value)))
  394. yf.addParm(parmName)
  395. elif data[0] == "alias":
  396. if in_ns:
  397. yf.alias = in_ns + ":" + data[1][0]
  398. else:
  399. yf.alias = data[1][0]
  400. elif data[0] == "content":
  401. yf.content = data[1]
  402. return code("")
  403. elif ctype == "funclist":
  404. result = ""
  405. for f in obj[1]:
  406. result += codegen(f)
  407. return code(result)
  408. elif ctype == "parentheses":
  409. if len(obj[1]):
  410. return codegen(('func', ['_parentheses', ('content', [obj[1][0]])]))
  411. else:
  412. return ""
  413. elif ctype == "fparm":
  414. if len(obj[1]):
  415. return codegen(('func', ['_parm', ('content', [obj[1][0]])]))
  416. else:
  417. return ""
  418. elif ctype == "generic":
  419. return codegen(('func', ['_generic', ('content', [obj[1][0]])]))
  420. elif ctype == "xbase":
  421. return codegen(('func', ['_base', ('content', [obj[1][0]])]))
  422. elif ctype == "func":
  423. avoidTag = False
  424. name = obj[1][0]
  425. if name == "decl":
  426. if ymlFunc[name] == "#error":
  427. if included:
  428. raise SyntaxError("in " + included + ":" + u(line) + ": syntax error in decl statement")
  429. else:
  430. raise SyntaxError("in " + u(line) + ": syntax error in decl statement")
  431. if name == "define" or name == "operator":
  432. if ymlFunc[name] == "#error":
  433. if included:
  434. raise SyntaxError("in " + included + ":" + u(line) + ": syntax error in define statement")
  435. else:
  436. raise SyntaxError("in " + u(line) + ": syntax error in define statement")
  437. if name[0] == "&":
  438. avoidTag = True
  439. name = name[1:]
  440. hasContent = False
  441. if len(name) > 2:
  442. if name[0:2] == "**":
  443. return code(eval(''+pointer(name[1:])))
  444. if name[0] == "*":
  445. name = eval(pointer(name))
  446. if name[0] == "&":
  447. avoidTag = True
  448. name = name[1:]
  449. try:
  450. ymlFunc[name]
  451. except KeyError:
  452. try:
  453. if ymlFunc["_"].alias != "-":
  454. return codegen(('func', ['_', ('content', [('funclist', [obj])])]))
  455. else:
  456. ymlFunc[name] = copy(ymlFunc["_"])
  457. ymlFunc[name].alias = name.replace("_", "-")
  458. return codegen(obj)
  459. except KeyError:
  460. ymlFunc[name] = YF(name)
  461. if ymlFunc[name].alias == "-": avoidTag = True
  462. to_add = []
  463. if len(ymlFunc[name].descends):
  464. if obj[1][-1][0] != 'content':
  465. if included:
  466. raise KeyError("in " + included + ":" + u(line) + ": " + name + " has descending attributes, but no descendants are following")
  467. else:
  468. raise KeyError("in " + u(line) + ": " + name + " has descending attributes, but no descendants are following")
  469. def first_func(obj):
  470. if type(obj) is tuple or type(obj) is Symbol:
  471. if obj[0] == 'func':
  472. return obj
  473. elif obj[0] == 'funclist':
  474. return first_func(obj[1])
  475. elif obj[0] == 'content':
  476. return first_func(obj[1])
  477. else:
  478. return None
  479. elif type(obj) == list:
  480. for e in obj:
  481. f = first_func(e)
  482. if f: return f
  483. return None
  484. def copy_without_first_func(o, found = False):
  485. c = []
  486. for obj in o:
  487. if found:
  488. c.append(obj)
  489. else:
  490. if obj[0] == 'func':
  491. if obj[1][-1][0] == 'content':
  492. c.extend( obj[1][-1][1] )
  493. found = True
  494. else:
  495. c.append( ( obj[0], copy_without_first_func(obj[1], False ) ) )
  496. return c
  497. def get_parms(obj):
  498. result = []
  499. for e in obj[1]:
  500. if type(e) is tuple or type(e) is Symbol:
  501. if e[0] == "parm":
  502. result.append( e )
  503. return result
  504. try:
  505. add_params = get_parms(obj)
  506. for e in obj[1][-1][1]:
  507. c = e[1]
  508. for dname in ymlFunc[name].descends:
  509. f, c = first_func(c), copy_without_first_func(c)
  510. if dname[0] == "*":
  511. pointers[dname[1:]] = "'" + f[1][0] + "'"
  512. else:
  513. add_params.append( ('parm', [dname, "'" + f[1][0] + "'"]) )
  514. try:
  515. add_params.extend( get_parms(f) )
  516. except: pass
  517. new_things = [ e[1][0] ]
  518. new_things.extend( add_params )
  519. new_things.append( ('content', c) )
  520. to_add.append( ('func', new_things ) )
  521. except:
  522. if included:
  523. raise KeyError("in " + included + ":" + u(line) + ": " + name + " has descending attributes, and too less descendants are following")
  524. else:
  525. raise KeyError("in " + u(line) + ": " + name + " has descending attributes, and too less descendants are following")
  526. if not to_add:
  527. to_add = ( obj, )
  528. complete = ""
  529. for obj in to_add:
  530. subtree = None
  531. try:
  532. if obj[1][-1][0] == "content":
  533. subtree = obj[1][-1][1]
  534. except: pass
  535. if ymlFunc[name].content:
  536. hasContent = True
  537. treetemplate = deepcopy(ymlFunc[name].content)
  538. subtree = replaceContent(treetemplate, subtree)
  539. if subtree:
  540. hasContent = True
  541. hasContent, result = ymlFunc[name](obj[1], hasContent, avoidTag)
  542. if subtree:
  543. for sel in subtree:
  544. result += codegen(sel)
  545. if hasContent and not(avoidTag):
  546. result += "</" + ymlFunc[name].alias + ">"
  547. complete += result
  548. return code(complete)
  549. elif ctype == "textsection":
  550. result = ''
  551. ll = obj[1].splitlines()
  552. space = len(ll[-1]) - 2
  553. for l in ll[1:-1]:
  554. m = re.match(bqq, l)
  555. if m:
  556. cmd = m.group(1)
  557. try:
  558. r, x = parseLine(cmd, _inner, [], True, comment)
  559. if x: raise SyntaxError(cmd)
  560. result += _finish(r)
  561. except SyntaxError:
  562. if included:
  563. raise SyntaxError("in " + included + ":" + u(line) + ": syntax error in executing command: " + cmd.strip())
  564. else:
  565. raise SyntaxError("in " + u(line) + ": syntax error in executing command: " + cmd.strip())
  566. else:
  567. result += codegen(Symbol('lineQuote', '| ' + l[space:]))
  568. return code(result)
  569. elif ctype == "textsectionu":
  570. result = ''
  571. ll = obj[1].splitlines()
  572. space = len(ll[-1]) - 2
  573. for l in ll[1:-1]:
  574. m = re.match(bqq, l)
  575. if m:
  576. cmd = m.group(1)
  577. try:
  578. r, x = parseLine(cmd, _inner, [], True, comment)
  579. if x: raise SyntaxError(cmd)
  580. result += _finish(r)
  581. except SyntaxError:
  582. if included:
  583. raise SyntaxError("in " + included + ":" + u(line) + ": syntax error in executing command: " + cmd.strip())
  584. else:
  585. raise SyntaxError("in " + u(line) + ": syntax error in executing command: " + cmd.strip())
  586. else:
  587. if result != '': result += ' '
  588. result += codegen(Symbol('quote', ['> ' + l[space:]]))
  589. return code(result)
  590. elif ctype == "lineQuote" or ctype == "quote":
  591. m, text, base, inds = None, "", 0, 0
  592. if ctype == "lineQuote":
  593. text = obj[1]
  594. m = lq.match(text)
  595. if m:
  596. inds = len(m.group(1))
  597. text = m.group(2)[1:]
  598. else: inds = 0
  599. elif ctype == "quote":
  600. inds = -1
  601. text = obj[1][0]
  602. m = sq.match(text)
  603. if m:
  604. if m.group(1):
  605. inds = int(m.group(1))
  606. text = m.group(2)[1:]
  607. else:
  608. if type(text) is str:
  609. text = u(evalPython(text))
  610. ind = ""
  611. if inds > -1:
  612. try:
  613. cmd = evalPython("indent(" + u(inds) + ")")
  614. result, rest = parseLine(u(cmd), _inner, [], True, comment)
  615. if rest:
  616. raise SyntaxError()
  617. ind = _finish(result)
  618. except: pass
  619. if ctype == "lineQuote": text += "\n"
  620. hasTextFunc = False
  621. try:
  622. ymlFunc["text"]
  623. hasTextFunc = True
  624. except: pass
  625. text = executeCmd(text)
  626. return code(ind + text)
  627. elif ctype == "tagQuote":
  628. m = tq.match(obj[1])
  629. if m.group(1) == "<":
  630. return code("<" + m.group(2))
  631. else:
  632. return code(m.group(2))
  633. elif ctype == "operator":
  634. operator.append((re.compile(evalPython(obj[1][0])), obj[1][1]))
  635. return code("")
  636. elif ctype == "constant":
  637. name = obj[1][0]
  638. if name[0] == "*":
  639. name = name[1:]
  640. value = obj[1][1]
  641. pointers[name] = value
  642. return code("")
  643. elif ctype == "include":
  644. reverse = False
  645. ktext, kxml, kpointer = False, False, False
  646. for arg in obj[1]:
  647. if type(arg) is tuple or type(arg) is Symbol:
  648. if arg[0] == "reverse":
  649. reverse = True
  650. elif arg[0] == "ktext":
  651. ktext = True
  652. elif arg[0] == "kxml":
  653. kxml = True
  654. elif arg[0] == "kpointer":
  655. kpointer = True
  656. elif type(arg) is str:
  657. filemask = arg
  658. if kpointer:
  659. filemask = eval(pointer(filemask))
  660. if filemask[0] == '/' or filemask[0] == '.':
  661. files = sorted(glob(filemask))
  662. else:
  663. files = []
  664. for directory in includePath:
  665. path = os.path.join(directory, filemask)
  666. files.extend(sorted(glob(path)))
  667. if files and reverse:
  668. files = files[-1::-1]
  669. if not(files):
  670. if included:
  671. raise IOError("in " + included + ":" + u(line) + ": include file(s) '" + filemask + "' not found")
  672. else:
  673. raise IOError("in " + u(line) + ": include file(s) '" + filemask + "' not found")
  674. includeFile = fileinput.input(files, mode="rU", openhook=fileinput.hook_encoded(encoding))
  675. _included = included
  676. if ktext or kxml:
  677. text = ""
  678. for line in includeFile:
  679. included = includeFile.filename()
  680. if kxml:
  681. if (not line[:6] == '<?xml ') and (not line[:6] == '<?XML '):
  682. text += line
  683. else:
  684. text += executeCmd(line)
  685. included = _included
  686. return code(text)
  687. else:
  688. result = parse(ymlCStyle(), includeFile, True, comment)
  689. included = u(filemask)
  690. x = _finish(result)
  691. included = _included
  692. return code(x)
  693. elif ctype == "pyExp":
  694. exp = obj[1][0]
  695. cmd = evalPython(exp)
  696. result, rest = parseLine(u(cmd), _inner, [], True, comment)
  697. if rest:
  698. raise SyntaxError(cmd)
  699. return code(_finish(result))
  700. elif ctype == "pythonCall":
  701. parms = []
  702. data = obj[1]
  703. for p in data:
  704. if type(p) is str:
  705. name = p
  706. elif type(p) is tuple or type(p) is Symbol:
  707. ptype = p[0]
  708. if ptype == "parm":
  709. if p[1][0][0] == "*":
  710. parms.append(pointer(p[1][0]))
  711. else:
  712. parms.append(p[1][0])
  713. if len(parms) == 0:
  714. exp = name + "()"
  715. elif len(parms) == 1:
  716. exp = name + "(" + u(parms[0]) + ")"
  717. else:
  718. exp = name + u(tuple(parms))
  719. cmd = evalPython(exp)
  720. result, rest = parseLine(u(cmd), _inner, [], True, comment)
  721. if rest:
  722. raise SyntaxError()
  723. return code(_finish(result))
  724. else:
  725. return code("")
  726. def _finish(tree):
  727. result = ""
  728. python = ""
  729. for el in tree:
  730. if el[0] == "python":
  731. if el[1][0][:2] == "!!":
  732. python += el[1][0][2:-2]
  733. else:
  734. python += el[1][0][1:] + "\n"
  735. continue
  736. else:
  737. if python:
  738. execPython(python)
  739. python = ""
  740. try:
  741. result += codegen(el)
  742. except RuntimeError:
  743. if included:
  744. raise RuntimeError("in " + included + ":" + u(line))
  745. else:
  746. raise RuntimeError("in " + u(line))
  747. if python:
  748. execPython(python)
  749. return result
  750. def finish(tree):
  751. global first
  752. first = True
  753. return _finish(tree)
  754. ymlFunc["_parentheses"] = YF("parms")
  755. ymlFunc["_parm"] = YF("parm")
  756. ymlFunc["_generic"] = YF("generic")
  757. ymlFunc["_base"] = YF("base")