Add new parser error code, E_OVERFLOW. This error is returned when
the number of children of a node exceeds the max possible value for the short that is used to count them. The Python runtime converts this parser error into the SyntaxError "expression too long."
This commit is contained in:
parent
56c807d318
commit
94988067b9
|
@ -52,6 +52,7 @@ PERFORMANCE OF THIS SOFTWARE.
|
|||
#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
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ typedef struct _node {
|
|||
} node;
|
||||
|
||||
extern DL_IMPORT(node *) PyNode_New Py_PROTO((int type));
|
||||
extern DL_IMPORT(node *) PyNode_AddChild Py_PROTO((node *n, int type, char *str, int lineno));
|
||||
extern DL_IMPORT(int) PyNode_AddChild Py_PROTO((node *n, int type, char *str, int lineno));
|
||||
extern DL_IMPORT(void) PyNode_Free Py_PROTO((node *n));
|
||||
|
||||
/* Node access functions */
|
||||
|
|
|
@ -29,10 +29,13 @@ PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
******************************************************************/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/* Parse tree node implementation */
|
||||
|
||||
#include "pgenheaders.h"
|
||||
#include "node.h"
|
||||
#include "errcode.h"
|
||||
|
||||
node *
|
||||
PyNode_New(type)
|
||||
|
@ -52,7 +55,7 @@ PyNode_New(type)
|
|||
#define XXX 3 /* Node alignment factor to speed up realloc */
|
||||
#define XXXROUNDUP(n) ((n) == 1 ? 1 : ((n) + XXX - 1) / XXX * XXX)
|
||||
|
||||
node *
|
||||
int
|
||||
PyNode_AddChild(n1, type, str, lineno)
|
||||
register node *n1;
|
||||
int type;
|
||||
|
@ -62,12 +65,14 @@ PyNode_AddChild(n1, type, str, lineno)
|
|||
register int nch = n1->n_nchildren;
|
||||
register int nch1 = nch+1;
|
||||
register node *n;
|
||||
if (nch == SHRT_MAX || nch < 0)
|
||||
return E_OVERFLOW;
|
||||
if (XXXROUNDUP(nch) < nch1) {
|
||||
n = n1->n_child;
|
||||
nch1 = XXXROUNDUP(nch1);
|
||||
PyMem_RESIZE(n, node, nch1);
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
return E_NOMEM;
|
||||
n1->n_child = n;
|
||||
}
|
||||
n = &n1->n_child[n1->n_nchildren++];
|
||||
|
@ -76,7 +81,7 @@ PyNode_AddChild(n1, type, str, lineno)
|
|||
n->n_lineno = lineno;
|
||||
n->n_nchildren = 0;
|
||||
n->n_child = NULL;
|
||||
return n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Forward */
|
||||
|
|
|
@ -153,11 +153,11 @@ shift(s, type, str, newstate, lineno)
|
|||
int newstate;
|
||||
int lineno;
|
||||
{
|
||||
int err;
|
||||
assert(!s_empty(s));
|
||||
if (PyNode_AddChild(s->s_top->s_parent, type, str, lineno) == NULL) {
|
||||
fprintf(stderr, "shift: no mem in addchild\n");
|
||||
return -1;
|
||||
}
|
||||
err = PyNode_AddChild(s->s_top->s_parent, type, str, lineno);
|
||||
if (err)
|
||||
return err;
|
||||
s->s_top->s_state = newstate;
|
||||
return 0;
|
||||
}
|
||||
|
@ -172,13 +172,13 @@ push(s, type, d, newstate, lineno)
|
|||
int newstate;
|
||||
int lineno;
|
||||
{
|
||||
int err;
|
||||
register node *n;
|
||||
n = s->s_top->s_parent;
|
||||
assert(!s_empty(s));
|
||||
if (PyNode_AddChild(n, type, (char *)NULL, lineno) == NULL) {
|
||||
fprintf(stderr, "push: no mem in addchild\n");
|
||||
return -1;
|
||||
}
|
||||
err = PyNode_AddChild(n, type, (char *)NULL, lineno);
|
||||
if (err)
|
||||
return err;
|
||||
s->s_top->s_state = newstate;
|
||||
return s_push(s, d, CHILD(n, NCH(n)-1));
|
||||
}
|
||||
|
@ -233,6 +233,7 @@ PyParser_AddToken(ps, type, str, lineno)
|
|||
int lineno;
|
||||
{
|
||||
register int ilabel;
|
||||
int err;
|
||||
|
||||
D(printf("Token %s/'%s' ... ", _PyParser_TokenNames[type], str));
|
||||
|
||||
|
@ -260,20 +261,20 @@ PyParser_AddToken(ps, type, str, lineno)
|
|||
int arrow = x & ((1<<7)-1);
|
||||
dfa *d1 = PyGrammar_FindDFA(
|
||||
ps->p_grammar, nt);
|
||||
if (push(&ps->p_stack, nt, d1,
|
||||
arrow, lineno) < 0) {
|
||||
if ((err = push(&ps->p_stack, nt, d1,
|
||||
arrow, lineno)) > 0) {
|
||||
D(printf(" MemError: push\n"));
|
||||
return E_NOMEM;
|
||||
return err;
|
||||
}
|
||||
D(printf(" Push ...\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Shift the token */
|
||||
if (shift(&ps->p_stack, type, str,
|
||||
x, lineno) < 0) {
|
||||
if ((err = shift(&ps->p_stack, type, str,
|
||||
x, lineno)) > 0) {
|
||||
D(printf(" MemError: shift.\n"));
|
||||
return E_NOMEM;
|
||||
return err;
|
||||
}
|
||||
D(printf(" Shift.\n"));
|
||||
/* Pop while we are in an accept-only state */
|
||||
|
|
|
@ -1033,6 +1033,9 @@ err_input(err)
|
|||
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";
|
||||
|
|
Loading…
Reference in New Issue