bpo-43833: Emit warnings for numeric literals followed by keyword (GH… · python/cpython@2ea6d89

GitHub

@@ -1121,6 +1121,113 @@ indenterror(struct tok_state *tok)

11211121returnERRORTOKEN;

11221122}

112311231124+staticint

1125+parser_warn(structtok_state*tok, constchar*format, ...)

1126+{

1127+PyObject*errmsg;

1128+va_listvargs;

1129+#ifdefHAVE_STDARG_PROTOTYPES

1130+va_start(vargs, format);

1131+#else

1132+va_start(vargs);

1133+#endif

1134+errmsg=PyUnicode_FromFormatV(format, vargs);

1135+va_end(vargs);

1136+if (!errmsg) {

1137+ goto error;

1138+ }

1139+1140+if (PyErr_WarnExplicitObject(PyExc_DeprecationWarning, errmsg, tok->filename,

1141+tok->lineno, NULL, NULL) <0) {

1142+if (PyErr_ExceptionMatches(PyExc_DeprecationWarning)) {

1143+/* Replace the DeprecationWarning exception with a SyntaxError

1144+ to get a more accurate error report */

1145+PyErr_Clear();

1146+syntaxerror(tok, "%U", errmsg);

1147+ }

1148+ goto error;

1149+ }

1150+Py_DECREF(errmsg);

1151+return0;

1152+1153+error:

1154+Py_XDECREF(errmsg);

1155+tok->done=E_ERROR;

1156+return-1;

1157+}

1158+1159+staticint

1160+lookahead(structtok_state*tok, constchar*test)

1161+{

1162+constchar*s=test;

1163+intres=0;

1164+while (1) {

1165+intc=tok_nextc(tok);

1166+if (*s==0) {

1167+res= !is_potential_identifier_char(c);

1168+ }

1169+elseif (c==*s) {

1170+s++;

1171+continue;

1172+ }

1173+1174+tok_backup(tok, c);

1175+while (s!=test) {

1176+tok_backup(tok, *--s);

1177+ }

1178+returnres;

1179+ }

1180+}

1181+1182+staticint

1183+verify_end_of_number(structtok_state*tok, intc, constchar*kind)

1184+{

1185+/* Emit a deprecation warning only if the numeric literal is immediately

1186+ * followed by one of keywords which can occurr after a numeric literal

1187+ * in valid code: "and", "else", "for", "if", "in", "is" and "or".

1188+ * It allows to gradually deprecate existing valid code without adding

1189+ * warning before error in most cases of invalid numeric literal (which

1190+ * would be confusiong and break existing tests).

1191+ * Raise a syntax error with slighly better message than plain

1192+ * "invalid syntax" if the numeric literal is immediately followed by

1193+ * other keyword or identifier.

1194+ */

1195+intr=0;

1196+if (c=='a') {

1197+r=lookahead(tok, "nd");

1198+ }

1199+elseif (c=='e') {

1200+r=lookahead(tok, "lse");

1201+ }

1202+elseif (c=='f') {

1203+r=lookahead(tok, "or");

1204+ }

1205+elseif (c=='i') {

1206+intc2=tok_nextc(tok);

1207+if (c2=='f'||c2=='n'||c2=='s') {

1208+r=1;

1209+ }

1210+tok_backup(tok, c2);

1211+ }

1212+elseif (c=='o') {

1213+r=lookahead(tok, "r");

1214+ }

1215+if (r) {

1216+tok_backup(tok, c);

1217+if (parser_warn(tok, "invalid %s literal", kind)) {

1218+return0;

1219+ }

1220+tok_nextc(tok);

1221+ }

1222+else/* In future releases, only error will remain. */

1223+if (is_potential_identifier_char(c)) {

1224+tok_backup(tok, c);

1225+syntaxerror(tok, "invalid %s literal", kind);

1226+return0;

1227+ }

1228+return1;

1229+}

1230+11241231/* Verify that the identifier follows PEP 3131.

11251232 All identifier strings are guaranteed to be "ready" unicode objects.

11261233 */

@@ -1569,6 +1676,9 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end)

15691676c=tok_nextc(tok);

15701677 } while (isxdigit(c));

15711678 } while (c=='_');

1679+if (!verify_end_of_number(tok, c, "hexadecimal")) {

1680+returnERRORTOKEN;

1681+ }

15721682 }

15731683elseif (c=='o'||c=='O') {

15741684/* Octal */

@@ -1595,6 +1705,9 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end)

15951705returnsyntaxerror(tok,

15961706"invalid digit '%c' in octal literal", c);

15971707 }

1708+if (!verify_end_of_number(tok, c, "octal")) {

1709+returnERRORTOKEN;

1710+ }

15981711 }

15991712elseif (c=='b'||c=='B') {

16001713/* Binary */

@@ -1621,6 +1734,9 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end)

16211734returnsyntaxerror(tok,

16221735"invalid digit '%c' in binary literal", c);

16231736 }

1737+if (!verify_end_of_number(tok, c, "binary")) {

1738+returnERRORTOKEN;

1739+ }

16241740 }

16251741else {

16261742intnonzero=0;

@@ -1664,6 +1780,9 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end)

16641780"literals are not permitted; "

16651781"use an 0o prefix for octal integers");

16661782 }

1783+if (!verify_end_of_number(tok, c, "decimal")) {

1784+returnERRORTOKEN;

1785+ }

16671786 }

16681787 }

16691788else {

@@ -1699,6 +1818,9 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end)

16991818 }

17001819 } elseif (!isdigit(c)) {

17011820tok_backup(tok, c);

1821+if (!verify_end_of_number(tok, e, "decimal")) {

1822+returnERRORTOKEN;

1823+ }

17021824tok_backup(tok, e);

17031825*p_start=tok->start;

17041826*p_end=tok->cur;

@@ -1713,6 +1835,12 @@ tok_get(struct tok_state *tok, const char **p_start, const char **p_end)

17131835/* Imaginary part */

17141836imaginary:

17151837c=tok_nextc(tok);

1838+if (!verify_end_of_number(tok, c, "imaginary")) {

1839+returnERRORTOKEN;

1840+ }

1841+ }

1842+elseif (!verify_end_of_number(tok, c, "decimal")) {

1843+returnERRORTOKEN;

17161844 }

17171845 }

17181846 }