summaryrefslogtreecommitdiffstats
path: root/Lib/compiler/syntax.py
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2001-09-17 18:03:55 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2001-09-17 18:03:55 (GMT)
commit37c9351cf6efbe58e01fd879a1d60cc6073ced6b (patch)
treeea89cd6bdc54124e7b36b203269c1f68a89442e0 /Lib/compiler/syntax.py
parent09392b77a4d8be766e394177a466d51c2a64480f (diff)
downloadcpython-37c9351cf6efbe58e01fd879a1d60cc6073ced6b.zip
cpython-37c9351cf6efbe58e01fd879a1d60cc6073ced6b.tar.gz
cpython-37c9351cf6efbe58e01fd879a1d60cc6073ced6b.tar.bz2
Handle more syntax errors.
Invoke compiler.syntax.check() after building AST. If a SyntaxError occurs, print the error and exit without generating a .pyc file. Refactor code to use compiler.misc.set_filename() rather than passing filename argument around to each CodeGenerator instance.
Diffstat (limited to 'Lib/compiler/syntax.py')
-rw-r--r--Lib/compiler/syntax.py45
1 files changed, 45 insertions, 0 deletions
diff --git a/Lib/compiler/syntax.py b/Lib/compiler/syntax.py
new file mode 100644
index 0000000..14613ef
--- /dev/null
+++ b/Lib/compiler/syntax.py
@@ -0,0 +1,45 @@
+"""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
+ 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")