summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1998-10-22 21:56:15 (GMT)
committerGuido van Rossum <guido@python.org>1998-10-22 21:56:15 (GMT)
commitc41c1a984e6d5ed4a3c247b503b5a8eefd0ec519 (patch)
treea98d45c86ae65b5705b4c000be69944afe561c2c /Lib
parentd370379186e1639ff43b245c54ed56dbdc8ab96c (diff)
downloadcpython-c41c1a984e6d5ed4a3c247b503b5a8eefd0ec519.zip
cpython-c41c1a984e6d5ed4a3c247b503b5a8eefd0ec519.tar.gz
cpython-c41c1a984e6d5ed4a3c247b503b5a8eefd0ec519.tar.bz2
Moved compile_command() here from code.py, so JPython can provide its
own version.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/codeop.py86
1 files changed, 86 insertions, 0 deletions
diff --git a/Lib/codeop.py b/Lib/codeop.py
new file mode 100644
index 0000000..080e00b
--- /dev/null
+++ b/Lib/codeop.py
@@ -0,0 +1,86 @@
+"""Utility to compile possibly incomplete Python source code."""
+
+import sys
+import string
+import traceback
+
+def compile_command(source, filename="<input>", symbol="single"):
+ r"""Compile a command and determine whether it is incomplete.
+
+ Arguments:
+
+ source -- the source string; may contain \n characters
+ filename -- optional filename from which source was read; default "<input>"
+ symbol -- optional grammar start symbol; "single" (default) or "eval"
+
+ Return value / exceptions raised:
+
+ - Return a code object if the command is complete and valid
+ - Return None if the command is incomplete
+ - Raise SyntaxError or OverflowError if the command is a syntax error
+ (OverflowError if the error is in a numeric constant)
+
+ Approach:
+
+ First, check if the source consists entirely of blank lines and
+ comments; if so, replace it with 'pass', because the built-in
+ parser doesn't always do the right thing for these.
+
+ Compile three times: as is, with \n, and with \n\n appended. If
+ it compiles as is, it's complete. If it compiles with one \n
+ appended, we expect more. If it doesn't compile either way, we
+ compare the error we get when compiling with \n or \n\n appended.
+ If the errors are the same, the code is broken. But if the errors
+ are different, we expect more. Not intuitive; not even guaranteed
+ to hold in future releases; but this matches the compiler's
+ behavior from Python 1.4 through 1.5.2, at least.
+
+ Caveat:
+
+ It is possible (but not likely) that the parser stops parsing
+ with a successful outcome before reaching the end of the source;
+ in this case, trailing symbols may be ignored instead of causing an
+ error. For example, a backslash followed by two newlines may be
+ followed by arbitrary garbage. This will be fixed once the API
+ for the parser is better.
+
+ """
+
+ # Check for source consisting of only blank lines and comments
+ for line in string.split(source, "\n"):
+ line = string.strip(line)
+ if line and line[0] != '#':
+ break # Leave it alone
+ else:
+ source = "pass" # Replace it with a 'pass' statement
+
+ err = err1 = err2 = None
+ code = code1 = code2 = None
+
+ try:
+ code = compile(source, filename, symbol)
+ except SyntaxError, err:
+ pass
+
+ try:
+ code1 = compile(source + "\n", filename, symbol)
+ except SyntaxError, err1:
+ pass
+
+ try:
+ code2 = compile(source + "\n\n", filename, symbol)
+ except SyntaxError, err2:
+ pass
+
+ if code:
+ return code
+ try:
+ e1 = err1.__dict__
+ except AttributeError:
+ e1 = err1
+ try:
+ e2 = err2.__dict__
+ except AttributeError:
+ e2 = err2
+ if not code1 and e1 == e2:
+ raise SyntaxError, err1