summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2000-07-11 17:53:00 (GMT)
committerFred Drake <fdrake@acm.org>2000-07-11 17:53:00 (GMT)
commit85f363990cbd6df21015eebdc171c533176e3407 (patch)
tree4aa69857ffe21991384e379799f42ba308a58086
parent88e1932930245b2f7ed300ff8b31034db7ecda5b (diff)
downloadcpython-85f363990cbd6df21015eebdc171c533176e3407.zip
cpython-85f363990cbd6df21015eebdc171c533176e3407.tar.gz
cpython-85f363990cbd6df21015eebdc171c533176e3407.tar.bz2
Create two new exceptions: IndentationError and TabError. These are
used for indentation related errors. This patch includes Ping's improvements for indentation-related error messages. Closes SourceForge patches #100734 and #100856.
-rw-r--r--Include/errcode.h6
-rw-r--r--Include/parsetok.h2
-rw-r--r--Lib/test/output/test_exceptions4
-rw-r--r--Lib/test/test_exceptions.py8
-rw-r--r--Parser/parser.c12
-rw-r--r--Parser/parser.h3
-rw-r--r--Parser/parsetok.c4
-rw-r--r--Parser/tokenizer.c14
-rw-r--r--Python/exceptions.c17
-rw-r--r--Python/pythonrun.c29
10 files changed, 80 insertions, 19 deletions
diff --git a/Include/errcode.h b/Include/errcode.h
index b872e18..0683317 100644
--- a/Include/errcode.h
+++ b/Include/errcode.h
@@ -30,8 +30,10 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#define E_NOMEM 15 /* Ran out of memory */
#define E_DONE 16 /* Parsing complete */
#define E_ERROR 17 /* Execution error */
-#define E_INDENT 18 /* Invalid indentation detected */
-#define E_OVERFLOW 19 /* Node had too many children */
+#define E_TABSPACE 18 /* Invalid indentation detected */
+#define E_OVERFLOW 19 /* Node had too many children */
+#define E_TOODEEP 20 /* Too many indentation levels */
+#define E_DEDENT 21 /* No matching outer block for dedent */
#ifdef __cplusplus
}
diff --git a/Include/parsetok.h b/Include/parsetok.h
index 5244e3f..71e7d89 100644
--- a/Include/parsetok.h
+++ b/Include/parsetok.h
@@ -22,6 +22,8 @@ typedef struct {
int lineno;
int offset;
char *text;
+ int token;
+ int expected;
} perrdetail;
extern DL_IMPORT(node *) PyParser_ParseString(char *, grammar *, int,
diff --git a/Lib/test/output/test_exceptions b/Lib/test/output/test_exceptions
index 5605114..9e021d2 100644
--- a/Lib/test/output/test_exceptions
+++ b/Lib/test/output/test_exceptions
@@ -28,6 +28,10 @@ RuntimeError
spam
SyntaxError
spam
+IndentationError
+spam
+TabError
+spam
SystemError
(hard to reproduce)
spam
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index 7bc515c..06861df 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -86,6 +86,14 @@ r(SyntaxError)
try: exec '/\n'
except SyntaxError: pass
+r(IndentationError)
+
+r(TabError)
+# can only be tested under -tt, and is the only test for -tt
+#try: compile("try:\n\t1/0\n \t1/0\nfinally:\n pass\n", '<string>', 'exec')
+#except TabError: pass
+#else: raise TestFailed
+
r(SystemError)
print '(hard to reproduce)'
diff --git a/Parser/parser.c b/Parser/parser.c
index ee40f21..b74de7f 100644
--- a/Parser/parser.c
+++ b/Parser/parser.c
@@ -205,11 +205,12 @@ classify(g, type, str)
}
int
-PyParser_AddToken(ps, type, str, lineno)
+PyParser_AddToken(ps, type, str, lineno, expected_ret)
register parser_state *ps;
register int type;
char *str;
int lineno;
+ int *expected_ret;
{
register int ilabel;
int err;
@@ -285,6 +286,15 @@ PyParser_AddToken(ps, type, str, lineno)
/* Stuck, report syntax error */
D(printf(" Error.\n"));
+ if (expected_ret) {
+ if (s->s_lower == s->s_upper - 1) {
+ /* Only one possible expected token */
+ *expected_ret = ps->p_grammar->
+ g_ll.ll_label[s->s_lower].lb_type;
+ }
+ else
+ *expected_ret = -1;
+ }
return E_SYNTAX;
}
}
diff --git a/Parser/parser.h b/Parser/parser.h
index 6087373..d0df8cf 100644
--- a/Parser/parser.h
+++ b/Parser/parser.h
@@ -38,7 +38,8 @@ typedef struct {
parser_state *PyParser_New(grammar *g, int start);
void PyParser_Delete(parser_state *ps);
-int PyParser_AddToken(parser_state *ps, int type, char *str, int lineno);
+int PyParser_AddToken(parser_state *ps, int type, char *str, int lineno,
+ int *expected_ret);
void PyGrammar_AddAccelerators(grammar *g);
#ifdef __cplusplus
diff --git a/Parser/parsetok.c b/Parser/parsetok.c
index 9ac1606..9d090f1 100644
--- a/Parser/parsetok.c
+++ b/Parser/parsetok.c
@@ -139,8 +139,8 @@ parsetok(tok, g, start, err_ret)
strncpy(str, a, len);
str[len] = '\0';
if ((err_ret->error =
- PyParser_AddToken(ps, (int)type, str,
- tok->lineno)) != E_OK) {
+ PyParser_AddToken(ps, (int)type, str, tok->lineno,
+ &(err_ret->expected))) != E_OK) {
if (err_ret->error != E_DONE)
PyMem_DEL(str);
break;
diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c
index 0ef3fc0..d4ec345 100644
--- a/Parser/tokenizer.c
+++ b/Parser/tokenizer.c
@@ -412,13 +412,13 @@ indenterror(tok)
struct tok_state *tok;
{
if (tok->alterror) {
- tok->done = E_INDENT;
+ tok->done = E_TABSPACE;
tok->cur = tok->inp;
return 1;
}
if (tok->altwarning) {
- PySys_WriteStderr("%s: inconsistent tab/space usage\n",
- tok->filename);
+ PySys_WriteStderr("%s: inconsistent use of tabs and spaces "
+ "in indentation\n", tok->filename);
tok->altwarning = 0;
}
return 0;
@@ -484,9 +484,7 @@ PyTokenizer_Get(tok, p_start, p_end)
else if (col > tok->indstack[tok->indent]) {
/* Indent -- always one */
if (tok->indent+1 >= MAXINDENT) {
- PySys_WriteStderr(
- "excessive indent\n");
- tok->done = E_TOKEN;
+ tok->done = E_TOODEEP;
tok->cur = tok->inp;
return ERRORTOKEN;
}
@@ -506,9 +504,7 @@ PyTokenizer_Get(tok, p_start, p_end)
tok->indent--;
}
if (col != tok->indstack[tok->indent]) {
- PySys_WriteStderr(
- "inconsistent dedent\n");
- tok->done = E_TOKEN;
+ tok->done = E_DEDENT;
tok->cur = tok->inp;
return ERRORTOKEN;
}
diff --git a/Python/exceptions.c b/Python/exceptions.c
index f766ba5..a70e6c6 100644
--- a/Python/exceptions.c
+++ b/Python/exceptions.c
@@ -68,6 +68,11 @@ Exception\n\
|\n\
+-- AttributeError\n\
+-- SyntaxError\n\
+ | |\n\
+ | +-- IndentationError\n\
+ | |\n\
+ | +-- TabError\n\
+ |\n\
+-- TypeError\n\
+-- AssertionError\n\
+-- LookupError\n\
@@ -783,6 +788,12 @@ the Python version, and the hardware/OS platform and version.";
static char
MemoryError__doc__[] = "Out of memory.";
+static char
+IndentationError__doc__[] = "Improper indentation.";
+
+static char
+TabError__doc__[] = "Improper mixture of spaces and tabs.";
+
/* module global functions */
@@ -817,6 +828,8 @@ PyObject *PyExc_OverflowError;
PyObject *PyExc_RuntimeError;
PyObject *PyExc_NotImplementedError;
PyObject *PyExc_SyntaxError;
+PyObject *PyExc_IndentationError;
+PyObject *PyExc_TabError;
PyObject *PyExc_SystemError;
PyObject *PyExc_SystemExit;
PyObject *PyExc_UnboundLocalError;
@@ -878,6 +891,10 @@ exctable[] = {
{"AttributeError", &PyExc_AttributeError, 0, AttributeError__doc__},
{"SyntaxError", &PyExc_SyntaxError, 0, SyntaxError__doc__,
SyntaxError_methods, SyntaxError__classinit__},
+ {"IndentationError", &PyExc_IndentationError, &PyExc_SyntaxError,
+ IndentationError__doc__},
+ {"TabError", &PyExc_TabError, &PyExc_IndentationError,
+ TabError__doc__},
{"AssertionError", &PyExc_AssertionError, 0, AssertionError__doc__},
{"LookupError", &PyExc_LookupError, 0, LookupError__doc__},
{"IndexError", &PyExc_IndexError, &PyExc_LookupError,
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 74dffae..9cc8072 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -14,6 +14,7 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#include "grammar.h"
#include "node.h"
+#include "token.h"
#include "parsetok.h"
#include "errcode.h"
#include "compile.h"
@@ -983,8 +984,9 @@ static void
err_input(err)
perrdetail *err;
{
- PyObject *v, *w;
+ PyObject *v, *w, *errtype;
char *msg = NULL;
+ errtype = PyExc_SyntaxError;
v = Py_BuildValue("(ziiz)", err->filename,
err->lineno, err->offset, err->text);
if (err->text != NULL) {
@@ -993,7 +995,17 @@ err_input(err)
}
switch (err->error) {
case E_SYNTAX:
- msg = "invalid syntax";
+ errtype = PyExc_IndentationError;
+ if (err->expected == INDENT)
+ msg = "expected an indented block";
+ else if (err->token == INDENT)
+ msg = "unexpected indent";
+ else if (err->token == DEDENT)
+ msg = "unexpected unindent";
+ else {
+ errtype = PyExc_SyntaxError;
+ msg = "invalid syntax";
+ }
break;
case E_TOKEN:
msg = "invalid token";
@@ -1009,12 +1021,21 @@ err_input(err)
case E_EOF:
msg = "unexpected EOF while parsing";
break;
- case E_INDENT:
+ case E_TABSPACE:
+ errtype = PyExc_TabError;
msg = "inconsistent use of tabs and spaces in indentation";
break;
case E_OVERFLOW:
msg = "expression too long";
break;
+ case E_DEDENT:
+ errtype = PyExc_IndentationError;
+ msg = "unindent does not match any outer indentation level";
+ break;
+ case E_TOODEEP:
+ errtype = PyExc_IndentationError;
+ msg = "too many levels of indentation";
+ break;
default:
fprintf(stderr, "error=%d\n", err->error);
msg = "unknown parsing error";
@@ -1022,7 +1043,7 @@ err_input(err)
}
w = Py_BuildValue("(sO)", msg, v);
Py_XDECREF(v);
- PyErr_SetObject(PyExc_SyntaxError, w);
+ PyErr_SetObject(errtype, w);
Py_XDECREF(w);
}