[Python-Dev] SyntaxError patches

Fred L. Drake, Jr. fdrake@beopen.com
Tue, 11 Jul 2000 12:22:43 -0400 (EDT)


--GVPtp1TfAH
Content-Type: text/plain; charset=us-ascii
Content-Description: message body and .signature
Content-Transfer-Encoding: 7bit


I wrote:
 >   At one point, we were discussing having specializations of
 > SyntaxError, and I posted a patch that defined  IndentationError and
 > TabError.  With Ping's changes, using these instead of plain
 > SyntaxError is trivial.  Should I include that, or only change the
 > error messages using Ping's patch?

  I've attached a combined patch, in case any is interested.  This
does not include updated documentation, and could use additional
tests.


  -Fred

-- 
Fred L. Drake, Jr.  <fdrake at beopen.com>
BeOpen PythonLabs Team Member


--GVPtp1TfAH
Content-Type: text/plain
Content-Description: combined SyntaxError patch
Content-Disposition: inline;
	filename="indentation-error.patch"
Content-Transfer-Encoding: 7bit

*** cvs-python/Include/errcode.h	Fri Jun 30 19:58:04 2000
--- python/Include/errcode.h	Tue Jul 11 11:06:11 2000
***************
*** 30,37 ****
  #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 */
  
  #ifdef __cplusplus
  }
--- 30,39 ----
  #define E_NOMEM		15	/* Ran out of memory */
  #define E_DONE		16	/* Parsing complete */
  #define E_ERROR		17	/* Execution error */
! #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
  }
*** cvs-python/Include/parsetok.h	Tue Jul 11 12:15:31 2000
--- python/Include/parsetok.h	Tue Jul 11 11:04:40 2000
***************
*** 22,27 ****
--- 22,29 ----
      int lineno;
      int offset;
      char *text;
+     int token;
+     int expected;
  } perrdetail;
  
  extern DL_IMPORT(node *) PyParser_ParseString(char *, grammar *, int,
*** cvs-python/Lib/test/test_exceptions.py	Tue Jun 20 14:52:57 2000
--- python/Lib/test/test_exceptions.py	Tue Jul  4 00:36:58 2000
***************
*** 86,91 ****
--- 86,99 ----
  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)'
  
*** cvs-python/Lib/test/output/test_exceptions	Sun Jun 25 06:44:57 2000
--- python/Lib/test/output/test_exceptions	Tue Jul  4 00:43:31 2000
***************
*** 28,33 ****
--- 28,37 ----
  spam
  SyntaxError
  spam
+ IndentationError
+ spam
+ TabError
+ spam
  SystemError
  (hard to reproduce)
  spam
*** cvs-python/Parser/parser.c	Tue Jul 11 12:15:34 2000
--- python/Parser/parser.c	Tue Jul 11 11:11:19 2000
***************
*** 205,215 ****
  }
  
  int
! PyParser_AddToken(ps, type, str, lineno)
  	register parser_state *ps;
  	register int type;
  	char *str;
  	int lineno;
  {
  	register int ilabel;
  	int err;
--- 205,216 ----
  }
  
  int
! 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,290 ****
--- 286,300 ----
  		
  		/* 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;
  	}
  }
*** cvs-python/Parser/parser.h	Tue Jul 11 12:15:34 2000
--- python/Parser/parser.h	Tue Jul 11 11:13:02 2000
***************
*** 38,44 ****
  
  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);
  void PyGrammar_AddAccelerators(grammar *g);
  
  #ifdef __cplusplus
--- 38,45 ----
  
  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 *expected_ret);
  void PyGrammar_AddAccelerators(grammar *g);
  
  #ifdef __cplusplus
*** cvs-python/Parser/parsetok.c	Tue Jul 11 12:15:34 2000
--- python/Parser/parsetok.c	Tue Jul 11 11:15:03 2000
***************
*** 139,146 ****
  			strncpy(str, a, len);
  		str[len] = '\0';
  		if ((err_ret->error =
! 		     PyParser_AddToken(ps, (int)type, str,
! 				       tok->lineno)) != E_OK) {
  			if (err_ret->error != E_DONE)
  				PyMem_DEL(str);
  			break;
--- 139,146 ----
  			strncpy(str, a, len);
  		str[len] = '\0';
  		if ((err_ret->error =
! 		     PyParser_AddToken(ps, (int)type, str, tok->lineno,
! 				       &(err_ret->expected))) != E_OK) {
  			if (err_ret->error != E_DONE)
  				PyMem_DEL(str);
  			break;
*** cvs-python/Parser/tokenizer.c	Tue Jul 11 12:15:34 2000
--- python/Parser/tokenizer.c	Tue Jul 11 11:32:37 2000
***************
*** 412,424 ****
  	struct tok_state *tok;
  {
  	if (tok->alterror) {
! 		tok->done = E_INDENT;
  		tok->cur = tok->inp;
  		return 1;
  	}
  	if (tok->altwarning) {
! 		PySys_WriteStderr("%s: inconsistent tab/space usage\n",
! 			tok->filename);
  		tok->altwarning = 0;
  	}
  	return 0;
--- 412,424 ----
  	struct tok_state *tok;
  {
  	if (tok->alterror) {
! 		tok->done = E_TABSPACE;
  		tok->cur = tok->inp;
  		return 1;
  	}
  	if (tok->altwarning) {
! 		PySys_WriteStderr("%s: inconsistent use of tabs and spaces "
!                                   "in indentation\n", tok->filename);
  		tok->altwarning = 0;
  	}
  	return 0;
***************
*** 484,492 ****
  			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->cur = tok->inp;
  					return ERRORTOKEN;
  				}
--- 484,490 ----
  			else if (col > tok->indstack[tok->indent]) {
  				/* Indent -- always one */
  				if (tok->indent+1 >= MAXINDENT) {
! 					tok->done = E_TOODEEP;
  					tok->cur = tok->inp;
  					return ERRORTOKEN;
  				}
***************
*** 506,514 ****
  					tok->indent--;
  				}
  				if (col != tok->indstack[tok->indent]) {
! 					PySys_WriteStderr(
! 						"inconsistent dedent\n");
! 					tok->done = E_TOKEN;
  					tok->cur = tok->inp;
  					return ERRORTOKEN;
  				}
--- 504,510 ----
  					tok->indent--;
  				}
  				if (col != tok->indstack[tok->indent]) {
! 					tok->done = E_DEDENT;
  					tok->cur = tok->inp;
  					return ERRORTOKEN;
  				}
*** cvs-python/Python/exceptions.c	Tue Jul 11 12:15:34 2000
--- python/Python/exceptions.c	Sun Jul  9 22:59:18 2000
***************
*** 68,73 ****
--- 68,78 ----
        |\n\
        +-- AttributeError\n\
        +-- SyntaxError\n\
+       |    |\n\
+       |    +-- IndentationError\n\
+       |         |\n\
+       |         +-- TabError\n\
+       |\n\
        +-- TypeError\n\
        +-- AssertionError\n\
        +-- LookupError\n\
***************
*** 783,788 ****
--- 788,799 ----
  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,822 ****
--- 828,835 ----
  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,883 ****
--- 891,900 ----
   {"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,
*** cvs-python/Python/pythonrun.c	Tue Jul 11 12:15:34 2000
--- python/Python/pythonrun.c	Tue Jul 11 12:10:33 2000
***************
*** 14,19 ****
--- 14,20 ----
  
  #include "grammar.h"
  #include "node.h"
+ #include "token.h"
  #include "parsetok.h"
  #include "errcode.h"
  #include "compile.h"
***************
*** 983,990 ****
  err_input(err)
  	perrdetail *err;
  {
! 	PyObject *v, *w;
  	char *msg = NULL;
  	v = Py_BuildValue("(ziiz)", err->filename,
  			    err->lineno, err->offset, err->text);
  	if (err->text != NULL) {
--- 984,992 ----
  err_input(err)
  	perrdetail *err;
  {
! 	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,999 ****
  	}
  	switch (err->error) {
  	case E_SYNTAX:
! 		msg = "invalid syntax";
  		break;
  	case E_TOKEN:
  		msg = "invalid token";
--- 995,1011 ----
  	}
  	switch (err->error) {
  	case E_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,1020 ****
  	case E_EOF:
  		msg = "unexpected EOF while parsing";
  		break;
! 	case E_INDENT:
  		msg = "inconsistent use of tabs and spaces in indentation";
  		break;
  	case E_OVERFLOW:
  		msg = "expression too long";
  		break;
  	default:
  		fprintf(stderr, "error=%d\n", err->error);
  		msg = "unknown parsing error";
--- 1021,1041 ----
  	case E_EOF:
  		msg = "unexpected EOF while parsing";
  		break;
! 	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,1028 ****
  	}
  	w = Py_BuildValue("(sO)", msg, v);
  	Py_XDECREF(v);
! 	PyErr_SetObject(PyExc_SyntaxError, w);
  	Py_XDECREF(w);
  }
  
--- 1043,1049 ----
  	}
  	w = Py_BuildValue("(sO)", msg, v);
  	Py_XDECREF(v);
! 	PyErr_SetObject(errtype, w);
  	Py_XDECREF(w);
  }
  

--GVPtp1TfAH--