Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a9d309c

Browse files
authored
Raise IndentationError on indentation-related errors (#111)
1 parent ef0f6fa commit a9d309c

File tree

6 files changed

+45
-42
lines changed

6 files changed

+45
-42
lines changed

Grammar/python.gram

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -523,17 +523,17 @@ t_atom[expr_ty]:
523523

524524
# From here on, there are rules for invalid syntax with specialised error messages
525525
incorrect_arguments:
526-
| args ',' '*' { _PyPegen_raise_syntax_error(p, "iterable argument unpacking follows keyword argument unpacking") }
526+
| args ',' '*' { RAISE_SYNTAX_ERROR("iterable argument unpacking follows keyword argument unpacking") }
527527
| a=args ',' args { _PyPegen_arguments_parsing_error(p, a) }
528528
invalid_named_expression:
529529
| a=expression ':=' expression {
530-
_PyPegen_raise_syntax_error(p, "cannot use assignment expressions with %s", _PyPegen_get_expr_name(a)) }
530+
RAISE_SYNTAX_ERROR("cannot use assignment expressions with %s", _PyPegen_get_expr_name(a)) }
531531
invalid_assignment:
532-
| list ':' { _PyPegen_raise_syntax_error(p, "only single target (not list) can be annotated") }
533-
| tuple ':' { _PyPegen_raise_syntax_error(p, "only single target (not tuple) can be annotated") }
532+
| list ':' { RAISE_SYNTAX_ERROR("only single target (not list) can be annotated") }
533+
| tuple ':' { RAISE_SYNTAX_ERROR("only single target (not tuple) can be annotated") }
534534
| expression ':' expression ['=' annotated_rhs] {
535-
_PyPegen_raise_syntax_error(p, "illegal target for annotation") }
535+
RAISE_SYNTAX_ERROR("illegal target for annotation") }
536536
| a=expression ('=' | augassign) (yield_expr | star_expressions) {
537-
_PyPegen_raise_syntax_error(p, "cannot assign to %s", _PyPegen_get_expr_name(a)) }
537+
RAISE_SYNTAX_ERROR("cannot assign to %s", _PyPegen_get_expr_name(a)) }
538538
invalid_block:
539-
| NEWLINE !INDENT { _PyPegen_raise_syntax_error(p, "expected an indented block") }
539+
| NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") }

Lib/test/test_peg_parser.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,8 @@ def test_incorrect_ast_generation_on_source_files(self) -> None:
711711

712712
def test_incorrect_ast_generation_with_specialized_errors(self) -> None:
713713
for source, error_text in FAIL_SPECIALIZED_MESSAGE_CASES:
714-
with self.assertRaises(SyntaxError) as se:
714+
exc = IndentationError if "indent" in error_text else SyntaxError
715+
with self.assertRaises(exc) as se:
715716
peg_parser.parse_string(source)
716717
self.assertTrue(
717718
error_text in se.exception.msg,

Parser/pegen/parse.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8899,7 +8899,7 @@ incorrect_arguments_rule(Parser *p)
88998899
(literal_1 = _PyPegen_expect_token(p, 16))
89008900
)
89018901
{
8902-
res = _PyPegen_raise_syntax_error ( p , "iterable argument unpacking follows keyword argument unpacking" );
8902+
res = RAISE_SYNTAX_ERROR ( "iterable argument unpacking follows keyword argument unpacking" );
89038903
if (res == NULL && PyErr_Occurred()) {
89048904
longjmp(p->error_env, 1);
89058905
}
@@ -8950,7 +8950,7 @@ invalid_named_expression_rule(Parser *p)
89508950
(expression_var = expression_rule(p))
89518951
)
89528952
{
8953-
res = _PyPegen_raise_syntax_error ( p , "cannot use assignment expressions with %s" , _PyPegen_get_expr_name ( a ) );
8953+
res = RAISE_SYNTAX_ERROR ( "cannot use assignment expressions with %s" , _PyPegen_get_expr_name ( a ) );
89548954
if (res == NULL && PyErr_Occurred()) {
89558955
longjmp(p->error_env, 1);
89568956
}
@@ -8982,7 +8982,7 @@ invalid_assignment_rule(Parser *p)
89828982
(literal = _PyPegen_expect_token(p, 11))
89838983
)
89848984
{
8985-
res = _PyPegen_raise_syntax_error ( p , "only single target (not list) can be annotated" );
8985+
res = RAISE_SYNTAX_ERROR ( "only single target (not list) can be annotated" );
89868986
if (res == NULL && PyErr_Occurred()) {
89878987
longjmp(p->error_env, 1);
89888988
}
@@ -8999,7 +8999,7 @@ invalid_assignment_rule(Parser *p)
89998999
(literal = _PyPegen_expect_token(p, 11))
90009000
)
90019001
{
9002-
res = _PyPegen_raise_syntax_error ( p , "only single target (not tuple) can be annotated" );
9002+
res = RAISE_SYNTAX_ERROR ( "only single target (not tuple) can be annotated" );
90039003
if (res == NULL && PyErr_Occurred()) {
90049004
longjmp(p->error_env, 1);
90059005
}
@@ -9023,7 +9023,7 @@ invalid_assignment_rule(Parser *p)
90239023
(opt_var = _tmp_115_rule(p), 1)
90249024
)
90259025
{
9026-
res = _PyPegen_raise_syntax_error ( p , "illegal target for annotation" );
9026+
res = RAISE_SYNTAX_ERROR ( "illegal target for annotation" );
90279027
if (res == NULL && PyErr_Occurred()) {
90289028
longjmp(p->error_env, 1);
90299029
}
@@ -9043,7 +9043,7 @@ invalid_assignment_rule(Parser *p)
90439043
(_tmp_117_var = _tmp_117_rule(p))
90449044
)
90459045
{
9046-
res = _PyPegen_raise_syntax_error ( p , "cannot assign to %s" , _PyPegen_get_expr_name ( a ) );
9046+
res = RAISE_SYNTAX_ERROR ( "cannot assign to %s" , _PyPegen_get_expr_name ( a ) );
90479047
if (res == NULL && PyErr_Occurred()) {
90489048
longjmp(p->error_env, 1);
90499049
}
@@ -9070,7 +9070,7 @@ invalid_block_rule(Parser *p)
90709070
_PyPegen_lookahead(0, _PyPegen_indent_token, p)
90719071
)
90729072
{
9073-
res = _PyPegen_raise_syntax_error ( p , "expected an indented block" );
9073+
res = RAISE_INDENTATION_ERROR ( "expected an indented block" );
90749074
if (res == NULL && PyErr_Occurred()) {
90759075
longjmp(p->error_env, 1);
90769076
}

Parser/pegen/parse_string.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ warn_invalid_escape_sequence(Parser *p, unsigned char first_invalid_escape_char)
2525
/* Replace the DeprecationWarning exception with a SyntaxError
2626
to get a more accurate error report */
2727
PyErr_Clear();
28-
_PyPegen_raise_syntax_error(p, "invalid escape sequence \\%c", first_invalid_escape_char);
28+
RAISE_SYNTAX_ERROR("invalid escape sequence \\%c", first_invalid_escape_char);
2929
}
3030
Py_DECREF(msg);
3131
return -1;
@@ -228,7 +228,7 @@ _PyPegen_parsestr(Parser *p, const char *s, int *bytesmode, int *rawmode, PyObje
228228
const char *ch;
229229
for (ch = s; *ch; ch++) {
230230
if (Py_CHARMASK(*ch) >= 0x80) {
231-
_PyPegen_raise_syntax_error(p,
231+
RAISE_SYNTAX_ERROR(
232232
"bytes can only contain ASCII "
233233
"literal characters.");
234234
return -1;
@@ -559,7 +559,7 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end,
559559
}
560560
}
561561
if (s == expr_end) {
562-
_PyPegen_raise_syntax_error(p, "f-string: empty expression not allowed");
562+
RAISE_SYNTAX_ERROR("f-string: empty expression not allowed");
563563
return NULL;
564564
}
565565

@@ -662,7 +662,7 @@ fstring_find_literal(Parser *p, const char **str, const char *end, int raw,
662662
single '}' is not allowed. */
663663
if (ch == '}') {
664664
*str = s - 1;
665-
_PyPegen_raise_syntax_error(p, "f-string: single '}' is not allowed");
665+
RAISE_SYNTAX_ERROR("f-string: single '}' is not allowed");
666666
return -1;
667667
}
668668
}
@@ -742,7 +742,7 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec
742742

743743
/* Can only nest one level deep. */
744744
if (recurse_lvl >= 2) {
745-
_PyPegen_raise_syntax_error(p, "f-string: expressions nested too deeply");
745+
RAISE_SYNTAX_ERROR("f-string: expressions nested too deeply");
746746
goto error;
747747
}
748748

@@ -768,7 +768,7 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec
768768
if (ch == '\\') {
769769
/* Error: can't include a backslash character, inside
770770
parens or strings or not. */
771-
_PyPegen_raise_syntax_error(p,
771+
RAISE_SYNTAX_ERROR(
772772
"f-string expression part "
773773
"cannot include a backslash");
774774
goto error;
@@ -815,15 +815,15 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec
815815
quote_char = ch;
816816
} else if (ch == '[' || ch == '{' || ch == '(') {
817817
if (nested_depth >= MAXLEVEL) {
818-
_PyPegen_raise_syntax_error(p, "f-string: too many nested parenthesis");
818+
RAISE_SYNTAX_ERROR("f-string: too many nested parenthesis");
819819
goto error;
820820
}
821821
parenstack[nested_depth] = ch;
822822
nested_depth++;
823823
} else if (ch == '#') {
824824
/* Error: can't include a comment character, inside parens
825825
or not. */
826-
_PyPegen_raise_syntax_error(p, "f-string expression part cannot include '#'");
826+
RAISE_SYNTAX_ERROR("f-string expression part cannot include '#'");
827827
goto error;
828828
} else if (nested_depth == 0 &&
829829
(ch == '!' || ch == ':' || ch == '}' ||
@@ -854,7 +854,7 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec
854854
break;
855855
} else if (ch == ']' || ch == '}' || ch == ')') {
856856
if (!nested_depth) {
857-
_PyPegen_raise_syntax_error(p, "f-string: unmatched '%c'", ch);
857+
RAISE_SYNTAX_ERROR("f-string: unmatched '%c'", ch);
858858
goto error;
859859
}
860860
nested_depth--;
@@ -863,7 +863,7 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec
863863
(opening == '[' && ch == ']') ||
864864
(opening == '{' && ch == '}')))
865865
{
866-
_PyPegen_raise_syntax_error(p,
866+
RAISE_SYNTAX_ERROR(
867867
"f-string: closing parenthesis '%c' "
868868
"does not match opening parenthesis '%c'",
869869
ch, opening);
@@ -879,12 +879,12 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec
879879
expression. But, we can produce a better error message, so
880880
let's just do that.*/
881881
if (quote_char) {
882-
_PyPegen_raise_syntax_error(p, "f-string: unterminated string");
882+
RAISE_SYNTAX_ERROR("f-string: unterminated string");
883883
goto error;
884884
}
885885
if (nested_depth) {
886886
int opening = parenstack[nested_depth - 1];
887-
_PyPegen_raise_syntax_error(p, "f-string: unmatched '%c'", opening);
887+
RAISE_SYNTAX_ERROR("f-string: unmatched '%c'", opening);
888888
goto error;
889889
}
890890

@@ -928,7 +928,7 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec
928928

929929
/* Validate the conversion. */
930930
if (!(conversion == 's' || conversion == 'r' || conversion == 'a')) {
931-
_PyPegen_raise_syntax_error(p,
931+
RAISE_SYNTAX_ERROR(
932932
"f-string: invalid conversion character: "
933933
"expected 's', 'r', or 'a'");
934934
goto error;
@@ -978,7 +978,7 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec
978978
return 0;
979979

980980
unexpected_end_of_string:
981-
_PyPegen_raise_syntax_error(p, "f-string: expecting '}'");
981+
RAISE_SYNTAX_ERROR("f-string: expecting '}'");
982982
/* Falls through to error. */
983983

984984
error:
@@ -1307,11 +1307,11 @@ _PyPegen_FstringParser_ConcatFstring(Parser *p, FstringParser *state, const char
13071307
string. Otherwise, we must be at a right brace. */
13081308

13091309
if (recurse_lvl == 0 && *str < end-1) {
1310-
_PyPegen_raise_syntax_error(p, "f-string: unexpected end of string");
1310+
RAISE_SYNTAX_ERROR("f-string: unexpected end of string");
13111311
return -1;
13121312
}
13131313
if (recurse_lvl != 0 && **str != '}') {
1314-
_PyPegen_raise_syntax_error(p, "f-string: expecting '}'");
1314+
RAISE_SYNTAX_ERROR("f-string: expecting '}'");
13151315
return -1;
13161316
}
13171317

Parser/pegen/pegen.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ get_error_line(char *buffer)
283283
}
284284

285285
void *
286-
_PyPegen_raise_syntax_error(Parser *p, const char *errmsg, ...)
286+
_PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...)
287287
{
288288
PyObject *value = NULL;
289289
PyObject *errstr = NULL;
@@ -327,7 +327,7 @@ _PyPegen_raise_syntax_error(Parser *p, const char *errmsg, ...)
327327
if (!value) {
328328
goto error;
329329
}
330-
PyErr_SetObject(PyExc_SyntaxError, value);
330+
PyErr_SetObject(errtype, value);
331331

332332
Py_DECREF(errstr);
333333
Py_DECREF(value);
@@ -355,7 +355,7 @@ void *_PyPegen_arguments_parsing_error(Parser *p, expr_ty e) {
355355
msg = "positional argument follows keyword argument";
356356
}
357357

358-
return _PyPegen_raise_syntax_error(p, msg);
358+
return RAISE_SYNTAX_ERROR(msg);
359359
}
360360

361361
#if 0
@@ -835,17 +835,17 @@ _PyPegen_run_parser(Parser *p)
835835
return NULL;
836836
}
837837
if (p->fill == 0) {
838-
_PyPegen_raise_syntax_error(p, "error at start before reading any input");
838+
RAISE_SYNTAX_ERROR("error at start before reading any input");
839839
}
840840
else {
841841
if (p->tokens[p->fill-1]->type == INDENT) {
842-
_PyPegen_raise_syntax_error(p, "unexpected indent");
842+
RAISE_INDENTATION_ERROR("unexpected indent");
843843
}
844844
else if (p->tokens[p->fill-1]->type == DEDENT) {
845-
_PyPegen_raise_syntax_error(p, "unexpected unindent");
845+
RAISE_INDENTATION_ERROR("unexpected unindent");
846846
}
847847
else {
848-
_PyPegen_raise_syntax_error(p, "invalid syntax");
848+
RAISE_SYNTAX_ERROR("invalid syntax");
849849
}
850850
}
851851
return NULL;
@@ -1709,7 +1709,7 @@ _PyPegen_concatenate_strings(Parser *p, asdl_seq *strings)
17091709

17101710
/* Check that we are not mixing bytes with unicode. */
17111711
if (i != 0 && bytesmode != this_bytesmode) {
1712-
_PyPegen_raise_syntax_error(p, "cannot mix bytes and nonbytes literals");
1712+
RAISE_SYNTAX_ERROR("cannot mix bytes and nonbytes literals");
17131713
Py_XDECREF(s);
17141714
goto error;
17151715
}
@@ -1775,12 +1775,12 @@ _PyPegen_concatenate_strings(Parser *p, asdl_seq *strings)
17751775
PyErr_Fetch(&type, &value, &tback);
17761776
errstr = PyObject_Str(value);
17771777
if (errstr) {
1778-
_PyPegen_raise_syntax_error(p, "(%s) %U", errtype, errstr);
1778+
RAISE_SYNTAX_ERROR("(%s) %U", errtype, errstr);
17791779
Py_DECREF(errstr);
17801780
}
17811781
else {
17821782
PyErr_Clear();
1783-
_PyPegen_raise_syntax_error(p, "(%s) unknown error", errtype);
1783+
RAISE_SYNTAX_ERROR("(%s) unknown error", errtype);
17841784
}
17851785
Py_XDECREF(type);
17861786
Py_XDECREF(value);

Parser/pegen/pegen.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,14 @@ void *_PyPegen_dedent_token(Parser *p);
100100
expr_ty _PyPegen_number_token(Parser *p);
101101
void *_PyPegen_string_token(Parser *p);
102102
const char *_PyPegen_get_expr_name(expr_ty);
103-
void *_PyPegen_raise_syntax_error(Parser *p, const char *errmsg, ...);
103+
void *_PyPegen_raise_error(Parser *p, PyObject *, const char *errmsg, ...);
104104
void *_PyPegen_dummy_name(Parser *p, ...);
105105

106106
#define UNUSED(expr) do { (void)(expr); } while (0)
107107
#define EXTRA_EXPR(head, tail) head->lineno, head->col_offset, tail->end_lineno, tail->end_col_offset, p->arena
108108
#define EXTRA start_lineno, start_col_offset, end_lineno, end_col_offset, p->arena
109+
#define RAISE_SYNTAX_ERROR(msg, ...) _PyPegen_raise_error(p, PyExc_SyntaxError, msg, ##__VA_ARGS__)
110+
#define RAISE_INDENTATION_ERROR(msg, ...) _PyPegen_raise_error(p, PyExc_IndentationError, msg, ##__VA_ARGS__)
109111

110112
Py_LOCAL_INLINE(void *)
111113
CHECK_CALL(Parser *p, void *result)

0 commit comments

Comments
 (0)