Kaydet (Commit) 434d0828 authored tarafından 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!
üst dd8dbdb7
...@@ -37,9 +37,10 @@ fplist: fpdef (',' fpdef)* [','] ...@@ -37,9 +37,10 @@ fplist: fpdef (',' fpdef)* [',']
stmt: simple_stmt | compound_stmt stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE 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 | access_stmt | exec_stmt
small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_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)* expr_stmt: testlist (augassign testlist | ('=' testlist)*)
# For assignments, additional restrictions enforced by the interpreter augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**='
# For normal assignments, additional restrictions enforced by the interpreter
print_stmt: 'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] ) print_stmt: 'print' ( [ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ] )
del_stmt: 'del' exprlist del_stmt: 'del' exprlist
pass_stmt: 'pass' pass_stmt: 'pass'
......
...@@ -211,6 +211,18 @@ translabel(grammar *g, label *lb) ...@@ -211,6 +211,18 @@ translabel(grammar *g, label *lb)
printf("Unknown OP label %s\n", printf("Unknown OP label %s\n",
lb->lb_str); 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 else
printf("Can't translate STRING label %s\n", printf("Can't translate STRING label %s\n",
lb->lb_str); lb->lb_str);
......
...@@ -78,6 +78,17 @@ char *_PyParser_TokenNames[] = { ...@@ -78,6 +78,17 @@ char *_PyParser_TokenNames[] = {
"LEFTSHIFT", "LEFTSHIFT",
"RIGHTSHIFT", "RIGHTSHIFT",
"DOUBLESTAR", "DOUBLESTAR",
"PLUSEQUAL",
"MINEQUAL",
"STAREQUAL",
"SLASHEQUAL",
"PERCENTEQUAL",
"AMPEREQUAL",
"VBAREQUAL",
"CIRCUMFLEXEQUAL",
"LEFTSHIFTEQUAL",
"RIGHTSHIFTEQUAL",
"DOUBLESTAREQUAL",
/* This table must match the #defines in token.h! */ /* This table must match the #defines in token.h! */
"OP", "OP",
"<ERRORTOKEN>", "<ERRORTOKEN>",
...@@ -388,15 +399,91 @@ PyToken_TwoChars(int c1, int c2) ...@@ -388,15 +399,91 @@ PyToken_TwoChars(int c1, int c2)
case '>': return RIGHTSHIFT; case '>': return RIGHTSHIFT;
} }
break; break;
case '+':
switch (c2) {
case '=': return PLUSEQUAL;
}
break;
case '-':
switch (c2) {
case '=': return MINEQUAL;
}
break;
case '*': case '*':
switch (c2) { switch (c2) {
case '*': return DOUBLESTAR; 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; break;
} }
return OP; 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 static int
indenterror(struct tok_state *tok) indenterror(struct tok_state *tok)
...@@ -770,6 +857,13 @@ PyTokenizer_Get(register struct tok_state *tok, char **p_start, ...@@ -770,6 +857,13 @@ PyTokenizer_Get(register struct tok_state *tok, char **p_start,
int c2 = tok_nextc(tok); int c2 = tok_nextc(tok);
int token = PyToken_TwoChars(c, c2); int token = PyToken_TwoChars(c, c2);
if (token != OP) { 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_start = tok->start;
*p_end = tok->cur; *p_end = tok->cur;
return token; return token;
......
...@@ -669,12 +669,69 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -669,12 +669,69 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
PUSH(w); PUSH(w);
continue; continue;
case ROT_FOUR:
u = POP();
v = POP();
w = POP();
x = POP();
PUSH(u);
PUSH(x);
PUSH(w);
PUSH(v);
continue;
case DUP_TOP: case DUP_TOP:
v = TOP(); v = TOP();
Py_INCREF(v); Py_INCREF(v);
PUSH(v); PUSH(v);
continue; 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: case UNARY_POSITIVE:
v = POP(); v = POP();
x = PyNumber_Positive(v); x = PyNumber_Positive(v);
...@@ -890,7 +947,147 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -890,7 +947,147 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
PUSH(x); PUSH(x);
if (x != NULL) continue; if (x != NULL) continue;
break; 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+0:
case SLICE+1: case SLICE+1:
case SLICE+2: case SLICE+2:
...@@ -1063,6 +1260,10 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -1063,6 +1260,10 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
stream = NULL; stream = NULL;
break; break;
#ifdef CASE_TOO_BIG
default: switch (opcode) {
#endif
case BREAK_LOOP: case BREAK_LOOP:
why = WHY_BREAK; why = WHY_BREAK;
break; break;
...@@ -1180,10 +1381,6 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -1180,10 +1381,6 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
PyErr_SetObject(PyExc_NameError, w); PyErr_SetObject(PyExc_NameError, w);
break; break;
#ifdef CASE_TOO_BIG
default: switch (opcode) {
#endif
case UNPACK_SEQUENCE: case UNPACK_SEQUENCE:
v = POP(); v = POP();
if (PyTuple_Check(v)) { if (PyTuple_Check(v)) {
......
This diff is collapsed.
This diff is collapsed.
...@@ -66,7 +66,7 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *); ...@@ -66,7 +66,7 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *);
/* XXX Perhaps the magic number should be frozen and a version field /* XXX Perhaps the magic number should be frozen and a version field
added to the .pyc file header? */ added to the .pyc file header? */
/* New way to come up with the magic number: (YEAR-1995), MONTH, DAY */ /* 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 /* Magic word as global; note that _PyImport_Init() can change the
value of this global to accommodate for alterations of how 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