2020-06-11 20:51:44 -03:00
|
|
|
# PEG grammar for Python
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
@trailer '''
|
|
|
|
void *
|
|
|
|
_PyPegen_parse(Parser *p)
|
|
|
|
{
|
|
|
|
// Initialize keywords
|
|
|
|
p->keywords = reserved_keywords;
|
|
|
|
p->n_keyword_lists = n_keyword_lists;
|
2021-04-15 17:38:45 -03:00
|
|
|
p->soft_keywords = soft_keywords;
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
// Run parser
|
|
|
|
void *result = NULL;
|
|
|
|
if (p->start_rule == Py_file_input) {
|
|
|
|
result = file_rule(p);
|
|
|
|
} else if (p->start_rule == Py_single_input) {
|
|
|
|
result = interactive_rule(p);
|
|
|
|
} else if (p->start_rule == Py_eval_input) {
|
|
|
|
result = eval_rule(p);
|
2020-04-30 16:12:19 -03:00
|
|
|
} else if (p->start_rule == Py_func_type_input) {
|
|
|
|
result = func_type_rule(p);
|
2020-04-22 19:29:27 -03:00
|
|
|
} else if (p->start_rule == Py_fstring_input) {
|
|
|
|
result = fstring_rule(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The end
|
|
|
|
'''
|
2020-04-30 16:12:19 -03:00
|
|
|
file[mod_ty]: a=[statements] ENDMARKER { _PyPegen_make_module(p, a) }
|
2021-04-07 16:34:22 -03:00
|
|
|
interactive[mod_ty]: a=statement_newline { _PyAST_Interactive(a, p->arena) }
|
|
|
|
eval[mod_ty]: a=expressions NEWLINE* ENDMARKER { _PyAST_Expression(a, p->arena) }
|
|
|
|
func_type[mod_ty]: '(' a=[type_expressions] ')' '->' b=expression NEWLINE* ENDMARKER { _PyAST_FunctionType(a, b, p->arena) }
|
2020-04-22 19:29:27 -03:00
|
|
|
fstring[expr_ty]: star_expressions
|
|
|
|
|
2020-04-30 16:12:19 -03:00
|
|
|
# type_expressions allow */** but ignore them
|
2020-09-16 15:42:00 -03:00
|
|
|
type_expressions[asdl_expr_seq*]:
|
2020-04-30 16:12:19 -03:00
|
|
|
| a=','.expression+ ',' '*' b=expression ',' '**' c=expression {
|
2020-10-21 16:53:14 -03:00
|
|
|
(asdl_expr_seq*)_PyPegen_seq_append_to_end(
|
|
|
|
p,
|
|
|
|
CHECK(asdl_seq*, _PyPegen_seq_append_to_end(p, a, b)),
|
|
|
|
c) }
|
2020-09-16 15:42:00 -03:00
|
|
|
| a=','.expression+ ',' '*' b=expression { (asdl_expr_seq*)_PyPegen_seq_append_to_end(p, a, b) }
|
|
|
|
| a=','.expression+ ',' '**' b=expression { (asdl_expr_seq*)_PyPegen_seq_append_to_end(p, a, b) }
|
2020-05-04 02:08:14 -03:00
|
|
|
| '*' a=expression ',' '**' b=expression {
|
2020-10-21 16:53:14 -03:00
|
|
|
(asdl_expr_seq*)_PyPegen_seq_append_to_end(
|
|
|
|
p,
|
|
|
|
CHECK(asdl_seq*, _PyPegen_singleton_seq(p, a)),
|
|
|
|
b) }
|
2020-09-16 15:42:00 -03:00
|
|
|
| '*' a=expression { (asdl_expr_seq*)_PyPegen_singleton_seq(p, a) }
|
|
|
|
| '**' a=expression { (asdl_expr_seq*)_PyPegen_singleton_seq(p, a) }
|
|
|
|
| a[asdl_expr_seq*]=','.expression+ {a}
|
|
|
|
|
|
|
|
statements[asdl_stmt_seq*]: a=statement+ { (asdl_stmt_seq*)_PyPegen_seq_flatten(p, a) }
|
2020-11-30 15:42:38 -04:00
|
|
|
statement[asdl_stmt_seq*]: a=compound_stmt { (asdl_stmt_seq*)_PyPegen_singleton_seq(p, a) } | a[asdl_stmt_seq*]=simple_stmts { a }
|
2020-09-16 15:42:00 -03:00
|
|
|
statement_newline[asdl_stmt_seq*]:
|
|
|
|
| a=compound_stmt NEWLINE { (asdl_stmt_seq*)_PyPegen_singleton_seq(p, a) }
|
2020-11-30 15:42:38 -04:00
|
|
|
| simple_stmts
|
2021-04-07 16:34:22 -03:00
|
|
|
| NEWLINE { (asdl_stmt_seq*)_PyPegen_singleton_seq(p, CHECK(stmt_ty, _PyAST_Pass(EXTRA))) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| ENDMARKER { _PyPegen_interactive_exit(p) }
|
2020-11-30 15:42:38 -04:00
|
|
|
simple_stmts[asdl_stmt_seq*]:
|
|
|
|
| a=simple_stmt !';' NEWLINE { (asdl_stmt_seq*)_PyPegen_singleton_seq(p, a) } # Not needed, there for speedup
|
|
|
|
| a[asdl_stmt_seq*]=';'.simple_stmt+ [';'] NEWLINE { a }
|
2020-04-22 19:29:27 -03:00
|
|
|
# NOTE: assignment MUST precede expression, else parsing a simple assignment
|
|
|
|
# will throw a SyntaxError.
|
2020-11-30 15:42:38 -04:00
|
|
|
simple_stmt[stmt_ty] (memo):
|
2020-04-22 19:29:27 -03:00
|
|
|
| assignment
|
2021-04-07 16:34:22 -03:00
|
|
|
| e=star_expressions { _PyAST_Expr(e, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| &'return' return_stmt
|
|
|
|
| &('import' | 'from') import_stmt
|
|
|
|
| &'raise' raise_stmt
|
2021-04-07 16:34:22 -03:00
|
|
|
| 'pass' { _PyAST_Pass(EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| &'del' del_stmt
|
|
|
|
| &'yield' yield_stmt
|
|
|
|
| &'assert' assert_stmt
|
2021-04-07 16:34:22 -03:00
|
|
|
| 'break' { _PyAST_Break(EXTRA) }
|
|
|
|
| 'continue' { _PyAST_Continue(EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| &'global' global_stmt
|
|
|
|
| &'nonlocal' nonlocal_stmt
|
|
|
|
compound_stmt[stmt_ty]:
|
|
|
|
| &('def' | '@' | ASYNC) function_def
|
|
|
|
| &'if' if_stmt
|
|
|
|
| &('class' | '@') class_def
|
|
|
|
| &('with' | ASYNC) with_stmt
|
|
|
|
| &('for' | ASYNC) for_stmt
|
|
|
|
| &'try' try_stmt
|
|
|
|
| &'while' while_stmt
|
2021-02-26 18:51:55 -04:00
|
|
|
| match_stmt
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
# NOTE: annotated_rhs may start with 'yield'; yield_expr must start with 'yield'
|
2020-05-06 15:11:04 -03:00
|
|
|
assignment[stmt_ty]:
|
2020-04-22 19:29:27 -03:00
|
|
|
| a=NAME ':' b=expression c=['=' d=annotated_rhs { d }] {
|
2020-05-01 00:27:52 -03:00
|
|
|
CHECK_VERSION(
|
2020-10-21 16:53:14 -03:00
|
|
|
stmt_ty,
|
2020-05-01 00:27:52 -03:00
|
|
|
6,
|
|
|
|
"Variable annotation syntax is",
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_AnnAssign(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), b, c, 1, EXTRA)
|
2020-05-01 00:27:52 -03:00
|
|
|
) }
|
2020-05-14 17:13:50 -03:00
|
|
|
| a=('(' b=single_target ')' { b }
|
|
|
|
| single_subscript_attribute_target) ':' b=expression c=['=' d=annotated_rhs { d }] {
|
2021-04-07 16:34:22 -03:00
|
|
|
CHECK_VERSION(stmt_ty, 6, "Variable annotations syntax is", _PyAST_AnnAssign(a, b, c, 0, EXTRA)) }
|
2020-09-16 15:42:00 -03:00
|
|
|
| a[asdl_expr_seq*]=(z=star_targets '=' { z })+ b=(yield_expr | star_expressions) !'=' tc=[TYPE_COMMENT] {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Assign(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA) }
|
2020-06-18 20:10:43 -03:00
|
|
|
| a=single_target b=augassign ~ c=(yield_expr | star_expressions) {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_AugAssign(a, b->kind, c, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| invalid_assignment
|
|
|
|
|
|
|
|
augassign[AugOperator*]:
|
2020-05-01 00:27:52 -03:00
|
|
|
| '+=' { _PyPegen_augoperator(p, Add) }
|
|
|
|
| '-=' { _PyPegen_augoperator(p, Sub) }
|
|
|
|
| '*=' { _PyPegen_augoperator(p, Mult) }
|
2020-10-21 16:53:14 -03:00
|
|
|
| '@=' { CHECK_VERSION(AugOperator*, 5, "The '@' operator is", _PyPegen_augoperator(p, MatMult)) }
|
2020-05-01 00:27:52 -03:00
|
|
|
| '/=' { _PyPegen_augoperator(p, Div) }
|
|
|
|
| '%=' { _PyPegen_augoperator(p, Mod) }
|
|
|
|
| '&=' { _PyPegen_augoperator(p, BitAnd) }
|
|
|
|
| '|=' { _PyPegen_augoperator(p, BitOr) }
|
|
|
|
| '^=' { _PyPegen_augoperator(p, BitXor) }
|
|
|
|
| '<<=' { _PyPegen_augoperator(p, LShift) }
|
|
|
|
| '>>=' { _PyPegen_augoperator(p, RShift) }
|
|
|
|
| '**=' { _PyPegen_augoperator(p, Pow) }
|
|
|
|
| '//=' { _PyPegen_augoperator(p, FloorDiv) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
2020-09-16 15:42:00 -03:00
|
|
|
global_stmt[stmt_ty]: 'global' a[asdl_expr_seq*]=','.NAME+ {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Global(CHECK(asdl_identifier_seq*, _PyPegen_map_names_to_ids(p, a)), EXTRA) }
|
2020-09-16 15:42:00 -03:00
|
|
|
nonlocal_stmt[stmt_ty]: 'nonlocal' a[asdl_expr_seq*]=','.NAME+ {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Nonlocal(CHECK(asdl_identifier_seq*, _PyPegen_map_names_to_ids(p, a)), EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
2021-04-07 16:34:22 -03:00
|
|
|
yield_stmt[stmt_ty]: y=yield_expr { _PyAST_Expr(y, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
2021-04-07 16:34:22 -03:00
|
|
|
assert_stmt[stmt_ty]: 'assert' a=expression b=[',' z=expression { z }] { _PyAST_Assert(a, b, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
2020-06-18 20:10:43 -03:00
|
|
|
del_stmt[stmt_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| 'del' a=del_targets &(';' | NEWLINE) { _PyAST_Delete(a, EXTRA) }
|
2020-06-18 20:10:43 -03:00
|
|
|
| invalid_del_stmt
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
import_stmt[stmt_ty]: import_name | import_from
|
2021-04-07 16:34:22 -03:00
|
|
|
import_name[stmt_ty]: 'import' a=dotted_as_names { _PyAST_Import(a, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
|
|
|
|
import_from[stmt_ty]:
|
|
|
|
| 'from' a=('.' | '...')* b=dotted_name 'import' c=import_from_targets {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_ImportFrom(b->v.Name.id, c, _PyPegen_seq_count_dots(a), EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| 'from' a=('.' | '...')+ 'import' b=import_from_targets {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_ImportFrom(NULL, b, _PyPegen_seq_count_dots(a), EXTRA) }
|
2020-09-16 15:42:00 -03:00
|
|
|
import_from_targets[asdl_alias_seq*]:
|
2020-04-22 19:29:27 -03:00
|
|
|
| '(' a=import_from_as_names [','] ')' { a }
|
2020-05-21 17:41:58 -03:00
|
|
|
| import_from_as_names !','
|
2021-04-10 17:56:28 -03:00
|
|
|
| '*' { (asdl_alias_seq*)_PyPegen_singleton_seq(p, CHECK(alias_ty, _PyPegen_alias_for_star(p, EXTRA))) }
|
2020-05-21 17:41:58 -03:00
|
|
|
| invalid_import_from_targets
|
2020-09-16 15:42:00 -03:00
|
|
|
import_from_as_names[asdl_alias_seq*]:
|
|
|
|
| a[asdl_alias_seq*]=','.import_from_as_name+ { a }
|
2020-04-22 19:29:27 -03:00
|
|
|
import_from_as_name[alias_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=NAME b=['as' z=NAME { z }] { _PyAST_alias(a->v.Name.id,
|
2020-04-22 19:29:27 -03:00
|
|
|
(b) ? ((expr_ty) b)->v.Name.id : NULL,
|
2021-04-10 17:56:28 -03:00
|
|
|
EXTRA) }
|
2020-09-16 15:42:00 -03:00
|
|
|
dotted_as_names[asdl_alias_seq*]:
|
|
|
|
| a[asdl_alias_seq*]=','.dotted_as_name+ { a }
|
2020-04-22 19:29:27 -03:00
|
|
|
dotted_as_name[alias_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=dotted_name b=['as' z=NAME { z }] { _PyAST_alias(a->v.Name.id,
|
2020-04-22 19:29:27 -03:00
|
|
|
(b) ? ((expr_ty) b)->v.Name.id : NULL,
|
2021-04-10 17:56:28 -03:00
|
|
|
EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
dotted_name[expr_ty]:
|
|
|
|
| a=dotted_name '.' b=NAME { _PyPegen_join_names_with_dot(p, a, b) }
|
|
|
|
| NAME
|
|
|
|
|
|
|
|
if_stmt[stmt_ty]:
|
2021-04-21 11:28:21 -03:00
|
|
|
| invalid_if_stmt
|
2021-04-12 12:59:30 -03:00
|
|
|
| 'if' a=named_expression ':' b=block c=elif_stmt {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_If(a, b, CHECK(asdl_stmt_seq*, _PyPegen_singleton_seq(p, c)), EXTRA) }
|
2021-04-12 12:59:30 -03:00
|
|
|
| 'if' a=named_expression ':' b=block c=[else_block] { _PyAST_If(a, b, c, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
elif_stmt[stmt_ty]:
|
2021-04-21 11:28:21 -03:00
|
|
|
| invalid_elif_stmt
|
2021-04-12 12:59:30 -03:00
|
|
|
| 'elif' a=named_expression ':' b=block c=elif_stmt {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_If(a, b, CHECK(asdl_stmt_seq*, _PyPegen_singleton_seq(p, c)), EXTRA) }
|
2021-04-12 12:59:30 -03:00
|
|
|
| 'elif' a=named_expression ':' b=block c=[else_block] { _PyAST_If(a, b, c, EXTRA) }
|
2021-04-21 11:28:21 -03:00
|
|
|
else_block[asdl_stmt_seq*]:
|
|
|
|
| invalid_else_stmt
|
|
|
|
| 'else' &&':' b=block { b }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
while_stmt[stmt_ty]:
|
2021-04-12 12:59:30 -03:00
|
|
|
| invalid_while_stmt
|
2021-04-21 11:28:21 -03:00
|
|
|
| 'while' a=named_expression ':' b=block c=[else_block] { _PyAST_While(a, b, c, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
for_stmt[stmt_ty]:
|
2021-04-21 11:28:21 -03:00
|
|
|
| invalid_for_stmt
|
2021-02-02 15:54:22 -04:00
|
|
|
| 'for' t=star_targets 'in' ~ ex=star_expressions &&':' tc=[TYPE_COMMENT] b=block el=[else_block] {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_For(t, ex, b, el, NEW_TYPE_COMMENT(p, tc), EXTRA) }
|
2021-02-02 15:54:22 -04:00
|
|
|
| ASYNC 'for' t=star_targets 'in' ~ ex=star_expressions &&':' tc=[TYPE_COMMENT] b=block el=[else_block] {
|
2021-04-07 16:34:22 -03:00
|
|
|
CHECK_VERSION(stmt_ty, 5, "Async for loops are", _PyAST_AsyncFor(t, ex, b, el, NEW_TYPE_COMMENT(p, tc), EXTRA)) }
|
2020-06-18 20:10:43 -03:00
|
|
|
| invalid_for_target
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
with_stmt[stmt_ty]:
|
2021-04-21 11:28:21 -03:00
|
|
|
| invalid_with_stmt_indent
|
2020-09-16 15:42:00 -03:00
|
|
|
| 'with' '(' a[asdl_withitem_seq*]=','.with_item+ ','? ')' ':' b=block {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_With(a, b, NULL, EXTRA) }
|
2020-09-16 15:42:00 -03:00
|
|
|
| 'with' a[asdl_withitem_seq*]=','.with_item+ ':' tc=[TYPE_COMMENT] b=block {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_With(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA) }
|
2020-09-16 15:42:00 -03:00
|
|
|
| ASYNC 'with' '(' a[asdl_withitem_seq*]=','.with_item+ ','? ')' ':' b=block {
|
2021-04-07 16:34:22 -03:00
|
|
|
CHECK_VERSION(stmt_ty, 5, "Async with statements are", _PyAST_AsyncWith(a, b, NULL, EXTRA)) }
|
2020-09-16 15:42:00 -03:00
|
|
|
| ASYNC 'with' a[asdl_withitem_seq*]=','.with_item+ ':' tc=[TYPE_COMMENT] b=block {
|
2021-04-07 16:34:22 -03:00
|
|
|
CHECK_VERSION(stmt_ty, 5, "Async with statements are", _PyAST_AsyncWith(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA)) }
|
2021-02-02 15:54:22 -04:00
|
|
|
| invalid_with_stmt
|
|
|
|
|
2020-04-22 19:29:27 -03:00
|
|
|
with_item[withitem_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| e=expression 'as' t=star_target &(',' | ')' | ':') { _PyAST_withitem(e, t, p->arena) }
|
2020-06-18 20:10:43 -03:00
|
|
|
| invalid_with_item
|
2021-04-07 16:34:22 -03:00
|
|
|
| e=expression { _PyAST_withitem(e, NULL, p->arena) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
try_stmt[stmt_ty]:
|
2021-04-21 11:28:21 -03:00
|
|
|
| invalid_try_stmt
|
2021-04-07 16:34:22 -03:00
|
|
|
| 'try' &&':' b=block f=finally_block { _PyAST_Try(b, NULL, NULL, f, EXTRA) }
|
|
|
|
| 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_block+ el=[else_block] f=[finally_block] { _PyAST_Try(b, ex, el, f, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
except_block[excepthandler_ty]:
|
2021-04-21 11:28:21 -03:00
|
|
|
| invalid_except_stmt_indent
|
2021-02-07 14:42:21 -04:00
|
|
|
| 'except' e=expression t=['as' z=NAME { z }] ':' b=block {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_ExceptHandler(e, (t) ? ((expr_ty) t)->v.Name.id : NULL, b, EXTRA) }
|
|
|
|
| 'except' ':' b=block { _PyAST_ExceptHandler(NULL, NULL, b, EXTRA) }
|
2021-04-21 11:28:21 -03:00
|
|
|
| invalid_except_stmt
|
|
|
|
finally_block[asdl_stmt_seq*]:
|
|
|
|
| invalid_finally_stmt
|
|
|
|
| 'finally' &&':' a=block { a }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
2021-02-26 18:51:55 -04:00
|
|
|
match_stmt[stmt_ty]:
|
|
|
|
| "match" subject=subject_expr ':' NEWLINE INDENT cases[asdl_match_case_seq*]=case_block+ DEDENT {
|
2021-04-07 16:34:22 -03:00
|
|
|
CHECK_VERSION(stmt_ty, 10, "Pattern matching is", _PyAST_Match(subject, cases, EXTRA)) }
|
2021-03-17 22:03:11 -03:00
|
|
|
| invalid_match_stmt
|
2021-02-26 18:51:55 -04:00
|
|
|
subject_expr[expr_ty]:
|
|
|
|
| value=star_named_expression ',' values=star_named_expressions? {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Tuple(CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, value, values)), Load, EXTRA) }
|
2021-02-26 18:51:55 -04:00
|
|
|
| named_expression
|
|
|
|
case_block[match_case_ty]:
|
2021-04-21 11:28:21 -03:00
|
|
|
| invalid_case_block
|
2021-02-26 18:51:55 -04:00
|
|
|
| "case" pattern=patterns guard=guard? ':' body=block {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_match_case(pattern, guard, body, p->arena) }
|
2021-02-26 18:51:55 -04:00
|
|
|
guard[expr_ty]: 'if' guard=named_expression { guard }
|
|
|
|
|
2021-04-29 02:58:44 -03:00
|
|
|
patterns[pattern_ty]:
|
|
|
|
| patterns[asdl_pattern_seq*]=open_sequence_pattern {
|
|
|
|
_PyAST_MatchSequence(patterns, EXTRA) }
|
2021-02-26 18:51:55 -04:00
|
|
|
| pattern
|
2021-04-29 02:58:44 -03:00
|
|
|
pattern[pattern_ty]:
|
2021-02-26 18:51:55 -04:00
|
|
|
| as_pattern
|
|
|
|
| or_pattern
|
2021-04-29 02:58:44 -03:00
|
|
|
as_pattern[pattern_ty]:
|
|
|
|
| pattern=or_pattern 'as' target=pattern_capture_target {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_MatchAs(pattern, target->v.Name.id, EXTRA) }
|
2021-04-29 02:58:44 -03:00
|
|
|
or_pattern[pattern_ty]:
|
|
|
|
| patterns[asdl_pattern_seq*]='|'.closed_pattern+ {
|
2021-04-07 16:34:22 -03:00
|
|
|
asdl_seq_LEN(patterns) == 1 ? asdl_seq_GET(patterns, 0) : _PyAST_MatchOr(patterns, EXTRA) }
|
2021-04-29 02:58:44 -03:00
|
|
|
closed_pattern[pattern_ty]:
|
2021-02-26 18:51:55 -04:00
|
|
|
| literal_pattern
|
|
|
|
| capture_pattern
|
|
|
|
| wildcard_pattern
|
|
|
|
| value_pattern
|
|
|
|
| group_pattern
|
|
|
|
| sequence_pattern
|
|
|
|
| mapping_pattern
|
|
|
|
| class_pattern
|
|
|
|
|
2021-04-29 02:58:44 -03:00
|
|
|
# Literal patterns are used for equality and identity constraints
|
|
|
|
literal_pattern[pattern_ty]:
|
|
|
|
| value=signed_number !('+' | '-') { _PyAST_MatchValue(value, EXTRA) }
|
|
|
|
| value=complex_number { _PyAST_MatchValue(value, EXTRA) }
|
|
|
|
| value=strings { _PyAST_MatchValue(value, EXTRA) }
|
|
|
|
| 'None' { _PyAST_MatchSingleton(Py_None, EXTRA) }
|
|
|
|
| 'True' { _PyAST_MatchSingleton(Py_True, EXTRA) }
|
|
|
|
| 'False' { _PyAST_MatchSingleton(Py_False, EXTRA) }
|
|
|
|
|
|
|
|
# Literal expressions are used to restrict permitted mapping pattern keys
|
|
|
|
literal_expr[expr_ty]:
|
2021-02-26 18:51:55 -04:00
|
|
|
| signed_number !('+' | '-')
|
2021-04-29 02:58:44 -03:00
|
|
|
| complex_number
|
2021-02-26 18:51:55 -04:00
|
|
|
| strings
|
2021-04-07 16:34:22 -03:00
|
|
|
| 'None' { _PyAST_Constant(Py_None, NULL, EXTRA) }
|
|
|
|
| 'True' { _PyAST_Constant(Py_True, NULL, EXTRA) }
|
|
|
|
| 'False' { _PyAST_Constant(Py_False, NULL, EXTRA) }
|
2021-04-29 02:58:44 -03:00
|
|
|
|
|
|
|
complex_number[expr_ty]:
|
2021-04-29 21:19:28 -03:00
|
|
|
| real=signed_real_number '+' imag=imaginary_number {
|
|
|
|
_PyAST_BinOp(real, Add, imag, EXTRA) }
|
|
|
|
| real=signed_real_number '-' imag=imaginary_number {
|
|
|
|
_PyAST_BinOp(real, Sub, imag, EXTRA) }
|
2021-04-29 02:58:44 -03:00
|
|
|
|
2021-02-26 18:51:55 -04:00
|
|
|
signed_number[expr_ty]:
|
|
|
|
| NUMBER
|
2021-04-07 16:34:22 -03:00
|
|
|
| '-' number=NUMBER { _PyAST_UnaryOp(USub, number, EXTRA) }
|
2021-02-26 18:51:55 -04:00
|
|
|
|
2021-04-29 21:19:28 -03:00
|
|
|
signed_real_number[expr_ty]:
|
|
|
|
| real_number
|
|
|
|
| '-' real=real_number { _PyAST_UnaryOp(USub, real, EXTRA) }
|
|
|
|
|
|
|
|
real_number[expr_ty]:
|
|
|
|
| real=NUMBER { _PyPegen_ensure_real(p, real) }
|
|
|
|
|
2021-04-29 02:58:44 -03:00
|
|
|
imaginary_number[expr_ty]:
|
|
|
|
| imag=NUMBER { _PyPegen_ensure_imaginary(p, imag) }
|
|
|
|
|
|
|
|
capture_pattern[pattern_ty]:
|
|
|
|
| target=pattern_capture_target { _PyAST_MatchAs(NULL, target->v.Name.id, EXTRA) }
|
|
|
|
|
|
|
|
pattern_capture_target[expr_ty]:
|
2021-02-26 18:51:55 -04:00
|
|
|
| !"_" name=NAME !('.' | '(' | '=') {
|
|
|
|
_PyPegen_set_expr_context(p, name, Store) }
|
|
|
|
|
2021-04-29 02:58:44 -03:00
|
|
|
wildcard_pattern[pattern_ty]:
|
|
|
|
| "_" { _PyAST_MatchAs(NULL, NULL, EXTRA) }
|
2021-02-26 18:51:55 -04:00
|
|
|
|
2021-04-29 02:58:44 -03:00
|
|
|
value_pattern[pattern_ty]:
|
|
|
|
| attr=attr !('.' | '(' | '=') { _PyAST_MatchValue(attr, EXTRA) }
|
2021-02-26 18:51:55 -04:00
|
|
|
attr[expr_ty]:
|
|
|
|
| value=name_or_attr '.' attr=NAME {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Attribute(value, attr->v.Name.id, Load, EXTRA) }
|
2021-02-26 18:51:55 -04:00
|
|
|
name_or_attr[expr_ty]:
|
|
|
|
| attr
|
|
|
|
| NAME
|
|
|
|
|
2021-04-29 02:58:44 -03:00
|
|
|
group_pattern[pattern_ty]:
|
2021-02-26 18:51:55 -04:00
|
|
|
| '(' pattern=pattern ')' { pattern }
|
|
|
|
|
2021-04-29 02:58:44 -03:00
|
|
|
sequence_pattern[pattern_ty]:
|
|
|
|
| '[' patterns=maybe_sequence_pattern? ']' { _PyAST_MatchSequence(patterns, EXTRA) }
|
|
|
|
| '(' patterns=open_sequence_pattern? ')' { _PyAST_MatchSequence(patterns, EXTRA) }
|
2021-02-26 18:51:55 -04:00
|
|
|
open_sequence_pattern[asdl_seq*]:
|
2021-04-29 02:58:44 -03:00
|
|
|
| pattern=maybe_star_pattern ',' patterns=maybe_sequence_pattern? {
|
|
|
|
_PyPegen_seq_insert_in_front(p, pattern, patterns) }
|
2021-02-26 18:51:55 -04:00
|
|
|
maybe_sequence_pattern[asdl_seq*]:
|
2021-04-29 02:58:44 -03:00
|
|
|
| patterns=','.maybe_star_pattern+ ','? { patterns }
|
|
|
|
maybe_star_pattern[pattern_ty]:
|
2021-02-26 18:51:55 -04:00
|
|
|
| star_pattern
|
|
|
|
| pattern
|
2021-04-29 02:58:44 -03:00
|
|
|
star_pattern[pattern_ty]:
|
|
|
|
| '*' target=pattern_capture_target {
|
|
|
|
_PyAST_MatchStar(target->v.Name.id, EXTRA) }
|
|
|
|
| '*' wildcard_pattern {
|
|
|
|
_PyAST_MatchStar(NULL, EXTRA) }
|
|
|
|
|
|
|
|
mapping_pattern[pattern_ty]:
|
|
|
|
| '{' '}' {
|
|
|
|
_PyAST_MatchMapping(NULL, NULL, NULL, EXTRA) }
|
|
|
|
| '{' rest=double_star_pattern ','? '}' {
|
|
|
|
_PyAST_MatchMapping(NULL, NULL, rest->v.Name.id, EXTRA) }
|
|
|
|
| '{' items=items_pattern ',' rest=double_star_pattern ','? '}' {
|
|
|
|
_PyAST_MatchMapping(
|
|
|
|
CHECK(asdl_expr_seq*, _PyPegen_get_pattern_keys(p, items)),
|
|
|
|
CHECK(asdl_pattern_seq*, _PyPegen_get_patterns(p, items)),
|
|
|
|
rest->v.Name.id,
|
|
|
|
EXTRA) }
|
|
|
|
| '{' items=items_pattern ','? '}' {
|
|
|
|
_PyAST_MatchMapping(
|
|
|
|
CHECK(asdl_expr_seq*, _PyPegen_get_pattern_keys(p, items)),
|
|
|
|
CHECK(asdl_pattern_seq*, _PyPegen_get_patterns(p, items)),
|
|
|
|
NULL,
|
|
|
|
EXTRA) }
|
2021-02-26 18:51:55 -04:00
|
|
|
items_pattern[asdl_seq*]:
|
2021-04-29 21:19:28 -03:00
|
|
|
| ','.key_value_pattern+
|
2021-04-29 02:58:44 -03:00
|
|
|
key_value_pattern[KeyPatternPair*]:
|
|
|
|
| key=(literal_expr | attr) ':' pattern=pattern {
|
|
|
|
_PyPegen_key_pattern_pair(p, key, pattern) }
|
|
|
|
double_star_pattern[expr_ty]:
|
|
|
|
| '**' target=pattern_capture_target { target }
|
|
|
|
|
|
|
|
class_pattern[pattern_ty]:
|
|
|
|
| cls=name_or_attr '(' ')' {
|
|
|
|
_PyAST_MatchClass(cls, NULL, NULL, NULL, EXTRA) }
|
|
|
|
| cls=name_or_attr '(' patterns=positional_patterns ','? ')' {
|
|
|
|
_PyAST_MatchClass(cls, patterns, NULL, NULL, EXTRA) }
|
|
|
|
| cls=name_or_attr '(' keywords=keyword_patterns ','? ')' {
|
|
|
|
_PyAST_MatchClass(
|
|
|
|
cls, NULL,
|
|
|
|
CHECK(asdl_identifier_seq*, _PyPegen_map_names_to_ids(p,
|
|
|
|
CHECK(asdl_expr_seq*, _PyPegen_get_pattern_keys(p, keywords)))),
|
|
|
|
CHECK(asdl_pattern_seq*, _PyPegen_get_patterns(p, keywords)),
|
|
|
|
EXTRA) }
|
|
|
|
| cls=name_or_attr '(' patterns=positional_patterns ',' keywords=keyword_patterns ','? ')' {
|
|
|
|
_PyAST_MatchClass(
|
|
|
|
cls,
|
|
|
|
patterns,
|
|
|
|
CHECK(asdl_identifier_seq*, _PyPegen_map_names_to_ids(p,
|
|
|
|
CHECK(asdl_expr_seq*, _PyPegen_get_pattern_keys(p, keywords)))),
|
|
|
|
CHECK(asdl_pattern_seq*, _PyPegen_get_patterns(p, keywords)),
|
|
|
|
EXTRA) }
|
|
|
|
positional_patterns[asdl_pattern_seq*]:
|
|
|
|
| args[asdl_pattern_seq*]=','.pattern+ { args }
|
|
|
|
keyword_patterns[asdl_seq*]:
|
2021-04-29 21:19:28 -03:00
|
|
|
| ','.keyword_pattern+
|
2021-04-29 02:58:44 -03:00
|
|
|
keyword_pattern[KeyPatternPair*]:
|
|
|
|
| arg=NAME '=' value=pattern { _PyPegen_key_pattern_pair(p, arg, value) }
|
2021-02-26 18:51:55 -04:00
|
|
|
|
2020-04-22 19:29:27 -03:00
|
|
|
return_stmt[stmt_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| 'return' a=[star_expressions] { _PyAST_Return(a, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
raise_stmt[stmt_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| 'raise' a=expression b=['from' z=expression { z }] { _PyAST_Raise(a, b, EXTRA) }
|
|
|
|
| 'raise' { _PyAST_Raise(NULL, NULL, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
function_def[stmt_ty]:
|
|
|
|
| d=decorators f=function_def_raw { _PyPegen_function_def_decorators(p, d, f) }
|
|
|
|
| function_def_raw
|
|
|
|
|
|
|
|
function_def_raw[stmt_ty]:
|
2021-04-21 11:28:21 -03:00
|
|
|
| invalid_def_raw
|
2021-02-02 15:54:22 -04:00
|
|
|
| 'def' n=NAME '(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_FunctionDef(n->v.Name.id,
|
2020-10-21 16:53:14 -03:00
|
|
|
(params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)),
|
2020-05-01 00:27:52 -03:00
|
|
|
b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA) }
|
2021-02-02 15:54:22 -04:00
|
|
|
| ASYNC 'def' n=NAME '(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
|
2020-05-01 00:27:52 -03:00
|
|
|
CHECK_VERSION(
|
2020-10-21 16:53:14 -03:00
|
|
|
stmt_ty,
|
2020-05-01 00:27:52 -03:00
|
|
|
5,
|
|
|
|
"Async functions are",
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_AsyncFunctionDef(n->v.Name.id,
|
2020-10-21 16:53:14 -03:00
|
|
|
(params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)),
|
2020-05-01 00:27:52 -03:00
|
|
|
b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA)
|
|
|
|
) }
|
2020-05-01 12:32:09 -03:00
|
|
|
func_type_comment[Token*]:
|
2020-04-30 16:12:19 -03:00
|
|
|
| NEWLINE t=TYPE_COMMENT &(NEWLINE INDENT) { t } # Must be followed by indented block
|
|
|
|
| invalid_double_type_comments
|
|
|
|
| TYPE_COMMENT
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
params[arguments_ty]:
|
|
|
|
| invalid_parameters
|
|
|
|
| parameters
|
2020-04-30 16:12:19 -03:00
|
|
|
|
2020-04-22 19:29:27 -03:00
|
|
|
parameters[arguments_ty]:
|
2020-09-16 15:42:00 -03:00
|
|
|
| a=slash_no_default b[asdl_arg_seq*]=param_no_default* c=param_with_default* d=[star_etc] {
|
2020-04-22 19:29:27 -03:00
|
|
|
_PyPegen_make_arguments(p, a, NULL, b, c, d) }
|
2020-04-30 16:12:19 -03:00
|
|
|
| a=slash_with_default b=param_with_default* c=[star_etc] {
|
2020-04-22 19:29:27 -03:00
|
|
|
_PyPegen_make_arguments(p, NULL, a, NULL, b, c) }
|
2020-09-16 15:42:00 -03:00
|
|
|
| a[asdl_arg_seq*]=param_no_default+ b=param_with_default* c=[star_etc] {
|
2020-04-22 19:29:27 -03:00
|
|
|
_PyPegen_make_arguments(p, NULL, NULL, a, b, c) }
|
2020-04-30 16:12:19 -03:00
|
|
|
| a=param_with_default+ b=[star_etc] { _PyPegen_make_arguments(p, NULL, NULL, NULL, a, b)}
|
2020-04-22 19:29:27 -03:00
|
|
|
| a=star_etc { _PyPegen_make_arguments(p, NULL, NULL, NULL, NULL, a) }
|
2020-04-30 16:12:19 -03:00
|
|
|
|
|
|
|
# Some duplication here because we can't write (',' | &')'),
|
|
|
|
# which is because we don't support empty alternatives (yet).
|
|
|
|
#
|
2020-09-16 15:42:00 -03:00
|
|
|
slash_no_default[asdl_arg_seq*]:
|
|
|
|
| a[asdl_arg_seq*]=param_no_default+ '/' ',' { a }
|
|
|
|
| a[asdl_arg_seq*]=param_no_default+ '/' &')' { a }
|
2020-04-30 16:12:19 -03:00
|
|
|
slash_with_default[SlashWithDefault*]:
|
2020-09-16 15:42:00 -03:00
|
|
|
| a=param_no_default* b=param_with_default+ '/' ',' { _PyPegen_slash_with_default(p, (asdl_arg_seq *)a, b) }
|
|
|
|
| a=param_no_default* b=param_with_default+ '/' &')' { _PyPegen_slash_with_default(p, (asdl_arg_seq *)a, b) }
|
2020-04-30 16:12:19 -03:00
|
|
|
|
2020-04-22 19:29:27 -03:00
|
|
|
star_etc[StarEtc*]:
|
2020-04-30 16:12:19 -03:00
|
|
|
| '*' a=param_no_default b=param_maybe_default* c=[kwds] {
|
2020-04-22 19:29:27 -03:00
|
|
|
_PyPegen_star_etc(p, a, b, c) }
|
2020-04-30 16:12:19 -03:00
|
|
|
| '*' ',' b=param_maybe_default+ c=[kwds] {
|
2020-04-22 19:29:27 -03:00
|
|
|
_PyPegen_star_etc(p, NULL, b, c) }
|
2020-04-30 16:12:19 -03:00
|
|
|
| a=kwds { _PyPegen_star_etc(p, NULL, NULL, a) }
|
2020-05-04 07:58:31 -03:00
|
|
|
| invalid_star_etc
|
2020-04-30 16:12:19 -03:00
|
|
|
|
2020-05-01 13:42:03 -03:00
|
|
|
kwds[arg_ty]: '**' a=param_no_default { a }
|
2020-04-30 16:12:19 -03:00
|
|
|
|
|
|
|
# One parameter. This *includes* a following comma and type comment.
|
|
|
|
#
|
|
|
|
# There are three styles:
|
|
|
|
# - No default
|
|
|
|
# - With default
|
|
|
|
# - Maybe with default
|
|
|
|
#
|
|
|
|
# There are two alternative forms of each, to deal with type comments:
|
|
|
|
# - Ends in a comma followed by an optional type comment
|
|
|
|
# - No comma, optional type comment, must be followed by close paren
|
|
|
|
# The latter form is for a final parameter without trailing comma.
|
|
|
|
#
|
|
|
|
param_no_default[arg_ty]:
|
|
|
|
| a=param ',' tc=TYPE_COMMENT? { _PyPegen_add_type_comment_to_arg(p, a, tc) }
|
|
|
|
| a=param tc=TYPE_COMMENT? &')' { _PyPegen_add_type_comment_to_arg(p, a, tc) }
|
|
|
|
param_with_default[NameDefaultPair*]:
|
|
|
|
| a=param c=default ',' tc=TYPE_COMMENT? { _PyPegen_name_default_pair(p, a, c, tc) }
|
|
|
|
| a=param c=default tc=TYPE_COMMENT? &')' { _PyPegen_name_default_pair(p, a, c, tc) }
|
|
|
|
param_maybe_default[NameDefaultPair*]:
|
|
|
|
| a=param c=default? ',' tc=TYPE_COMMENT? { _PyPegen_name_default_pair(p, a, c, tc) }
|
|
|
|
| a=param c=default? tc=TYPE_COMMENT? &')' { _PyPegen_name_default_pair(p, a, c, tc) }
|
2021-04-07 16:34:22 -03:00
|
|
|
param[arg_ty]: a=NAME b=annotation? { _PyAST_arg(a->v.Name.id, b, NULL, EXTRA) }
|
2020-04-30 16:12:19 -03:00
|
|
|
|
|
|
|
annotation[expr_ty]: ':' a=expression { a }
|
|
|
|
default[expr_ty]: '=' a=expression { a }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
2020-09-16 15:42:00 -03:00
|
|
|
decorators[asdl_expr_seq*]: a[asdl_expr_seq*]=('@' f=named_expression NEWLINE { f })+ { a }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
class_def[stmt_ty]:
|
|
|
|
| a=decorators b=class_def_raw { _PyPegen_class_def_decorators(p, a, b) }
|
|
|
|
| class_def_raw
|
|
|
|
class_def_raw[stmt_ty]:
|
2021-04-21 11:28:21 -03:00
|
|
|
| invalid_class_def_raw
|
2021-02-02 15:54:22 -04:00
|
|
|
| 'class' a=NAME b=['(' z=[arguments] ')' { z }] &&':' c=block {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_ClassDef(a->v.Name.id,
|
2020-04-22 19:29:27 -03:00
|
|
|
(b) ? ((expr_ty) b)->v.Call.args : NULL,
|
|
|
|
(b) ? ((expr_ty) b)->v.Call.keywords : NULL,
|
|
|
|
c, NULL, EXTRA) }
|
|
|
|
|
2020-09-16 15:42:00 -03:00
|
|
|
block[asdl_stmt_seq*] (memo):
|
2020-04-22 19:29:27 -03:00
|
|
|
| NEWLINE INDENT a=statements DEDENT { a }
|
2020-11-30 15:42:38 -04:00
|
|
|
| simple_stmts
|
2020-04-22 19:29:27 -03:00
|
|
|
| invalid_block
|
|
|
|
|
|
|
|
star_expressions[expr_ty]:
|
|
|
|
| a=star_expression b=(',' c=star_expression { c })+ [','] {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Tuple(CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, a, b)), Load, EXTRA) }
|
|
|
|
| a=star_expression ',' { _PyAST_Tuple(CHECK(asdl_expr_seq*, _PyPegen_singleton_seq(p, a)), Load, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| star_expression
|
|
|
|
star_expression[expr_ty] (memo):
|
2021-04-07 16:34:22 -03:00
|
|
|
| '*' a=bitwise_or { _PyAST_Starred(a, Load, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| expression
|
|
|
|
|
2020-09-16 15:42:00 -03:00
|
|
|
star_named_expressions[asdl_expr_seq*]: a[asdl_expr_seq*]=','.star_named_expression+ [','] { a }
|
2020-04-22 19:29:27 -03:00
|
|
|
star_named_expression[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| '*' a=bitwise_or { _PyAST_Starred(a, Load, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| named_expression
|
2021-04-12 12:59:30 -03:00
|
|
|
|
2020-04-22 19:29:27 -03:00
|
|
|
named_expression[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=NAME ':=' ~ b=expression { _PyAST_NamedExpr(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), b, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| invalid_named_expression
|
2021-04-12 12:59:30 -03:00
|
|
|
| expression !':='
|
2020-04-22 19:29:27 -03:00
|
|
|
|
2021-04-12 22:32:33 -03:00
|
|
|
direct_named_expression[expr_ty]:
|
|
|
|
| a=NAME ':=' ~ b=expression { _PyAST_NamedExpr(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), b, EXTRA) }
|
|
|
|
| expression !':='
|
|
|
|
|
2020-04-22 19:29:27 -03:00
|
|
|
annotated_rhs[expr_ty]: yield_expr | star_expressions
|
|
|
|
|
|
|
|
expressions[expr_ty]:
|
|
|
|
| a=expression b=(',' c=expression { c })+ [','] {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Tuple(CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, a, b)), Load, EXTRA) }
|
|
|
|
| a=expression ',' { _PyAST_Tuple(CHECK(asdl_expr_seq*, _PyPegen_singleton_seq(p, a)), Load, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| expression
|
|
|
|
expression[expr_ty] (memo):
|
2021-04-15 17:38:45 -03:00
|
|
|
| invalid_expression
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=disjunction 'if' b=disjunction 'else' c=expression { _PyAST_IfExp(b, a, c, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| disjunction
|
|
|
|
| lambdef
|
|
|
|
|
|
|
|
lambdef[expr_ty]:
|
2020-10-21 16:53:14 -03:00
|
|
|
| 'lambda' a=[lambda_params] ':' b=expression {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Lambda((a) ? a : CHECK(arguments_ty, _PyPegen_empty_arguments(p)), b, EXTRA) }
|
2020-06-10 10:07:06 -03:00
|
|
|
|
|
|
|
lambda_params[arguments_ty]:
|
|
|
|
| invalid_lambda_parameters
|
|
|
|
| lambda_parameters
|
2020-05-01 13:42:03 -03:00
|
|
|
|
|
|
|
# lambda_parameters etc. duplicates parameters but without annotations
|
|
|
|
# or type comments, and if there's no comma after a parameter, we expect
|
|
|
|
# a colon, not a close parenthesis. (For more, see parameters above.)
|
|
|
|
#
|
2020-04-22 19:29:27 -03:00
|
|
|
lambda_parameters[arguments_ty]:
|
2020-09-16 15:42:00 -03:00
|
|
|
| a=lambda_slash_no_default b[asdl_arg_seq*]=lambda_param_no_default* c=lambda_param_with_default* d=[lambda_star_etc] {
|
2020-04-22 19:29:27 -03:00
|
|
|
_PyPegen_make_arguments(p, a, NULL, b, c, d) }
|
2020-05-01 13:42:03 -03:00
|
|
|
| a=lambda_slash_with_default b=lambda_param_with_default* c=[lambda_star_etc] {
|
2020-04-22 19:29:27 -03:00
|
|
|
_PyPegen_make_arguments(p, NULL, a, NULL, b, c) }
|
2020-09-16 15:42:00 -03:00
|
|
|
| a[asdl_arg_seq*]=lambda_param_no_default+ b=lambda_param_with_default* c=[lambda_star_etc] {
|
2020-04-22 19:29:27 -03:00
|
|
|
_PyPegen_make_arguments(p, NULL, NULL, a, b, c) }
|
2020-05-01 13:42:03 -03:00
|
|
|
| a=lambda_param_with_default+ b=[lambda_star_etc] { _PyPegen_make_arguments(p, NULL, NULL, NULL, a, b)}
|
2020-04-22 19:29:27 -03:00
|
|
|
| a=lambda_star_etc { _PyPegen_make_arguments(p, NULL, NULL, NULL, NULL, a) }
|
2020-05-01 13:42:03 -03:00
|
|
|
|
2020-09-16 15:42:00 -03:00
|
|
|
lambda_slash_no_default[asdl_arg_seq*]:
|
|
|
|
| a[asdl_arg_seq*]=lambda_param_no_default+ '/' ',' { a }
|
|
|
|
| a[asdl_arg_seq*]=lambda_param_no_default+ '/' &':' { a }
|
2020-05-01 13:42:03 -03:00
|
|
|
lambda_slash_with_default[SlashWithDefault*]:
|
2020-09-16 15:42:00 -03:00
|
|
|
| a=lambda_param_no_default* b=lambda_param_with_default+ '/' ',' { _PyPegen_slash_with_default(p, (asdl_arg_seq *)a, b) }
|
|
|
|
| a=lambda_param_no_default* b=lambda_param_with_default+ '/' &':' { _PyPegen_slash_with_default(p, (asdl_arg_seq *)a, b) }
|
2020-05-01 13:42:03 -03:00
|
|
|
|
2020-04-22 19:29:27 -03:00
|
|
|
lambda_star_etc[StarEtc*]:
|
2020-05-01 13:42:03 -03:00
|
|
|
| '*' a=lambda_param_no_default b=lambda_param_maybe_default* c=[lambda_kwds] {
|
2020-04-22 19:29:27 -03:00
|
|
|
_PyPegen_star_etc(p, a, b, c) }
|
2020-05-01 13:42:03 -03:00
|
|
|
| '*' ',' b=lambda_param_maybe_default+ c=[lambda_kwds] {
|
2020-04-22 19:29:27 -03:00
|
|
|
_PyPegen_star_etc(p, NULL, b, c) }
|
2020-05-01 13:42:03 -03:00
|
|
|
| a=lambda_kwds { _PyPegen_star_etc(p, NULL, NULL, a) }
|
2020-05-04 07:58:31 -03:00
|
|
|
| invalid_lambda_star_etc
|
2020-05-01 13:42:03 -03:00
|
|
|
|
|
|
|
lambda_kwds[arg_ty]: '**' a=lambda_param_no_default { a }
|
|
|
|
|
|
|
|
lambda_param_no_default[arg_ty]:
|
|
|
|
| a=lambda_param ',' { a }
|
|
|
|
| a=lambda_param &':' { a }
|
|
|
|
lambda_param_with_default[NameDefaultPair*]:
|
|
|
|
| a=lambda_param c=default ',' { _PyPegen_name_default_pair(p, a, c, NULL) }
|
|
|
|
| a=lambda_param c=default &':' { _PyPegen_name_default_pair(p, a, c, NULL) }
|
|
|
|
lambda_param_maybe_default[NameDefaultPair*]:
|
|
|
|
| a=lambda_param c=default? ',' { _PyPegen_name_default_pair(p, a, c, NULL) }
|
|
|
|
| a=lambda_param c=default? &':' { _PyPegen_name_default_pair(p, a, c, NULL) }
|
2021-04-07 16:34:22 -03:00
|
|
|
lambda_param[arg_ty]: a=NAME { _PyAST_arg(a->v.Name.id, NULL, NULL, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
disjunction[expr_ty] (memo):
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=conjunction b=('or' c=conjunction { c })+ { _PyAST_BoolOp(
|
2020-04-22 19:29:27 -03:00
|
|
|
Or,
|
2020-10-21 16:53:14 -03:00
|
|
|
CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, a, b)),
|
2020-04-22 19:29:27 -03:00
|
|
|
EXTRA) }
|
|
|
|
| conjunction
|
|
|
|
conjunction[expr_ty] (memo):
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=inversion b=('and' c=inversion { c })+ { _PyAST_BoolOp(
|
2020-04-22 19:29:27 -03:00
|
|
|
And,
|
2020-10-21 16:53:14 -03:00
|
|
|
CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, a, b)),
|
2020-04-22 19:29:27 -03:00
|
|
|
EXTRA) }
|
|
|
|
| inversion
|
|
|
|
inversion[expr_ty] (memo):
|
2021-04-07 16:34:22 -03:00
|
|
|
| 'not' a=inversion { _PyAST_UnaryOp(Not, a, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| comparison
|
|
|
|
comparison[expr_ty]:
|
|
|
|
| a=bitwise_or b=compare_op_bitwise_or_pair+ {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Compare(
|
2020-10-21 16:53:14 -03:00
|
|
|
a,
|
|
|
|
CHECK(asdl_int_seq*, _PyPegen_get_cmpops(p, b)),
|
|
|
|
CHECK(asdl_expr_seq*, _PyPegen_get_exprs(p, b)),
|
|
|
|
EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| bitwise_or
|
|
|
|
compare_op_bitwise_or_pair[CmpopExprPair*]:
|
|
|
|
| eq_bitwise_or
|
|
|
|
| noteq_bitwise_or
|
|
|
|
| lte_bitwise_or
|
|
|
|
| lt_bitwise_or
|
|
|
|
| gte_bitwise_or
|
|
|
|
| gt_bitwise_or
|
|
|
|
| notin_bitwise_or
|
|
|
|
| in_bitwise_or
|
|
|
|
| isnot_bitwise_or
|
|
|
|
| is_bitwise_or
|
|
|
|
eq_bitwise_or[CmpopExprPair*]: '==' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, Eq, a) }
|
2020-04-27 14:02:07 -03:00
|
|
|
noteq_bitwise_or[CmpopExprPair*]:
|
2020-10-30 20:48:42 -03:00
|
|
|
| (tok='!=' { _PyPegen_check_barry_as_flufl(p, tok) ? NULL : tok}) a=bitwise_or {_PyPegen_cmpop_expr_pair(p, NotEq, a) }
|
2020-04-22 19:29:27 -03:00
|
|
|
lte_bitwise_or[CmpopExprPair*]: '<=' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, LtE, a) }
|
|
|
|
lt_bitwise_or[CmpopExprPair*]: '<' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, Lt, a) }
|
|
|
|
gte_bitwise_or[CmpopExprPair*]: '>=' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, GtE, a) }
|
|
|
|
gt_bitwise_or[CmpopExprPair*]: '>' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, Gt, a) }
|
|
|
|
notin_bitwise_or[CmpopExprPair*]: 'not' 'in' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, NotIn, a) }
|
|
|
|
in_bitwise_or[CmpopExprPair*]: 'in' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, In, a) }
|
|
|
|
isnot_bitwise_or[CmpopExprPair*]: 'is' 'not' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, IsNot, a) }
|
|
|
|
is_bitwise_or[CmpopExprPair*]: 'is' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, Is, a) }
|
|
|
|
|
|
|
|
bitwise_or[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=bitwise_or '|' b=bitwise_xor { _PyAST_BinOp(a, BitOr, b, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| bitwise_xor
|
|
|
|
bitwise_xor[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=bitwise_xor '^' b=bitwise_and { _PyAST_BinOp(a, BitXor, b, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| bitwise_and
|
|
|
|
bitwise_and[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=bitwise_and '&' b=shift_expr { _PyAST_BinOp(a, BitAnd, b, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| shift_expr
|
|
|
|
shift_expr[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=shift_expr '<<' b=sum { _PyAST_BinOp(a, LShift, b, EXTRA) }
|
|
|
|
| a=shift_expr '>>' b=sum { _PyAST_BinOp(a, RShift, b, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| sum
|
|
|
|
|
|
|
|
sum[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=sum '+' b=term { _PyAST_BinOp(a, Add, b, EXTRA) }
|
|
|
|
| a=sum '-' b=term { _PyAST_BinOp(a, Sub, b, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| term
|
|
|
|
term[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=term '*' b=factor { _PyAST_BinOp(a, Mult, b, EXTRA) }
|
|
|
|
| a=term '/' b=factor { _PyAST_BinOp(a, Div, b, EXTRA) }
|
|
|
|
| a=term '//' b=factor { _PyAST_BinOp(a, FloorDiv, b, EXTRA) }
|
|
|
|
| a=term '%' b=factor { _PyAST_BinOp(a, Mod, b, EXTRA) }
|
|
|
|
| a=term '@' b=factor { CHECK_VERSION(expr_ty, 5, "The '@' operator is", _PyAST_BinOp(a, MatMult, b, EXTRA)) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| factor
|
|
|
|
factor[expr_ty] (memo):
|
2021-04-07 16:34:22 -03:00
|
|
|
| '+' a=factor { _PyAST_UnaryOp(UAdd, a, EXTRA) }
|
|
|
|
| '-' a=factor { _PyAST_UnaryOp(USub, a, EXTRA) }
|
|
|
|
| '~' a=factor { _PyAST_UnaryOp(Invert, a, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| power
|
|
|
|
power[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=await_primary '**' b=factor { _PyAST_BinOp(a, Pow, b, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| await_primary
|
|
|
|
await_primary[expr_ty] (memo):
|
2021-04-07 16:34:22 -03:00
|
|
|
| AWAIT a=primary { CHECK_VERSION(expr_ty, 5, "Await expressions are", _PyAST_Await(a, EXTRA)) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| primary
|
|
|
|
primary[expr_ty]:
|
2020-10-27 15:54:20 -03:00
|
|
|
| invalid_primary # must be before 'primay genexp' because of invalid_genexp
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=primary '.' b=NAME { _PyAST_Attribute(a, b->v.Name.id, Load, EXTRA) }
|
|
|
|
| a=primary b=genexp { _PyAST_Call(a, CHECK(asdl_expr_seq*, (asdl_expr_seq*)_PyPegen_singleton_seq(p, b)), NULL, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| a=primary '(' b=[arguments] ')' {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Call(a,
|
2020-04-22 19:29:27 -03:00
|
|
|
(b) ? ((expr_ty) b)->v.Call.args : NULL,
|
|
|
|
(b) ? ((expr_ty) b)->v.Call.keywords : NULL,
|
|
|
|
EXTRA) }
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=primary '[' b=slices ']' { _PyAST_Subscript(a, b, Load, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| atom
|
|
|
|
|
|
|
|
slices[expr_ty]:
|
|
|
|
| a=slice !',' { a }
|
2021-04-07 16:34:22 -03:00
|
|
|
| a[asdl_expr_seq*]=','.slice+ [','] { _PyAST_Tuple(a, Load, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
slice[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=[expression] ':' b=[expression] c=[':' d=[expression] { d }] { _PyAST_Slice(a, b, c, EXTRA) }
|
2020-11-16 19:09:35 -04:00
|
|
|
| a=named_expression { a }
|
2020-04-22 19:29:27 -03:00
|
|
|
atom[expr_ty]:
|
|
|
|
| NAME
|
2021-04-07 16:34:22 -03:00
|
|
|
| 'True' { _PyAST_Constant(Py_True, NULL, EXTRA) }
|
|
|
|
| 'False' { _PyAST_Constant(Py_False, NULL, EXTRA) }
|
|
|
|
| 'None' { _PyAST_Constant(Py_None, NULL, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| &STRING strings
|
|
|
|
| NUMBER
|
|
|
|
| &'(' (tuple | group | genexp)
|
|
|
|
| &'[' (list | listcomp)
|
|
|
|
| &'{' (dict | set | dictcomp | setcomp)
|
2021-04-07 16:34:22 -03:00
|
|
|
| '...' { _PyAST_Constant(Py_Ellipsis, NULL, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
strings[expr_ty] (memo): a=STRING+ { _PyPegen_concatenate_strings(p, a) }
|
|
|
|
list[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| '[' a=[star_named_expressions] ']' { _PyAST_List(a, Load, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
listcomp[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| '[' a=named_expression b=for_if_clauses ']' { _PyAST_ListComp(a, b, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| invalid_comprehension
|
|
|
|
tuple[expr_ty]:
|
|
|
|
| '(' a=[y=star_named_expression ',' z=[star_named_expressions] { _PyPegen_seq_insert_in_front(p, y, z) } ] ')' {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Tuple(a, Load, EXTRA) }
|
2020-06-18 20:10:43 -03:00
|
|
|
group[expr_ty]:
|
|
|
|
| '(' a=(yield_expr | named_expression) ')' { a }
|
|
|
|
| invalid_group
|
2020-04-22 19:29:27 -03:00
|
|
|
genexp[expr_ty]:
|
2021-04-13 13:51:21 -03:00
|
|
|
| '(' a=direct_named_expression b=for_if_clauses ')' { _PyAST_GeneratorExp(a, b, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| invalid_comprehension
|
2021-04-07 16:34:22 -03:00
|
|
|
set[expr_ty]: '{' a=star_named_expressions '}' { _PyAST_Set(a, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
setcomp[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| '{' a=named_expression b=for_if_clauses '}' { _PyAST_SetComp(a, b, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| invalid_comprehension
|
|
|
|
dict[expr_ty]:
|
2020-05-21 19:39:56 -03:00
|
|
|
| '{' a=[double_starred_kvpairs] '}' {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Dict(
|
2020-10-21 16:53:14 -03:00
|
|
|
CHECK(asdl_expr_seq*, _PyPegen_get_keys(p, a)),
|
|
|
|
CHECK(asdl_expr_seq*, _PyPegen_get_values(p, a)),
|
|
|
|
EXTRA) }
|
2021-04-15 10:06:39 -03:00
|
|
|
| '{' invalid_double_starred_kvpairs '}'
|
|
|
|
|
2020-04-22 19:29:27 -03:00
|
|
|
dictcomp[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| '{' a=kvpair b=for_if_clauses '}' { _PyAST_DictComp(a->key, a->value, b, EXTRA) }
|
2020-05-21 19:39:56 -03:00
|
|
|
| invalid_dict_comprehension
|
|
|
|
double_starred_kvpairs[asdl_seq*]: a=','.double_starred_kvpair+ [','] { a }
|
|
|
|
double_starred_kvpair[KeyValuePair*]:
|
2020-04-22 19:29:27 -03:00
|
|
|
| '**' a=bitwise_or { _PyPegen_key_value_pair(p, NULL, a) }
|
2020-05-21 19:39:56 -03:00
|
|
|
| kvpair
|
|
|
|
kvpair[KeyValuePair*]: a=expression ':' b=expression { _PyPegen_key_value_pair(p, a, b) }
|
2020-09-16 15:42:00 -03:00
|
|
|
for_if_clauses[asdl_comprehension_seq*]:
|
|
|
|
| a[asdl_comprehension_seq*]=for_if_clause+ { a }
|
2020-05-01 00:27:52 -03:00
|
|
|
for_if_clause[comprehension_ty]:
|
2020-09-16 15:42:00 -03:00
|
|
|
| ASYNC 'for' a=star_targets 'in' ~ b=disjunction c[asdl_expr_seq*]=('if' z=disjunction { z })* {
|
2021-04-07 16:34:22 -03:00
|
|
|
CHECK_VERSION(comprehension_ty, 6, "Async comprehensions are", _PyAST_comprehension(a, b, c, 1, p->arena)) }
|
2020-09-16 15:42:00 -03:00
|
|
|
| 'for' a=star_targets 'in' ~ b=disjunction c[asdl_expr_seq*]=('if' z=disjunction { z })* {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_comprehension(a, b, c, 0, p->arena) }
|
2020-06-18 20:10:43 -03:00
|
|
|
| invalid_for_target
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
yield_expr[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| 'yield' 'from' a=expression { _PyAST_YieldFrom(a, EXTRA) }
|
|
|
|
| 'yield' a=[star_expressions] { _PyAST_Yield(a, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
arguments[expr_ty] (memo):
|
|
|
|
| a=args [','] &')' { a }
|
2020-10-26 19:42:04 -03:00
|
|
|
| invalid_arguments
|
2020-04-22 19:29:27 -03:00
|
|
|
args[expr_ty]:
|
2021-04-12 22:32:33 -03:00
|
|
|
| a[asdl_expr_seq*]=','.(starred_expression | direct_named_expression !'=')+ b=[',' k=kwargs {k}] { _PyPegen_collect_call_seqs(p, a, b, EXTRA) }
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=kwargs { _PyAST_Call(_PyPegen_dummy_name(p),
|
2020-10-21 16:53:14 -03:00
|
|
|
CHECK_NULL_ALLOWED(asdl_expr_seq*, _PyPegen_seq_extract_starred_exprs(p, a)),
|
|
|
|
CHECK_NULL_ALLOWED(asdl_keyword_seq*, _PyPegen_seq_delete_starred_exprs(p, a)),
|
2020-04-22 19:29:27 -03:00
|
|
|
EXTRA) }
|
|
|
|
kwargs[asdl_seq*]:
|
|
|
|
| a=','.kwarg_or_starred+ ',' b=','.kwarg_or_double_starred+ { _PyPegen_join_sequences(p, a, b) }
|
|
|
|
| ','.kwarg_or_starred+
|
|
|
|
| ','.kwarg_or_double_starred+
|
|
|
|
starred_expression[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| '*' a=expression { _PyAST_Starred(a, Load, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
kwarg_or_starred[KeywordOrStarred*]:
|
|
|
|
| a=NAME '=' b=expression {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyPegen_keyword_or_starred(p, CHECK(keyword_ty, _PyAST_keyword(a->v.Name.id, b, EXTRA)), 1) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| a=starred_expression { _PyPegen_keyword_or_starred(p, a, 0) }
|
2020-05-07 07:44:06 -03:00
|
|
|
| invalid_kwarg
|
2020-04-22 19:29:27 -03:00
|
|
|
kwarg_or_double_starred[KeywordOrStarred*]:
|
|
|
|
| a=NAME '=' b=expression {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyPegen_keyword_or_starred(p, CHECK(keyword_ty, _PyAST_keyword(a->v.Name.id, b, EXTRA)), 1) }
|
|
|
|
| '**' a=expression { _PyPegen_keyword_or_starred(p, CHECK(keyword_ty, _PyAST_keyword(NULL, a, EXTRA)), 1) }
|
2020-05-07 07:44:06 -03:00
|
|
|
| invalid_kwarg
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
# NOTE: star_targets may contain *bitwise_or, targets may not.
|
|
|
|
star_targets[expr_ty]:
|
|
|
|
| a=star_target !',' { a }
|
|
|
|
| a=star_target b=(',' c=star_target { c })* [','] {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Tuple(CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, a, b)), Store, EXTRA) }
|
2021-01-02 19:14:21 -04:00
|
|
|
star_targets_list_seq[asdl_expr_seq*]: a[asdl_expr_seq*]=','.star_target+ [','] { a }
|
|
|
|
star_targets_tuple_seq[asdl_expr_seq*]:
|
|
|
|
| a=star_target b=(',' c=star_target { c })+ [','] { (asdl_expr_seq*) _PyPegen_seq_insert_in_front(p, a, b) }
|
|
|
|
| a=star_target ',' { (asdl_expr_seq*) _PyPegen_singleton_seq(p, a) }
|
2020-04-22 19:29:27 -03:00
|
|
|
star_target[expr_ty] (memo):
|
|
|
|
| '*' a=(!'*' star_target) {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Starred(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), Store, EXTRA) }
|
2021-01-02 19:14:21 -04:00
|
|
|
| target_with_star_atom
|
|
|
|
target_with_star_atom[expr_ty] (memo):
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=t_primary '.' b=NAME !t_lookahead { _PyAST_Attribute(a, b->v.Name.id, Store, EXTRA) }
|
|
|
|
| a=t_primary '[' b=slices ']' !t_lookahead { _PyAST_Subscript(a, b, Store, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| star_atom
|
|
|
|
star_atom[expr_ty]:
|
|
|
|
| a=NAME { _PyPegen_set_expr_context(p, a, Store) }
|
2021-01-02 19:14:21 -04:00
|
|
|
| '(' a=target_with_star_atom ')' { _PyPegen_set_expr_context(p, a, Store) }
|
2021-04-07 16:34:22 -03:00
|
|
|
| '(' a=[star_targets_tuple_seq] ')' { _PyAST_Tuple(a, Store, EXTRA) }
|
|
|
|
| '[' a=[star_targets_list_seq] ']' { _PyAST_List(a, Store, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
2020-05-14 17:13:50 -03:00
|
|
|
single_target[expr_ty]:
|
|
|
|
| single_subscript_attribute_target
|
2020-04-22 19:29:27 -03:00
|
|
|
| a=NAME { _PyPegen_set_expr_context(p, a, Store) }
|
2020-05-14 17:13:50 -03:00
|
|
|
| '(' a=single_target ')' { a }
|
|
|
|
single_subscript_attribute_target[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=t_primary '.' b=NAME !t_lookahead { _PyAST_Attribute(a, b->v.Name.id, Store, EXTRA) }
|
|
|
|
| a=t_primary '[' b=slices ']' !t_lookahead { _PyAST_Subscript(a, b, Store, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
2020-09-16 15:42:00 -03:00
|
|
|
del_targets[asdl_expr_seq*]: a[asdl_expr_seq*]=','.del_target+ [','] { a }
|
2020-04-22 19:29:27 -03:00
|
|
|
del_target[expr_ty] (memo):
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=t_primary '.' b=NAME !t_lookahead { _PyAST_Attribute(a, b->v.Name.id, Del, EXTRA) }
|
|
|
|
| a=t_primary '[' b=slices ']' !t_lookahead { _PyAST_Subscript(a, b, Del, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| del_t_atom
|
|
|
|
del_t_atom[expr_ty]:
|
2020-06-18 20:10:43 -03:00
|
|
|
| a=NAME { _PyPegen_set_expr_context(p, a, Del) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| '(' a=del_target ')' { _PyPegen_set_expr_context(p, a, Del) }
|
2021-04-07 16:34:22 -03:00
|
|
|
| '(' a=[del_targets] ')' { _PyAST_Tuple(a, Del, EXTRA) }
|
|
|
|
| '[' a=[del_targets] ']' { _PyAST_List(a, Del, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
2020-09-16 15:42:00 -03:00
|
|
|
targets[asdl_expr_seq*]: a[asdl_expr_seq*]=','.target+ [','] { a }
|
2020-04-22 19:29:27 -03:00
|
|
|
target[expr_ty] (memo):
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=t_primary '.' b=NAME !t_lookahead { _PyAST_Attribute(a, b->v.Name.id, Store, EXTRA) }
|
|
|
|
| a=t_primary '[' b=slices ']' !t_lookahead { _PyAST_Subscript(a, b, Store, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| t_atom
|
|
|
|
t_primary[expr_ty]:
|
2021-04-07 16:34:22 -03:00
|
|
|
| a=t_primary '.' b=NAME &t_lookahead { _PyAST_Attribute(a, b->v.Name.id, Load, EXTRA) }
|
|
|
|
| a=t_primary '[' b=slices ']' &t_lookahead { _PyAST_Subscript(a, b, Load, EXTRA) }
|
2020-10-21 16:53:14 -03:00
|
|
|
| a=t_primary b=genexp &t_lookahead {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Call(a, CHECK(asdl_expr_seq*, (asdl_expr_seq*)_PyPegen_singleton_seq(p, b)), NULL, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
| a=t_primary '(' b=[arguments] ')' &t_lookahead {
|
2021-04-07 16:34:22 -03:00
|
|
|
_PyAST_Call(a,
|
2020-04-22 19:29:27 -03:00
|
|
|
(b) ? ((expr_ty) b)->v.Call.args : NULL,
|
|
|
|
(b) ? ((expr_ty) b)->v.Call.keywords : NULL,
|
|
|
|
EXTRA) }
|
|
|
|
| a=atom &t_lookahead { a }
|
|
|
|
t_lookahead: '(' | '[' | '.'
|
|
|
|
t_atom[expr_ty]:
|
|
|
|
| a=NAME { _PyPegen_set_expr_context(p, a, Store) }
|
|
|
|
| '(' a=target ')' { _PyPegen_set_expr_context(p, a, Store) }
|
2021-04-07 16:34:22 -03:00
|
|
|
| '(' b=[targets] ')' { _PyAST_Tuple(b, Store, EXTRA) }
|
|
|
|
| '[' b=[targets] ']' { _PyAST_List(b, Store, EXTRA) }
|
2020-04-22 19:29:27 -03:00
|
|
|
|
|
|
|
|
|
|
|
# From here on, there are rules for invalid syntax with specialised error messages
|
2020-10-26 19:42:04 -03:00
|
|
|
invalid_arguments:
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
| a=args ',' '*' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "iterable argument unpacking follows keyword argument unpacking") }
|
|
|
|
| a=expression b=for_if_clauses ',' [args | expression for_if_clauses] {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, PyPegen_last_item(b, comprehension_ty)->target, "Generator expression must be parenthesized") }
|
2020-05-21 21:56:52 -03:00
|
|
|
| a=args for_if_clauses { _PyPegen_nonparen_genexp_in_call(p, a) }
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
| args ',' a=expression b=for_if_clauses {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, asdl_seq_GET(b, b->size-1)->target, "Generator expression must be parenthesized") }
|
2020-04-22 19:29:27 -03:00
|
|
|
| a=args ',' args { _PyPegen_arguments_parsing_error(p, a) }
|
2020-05-07 07:44:06 -03:00
|
|
|
invalid_kwarg:
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
| a=expression b='=' {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_RANGE(
|
|
|
|
a, b, "expression cannot contain assignment, perhaps you meant \"==\"?") }
|
2021-04-15 17:38:45 -03:00
|
|
|
|
|
|
|
invalid_expression:
|
|
|
|
# !(NAME STRING) is not matched so we don't show this error with some invalid string prefixes like: kf"dsfsdf"
|
|
|
|
# Soft keywords need to also be ignored because they can be parsed as NAME NAME
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
| !(NAME STRING | SOFT_KEYWORD) a=disjunction b=expression {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") }
|
2021-04-15 17:38:45 -03:00
|
|
|
|
2020-04-22 19:29:27 -03:00
|
|
|
invalid_named_expression:
|
|
|
|
| a=expression ':=' expression {
|
2020-05-13 16:36:27 -03:00
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
|
|
|
a, "cannot use assignment expressions with %s", _PyPegen_get_expr_name(a)) }
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
| a=NAME '=' b=bitwise_or !('='|':='|',') {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Maybe you meant '==' or ':=' instead of '='?") }
|
2021-04-12 12:59:30 -03:00
|
|
|
| !(list|tuple|genexp|'True'|'None'|'False') a=bitwise_or b='=' bitwise_or !('='|':='|',') {
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot assign to %s here. Maybe you meant '==' instead of '='?",
|
2021-04-12 12:59:30 -03:00
|
|
|
_PyPegen_get_expr_name(a)) }
|
|
|
|
|
2020-04-22 19:29:27 -03:00
|
|
|
invalid_assignment:
|
2020-06-27 15:33:08 -03:00
|
|
|
| a=invalid_ann_assign_target ':' expression {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
|
|
|
a,
|
|
|
|
"only single target (not %s) can be annotated",
|
|
|
|
_PyPegen_get_expr_name(a)
|
|
|
|
)}
|
2020-06-25 20:22:36 -03:00
|
|
|
| a=star_named_expression ',' star_named_expressions* ':' expression {
|
2020-05-13 16:36:27 -03:00
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "only single target (not tuple) can be annotated") }
|
2020-06-25 20:22:36 -03:00
|
|
|
| a=expression ':' expression {
|
2020-05-13 16:36:27 -03:00
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "illegal target for annotation") }
|
2020-06-07 22:57:00 -03:00
|
|
|
| (star_targets '=')* a=star_expressions '=' {
|
2020-06-20 23:18:01 -03:00
|
|
|
RAISE_SYNTAX_ERROR_INVALID_TARGET(STAR_TARGETS, a) }
|
2020-06-07 22:57:00 -03:00
|
|
|
| (star_targets '=')* a=yield_expr '=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "assignment to yield expression not possible") }
|
2020-05-14 22:04:52 -03:00
|
|
|
| a=star_expressions augassign (yield_expr | star_expressions) {
|
2021-02-26 18:51:55 -04:00
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
|
2020-06-25 20:22:36 -03:00
|
|
|
a,
|
2020-05-14 22:04:52 -03:00
|
|
|
"'%s' is an illegal expression for augmented assignment",
|
|
|
|
_PyPegen_get_expr_name(a)
|
|
|
|
)}
|
2020-06-27 15:33:08 -03:00
|
|
|
invalid_ann_assign_target[expr_ty]:
|
|
|
|
| list
|
|
|
|
| tuple
|
|
|
|
| '(' a=invalid_ann_assign_target ')' { a }
|
2020-06-18 20:10:43 -03:00
|
|
|
invalid_del_stmt:
|
|
|
|
| 'del' a=star_expressions {
|
2020-06-20 23:18:01 -03:00
|
|
|
RAISE_SYNTAX_ERROR_INVALID_TARGET(DEL_TARGETS, a) }
|
2020-04-22 19:29:27 -03:00
|
|
|
invalid_block:
|
|
|
|
| NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") }
|
2020-10-27 15:54:20 -03:00
|
|
|
invalid_primary:
|
|
|
|
| primary a='{' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "invalid syntax") }
|
2020-04-22 19:29:27 -03:00
|
|
|
invalid_comprehension:
|
2020-05-13 16:36:27 -03:00
|
|
|
| ('[' | '(' | '{') a=starred_expression for_if_clauses {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "iterable unpacking cannot be used in comprehension") }
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
| ('[' | '{') a=star_named_expression ',' b=star_named_expressions for_if_clauses {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, PyPegen_last_item(b, expr_ty),
|
|
|
|
"did you forget parentheses around the comprehension target?") }
|
|
|
|
| ('[' | '{') a=star_named_expression b=',' for_if_clauses {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "did you forget parentheses around the comprehension target?") }
|
2020-05-21 19:39:56 -03:00
|
|
|
invalid_dict_comprehension:
|
|
|
|
| '{' a='**' bitwise_or for_if_clauses '}' {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "dict unpacking cannot be used in dict comprehension") }
|
2020-04-22 19:29:27 -03:00
|
|
|
invalid_parameters:
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
| param_no_default* invalid_parameters_helper a=param_no_default {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "non-default argument follows default argument") }
|
2021-01-07 18:31:25 -04:00
|
|
|
invalid_parameters_helper: # This is only there to avoid type errors
|
|
|
|
| a=slash_with_default { _PyPegen_singleton_seq(p, a) }
|
|
|
|
| param_with_default+
|
2020-06-10 10:07:06 -03:00
|
|
|
invalid_lambda_parameters:
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
| lambda_param_no_default* invalid_lambda_parameters_helper a=lambda_param_no_default {
|
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "non-default argument follows default argument") }
|
2021-01-07 18:31:25 -04:00
|
|
|
invalid_lambda_parameters_helper:
|
|
|
|
| a=lambda_slash_with_default { _PyPegen_singleton_seq(p, a) }
|
|
|
|
| lambda_param_with_default+
|
2020-05-04 07:58:31 -03:00
|
|
|
invalid_star_etc:
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
| a='*' (')' | ',' (')' | '**')) { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "named arguments must follow bare *") }
|
2020-05-18 16:14:47 -03:00
|
|
|
| '*' ',' TYPE_COMMENT { RAISE_SYNTAX_ERROR("bare * has associated type comment") }
|
2020-05-04 07:58:31 -03:00
|
|
|
invalid_lambda_star_etc:
|
|
|
|
| '*' (':' | ',' (':' | '**')) { RAISE_SYNTAX_ERROR("named arguments must follow bare *") }
|
2020-04-30 16:12:19 -03:00
|
|
|
invalid_double_type_comments:
|
|
|
|
| TYPE_COMMENT NEWLINE TYPE_COMMENT NEWLINE INDENT {
|
|
|
|
RAISE_SYNTAX_ERROR("Cannot have two type comments on def") }
|
2020-06-18 20:10:43 -03:00
|
|
|
invalid_with_item:
|
2021-02-02 15:54:22 -04:00
|
|
|
| expression 'as' a=expression &(',' | ')' | ':') {
|
2020-06-20 23:18:01 -03:00
|
|
|
RAISE_SYNTAX_ERROR_INVALID_TARGET(STAR_TARGETS, a) }
|
2020-06-18 20:10:43 -03:00
|
|
|
|
|
|
|
invalid_for_target:
|
|
|
|
| ASYNC? 'for' a=star_expressions {
|
2020-06-20 23:18:01 -03:00
|
|
|
RAISE_SYNTAX_ERROR_INVALID_TARGET(FOR_TARGETS, a) }
|
2020-06-18 20:10:43 -03:00
|
|
|
|
|
|
|
invalid_group:
|
|
|
|
| '(' a=starred_expression ')' {
|
2021-04-12 12:59:30 -03:00
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot use starred expression here") }
|
2021-03-24 16:34:17 -03:00
|
|
|
| '(' a='**' expression ')' {
|
2021-04-12 12:59:30 -03:00
|
|
|
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot use double starred expression here") }
|
2020-05-21 17:41:58 -03:00
|
|
|
invalid_import_from_targets:
|
|
|
|
| import_from_as_names ',' {
|
|
|
|
RAISE_SYNTAX_ERROR("trailing comma not allowed without surrounding parentheses") }
|
2021-02-02 15:54:22 -04:00
|
|
|
|
|
|
|
invalid_with_stmt:
|
|
|
|
| [ASYNC] 'with' ','.(expression ['as' star_target])+ &&':'
|
|
|
|
| [ASYNC] 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' &&':'
|
2021-04-21 11:28:21 -03:00
|
|
|
invalid_with_stmt_indent:
|
|
|
|
| [ASYNC] a='with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'with' statement on line %d", a->lineno) }
|
|
|
|
| [ASYNC] a='with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'with' statement on line %d", a->lineno) }
|
|
|
|
|
|
|
|
invalid_try_stmt:
|
|
|
|
| a='try' ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'try' statement on line %d", a->lineno) }
|
|
|
|
invalid_except_stmt:
|
2021-02-07 14:42:21 -04:00
|
|
|
| 'except' a=expression ',' expressions ['as' NAME ] ':' {
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
RAISE_SYNTAX_ERROR_STARTING_FROM(a, "exception group must be parenthesized") }
|
2021-04-21 11:28:21 -03:00
|
|
|
| a='except' expression ['as' NAME ] NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
|
|
|
|
| a='except' NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
|
|
|
|
invalid_finally_stmt:
|
|
|
|
| a='finally' ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'finally' statement on line %d", a->lineno) }
|
|
|
|
invalid_except_stmt_indent:
|
2021-04-29 21:19:28 -03:00
|
|
|
| a='except' expression ['as' NAME ] ':' NEWLINE !INDENT {
|
2021-04-21 11:28:21 -03:00
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'except' statement on line %d", a->lineno) }
|
|
|
|
| a='except' ':' NEWLINE !INDENT { RAISE_SYNTAX_ERROR("expected an indented block after except statement on line %d", a->lineno) }
|
2021-03-17 22:03:11 -03:00
|
|
|
invalid_match_stmt:
|
|
|
|
| "match" subject_expr !':' { CHECK_VERSION(void*, 10, "Pattern matching is", RAISE_SYNTAX_ERROR("expected ':'") ) }
|
2021-04-29 21:19:28 -03:00
|
|
|
| a="match" subject=subject_expr ':' NEWLINE !INDENT {
|
2021-04-21 11:28:21 -03:00
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'match' statement on line %d", a->lineno) }
|
2021-03-17 22:03:11 -03:00
|
|
|
invalid_case_block:
|
|
|
|
| "case" patterns guard? !':' { RAISE_SYNTAX_ERROR("expected ':'") }
|
2021-04-21 11:28:21 -03:00
|
|
|
| a="case" patterns guard? ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'case' statement on line %d", a->lineno) }
|
2021-04-12 12:59:30 -03:00
|
|
|
invalid_if_stmt:
|
|
|
|
| 'if' named_expression NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
|
2021-04-21 11:28:21 -03:00
|
|
|
| a='if' a=named_expression ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'if' statement on line %d", a->lineno) }
|
2021-04-12 12:59:30 -03:00
|
|
|
invalid_elif_stmt:
|
|
|
|
| 'elif' named_expression NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
|
2021-04-21 11:28:21 -03:00
|
|
|
| a='elif' named_expression ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'elif' statement on line %d", a->lineno) }
|
|
|
|
invalid_else_stmt:
|
|
|
|
| a='else' ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'else' statement on line %d", a->lineno) }
|
2021-04-12 12:59:30 -03:00
|
|
|
invalid_while_stmt:
|
|
|
|
| 'while' named_expression NEWLINE { RAISE_SYNTAX_ERROR("expected ':'") }
|
2021-04-21 11:28:21 -03:00
|
|
|
| a='while' named_expression ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'while' statement on line %d", a->lineno) }
|
|
|
|
invalid_for_stmt:
|
|
|
|
| [ASYNC] a='for' star_targets 'in' star_expressions ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after 'for' statement on line %d", a->lineno) }
|
|
|
|
invalid_def_raw:
|
|
|
|
| [ASYNC] a='def' NAME '(' [params] ')' ['->' expression] ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after function definition on line %d", a->lineno) }
|
|
|
|
invalid_class_def_raw:
|
|
|
|
| a='class' NAME ['('[arguments] ')'] ':' NEWLINE !INDENT {
|
|
|
|
RAISE_INDENTATION_ERROR("expected an indented block after class definition on line %d", a->lineno) }
|
2021-04-15 10:06:39 -03:00
|
|
|
|
|
|
|
invalid_double_starred_kvpairs:
|
|
|
|
| ','.double_starred_kvpair+ ',' invalid_kvpair
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
| expression ':' a='*' bitwise_or { RAISE_SYNTAX_ERROR_STARTING_FROM(a, "cannot use a starred expression in a dictionary value") }
|
2021-04-15 10:06:39 -03:00
|
|
|
| expression a=':' &('}'|',') { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "expression expected after dictionary key and ':'") }
|
|
|
|
invalid_kvpair:
|
2021-04-15 20:45:42 -03:00
|
|
|
| a=expression !(':') {
|
bpo-43914: Highlight invalid ranges in SyntaxErrors (#25525)
To improve the user experience understanding what part of the error messages associated with SyntaxErrors is wrong, we can highlight the whole error range and not only place the caret at the first character. In this way:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
becomes
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
2021-04-23 10:27:05 -03:00
|
|
|
RAISE_ERROR_KNOWN_LOCATION(p, PyExc_SyntaxError, a->lineno, a->end_col_offset - 1, a->end_lineno, -1, "':' expected after dictionary key") }
|
|
|
|
| expression ':' a='*' bitwise_or { RAISE_SYNTAX_ERROR_STARTING_FROM(a, "cannot use a starred expression in a dictionary value") }
|
2021-04-15 10:06:39 -03:00
|
|
|
| expression a=':' {RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "expression expected after dictionary key and ':'") }
|