def tagCall(tag, argspec, tcol=None, kwcol=None): t, d = tag.tupargs, tag.dictargs try: return pseudoApply(argspec, t, d, tcol, kwcol) except: raise DTExcept.DTCompileError( tag, 'error parsing arguments: %s\n' 'args are %s, tuple args are %s, dictargs are %s' % (sys.exc_info()[1], argspec, t, d))
def genHandler(text, taglist, start, tagreg, name): '''we got a tag that needs to be parsed''' curTag = taglist[start] tagname = curTag.tagname #get the DTTag object for the current tag try: dttag = tagreg.getTag(tagname) except KeyError, val: #not a valid tagname, barf raise DTExcept.DTCompileError(curTag, 'invalid tag name %s' % tagname)
def checkName(tag, argname, val, ppval=None): """ tag is the tag which we are currently on argname is the tag argument name val is the val after pyifyArg* ppval is optional and is the val before pyifyArg* The reason for ppval is that it is possible for checkname to succeed on a val of `"foo bar"` and `"foo" + foo + "bar"` """ if ppval and ppval[0] == ppval[-1] == '`': raise DTExcept.DTCompileError(tag, ('argument %s is an expression' ' and should be a string') % argname) if len(val) and (val[0] == val[-1] == '"' or val[0] == val[-1] == "'"): return val[1:-1] raise DTExcept.DTCompileError(tag, ('argument %s is an expression and ' 'should be a string') % argname)
def genCode(self, indent, codeout, tagreg, tag): DTCompilerUtil.tagDebug(indent, codeout, tag) pargs = args = DTUtil.tagCall(tag, [('expr', 'None')]) args = DTCompilerUtil.pyifyArgs(tag, args) try: DTCompilerUtil.checkName(tag, 'expr', args['expr'], pargs['expr']) except: pass else: raise DTExcept.DTCompileError(tag, 'cannot call a string') stmt = args['expr'] + '\n' try: compile(stmt, stmt, 'exec') except SyntaxError: raise DTExcept.DTCompileError( tag, 'syntax error in statement "%s"' % stmt) codeout.writemultiline(indent, stmt)
def parseBlock(self, text, taglist, start, tagreg, name): """ should return node, last. This is only called for non-empty tags """ cur = start #create a new node n = DTParser.Node() #get current tag t = taglist[cur] #this is in case they started a block with the close tag (for whatever #reason) if t.isclose: raise DTExcept.DTCompileError(t, 'close tag out of context') #add current tag to the node n.add(t) #while we haven't eaten the taglist while cur < (len(taglist) - 1): cur = cur + 1 curtag = taglist[cur] if type(curtag) == types.StringType: n.add(curtag) else: #if it's our close tag, add it and return if curtag.tagname == self.tagname and curtag.isclose: n.add(curtag) return n, cur #else it's not our tag so we pass it to the generic handler nodeortag, last = DTParser.genHandler(text, taglist, cur, tagreg, name) n.add(nodeortag) cur = last raise DTExcept.DTCompileError( t, 'unexpected EOF encountered ' 'parsing <:%s:> block' % self.tagname)
def parseBlock(self, text, taglist, start, tagreg, name): cur = start n = DTParser.Node() t = taglist[cur] while cur < (len(taglist) - 1): #basically, ignore tokens until we see <:/comment:> cur = cur + 1 curtagl = taglist[cur] if type(curtagl) == types.StringType: pass else: if curtagl.tagname == self.tagname and curtagl.isclose: n.add(curtagl) return n, cur else: pass raise DTExcept.DTCompileError( t, 'unexpected EOF encountered ' 'parsing <:%s:> block' % self.tagname)
def pyifyArgs(tag, args, parenthesize_exprs=0): """convert arguments to an evalable format""" nd = {} for k, v in args.items(): if type(v) == types.StringType: if len(v) > 1 and v[0] == v[-1] == "`": if parenthesize_exprs: nd[k] = "(%s)" % convertToNativeLineEndings(v[1:-1]) else: nd[k] = convertToNativeLineEndings(v[1:-1]) else: nd[k] = repr(v) else: nd[k] = v if type(nd[k]) == types.StringType: try: compile(nd[k] + '\n', nd[k], 'exec') except SyntaxError, val: raise DTExcept.DTCompileError( tag, 'syntax error in argument: %s' % val)
def genHandler(text, taglist, start, tagreg, name): '''we got a tag that needs to be parsed''' curTag = taglist[start] tagname = curTag.tagname #get the DTTag object for the current tag try: dttag = tagreg.getTag(tagname) except KeyError, val: #not a valid tagname, barf raise DTExcept.DTCompileError(curTag, 'invalid tag name %s' % tagname) #if an empty tag (like <:var:>, <:break:>, et. al.) if dttag.isempty: if curTag.isclose: #it's a closing empty tag???? raise DTExcept.DTCompileError( curTag, 'empty close tag??? %s' % curTag.tagname) return curTag, start else: #it's a non-empty tag (like <:if:><:/if:>) #have the DTTag parse it's block return dttag.parseBlock(text, taglist, start, tagreg, name) if __name__ == '__main__': import DTLexer import sys import DTTagRegistry text = open(sys.argv[1]).read() taglist = DTLexer.doTag(text) node = parseit(text, taglist, DTTagRegistry.defaultTagRegistry, None) print '--------------------' print node
def genCode(self, indent, codeout, tagreg, node, meta): tag = node.children[0] # Do the debug DTCompilerUtil.tagDebug(indent, codeout, tag) DTUtil.tagCall(tag, []) oldout = DTCompilerUtil.getTempName() # # First, determine if this is a 'try...finally' form # for i in node.children[1:-1]: if (type(i) == InstanceType and i.__class__ == DTLexer.DTToken and i.tagname in ('finally', )): has_finally = 1 break else: has_finally = 0 if has_finally: # This is a try...finally block codeout.write(indent, 'try:') for i in node.children[1:-1]: if (type(i) == InstanceType and i.__class__ == DTLexer.DTToken and i.tagname in ('else', 'except', 'finally')): if i.tagname in ('else', 'except'): # This is an error raise DTExcept.DTCompileError( i, 'tag %s inside of a try...finally block' % str(i)) else: # i.tagname == 'finally': codeout.write(indent, 'finally:') codeout.write(indent + 4, '__d.FTAG=__d.CURRENT_TAG') codeout.write(indent + 4, '__d.FLINENO=__d.CURRENT_LINENO') DTCompilerUtil.tagDebug(indent + 4, codeout, i) else: DTCompilerUtil.genCodeChild(indent + 4, codeout, tagreg, i, meta) codeout.write(indent + 4, '__d.CURRENT_TAG=__d.FTAG') codeout.write(indent + 4, '__d.CURRENT_LINENO=__d.FLINENO') codeout.write(indent + 4, 'del __d.FTAG, __d.FLINENO') # # Ok, we're done - return # return # # Store a reference to current output object. Basically, if an exception # occurs we kind of rollback to the point before the 'try' block # codeout.write(indent, '%s = __h.OUTPUT' % oldout) codeout.write(indent, '__h.OUTPUT=__h.NEWOUTPUT()') codeout.write(indent, 'try:') waselse = 0 wasexcept = 0 for i in node.children[1:-1]: if (type(i) == InstanceType and i.__class__ == DTLexer.DTToken and i.tagname in ('else', 'except')): if i.tagname == 'except': # Get the arguments for the except clause args = DTUtil.tagCall(i, [('exc', 'None')]) args = DTCompilerUtil.pyifyArgs(tag, args) if args['exc'] != None: codeout.write(indent, 'except %s:' % args['exc']) else: codeout.write(indent, 'except:') # Do the debugging DTCompilerUtil.tagDebug(indent + 4, codeout, i) # Restore the original output codeout.write(indent + 4, '__h.OUTPUT = %s' % oldout) codeout.write(indent + 4, 'del %s' % oldout) wasexcept = 1 else: # i.tagname == 'else': codeout.write(indent, 'else:') DTCompilerUtil.tagDebug(indent + 4, codeout, i) # Print and restore the original output codeout.write(indent + 4, '%s.write(__h.OUTPUT.getvalue())' % oldout) codeout.write(indent + 4, '__h.OUTPUT = %s' % oldout) codeout.write(indent + 4, 'del %s' % oldout) waselse = 1 else: DTCompilerUtil.genCodeChild(indent + 4, codeout, tagreg, i, meta) if not wasexcept: raise DTExcept.DTCompileError(tag, '<:try:> without <:except:>') if not waselse: codeout.write(indent, 'else:') codeout.write(indent + 4, '%s.write(__h.OUTPUT.getvalue())' % oldout) codeout.write(indent + 4, '__h.OUTPUT = %s' % oldout) codeout.write(indent + 4, 'del %s' % oldout)