| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 09392b7 commit 37c9351
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,7 +8,7 @@ | |||
| 8 | 8 | import types | |
| 9 | 9 | from cStringIO import StringIO | |
| 10 | 10 | ||
| 11 | - from compiler import ast, parse, walk | ||
| 11 | + from compiler import ast, parse, walk, syntax | ||
| 12 | 12 | from compiler import pyassem, misc, future, symbols | |
| 13 | 13 | from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL | |
| 14 | 14 | from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\ | |
@@ -41,17 +41,19 @@ def __init__(self): | |||
| 41 | 41 | self.__super_init(self) | |
| 42 | 42 | self.loop = None | |
| 43 | 43 | ||
| 44 | - | ||
| 45 | - | ||
| 46 | 44 | def compile(filename, display=0): | |
| 47 | 45 | f = open(filename) | |
| 48 | 46 | buf = f.read() | |
| 49 | 47 | f.close() | |
| 50 | 48 | mod = Module(buf, filename) | |
| 51 | - mod.compile(display) | ||
| 52 | - f = open(filename + "c", "wb") | ||
| 53 | - mod.dump(f) | ||
| 54 | - f.close() | ||
| 49 | + try: | ||
| 50 | + mod.compile(display) | ||
| 51 | + except SyntaxError, err: | ||
| 52 | + print "SyntaxError:", err | ||
| 53 | + else: | ||
| 54 | + f = open(filename + "c", "wb") | ||
| 55 | + mod.dump(f) | ||
| 56 | + f.close() | ||
| 55 | 57 | ||
| 56 | 58 | class Module: | |
| 57 | 59 | def __init__(self, source, filename): | |
@@ -61,7 +63,9 @@ def __init__(self, source, filename): | |||
| 61 | 63 | ||
| 62 | 64 | def compile(self, display=0): | |
| 63 | 65 | tree = parse(self.source) | |
| 64 | - gen = ModuleCodeGenerator(self.filename, tree) | ||
| 66 | + misc.set_filename(self.filename, tree) | ||
| 67 | + syntax.check(tree) | ||
| 68 | + gen = ModuleCodeGenerator(tree) | ||
| 65 | 69 | if display: | |
| 66 | 70 | import pprint | |
| 67 | 71 | print pprint.pprint(tree) | |
@@ -149,12 +153,11 @@ class CodeGenerator: | |||
| 149 | 153 | __initialized = None | |
| 150 | 154 | class_name = None # provide default for instance variable | |
| 151 | 155 | ||
| 152 | - def __init__(self, filename): | ||
| 156 | + def __init__(self): | ||
| 153 | 157 | if self.__initialized is None: | |
| 154 | 158 | self.initClass() | |
| 155 | 159 | self.__class__.__initialized = 1 | |
| 156 | 160 | self.checkClass() | |
| 157 | - self.filename = filename | ||
| 158 | 161 | self.locals = misc.Stack() | |
| 159 | 162 | self.setups = misc.Stack() | |
| 160 | 163 | self.curStack = 0 | |
@@ -306,7 +309,7 @@ def visitLambda(self, node): | |||
| 306 | 309 | self._visitFuncOrLambda(node, isLambda=1) | |
| 307 | 310 | ||
| 308 | 311 | def _visitFuncOrLambda(self, node, isLambda=0): | |
| 309 | - gen = self.FunctionGen(node, self.filename, self.scopes, isLambda, | ||
| 312 | + gen = self.FunctionGen(node, self.scopes, isLambda, | ||
| 310 | 313 | self.class_name, self.get_module()) | |
| 311 | 314 | walk(node.code, gen) | |
| 312 | 315 | gen.finish() | |
@@ -324,7 +327,7 @@ def _visitFuncOrLambda(self, node, isLambda=0): | |||
| 324 | 327 | self.emit('MAKE_FUNCTION', len(node.defaults)) | |
| 325 | 328 | ||
| 326 | 329 | def visitClass(self, node): | |
| 327 | - gen = self.ClassGen(node, self.filename, self.scopes, | ||
| 330 | + gen = self.ClassGen(node, self.scopes, | ||
| 328 | 331 | self.get_module()) | |
| 329 | 332 | if node.doc: | |
| 330 | 333 | self.emit('LOAD_CONST', node.doc) | |
@@ -430,14 +433,14 @@ def visitFor(self, node): | |||
| 430 | 433 | def visitBreak(self, node): | |
| 431 | 434 | if not self.setups: | |
| 432 | 435 | raise SyntaxError, "'break' outside loop (%s, %d)" % \ | |
| 433 | - (self.filename, node.lineno) | ||
| 436 | + (node.filename, node.lineno) | ||
| 434 | 437 | self.set_lineno(node) | |
| 435 | 438 | self.emit('BREAK_LOOP') | |
| 436 | 439 | ||
| 437 | 440 | def visitContinue(self, node): | |
| 438 | 441 | if not self.setups: | |
| 439 | 442 | raise SyntaxError, "'continue' outside loop (%s, %d)" % \ | |
| 440 | - (self.filename, node.lineno) | ||
| 443 | + (node.filename, node.lineno) | ||
| 441 | 444 | kind, block = self.setups.top() | |
| 442 | 445 | if kind == LOOP: | |
| 443 | 446 | self.set_lineno(node) | |
@@ -454,12 +457,12 @@ def visitContinue(self, node): | |||
| 454 | 457 | break | |
| 455 | 458 | if kind != LOOP: | |
| 456 | 459 | raise SyntaxError, "'continue' outside loop (%s, %d)" % \ | |
| 457 | - (self.filename, node.lineno) | ||
| 460 | + (node.filename, node.lineno) | ||
| 458 | 461 | self.emit('CONTINUE_LOOP', loop_block) | |
| 459 | 462 | self.nextBlock() | |
| 460 | 463 | elif kind == END_FINALLY: | |
| 461 | 464 | msg = "'continue' not allowed inside 'finally' clause (%s, %d)" | |
| 462 | - raise SyntaxError, msg % (self.filename, node.lineno) | ||
| 465 | + raise SyntaxError, msg % (node.filename, node.lineno) | ||
| 463 | 466 | ||
| 464 | 467 | def visitTest(self, node, jump): | |
| 465 | 468 | end = self.newBlock() | |
@@ -1085,10 +1088,10 @@ class ModuleCodeGenerator(NestedScopeMixin, CodeGenerator): | |||
| 1085 | 1088 | ||
| 1086 | 1089 | scopes = None | |
| 1087 | 1090 | ||
| 1088 | - def __init__(self, filename, tree): | ||
| 1089 | - self.graph = pyassem.PyFlowGraph("<module>", filename) | ||
| 1091 | + def __init__(self, tree): | ||
| 1092 | + self.graph = pyassem.PyFlowGraph("<module>", tree.filename) | ||
| 1090 | 1093 | self.futures = future.find_futures(tree) | |
| 1091 | - self.__super_init(filename) | ||
| 1094 | + self.__super_init() | ||
| 1092 | 1095 | walk(tree, self) | |
| 1093 | 1096 | ||
| 1094 | 1097 | def get_module(self): | |
@@ -1098,7 +1101,7 @@ class AbstractFunctionCode: | |||
| 1098 | 1101 | optimized = 1 | |
| 1099 | 1102 | lambdaCount = 0 | |
| 1100 | 1103 | ||
| 1101 | - def __init__(self, func, filename, scopes, isLambda, class_name, mod): | ||
| 1104 | + def __init__(self, func, scopes, isLambda, class_name, mod): | ||
| 1102 | 1105 | self.class_name = class_name | |
| 1103 | 1106 | self.module = mod | |
| 1104 | 1107 | if isLambda: | |
@@ -1108,10 +1111,10 @@ def __init__(self, func, filename, scopes, isLambda, class_name, mod): | |||
| 1108 | 1111 | else: | |
| 1109 | 1112 | name = func.name | |
| 1110 | 1113 | args, hasTupleArg = generateArgList(func.argnames) | |
| 1111 | - self.graph = pyassem.PyFlowGraph(name, filename, args, | ||
| 1114 | + self.graph = pyassem.PyFlowGraph(name, func.filename, args, | ||
| 1112 | 1115 | optimized=1) | |
| 1113 | 1116 | self.isLambda = isLambda | |
| 1114 | - self.super_init(filename) | ||
| 1117 | + self.super_init() | ||
| 1115 | 1118 | ||
| 1116 | 1119 | if not isLambda and func.doc: | |
| 1117 | 1120 | self.setDocstring(func.doc) | |
@@ -1162,10 +1165,10 @@ class FunctionCodeGenerator(NestedScopeMixin, AbstractFunctionCode, | |||
| 1162 | 1165 | ||
| 1163 | 1166 | __super_init = AbstractFunctionCode.__init__ | |
| 1164 | 1167 | ||
| 1165 | - def __init__(self, func, filename, scopes, isLambda, class_name, mod): | ||
| 1168 | + def __init__(self, func, scopes, isLambda, class_name, mod): | ||
| 1166 | 1169 | self.scopes = scopes | |
| 1167 | 1170 | self.scope = scopes[func] | |
| 1168 | - self.__super_init(func, filename, scopes, isLambda, class_name, mod) | ||
| 1171 | + self.__super_init(func, scopes, isLambda, class_name, mod) | ||
| 1169 | 1172 | self.graph.setFreeVars(self.scope.get_free_vars()) | |
| 1170 | 1173 | self.graph.setCellVars(self.scope.get_cell_vars()) | |
| 1171 | 1174 | if self.graph.checkFlag(CO_GENERATOR_ALLOWED): | |
@@ -1174,12 +1177,12 @@ def __init__(self, func, filename, scopes, isLambda, class_name, mod): | |||
| 1174 | 1177 | ||
| 1175 | 1178 | class AbstractClassCode: | |
| 1176 | 1179 | ||
| 1177 | - def __init__(self, klass, filename, scopes, module): | ||
| 1180 | + def __init__(self, klass, scopes, module): | ||
| 1178 | 1181 | self.class_name = klass.name | |
| 1179 | 1182 | self.module = module | |
| 1180 | - self.graph = pyassem.PyFlowGraph(klass.name, filename, | ||
| 1183 | + self.graph = pyassem.PyFlowGraph(klass.name, klass.filename, | ||
| 1181 | 1184 | optimized=0, klass=1) | |
| 1182 | - self.super_init(filename) | ||
| 1185 | + self.super_init() | ||
| 1183 | 1186 | lnf = walk(klass.code, self.NameFinder(), verbose=0) | |
| 1184 | 1187 | self.locals.push(lnf.getLocals()) | |
| 1185 | 1188 | self.graph.setFlag(CO_NEWLOCALS) | |
@@ -1200,10 +1203,10 @@ class ClassCodeGenerator(NestedScopeMixin, AbstractClassCode, CodeGenerator): | |||
| 1200 | 1203 | ||
| 1201 | 1204 | __super_init = AbstractClassCode.__init__ | |
| 1202 | 1205 | ||
| 1203 | - def __init__(self, klass, filename, scopes, module): | ||
| 1206 | + def __init__(self, klass, scopes, module): | ||
| 1204 | 1207 | self.scopes = scopes | |
| 1205 | 1208 | self.scope = scopes[klass] | |
| 1206 | - self.__super_init(klass, filename, scopes, module) | ||
| 1209 | + self.__super_init(klass, scopes, module) | ||
| 1207 | 1210 | self.graph.setFreeVars(self.scope.get_free_vars()) | |
| 1208 | 1211 | self.graph.setCellVars(self.scope.get_cell_vars()) | |
| 1209 | 1212 | ## self.graph.setFlag(CO_NESTED) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,45 @@ | |||
| 1 | + """Check for errs in the AST. | ||
| 2 | + | ||
| 3 | + The Python parser does not catch all syntax errors. Others, like | ||
| 4 | + assignments with invalid targets, are caught in the code generation | ||
| 5 | + phase. | ||
| 6 | + | ||
| 7 | + The compiler package catches some errors in the transformer module. | ||
| 8 | + But it seems clearer to write checkers that use the AST to detect | ||
| 9 | + errors. | ||
| 10 | + """ | ||
| 11 | + | ||
| 12 | + from compiler import ast, walk | ||
| 13 | + | ||
| 14 | + def check(tree, multi=None): | ||
| 15 | + v = SyntaxErrorChecker(multi) | ||
| 16 | + walk(tree, v) | ||
| 17 | + return v.errors | ||
| 18 | + | ||
| 19 | + class SyntaxErrorChecker: | ||
| 20 | + """A visitor to find syntax errors in the AST.""" | ||
| 21 | + | ||
| 22 | + def __init__(self, multi=None): | ||
| 23 | + """Create new visitor object. | ||
| 24 | + | ||
| 25 | + If optional argument multi is not None, then print messages | ||
| 26 | + for each error rather than raising a SyntaxError for the | ||
| 27 | + first. | ||
| 28 | + """ | ||
| 29 | + self.multi = multi | ||
| 30 | + self.errors = 0 | ||
| 31 | + | ||
| 32 | + def error(self, node, msg): | ||
| 33 | + self.errors = self.errors + 1 | ||
| 34 | + if self.multi is not None: | ||
| 35 | + print "%s:%s: %s" % (node.filename, node.lineno, msg) | ||
| 36 | + else: | ||
| 37 | + raise SyntaxError, "%s (%s:%s)" % (msg, node.filename, node.lineno) | ||
| 38 | + | ||
| 39 | + def visitAssign(self, node): | ||
| 40 | + # the transformer module handles many of these | ||
| 41 | + for target in node.nodes: | ||
| 42 | + if isinstance(target, ast.AssList): | ||
| 43 | + if target.lineno is None: | ||
| 44 | + target.lineno = node.lineno | ||
| 45 | + self.error(target, "can't assign to list comprehension") | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments