| """Check for errs in the AST. | |
| The Python parser does not catch all syntax errors. Others, like | |
| assignments with invalid targets, are caught in the code generation | |
| phase. | |
| The compiler package catches some errors in the transformer module. | |
| But it seems clearer to write checkers that use the AST to detect | |
| errors. | |
| """ | |
| from compiler import ast, walk | |
| def check(tree, multi=None): | |
| v = SyntaxErrorChecker(multi) | |
| walk(tree, v) | |
| return v.errors | |
| class SyntaxErrorChecker: | |
| """A visitor to find syntax errors in the AST.""" | |
| def __init__(self, multi=None): | |
| """Create new visitor object. | |
| If optional argument multi is not None, then print messages | |
| for each error rather than raising a SyntaxError for the | |
| first. | |
| """ | |
| self.multi = multi | |
| self.errors = 0 | |
| def error(self, node, msg): | |
| self.errors = self.errors + 1 | |
| if self.multi is not None: | |
| print "%s:%s: %s" % (node.filename, node.lineno, msg) | |
| else: | |
| raise SyntaxError, "%s (%s:%s)" % (msg, node.filename, node.lineno) | |
| def visitAssign(self, node): | |
| # the transformer module handles many of these | |
| pass | |
| ## for target in node.nodes: | |
| ## if isinstance(target, ast.AssList): | |
| ## if target.lineno is None: | |
| ## target.lineno = node.lineno | |
| ## self.error(target, "can't assign to list comprehension") |