diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-11-13 14:16:10 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-11-13 14:16:10 -0500 |
commit | 4905370b965f7ccaf866c2cfbf9266e265d66709 (patch) | |
tree | 07dbb65ffa17681b67f8706629694075971653d5 /mako/pyparser.py | |
parent | 6eea95175349e1e2383e74a1157ffbdee5a258d4 (diff) | |
download | external_python_mako-4905370b965f7ccaf866c2cfbf9266e265d66709.tar.gz external_python_mako-4905370b965f7ccaf866c2cfbf9266e265d66709.tar.bz2 external_python_mako-4905370b965f7ccaf866c2cfbf9266e265d66709.zip |
- [ticket:98] for the pyparser module
Diffstat (limited to 'mako/pyparser.py')
-rw-r--r-- | mako/pyparser.py | 297 |
1 files changed, 201 insertions, 96 deletions
diff --git a/mako/pyparser.py b/mako/pyparser.py index d011690..ab9c2b6 100644 --- a/mako/pyparser.py +++ b/mako/pyparser.py @@ -52,35 +52,49 @@ def parse(code, mode='exec', **exception_kwargs): code = code.encode('ascii', 'backslashreplace') return compiler_parse(code, mode) except Exception, e: - raise exceptions.SyntaxException("(%s) %s (%s)" % (e.__class__.__name__, str(e), repr(code[0:50])), **exception_kwargs) + raise exceptions.SyntaxException( + "(%s) %s (%r)" % ( + e.__class__.__name__, + e, + code[0:50] + ), **exception_kwargs) if _ast: class FindIdentifiers(_ast_util.NodeVisitor): + def __init__(self, listener, **exception_kwargs): self.in_function = False self.in_assign_targets = False self.local_ident_stack = {} self.listener = listener self.exception_kwargs = exception_kwargs + def _add_declared(self, name): if not self.in_function: self.listener.declared_identifiers.add(name) + def visit_ClassDef(self, node): self._add_declared(node.name) + def visit_Assign(self, node): - # flip around the visiting of Assign so the expression gets evaluated first, - # in the case of a clause like "x=x+5" (x is undeclared) + + # flip around the visiting of Assign so the expression gets + # evaluated first, in the case of a clause like "x=x+5" (x + # is undeclared) + self.visit(node.value) in_a = self.in_assign_targets self.in_assign_targets = True for n in node.targets: self.visit(n) self.in_assign_targets = in_a - + if util.py3k: - # ExceptHandler is in Python 2, but this - # block only works in Python 3 (and is required there) + + # ExceptHandler is in Python 2, but this block only works in + # Python 3 (and is required there) + def visit_ExceptHandler(self, node): if node.name is not None: self._add_declared(node.name) @@ -88,24 +102,25 @@ if _ast: self.listener.undeclared_identifiers.add(node.type.id) for statement in node.body: self.visit(statement) - + def visit_Lambda(self, node, *args): self._visit_function(node, True) def visit_FunctionDef(self, node): self._add_declared(node.name) self._visit_function(node, False) - + def _visit_function(self, node, islambda): - # push function state onto stack. dont log any - # more identifiers as "declared" until outside of the function, - # but keep logging identifiers as "undeclared". - # track argument names in each function header - # so they arent counted as "undeclared" + + # push function state onto stack. dont log any more + # identifiers as "declared" until outside of the function, + # but keep logging identifiers as "undeclared". track + # argument names in each function header so they arent + # counted as "undeclared" + saved = {} inf = self.in_function self.in_function = True - for arg in node.args.args: if arg_id(arg) in self.local_ident_stack: saved[arg_id(arg)] = True @@ -120,28 +135,33 @@ if _ast: for arg in node.args.args: if arg_id(arg) not in saved: del self.local_ident_stack[arg_id(arg)] - + def visit_For(self, node): + # flip around visit + self.visit(node.iter) self.visit(node.target) for statement in node.body: self.visit(statement) for statement in node.orelse: self.visit(statement) + def visit_Name(self, node): if isinstance(node.ctx, _ast.Store): self._add_declared(node.id) - if node.id not in reserved and \ - node.id not in self.listener.declared_identifiers and \ - node.id not in self.local_ident_stack: + if node.id not in reserved and node.id \ + not in self.listener.declared_identifiers and node.id \ + not in self.local_ident_stack: self.listener.undeclared_identifiers.add(node.id) + def visit_Import(self, node): for name in node.names: if name.asname is not None: self._add_declared(name.asname) else: self._add_declared(name.name.split('.')[0]) + def visit_ImportFrom(self, node): for name in node.names: if name.asname is not None: @@ -149,32 +169,39 @@ if _ast: else: if name.name == '*': raise exceptions.CompileException( - "'import *' is not supported, since all " - "identifier names must be explicitly " - "declared. Please use the form 'from " - "<modulename> import <name1>, " - "<name2>, ...' instead.", - **self.exception_kwargs) + "'import *' is not supported, since all identifier " + "names must be explicitly declared. Please use the " + "form 'from <modulename> import <name1>, <name2>, " + "...' instead.", **self.exception_kwargs) self._add_declared(name.name) + class FindTuple(_ast_util.NodeVisitor): + def __init__(self, listener, code_factory, **exception_kwargs): self.listener = listener self.exception_kwargs = exception_kwargs self.code_factory = code_factory + def visit_Tuple(self, node): for n in node.elts: p = self.code_factory(n, **self.exception_kwargs) self.listener.codeargs.append(p) self.listener.args.append(ExpressionGenerator(n).value()) - self.listener.declared_identifiers = self.listener.declared_identifiers.union(p.declared_identifiers) - self.listener.undeclared_identifiers = self.listener.undeclared_identifiers.union(p.undeclared_identifiers) + self.listener.declared_identifiers = \ + self.listener.declared_identifiers.union( + p.declared_identifiers) + self.listener.undeclared_identifiers = \ + self.listener.undeclared_identifiers.union( + p.undeclared_identifiers) + class ParseFunc(_ast_util.NodeVisitor): + def __init__(self, listener, **exception_kwargs): self.listener = listener self.exception_kwargs = exception_kwargs - + def visit_FunctionDef(self, node): self.listener.funcname = node.name argnames = [arg_id(arg) for arg in node.args.args] @@ -183,47 +210,63 @@ if _ast: if node.args.kwarg: argnames.append(node.args.kwarg) self.listener.argnames = argnames - self.listener.defaults = node.args.defaults # ast + self.listener.defaults = node.args.defaults # ast self.listener.varargs = node.args.vararg self.listener.kwargs = node.args.kwarg + class ExpressionGenerator(object): + def __init__(self, astnode): self.generator = _ast_util.SourceGenerator(' ' * 4) self.generator.visit(astnode) + def value(self): return ''.join(self.generator.result) else: class FindIdentifiers(object): + def __init__(self, listener, **exception_kwargs): self.in_function = False self.local_ident_stack = {} self.listener = listener self.exception_kwargs = exception_kwargs + def _add_declared(self, name): if not self.in_function: self.listener.declared_identifiers.add(name) + def visitClass(self, node, *args): self._add_declared(node.name) + def visitAssName(self, node, *args): self._add_declared(node.name) + def visitAssign(self, node, *args): - # flip around the visiting of Assign so the expression gets evaluated first, - # in the case of a clause like "x=x+5" (x is undeclared) + + # flip around the visiting of Assign so the expression gets + # evaluated first, in the case of a clause like "x=x+5" (x + # is undeclared) + self.visit(node.expr, *args) for n in node.nodes: self.visit(n, *args) + def visitLambda(self, node, *args): self._visit_function(node, args) - def visitFunction(self,node, *args): + + def visitFunction(self, node, *args): self._add_declared(node.name) self._visit_function(node, args) + def _visit_function(self, node, args): - # push function state onto stack. dont log any - # more identifiers as "declared" until outside of the function, - # but keep logging identifiers as "undeclared". - # track argument names in each function header so - # they arent counted as "undeclared" + + # push function state onto stack. dont log any more + # identifiers as "declared" until outside of the function, + # but keep logging identifiers as "undeclared". track + # argument names in each function header so they arent + # counted as "undeclared" + saved = {} inf = self.in_function self.in_function = True @@ -238,191 +281,253 @@ else: for arg in node.argnames: if arg not in saved: del self.local_ident_stack[arg] - + def visitFor(self, node, *args): + # flip around visit + self.visit(node.list, *args) self.visit(node.assign, *args) self.visit(node.body, *args) + def visitName(self, node, *args): - if node.name not in reserved and node.name not in self.listener.declared_identifiers and node.name not in self.local_ident_stack: + if node.name not in reserved and node.name \ + not in self.listener.declared_identifiers and node.name \ + not in self.local_ident_stack: self.listener.undeclared_identifiers.add(node.name) + def visitImport(self, node, *args): - for (mod, alias) in node.names: + for mod, alias in node.names: if alias is not None: self._add_declared(alias) else: self._add_declared(mod.split('.')[0]) + def visitFrom(self, node, *args): - for (mod, alias) in node.names: + for mod, alias in node.names: if alias is not None: self._add_declared(alias) else: if mod == '*': - raise exceptions.CompileException("'import *' is not supported, since all identifier names must be explicitly declared. Please use the form 'from <modulename> import <name1>, <name2>, ...' instead.", **self.exception_kwargs) + raise exceptions.CompileException( + "'import *' is not supported, since all identifier " + "names must be explicitly declared. Please use the " + "form 'from <modulename> import <name1>, <name2>, " + "...' instead.", **self.exception_kwargs) self._add_declared(mod) + def visit(self, expr): - visitor.walk(expr, self) #, walker=walker()) + visitor.walk(expr, self) # , walker=walker()) + class FindTuple(object): + def __init__(self, listener, code_factory, **exception_kwargs): self.listener = listener self.exception_kwargs = exception_kwargs self.code_factory = code_factory + def visitTuple(self, node, *args): for n in node.nodes: p = self.code_factory(n, **self.exception_kwargs) self.listener.codeargs.append(p) self.listener.args.append(ExpressionGenerator(n).value()) - self.listener.declared_identifiers = self.listener.declared_identifiers.union(p.declared_identifiers) - self.listener.undeclared_identifiers = self.listener.undeclared_identifiers.union(p.undeclared_identifiers) + self.listener.declared_identifiers = \ + self.listener.declared_identifiers.union(p.declared_identifiers) + self.listener.undeclared_identifiers = \ + self.listener.undeclared_identifiers.union(p.undeclared_identifiers) + def visit(self, expr): - visitor.walk(expr, self) #, walker=walker()) + visitor.walk(expr, self) # , walker=walker()) + class ParseFunc(object): + def __init__(self, listener, **exception_kwargs): self.listener = listener self.exception_kwargs = exception_kwargs + def visitFunction(self, node, *args): self.listener.funcname = node.name self.listener.argnames = node.argnames self.listener.defaults = node.defaults self.listener.varargs = node.varargs self.listener.kwargs = node.kwargs + def visit(self, expr): visitor.walk(expr, self) + class ExpressionGenerator(object): - """given an AST node, generates an equivalent literal Python expression.""" + + """given an AST node, generates an equivalent literal Python + expression.""" + def __init__(self, astnode): self.buf = StringIO() - visitor.walk(astnode, self) #, walker=walker()) + visitor.walk(astnode, self) # , walker=walker()) + def value(self): - return self.buf.getvalue() + return self.buf.getvalue() + def operator(self, op, node, *args): - self.buf.write("(") + self.buf.write('(') self.visit(node.left, *args) - self.buf.write(" %s " % op) + self.buf.write(' %s ' % op) self.visit(node.right, *args) - self.buf.write(")") + self.buf.write(')') + def booleanop(self, op, node, *args): self.visit(node.nodes[0]) for n in node.nodes[1:]: - self.buf.write(" " + op + " ") + self.buf.write(' ' + op + ' ') self.visit(n, *args) + def visitConst(self, node, *args): self.buf.write(repr(node.value)) + def visitAssName(self, node, *args): + # TODO: figure out OP_ASSIGN, other OP_s + self.buf.write(node.name) + def visitName(self, node, *args): self.buf.write(node.name) + def visitMul(self, node, *args): - self.operator("*", node, *args) + self.operator('*', node, *args) + def visitAnd(self, node, *args): - self.booleanop("and", node, *args) + self.booleanop('and', node, *args) + def visitOr(self, node, *args): - self.booleanop("or", node, *args) + self.booleanop('or', node, *args) + def visitBitand(self, node, *args): - self.booleanop("&", node, *args) + self.booleanop('&', node, *args) + def visitBitor(self, node, *args): - self.booleanop("|", node, *args) + self.booleanop('|', node, *args) + def visitBitxor(self, node, *args): - self.booleanop("^", node, *args) + self.booleanop('^', node, *args) + def visitAdd(self, node, *args): - self.operator("+", node, *args) + self.operator('+', node, *args) + def visitGetattr(self, node, *args): self.visit(node.expr, *args) - self.buf.write(".%s" % node.attrname) + self.buf.write('.%s' % node.attrname) + def visitSub(self, node, *args): - self.operator("-", node, *args) + self.operator('-', node, *args) + def visitNot(self, node, *args): - self.buf.write("not ") + self.buf.write('not ') self.visit(node.expr) + def visitDiv(self, node, *args): - self.operator("/", node, *args) + self.operator('/', node, *args) + def visitFloorDiv(self, node, *args): - self.operator("//", node, *args) + self.operator('//', node, *args) + def visitSubscript(self, node, *args): self.visit(node.expr) - self.buf.write("[") + self.buf.write('[') [self.visit(x) for x in node.subs] - self.buf.write("]") + self.buf.write(']') + def visitUnarySub(self, node, *args): - self.buf.write("-") + self.buf.write('-') self.visit(node.expr) + def visitUnaryAdd(self, node, *args): - self.buf.write("-") + self.buf.write('-') self.visit(node.expr) + def visitSlice(self, node, *args): self.visit(node.expr) - self.buf.write("[") + self.buf.write('[') if node.lower is not None: self.visit(node.lower) - self.buf.write(":") + self.buf.write(':') if node.upper is not None: self.visit(node.upper) - self.buf.write("]") + self.buf.write(']') + def visitDict(self, node): - self.buf.write("{") + self.buf.write('{') c = node.getChildren() for i in range(0, len(c), 2): self.visit(c[i]) - self.buf.write(": ") - self.visit(c[i+1]) - if i<len(c) -2: - self.buf.write(", ") - self.buf.write("}") + self.buf.write(': ') + self.visit(c[i + 1]) + if i < len(c) - 2: + self.buf.write(', ') + self.buf.write('}') + def visitTuple(self, node): - self.buf.write("(") + self.buf.write('(') c = node.getChildren() for i in range(0, len(c)): self.visit(c[i]) - if i<len(c) - 1: - self.buf.write(", ") - self.buf.write(")") + if i < len(c) - 1: + self.buf.write(', ') + self.buf.write(')') + def visitList(self, node): - self.buf.write("[") + self.buf.write('[') c = node.getChildren() for i in range(0, len(c)): self.visit(c[i]) - if i<len(c) - 1: - self.buf.write(", ") - self.buf.write("]") + if i < len(c) - 1: + self.buf.write(', ') + self.buf.write(']') + def visitListComp(self, node): - self.buf.write("[") + self.buf.write('[') self.visit(node.expr) - self.buf.write(" ") + self.buf.write(' ') for n in node.quals: self.visit(n) - self.buf.write("]") + self.buf.write(']') + def visitListCompFor(self, node): - self.buf.write(" for ") + self.buf.write(' for ') self.visit(node.assign) - self.buf.write(" in ") + self.buf.write(' in ') self.visit(node.list) for n in node.ifs: self.visit(n) + def visitListCompIf(self, node): - self.buf.write(" if ") + self.buf.write(' if ') self.visit(node.test) + def visitCompare(self, node): self.visit(node.expr) for tup in node.ops: self.buf.write(tup[0]) self.visit(tup[1]) + def visitCallFunc(self, node, *args): self.visit(node.node) - self.buf.write("(") + self.buf.write('(') if len(node.args): self.visit(node.args[0]) for a in node.args[1:]: - self.buf.write(", ") + self.buf.write(', ') self.visit(a) - self.buf.write(")") + self.buf.write(')') + class walker(visitor.ASTVisitor): + def dispatch(self, node, *args): - print "Node:", str(node) - #print "dir:", dir(node) + print 'Node:', str(node) + + # print "dir:", dir(node) + return visitor.ASTVisitor.dispatch(self, node, *args) |