class TokenTests(unittest.TestCase):
+ check_syntax_error = check_syntax_error
+
def test_backslash(self):
# Backslash means line continuation:
x = 1 \
# Sanity check: no literal begins with an underscore
self.assertRaises(NameError, eval, "_0")
+ def test_bad_numerical_literals(self):
+ check = self.check_syntax_error
+ check("0b12", "invalid digit '2' in binary literal")
+ check("0b1_2", "invalid digit '2' in binary literal")
+ check("0b2", "invalid digit '2' in binary literal")
+ check("0b1_", "invalid binary literal")
+ check("0b", "invalid binary literal")
+ check("0o18", "invalid digit '8' in octal literal")
+ check("0o1_8", "invalid digit '8' in octal literal")
+ check("0o8", "invalid digit '8' in octal literal")
+ check("0o1_", "invalid octal literal")
+ check("0o", "invalid octal literal")
+ check("0x1_", "invalid hexadecimal literal")
+ check("0x", "invalid hexadecimal literal")
+ check("1_", "invalid decimal literal")
+ check("012",
+ "leading zeros in decimal integer literals are not permitted; "
+ "use an 0o prefix for octal integers")
+ check("1.2_", "invalid decimal literal")
+ check("1e2_", "invalid decimal literal")
+ check("1e+", "invalid decimal literal")
+
def test_string_literals(self):
x = ''; y = ""; self.assertTrue(len(x) == 0 and x == y)
x = '\''; y = "'"; self.assertTrue(len(x) == 1 and x == y and ord(x) == 39)
return OP;
}
+static int
+syntaxerror(struct tok_state *tok, const char *format, ...)
+{
+#ifndef PGEN
+ va_list vargs;
+#ifdef HAVE_STDARG_PROTOTYPES
+ va_start(vargs, format);
+#else
+ va_start(vargs);
+#endif
+ PyErr_FormatV(PyExc_SyntaxError, format, vargs);
+ va_end(vargs);
+ PyErr_SyntaxLocationObject(tok->filename,
+ tok->lineno,
+ tok->cur - tok->line_start);
+ tok->done = E_ERROR;
+#else
+ tok->done = E_TOKEN;
+#endif
+ return ERRORTOKEN;
+}
+
static int
indenterror(struct tok_state *tok)
{
}
c = tok_nextc(tok);
if (!isdigit(c)) {
- tok->done = E_TOKEN;
tok_backup(tok, c);
+ syntaxerror(tok, "invalid decimal literal");
return 0;
}
}
c = tok_nextc(tok);
}
if (!isxdigit(c)) {
- tok->done = E_TOKEN;
tok_backup(tok, c);
- return ERRORTOKEN;
+ return syntaxerror(tok, "invalid hexadecimal literal");
}
do {
c = tok_nextc(tok);
c = tok_nextc(tok);
}
if (c < '0' || c >= '8') {
- tok->done = E_TOKEN;
tok_backup(tok, c);
- return ERRORTOKEN;
+ if (isdigit(c)) {
+ return syntaxerror(tok,
+ "invalid digit '%c' in octal literal", c);
+ }
+ else {
+ return syntaxerror(tok, "invalid octal literal");
+ }
}
do {
c = tok_nextc(tok);
} while ('0' <= c && c < '8');
} while (c == '_');
+ if (isdigit(c)) {
+ return syntaxerror(tok,
+ "invalid digit '%c' in octal literal", c);
+ }
}
else if (c == 'b' || c == 'B') {
/* Binary */
c = tok_nextc(tok);
}
if (c != '0' && c != '1') {
- tok->done = E_TOKEN;
tok_backup(tok, c);
- return ERRORTOKEN;
+ if (isdigit(c)) {
+ return syntaxerror(tok,
+ "invalid digit '%c' in binary literal", c);
+ }
+ else {
+ return syntaxerror(tok, "invalid binary literal");
+ }
}
do {
c = tok_nextc(tok);
} while (c == '0' || c == '1');
} while (c == '_');
+ if (isdigit(c)) {
+ return syntaxerror(tok,
+ "invalid digit '%c' in binary literal", c);
+ }
}
else {
int nonzero = 0;
if (c == '_') {
c = tok_nextc(tok);
if (!isdigit(c)) {
- tok->done = E_TOKEN;
tok_backup(tok, c);
- return ERRORTOKEN;
+ return syntaxerror(tok, "invalid decimal literal");
}
}
if (c != '0') {
}
else if (nonzero) {
/* Old-style octal: now disallowed. */
- tok->done = E_TOKEN;
tok_backup(tok, c);
- return ERRORTOKEN;
+ return syntaxerror(tok,
+ "leading zeros in decimal integer "
+ "literals are not permitted; "
+ "use an 0o prefix for octal integers");
}
}
}
if (c == '+' || c == '-') {
c = tok_nextc(tok);
if (!isdigit(c)) {
- tok->done = E_TOKEN;
tok_backup(tok, c);
- return ERRORTOKEN;
+ return syntaxerror(tok, "invalid decimal literal");
}
} else if (!isdigit(c)) {
tok_backup(tok, c);