Commit 745303b0 authored by Thomas Wouters's avatar Thomas Wouters

Support for three-token characters (**=, >>=, <<=) which was written by

Michael Hudson, and support in general for the augmented assignment syntax.
The graminit.c patch is large!
parent ddf8d813
......@@ -37,9 +37,10 @@ fplist: fpdef (',' fpdef)* [',']
stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
#small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt
small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt
expr_stmt: testlist ('=' testlist)*
# For assignments, additional restrictions enforced by the interpreter
small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt
expr_stmt: testlist (augassign testlist | ('=' testlist)*)
augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**='
# For normal assignments, additional restrictions enforced by the interpreter
print_stmt: 'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] )
del_stmt: 'del' exprlist
pass_stmt: 'pass'
......
......@@ -211,6 +211,18 @@ translabel(grammar *g, label *lb)
printf("Unknown OP label %s\n",
lb->lb_str);
}
else if (lb->lb_str[2] && lb->lb_str[3] && lb->lb_str[4] == lb->lb_str[0]) {
int type = (int) PyToken_ThreeChars(lb->lb_str[1],
lb->lb_str[2],
lb->lb_str[3]);
if (type != OP) {
lb->lb_type = type;
lb->lb_str = NULL;
}
else
printf("Unknown OP label %s\n",
lb->lb_str);
}
else
printf("Can't translate STRING label %s\n",
lb->lb_str);
......
......@@ -78,6 +78,17 @@ char *_PyParser_TokenNames[] = {
"LEFTSHIFT",
"RIGHTSHIFT",
"DOUBLESTAR",
"PLUSEQUAL",
"MINEQUAL",
"STAREQUAL",
"SLASHEQUAL",
"PERCENTEQUAL",
"AMPEREQUAL",
"VBAREQUAL",
"CIRCUMFLEXEQUAL",
"LEFTSHIFTEQUAL",
"RIGHTSHIFTEQUAL",
"DOUBLESTAREQUAL",
/* This table must match the #defines in token.h! */
"OP",
"<ERRORTOKEN>",
......@@ -388,15 +399,91 @@ PyToken_TwoChars(int c1, int c2)
case '>': return RIGHTSHIFT;
}
break;
case '+':
switch (c2) {
case '=': return PLUSEQUAL;
}
break;
case '-':
switch (c2) {
case '=': return MINEQUAL;
}
break;
case '*':
switch (c2) {
case '*': return DOUBLESTAR;
case '=': return STAREQUAL;
}
break;
case '/':
switch (c2) {
case '=': return SLASHEQUAL;
}
break;
case '|':
switch (c2) {
case '=': return VBAREQUAL;
}
break;
case '%':
switch (c2) {
case '=': return PERCENTEQUAL;
}
break;
case '&':
switch (c2) {
case '=': return AMPEREQUAL;
}
break;
case '^':
switch (c2) {
case '=': return CIRCUMFLEXEQUAL;
}
break;
}
return OP;
}
int
PyToken_ThreeChars(int c1, int c2, int c3)
{
switch (c1) {
case '<':
switch (c2) {
case '<':
switch (c3) {
case '=':
return LEFTSHIFTEQUAL;
break;
}
break;
}
break;
case '>':
switch (c2) {
case '>':
switch (c3) {
case '=':
return RIGHTSHIFTEQUAL;
break;
}
break;
}
break;
case '*':
switch (c2) {
case '*':
switch (c3) {
case '=':
return DOUBLESTAREQUAL;
break;
}
break;
}
break;
}
return OP;
}
static int
indenterror(struct tok_state *tok)
......@@ -770,6 +857,13 @@ PyTokenizer_Get(register struct tok_state *tok, char **p_start,
int c2 = tok_nextc(tok);
int token = PyToken_TwoChars(c, c2);
if (token != OP) {
int c3 = tok_nextc(tok);
int token3 = PyToken_ThreeChars(c, c2, c3);
if (token3 != OP) {
token = token3;
} else {
tok_backup(tok, c3);
}
*p_start = tok->start;
*p_end = tok->cur;
return token;
......
......@@ -669,12 +669,69 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
PUSH(w);
continue;
case ROT_FOUR:
u = POP();
v = POP();
w = POP();
x = POP();
PUSH(u);
PUSH(x);
PUSH(w);
PUSH(v);
continue;
case DUP_TOP:
v = TOP();
Py_INCREF(v);
PUSH(v);
continue;
case DUP_TOPX:
switch (oparg) {
case 5:
case 4:
case 3:
case 2:
case 1:
x = POP();
if (oparg == 1) break;
w = POP();
if (oparg == 2) break;
v = POP();
if (oparg == 3) break;
u = POP();
if (oparg == 4) break;
t = POP();
break;
default:
fprintf(stderr, "Invalid argument to DUP_TOPX: %d!\n", oparg);
PyErr_SetString(PyExc_SystemError,
"invalid argument to DUP_TOPX");
x = NULL;
}
if (x == NULL)
break;
switch (oparg) {
case 5: PUSH(t);
Py_INCREF(t); /* Fallthrough */
case 4: PUSH(u);
Py_INCREF(u); /* Fallthrough */
case 3: PUSH(v);
Py_INCREF(v); /* Fallthrough */
case 2: PUSH(w);
Py_INCREF(w); /* Fallthrough */
case 1: PUSH(x);
Py_INCREF(x); /* Fallthrough */
}
switch (oparg) {
case 5: PUSH(t); /* Fallthrough */
case 4: PUSH(u); /* Fallthrough */
case 3: PUSH(v); /* Fallthrough */
case 2: PUSH(w); /* Fallthrough */
case 1: PUSH(x); /* Fallthrough */
}
continue;
case UNARY_POSITIVE:
v = POP();
x = PyNumber_Positive(v);
......@@ -890,7 +947,147 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
PUSH(x);
if (x != NULL) continue;
break;
case INPLACE_POWER:
w = POP();
v = POP();
x = PyNumber_InPlacePower(v, w, Py_None);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case INPLACE_MULTIPLY:
w = POP();
v = POP();
x = PyNumber_InPlaceMultiply(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case INPLACE_DIVIDE:
w = POP();
v = POP();
x = PyNumber_InPlaceDivide(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case INPLACE_MODULO:
w = POP();
v = POP();
x = PyNumber_InPlaceRemainder(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case INPLACE_ADD:
w = POP();
v = POP();
if (PyInt_Check(v) && PyInt_Check(w)) {
/* INLINE: int + int */
register long a, b, i;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
i = a + b;
if ((i^a) < 0 && (i^b) < 0) {
PyErr_SetString(PyExc_OverflowError,
"integer addition");
x = NULL;
}
else
x = PyInt_FromLong(i);
}
else
x = PyNumber_InPlaceAdd(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case INPLACE_SUBTRACT:
w = POP();
v = POP();
if (PyInt_Check(v) && PyInt_Check(w)) {
/* INLINE: int - int */
register long a, b, i;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
i = a - b;
if ((i^a) < 0 && (i^~b) < 0) {
PyErr_SetString(PyExc_OverflowError,
"integer subtraction");
x = NULL;
}
else
x = PyInt_FromLong(i);
}
else
x = PyNumber_InPlaceSubtract(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case INPLACE_LSHIFT:
w = POP();
v = POP();
x = PyNumber_InPlaceLshift(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case INPLACE_RSHIFT:
w = POP();
v = POP();
x = PyNumber_InPlaceRshift(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case INPLACE_AND:
w = POP();
v = POP();
x = PyNumber_InPlaceAnd(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case INPLACE_XOR:
w = POP();
v = POP();
x = PyNumber_InPlaceXor(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case INPLACE_OR:
w = POP();
v = POP();
x = PyNumber_InPlaceOr(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case SLICE+0:
case SLICE+1:
case SLICE+2:
......@@ -1063,6 +1260,10 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
stream = NULL;
break;
#ifdef CASE_TOO_BIG
default: switch (opcode) {
#endif
case BREAK_LOOP:
why = WHY_BREAK;
break;
......@@ -1180,10 +1381,6 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
PyErr_SetObject(PyExc_NameError, w);
break;
#ifdef CASE_TOO_BIG
default: switch (opcode) {
#endif
case UNPACK_SEQUENCE:
v = POP();
if (PyTuple_Check(v)) {
......
This diff is collapsed.
This diff is collapsed.
......@@ -66,7 +66,7 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *);
/* XXX Perhaps the magic number should be frozen and a version field
added to the .pyc file header? */
/* New way to come up with the magic number: (YEAR-1995), MONTH, DAY */
#define MAGIC (50821 | ((long)'\r'<<16) | ((long)'\n'<<24))
#define MAGIC (50822 | ((long)'\r'<<16) | ((long)'\n'<<24))
/* Magic word as global; note that _PyImport_Init() can change the
value of this global to accommodate for alterations of how the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment