Skip to content

Commit b28ffaa

Browse files
authored
gh-109596: Ensure repeated rules in the grammar are not allowed and fix incorrect soft keywords (#109606)
1 parent 7c55399 commit b28ffaa

File tree

7 files changed

+1203
-1219
lines changed

7 files changed

+1203
-1219
lines changed

Grammar/python.gram

+4-7
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ _PyPegen_parse(Parser *p)
1919
result = eval_rule(p);
2020
} else if (p->start_rule == Py_func_type_input) {
2121
result = func_type_rule(p);
22-
} else if (p->start_rule == Py_fstring_input) {
23-
result = fstring_rule(p);
2422
}
2523

2624
return result;
@@ -89,7 +87,6 @@ file[mod_ty]: a=[statements] ENDMARKER { _PyPegen_make_module(p, a) }
8987
interactive[mod_ty]: a=statement_newline { _PyAST_Interactive(a, p->arena) }
9088
eval[mod_ty]: a=expressions NEWLINE* ENDMARKER { _PyAST_Expression(a, p->arena) }
9189
func_type[mod_ty]: '(' a=[type_expressions] ')' '->' b=expression NEWLINE* ENDMARKER { _PyAST_FunctionType(a, b, p->arena) }
92-
fstring[expr_ty]: star_expressions
9390

9491
# GENERAL STATEMENTS
9592
# ==================
@@ -647,20 +644,20 @@ type_param_seq[asdl_type_param_seq*]: a[asdl_type_param_seq*]=','.type_param+ ['
647644

648645
type_param[type_param_ty] (memo):
649646
| a=NAME b=[type_param_bound] { _PyAST_TypeVar(a->v.Name.id, b, EXTRA) }
650-
| '*' a=NAME colon=":" e=expression {
647+
| '*' a=NAME colon=':' e=expression {
651648
RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind
652649
? "cannot use constraints with TypeVarTuple"
653650
: "cannot use bound with TypeVarTuple")
654651
}
655652
| '*' a=NAME { _PyAST_TypeVarTuple(a->v.Name.id, EXTRA) }
656-
| '**' a=NAME colon=":" e=expression {
653+
| '**' a=NAME colon=':' e=expression {
657654
RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind
658655
? "cannot use constraints with ParamSpec"
659656
: "cannot use bound with ParamSpec")
660657
}
661658
| '**' a=NAME { _PyAST_ParamSpec(a->v.Name.id, EXTRA) }
662659

663-
type_param_bound[expr_ty]: ":" e=expression { e }
660+
type_param_bound[expr_ty]: ':' e=expression { e }
664661

665662
# EXPRESSIONS
666663
# -----------
@@ -915,7 +912,7 @@ fstring_middle[expr_ty]:
915912
| fstring_replacement_field
916913
| t=FSTRING_MIDDLE { _PyPegen_constant_from_token(p, t) }
917914
fstring_replacement_field[expr_ty]:
918-
| '{' a=(yield_expr | star_expressions) debug_expr="="? conversion=[fstring_conversion] format=[fstring_full_format_spec] rbrace='}' {
915+
| '{' a=(yield_expr | star_expressions) debug_expr='='? conversion=[fstring_conversion] format=[fstring_full_format_spec] rbrace='}' {
919916
_PyPegen_formatted_value(p, a, debug_expr, conversion, format, rbrace, EXTRA) }
920917
| invalid_replacement_field
921918
fstring_conversion[ResultTokenWithMetadata*]:

Include/compile.h

-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ extern "C" {
1010
#define Py_eval_input 258
1111
#define Py_func_type_input 345
1212

13-
/* This doesn't need to match anything */
14-
#define Py_fstring_input 800
15-
1613
#ifndef Py_LIMITED_API
1714
# define Py_CPYTHON_COMPILE_H
1815
# include "cpython/compile.h"

Lib/test/test_peg_generator/test_pegen.py

+9
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ def test_parse_grammar(self) -> None:
4242
)
4343
self.assertEqual(repr(rules["term"]), expected_repr)
4444

45+
def test_repeated_rules(self) -> None:
46+
grammar_source = """
47+
start: the_rule NEWLINE
48+
the_rule: 'b' NEWLINE
49+
the_rule: 'a' NEWLINE
50+
"""
51+
with self.assertRaisesRegex(GrammarError, "Repeated rule 'the_rule'"):
52+
parse_string(grammar_source, GrammarParser)
53+
4554
def test_long_rule_str(self) -> None:
4655
grammar_source = """
4756
start: zero | one | one zero | one one | one zero zero | one zero one | one one zero | one one one
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix some tokens in the grammar that were incorrectly marked as soft
2+
keywords. Also fix some repeated rule names and ensure that repeated rules
3+
are not allowed. Patch by Pablo Galindo

0 commit comments

Comments
 (0)