Fork of yml2 for pypi maintenance
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.

815 lines
27 KiB

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