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.
This commit is contained in:
parent
88e1932930
commit
85f363990c
|
@ -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_NOMEM 15 /* Ran out of memory */
|
||||||
#define E_DONE 16 /* Parsing complete */
|
#define E_DONE 16 /* Parsing complete */
|
||||||
#define E_ERROR 17 /* Execution error */
|
#define E_ERROR 17 /* Execution error */
|
||||||
#define E_INDENT 18 /* Invalid indentation detected */
|
#define E_TABSPACE 18 /* Invalid indentation detected */
|
||||||
#define E_OVERFLOW 19 /* Node had too many children */
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ typedef struct {
|
||||||
int lineno;
|
int lineno;
|
||||||
int offset;
|
int offset;
|
||||||
char *text;
|
char *text;
|
||||||
|
int token;
|
||||||
|
int expected;
|
||||||
} perrdetail;
|
} perrdetail;
|
||||||
|
|
||||||
extern DL_IMPORT(node *) PyParser_ParseString(char *, grammar *, int,
|
extern DL_IMPORT(node *) PyParser_ParseString(char *, grammar *, int,
|
||||||
|
|
|
@ -28,6 +28,10 @@ RuntimeError
|
||||||
spam
|
spam
|
||||||
SyntaxError
|
SyntaxError
|
||||||
spam
|
spam
|
||||||
|
IndentationError
|
||||||
|
spam
|
||||||
|
TabError
|
||||||
|
spam
|
||||||
SystemError
|
SystemError
|
||||||
(hard to reproduce)
|
(hard to reproduce)
|
||||||
spam
|
spam
|
||||||
|
|
|
@ -86,6 +86,14 @@ r(SyntaxError)
|
||||||
try: exec '/\n'
|
try: exec '/\n'
|
||||||
except SyntaxError: pass
|
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)
|
r(SystemError)
|
||||||
print '(hard to reproduce)'
|
print '(hard to reproduce)'
|
||||||
|
|
||||||
|
|
|
@ -205,11 +205,12 @@ classify(g, type, str)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
PyParser_AddToken(ps, type, str, lineno)
|
PyParser_AddToken(ps, type, str, lineno, expected_ret)
|
||||||
register parser_state *ps;
|
register parser_state *ps;
|
||||||
register int type;
|
register int type;
|
||||||
char *str;
|
char *str;
|
||||||
int lineno;
|
int lineno;
|
||||||
|
int *expected_ret;
|
||||||
{
|
{
|
||||||
register int ilabel;
|
register int ilabel;
|
||||||
int err;
|
int err;
|
||||||
|
@ -285,6 +286,15 @@ PyParser_AddToken(ps, type, str, lineno)
|
||||||
|
|
||||||
/* Stuck, report syntax error */
|
/* Stuck, report syntax error */
|
||||||
D(printf(" Error.\n"));
|
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;
|
return E_SYNTAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,8 @@ typedef struct {
|
||||||
|
|
||||||
parser_state *PyParser_New(grammar *g, int start);
|
parser_state *PyParser_New(grammar *g, int start);
|
||||||
void PyParser_Delete(parser_state *ps);
|
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);
|
void PyGrammar_AddAccelerators(grammar *g);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -139,8 +139,8 @@ parsetok(tok, g, start, err_ret)
|
||||||
strncpy(str, a, len);
|
strncpy(str, a, len);
|
||||||
str[len] = '\0';
|
str[len] = '\0';
|
||||||
if ((err_ret->error =
|
if ((err_ret->error =
|
||||||
PyParser_AddToken(ps, (int)type, str,
|
PyParser_AddToken(ps, (int)type, str, tok->lineno,
|
||||||
tok->lineno)) != E_OK) {
|
&(err_ret->expected))) != E_OK) {
|
||||||
if (err_ret->error != E_DONE)
|
if (err_ret->error != E_DONE)
|
||||||
PyMem_DEL(str);
|
PyMem_DEL(str);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -412,13 +412,13 @@ indenterror(tok)
|
||||||
struct tok_state *tok;
|
struct tok_state *tok;
|
||||||
{
|
{
|
||||||
if (tok->alterror) {
|
if (tok->alterror) {
|
||||||
tok->done = E_INDENT;
|
tok->done = E_TABSPACE;
|
||||||
tok->cur = tok->inp;
|
tok->cur = tok->inp;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (tok->altwarning) {
|
if (tok->altwarning) {
|
||||||
PySys_WriteStderr("%s: inconsistent tab/space usage\n",
|
PySys_WriteStderr("%s: inconsistent use of tabs and spaces "
|
||||||
tok->filename);
|
"in indentation\n", tok->filename);
|
||||||
tok->altwarning = 0;
|
tok->altwarning = 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -484,9 +484,7 @@ PyTokenizer_Get(tok, p_start, p_end)
|
||||||
else if (col > tok->indstack[tok->indent]) {
|
else if (col > tok->indstack[tok->indent]) {
|
||||||
/* Indent -- always one */
|
/* Indent -- always one */
|
||||||
if (tok->indent+1 >= MAXINDENT) {
|
if (tok->indent+1 >= MAXINDENT) {
|
||||||
PySys_WriteStderr(
|
tok->done = E_TOODEEP;
|
||||||
"excessive indent\n");
|
|
||||||
tok->done = E_TOKEN;
|
|
||||||
tok->cur = tok->inp;
|
tok->cur = tok->inp;
|
||||||
return ERRORTOKEN;
|
return ERRORTOKEN;
|
||||||
}
|
}
|
||||||
|
@ -506,9 +504,7 @@ PyTokenizer_Get(tok, p_start, p_end)
|
||||||
tok->indent--;
|
tok->indent--;
|
||||||
}
|
}
|
||||||
if (col != tok->indstack[tok->indent]) {
|
if (col != tok->indstack[tok->indent]) {
|
||||||
PySys_WriteStderr(
|
tok->done = E_DEDENT;
|
||||||
"inconsistent dedent\n");
|
|
||||||
tok->done = E_TOKEN;
|
|
||||||
tok->cur = tok->inp;
|
tok->cur = tok->inp;
|
||||||
return ERRORTOKEN;
|
return ERRORTOKEN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,11 @@ Exception\n\
|
||||||
|\n\
|
|\n\
|
||||||
+-- AttributeError\n\
|
+-- AttributeError\n\
|
||||||
+-- SyntaxError\n\
|
+-- SyntaxError\n\
|
||||||
|
| |\n\
|
||||||
|
| +-- IndentationError\n\
|
||||||
|
| |\n\
|
||||||
|
| +-- TabError\n\
|
||||||
|
|\n\
|
||||||
+-- TypeError\n\
|
+-- TypeError\n\
|
||||||
+-- AssertionError\n\
|
+-- AssertionError\n\
|
||||||
+-- LookupError\n\
|
+-- LookupError\n\
|
||||||
|
@ -783,6 +788,12 @@ the Python version, and the hardware/OS platform and version.";
|
||||||
static char
|
static char
|
||||||
MemoryError__doc__[] = "Out of memory.";
|
MemoryError__doc__[] = "Out of memory.";
|
||||||
|
|
||||||
|
static char
|
||||||
|
IndentationError__doc__[] = "Improper indentation.";
|
||||||
|
|
||||||
|
static char
|
||||||
|
TabError__doc__[] = "Improper mixture of spaces and tabs.";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* module global functions */
|
/* module global functions */
|
||||||
|
@ -817,6 +828,8 @@ PyObject *PyExc_OverflowError;
|
||||||
PyObject *PyExc_RuntimeError;
|
PyObject *PyExc_RuntimeError;
|
||||||
PyObject *PyExc_NotImplementedError;
|
PyObject *PyExc_NotImplementedError;
|
||||||
PyObject *PyExc_SyntaxError;
|
PyObject *PyExc_SyntaxError;
|
||||||
|
PyObject *PyExc_IndentationError;
|
||||||
|
PyObject *PyExc_TabError;
|
||||||
PyObject *PyExc_SystemError;
|
PyObject *PyExc_SystemError;
|
||||||
PyObject *PyExc_SystemExit;
|
PyObject *PyExc_SystemExit;
|
||||||
PyObject *PyExc_UnboundLocalError;
|
PyObject *PyExc_UnboundLocalError;
|
||||||
|
@ -878,6 +891,10 @@ exctable[] = {
|
||||||
{"AttributeError", &PyExc_AttributeError, 0, AttributeError__doc__},
|
{"AttributeError", &PyExc_AttributeError, 0, AttributeError__doc__},
|
||||||
{"SyntaxError", &PyExc_SyntaxError, 0, SyntaxError__doc__,
|
{"SyntaxError", &PyExc_SyntaxError, 0, SyntaxError__doc__,
|
||||||
SyntaxError_methods, SyntaxError__classinit__},
|
SyntaxError_methods, SyntaxError__classinit__},
|
||||||
|
{"IndentationError", &PyExc_IndentationError, &PyExc_SyntaxError,
|
||||||
|
IndentationError__doc__},
|
||||||
|
{"TabError", &PyExc_TabError, &PyExc_IndentationError,
|
||||||
|
TabError__doc__},
|
||||||
{"AssertionError", &PyExc_AssertionError, 0, AssertionError__doc__},
|
{"AssertionError", &PyExc_AssertionError, 0, AssertionError__doc__},
|
||||||
{"LookupError", &PyExc_LookupError, 0, LookupError__doc__},
|
{"LookupError", &PyExc_LookupError, 0, LookupError__doc__},
|
||||||
{"IndexError", &PyExc_IndexError, &PyExc_LookupError,
|
{"IndexError", &PyExc_IndexError, &PyExc_LookupError,
|
||||||
|
|
|
@ -14,6 +14,7 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
|
||||||
#include "grammar.h"
|
#include "grammar.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
#include "token.h"
|
||||||
#include "parsetok.h"
|
#include "parsetok.h"
|
||||||
#include "errcode.h"
|
#include "errcode.h"
|
||||||
#include "compile.h"
|
#include "compile.h"
|
||||||
|
@ -983,8 +984,9 @@ static void
|
||||||
err_input(err)
|
err_input(err)
|
||||||
perrdetail *err;
|
perrdetail *err;
|
||||||
{
|
{
|
||||||
PyObject *v, *w;
|
PyObject *v, *w, *errtype;
|
||||||
char *msg = NULL;
|
char *msg = NULL;
|
||||||
|
errtype = PyExc_SyntaxError;
|
||||||
v = Py_BuildValue("(ziiz)", err->filename,
|
v = Py_BuildValue("(ziiz)", err->filename,
|
||||||
err->lineno, err->offset, err->text);
|
err->lineno, err->offset, err->text);
|
||||||
if (err->text != NULL) {
|
if (err->text != NULL) {
|
||||||
|
@ -993,7 +995,17 @@ err_input(err)
|
||||||
}
|
}
|
||||||
switch (err->error) {
|
switch (err->error) {
|
||||||
case E_SYNTAX:
|
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;
|
break;
|
||||||
case E_TOKEN:
|
case E_TOKEN:
|
||||||
msg = "invalid token";
|
msg = "invalid token";
|
||||||
|
@ -1009,12 +1021,21 @@ err_input(err)
|
||||||
case E_EOF:
|
case E_EOF:
|
||||||
msg = "unexpected EOF while parsing";
|
msg = "unexpected EOF while parsing";
|
||||||
break;
|
break;
|
||||||
case E_INDENT:
|
case E_TABSPACE:
|
||||||
|
errtype = PyExc_TabError;
|
||||||
msg = "inconsistent use of tabs and spaces in indentation";
|
msg = "inconsistent use of tabs and spaces in indentation";
|
||||||
break;
|
break;
|
||||||
case E_OVERFLOW:
|
case E_OVERFLOW:
|
||||||
msg = "expression too long";
|
msg = "expression too long";
|
||||||
break;
|
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:
|
default:
|
||||||
fprintf(stderr, "error=%d\n", err->error);
|
fprintf(stderr, "error=%d\n", err->error);
|
||||||
msg = "unknown parsing error";
|
msg = "unknown parsing error";
|
||||||
|
@ -1022,7 +1043,7 @@ err_input(err)
|
||||||
}
|
}
|
||||||
w = Py_BuildValue("(sO)", msg, v);
|
w = Py_BuildValue("(sO)", msg, v);
|
||||||
Py_XDECREF(v);
|
Py_XDECREF(v);
|
||||||
PyErr_SetObject(PyExc_SyntaxError, w);
|
PyErr_SetObject(errtype, w);
|
||||||
Py_XDECREF(w);
|
Py_XDECREF(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue