diff --git a/src/lpython/parser/parser.yy b/src/lpython/parser/parser.yy index 868f37ccfa..370bb53277 100644 --- a/src/lpython/parser/parser.yy +++ b/src/lpython/parser/parser.yy @@ -178,7 +178,6 @@ void yyerror(YYLTYPE *yyloc, LFortran::Parser &p, const std::string &msg) %type id %type expr %type expr_list -%type expr_for_list %type expr_list_opt %type tuple_list %type statement @@ -199,8 +198,6 @@ void yyerror(YYLTYPE *yyloc, LFortran::Parser &p, const std::string &msg) %type nonlocal_statement %type assignment_statement %type target_list -%type tuple_item -%type for_tuple_item %type ann_assignment_statement %type delete_statement %type return_statement @@ -211,6 +208,7 @@ void yyerror(YYLTYPE *yyloc, LFortran::Parser &p, const std::string &msg) %type if_statement %type elif_statement %type for_statement +%type for_target_list %type except_statement %type except_list %type try_statement @@ -227,8 +225,8 @@ void yyerror(YYLTYPE *yyloc, LFortran::Parser &p, const std::string &msg) %type slice_item %type slice_item_list %type with_statement -%type with_item -%type with_item_list +%type with_as_items +%type with_as_items_list %type async_func_def %type async_for_stmt %type async_with_stmt @@ -258,8 +256,8 @@ void yyerror(YYLTYPE *yyloc, LFortran::Parser &p, const std::string &msg) %left "and" %precedence "not" %left "==" "!=" ">=" ">" "<=" "<" "is not" "is" "not in" "in" -%precedence FOR %left KW_IF KW_ELSE +%precedence FOR %left "|" %left "^" %left "&" @@ -368,28 +366,22 @@ assert_statement | KW_ASSERT expr "," expr { $$ = ASSERT_02($2, $4, @$); } ; -tuple_item - : expr_list { $$ = TUPLE_01($1, @$); } - | expr_list "," { $$ = TUPLE_03($1, @$); } - | "(" expr_list "," ")" { $$ = TUPLE_03($2, @$); } - | "(" expr_list "," expr ")" { $$ = TUPLE_01(TUPLE_($2, $4), @$); } - ; - -for_tuple_item - : expr_for_list { $$ = TUPLE_01($1, @$); } - | expr_for_list "," { $$ = TUPLE_03($1, @$); } - | "(" expr_for_list "," ")" { $$ = TUPLE_03($2, @$); } - | "(" expr_for_list "," expr ")" { $$ = TUPLE_01(TUPLE_($2, $4), @$); } - ; - target_list - : target_list tuple_item "=" { $$ = $1; LIST_ADD($$, $2); } - | tuple_item "=" { LIST_NEW($$); LIST_ADD($$, $1); } + : target_list expr "=" { $$ = $1; LIST_ADD($$, $2); } + | expr "=" { LIST_NEW($$); LIST_ADD($$, $1); } + | target_list expr_list "," expr "=" { + $$ = $1; LIST_ADD($$, TUPLE_01(TUPLE_($2, $4), @$)); } + | expr_list "," expr "=" { + LIST_NEW($$); LIST_ADD($$, TUPLE_01(TUPLE_($1, $3), @$)); } + | target_list expr_list "," "=" { $$ = $1; LIST_ADD($$, TUPLE_03($2, @$)); } + | expr_list "," "=" { LIST_NEW($$); LIST_ADD($$, TUPLE_03($1, @$)); } ; assignment_statement - : target_list tuple_item { $$ = ASSIGNMENT($1, $2, @$); } - | target_list tuple_item TK_TYPE_COMMENT { $$ = ASSIGNMENT2($1, $2, $3, @$); } + : target_list expr { $$ = ASSIGNMENT($1, $2, @$); } + | target_list expr_list "," expr { + $$ = ASSIGNMENT($1, TUPLE_01(TUPLE_($2, $4), @$), @$); } + | target_list expr TK_TYPE_COMMENT { $$ = ASSIGNMENT2($1, $2, $3, @$); } ; augassign_statement @@ -419,15 +411,14 @@ ann_assignment_statement delete_statement : KW_DEL expr_list { $$ = DELETE_01($2, @$); } | KW_DEL expr_list "," { $$ = DELETE_01($2, @$); } - | KW_DEL "(" expr_list "," ")" { - $$ = DELETE_02(SET_EXPR_CTX_02($3, Del), @$); } - | KW_DEL "(" expr_list "," expr ")" { - $$ = DELETE_02(SET_EXPR_CTX_02(TUPLE_($3, $5), Del), @$); } ; return_statement : KW_RETURN { $$ = RETURN_01(@$); } - | KW_RETURN tuple_item { $$ = RETURN_02($2, @$); } + | KW_RETURN expr { $$ = RETURN_02($2, @$); } + | KW_RETURN expr_list "," expr { + $$ = RETURN_02(TUPLE_01(TUPLE_($2, $4), @$), @$); } + | KW_RETURN expr_list "," { $$ = RETURN_02(TUPLE_03($2, @$), @$); } ; module @@ -501,17 +492,23 @@ if_statement $$ = IF_STMT_03($2, $5, $6, @$); } ; +for_target_list + : expr %prec FOR { $$ = $1; } + | expr_list "," expr %prec FOR { $$ = TUPLE_01(TUPLE_($1, $3), @$); } + ; + for_statement - : KW_FOR for_tuple_item KW_IN tuple_item ":" sep statements { + : KW_FOR for_target_list KW_IN expr ":" sep statements { $$ = FOR_01($2, $4, $7, @$); } - | KW_FOR for_tuple_item KW_IN tuple_item ":" sep statements KW_ELSE ":" + | KW_FOR for_target_list KW_IN expr "," ":" sep statements { + $$ = FOR_01($2, TUPLE_03(A2LIST(p.m_a, $4), @$), $8, @$); } + | KW_FOR for_target_list KW_IN expr ":" sep statements KW_ELSE ":" sep statements { $$ = FOR_02($2, $4, $7, $11, @$); } - | KW_FOR for_tuple_item KW_IN tuple_item ":" - TK_TYPE_COMMENT TK_NEWLINE statements { - $$ = FOR_03($2, $4, $6, $8, @$); } - | KW_FOR for_tuple_item KW_IN tuple_item ":" - TK_TYPE_COMMENT TK_NEWLINE statements - KW_ELSE ":" sep statements { $$ = FOR_04($2, $4, $8, $12, $6, @$); } + | KW_FOR for_target_list KW_IN expr ":" TK_TYPE_COMMENT TK_NEWLINE + statements { $$ = FOR_03($2, $4, $6, $8, @$); } + | KW_FOR for_target_list KW_IN expr ":" TK_TYPE_COMMENT TK_NEWLINE + statements KW_ELSE ":" sep statements { + $$ = FOR_04($2, $4, $8, $12, $6, @$); } ; except_statement @@ -535,24 +532,25 @@ try_statement | KW_TRY ":" sep statements KW_FINALLY ":" sep statements { $$ = TRY_05($4, $8, @$); } ; -with_item - : expr { $$ = WITH_ITEM_01($1, @$); } - | expr KW_AS expr { $$ = WITH_ITEM_02($1, $3, @$); } +with_as_items_list + : with_as_items_list "," expr KW_AS expr { + $$ = $1; PLIST_ADD($$, WITH_ITEM_01($3, $5, @$)); } + | expr KW_AS expr { LIST_NEW($$); PLIST_ADD($$, WITH_ITEM_01($1, $3, @$)); } ; -with_item_list - : with_item_list "," with_item { $$ = $1; PLIST_ADD($$, $3); } - | with_item { LIST_NEW($$); PLIST_ADD($$, $1); } +with_as_items + : with_as_items_list { $$ = $1; } + | "(" with_as_items_list ")" { $$ = $2; } + | "(" with_as_items_list "," ")" { $$ = $2; } ; with_statement - : KW_WITH with_item_list ":" sep statements { $$ = WITH($2, $5, @$); } - | KW_WITH "(" with_item_list "," ")" ":" sep statements { - $$ = WITH($3, $8, @$); } - | KW_WITH with_item_list ":" TK_TYPE_COMMENT TK_NEWLINE + : KW_WITH expr_list ":" sep statements { $$ = WITH($2, $5, @$); } + | KW_WITH with_as_items ":" sep statements { $$ = WITH_02($2, $5, @$); } + | KW_WITH expr_list ":" TK_TYPE_COMMENT TK_NEWLINE statements { $$ = WITH_01($2, $6, $4, @$); } - | KW_WITH "(" with_item_list "," ")" ":" TK_TYPE_COMMENT - TK_NEWLINE statements { $$ = WITH_01($3, $9, $7, @$); } + | KW_WITH with_as_items ":" TK_TYPE_COMMENT TK_NEWLINE + statements { $$ = WITH_03($2, $6, $4, @$); } ; decorators_opt @@ -679,28 +677,28 @@ async_func_def ; async_for_stmt - : KW_ASYNC KW_FOR for_tuple_item KW_IN tuple_item ":" sep statements { + : KW_ASYNC KW_FOR expr KW_IN expr ":" sep statements { $$ = ASYNC_FOR_01($3, $5, $8, @$); } - | KW_ASYNC KW_FOR for_tuple_item KW_IN tuple_item ":" sep + | KW_ASYNC KW_FOR expr KW_IN expr ":" sep statements KW_ELSE ":" sep statements { $$ = ASYNC_FOR_02($3, $5, $8, $12, @$); } - | KW_ASYNC KW_FOR for_tuple_item KW_IN tuple_item ":" + | KW_ASYNC KW_FOR expr KW_IN expr ":" TK_TYPE_COMMENT TK_NEWLINE statements { $$ = ASYNC_FOR_03($3, $5, $9, $7, @$); } - | KW_ASYNC KW_FOR for_tuple_item KW_IN tuple_item ":" + | KW_ASYNC KW_FOR expr KW_IN expr ":" TK_TYPE_COMMENT TK_NEWLINE statements KW_ELSE ":" sep statements { $$ = ASYNC_FOR_04($3, $5, $9, $13, $7, @$); } ; async_with_stmt - : KW_ASYNC KW_WITH with_item_list ":" sep statements { + : KW_ASYNC KW_WITH expr_list ":" sep statements { $$ = ASYNC_WITH($3, $6, @$); } - | KW_ASYNC KW_WITH "(" with_item_list "," ")" ":" sep statements { - $$ = ASYNC_WITH($4, $9, @$); } - | KW_ASYNC KW_WITH with_item_list ":" TK_TYPE_COMMENT + | KW_ASYNC KW_WITH with_as_items ":" sep statements { + $$ = ASYNC_WITH_02($3, $6, @$); } + | KW_ASYNC KW_WITH expr_list ":" TK_TYPE_COMMENT TK_NEWLINE statements { $$ = ASYNC_WITH_01($3, $7, $5, @$); } - | KW_ASYNC KW_WITH "(" with_item_list "," ")" ":" TK_TYPE_COMMENT - TK_NEWLINE statements { $$ = ASYNC_WITH_01($4, $10, $8, @$); } + | KW_ASYNC KW_WITH with_as_items ":" TK_TYPE_COMMENT + TK_NEWLINE statements { $$ = ASYNC_WITH_03($3, $7, $5, @$); } ; while_statement @@ -739,11 +737,6 @@ expr_list | expr %prec "not" { LIST_NEW($$); LIST_ADD($$, $1); } ; -expr_for_list - : expr_for_list "," expr %prec FOR { $$ = $1; LIST_ADD($$, $3); } - | expr %prec FOR { LIST_NEW($$); LIST_ADD($$, $1); } - ; - dict : expr ":" expr { $$ = DICT_EXPR($1, $3, @$); } ; @@ -861,6 +854,8 @@ expr | TK_ELLIPSIS { $$ = ELLIPSIS(@$); } | "(" expr ")" { $$ = $2; } | "(" ")" { $$ = TUPLE_EMPTY(@$); } + | "(" expr_list "," ")" { $$ = TUPLE_03($2, @$); } + | "(" expr_list "," expr ")" { $$ = TUPLE_01(TUPLE_($2, $4), @$); } | function_call { $$ = $1; } | subscription { $$ = $1; } | "[" expr_list_opt "]" { $$ = LIST($2, @$); } diff --git a/src/lpython/parser/semantics.h b/src/lpython/parser/semantics.h index abdf6b1de2..566b62de9a 100644 --- a/src/lpython/parser/semantics.h +++ b/src/lpython/parser/semantics.h @@ -111,9 +111,7 @@ static inline Vec SET_EXPR_CTX_02(Vec x, expr_contextType ctx) { EXPR(SET_EXPR_CTX_01(x, Store)), EXPR(y), EXPR(val), 1) #define DELETE_01(e, l) make_Delete_t(p.m_a, l, \ - EXPRS(SET_EXPR_CTX_02(e, Del)), e.size()) -#define DELETE_02(e, l) make_Delete_t(p.m_a, l, \ - EXPRS(A2LIST(p.m_a, SET_EXPR_CTX_01(TUPLE_01(e, l), Del))), 1) + EXPRS(SET_EXPR_CTX_02(SET_CTX_02(e, Del), Del)), e.size()) #define EXPR_01(e, l) make_Expr_t(p.m_a, l, EXPR(e)) @@ -140,27 +138,26 @@ static inline Vec SET_EXPR_CTX_02(Vec x, expr_contextType ctx) { #define NON_LOCAL(names, l) make_Nonlocal_t(p.m_a, l, \ REDUCE_ARGS(p.m_a, names), names.size()) -static inline ast_t *SET_STORE_01(ast_t *x) { +static inline ast_t *SET_CTX_01(ast_t *x, expr_contextType ctx) { if(is_a(*EXPR(x))) { size_t n_elts = down_cast2(x)->n_elts; for(size_t i=0; i < n_elts; i++) { - SET_EXPR_CTX_01( - (ast_t *) down_cast2(x)->m_elts[i], Store); + SET_EXPR_CTX_01((ast_t *) down_cast2(x)->m_elts[i], ctx); } } return x; } -static inline Vec SET_STORE_02(Vec x) { +static inline Vec SET_CTX_02(Vec x, expr_contextType ctx) { for (size_t i=0; i < x.size(); i++) { - SET_STORE_01(x[i]); + SET_CTX_01(x[i], ctx); } return x; } #define ASSIGNMENT(targets, val, l) make_Assign_t(p.m_a, l, \ - EXPRS(SET_EXPR_CTX_02(SET_STORE_02(targets), Store)), targets.size(), \ + EXPRS(SET_EXPR_CTX_02(SET_CTX_02(targets, Store), Store)), targets.size(), \ EXPR(val), nullptr) #define ASSIGNMENT2(targets, val, type_comment, l) make_Assign_t(p.m_a, l, \ - EXPRS(SET_EXPR_CTX_02(SET_STORE_02(targets), Store)), targets.size(), \ + EXPRS(SET_EXPR_CTX_02(SET_CTX_02(targets, Store), Store)), targets.size(), \ EXPR(val), extract_type_comment(p, l, type_comment)) static inline ast_t* TUPLE_02(Allocator &al, Location &l, Vec elts) { @@ -171,7 +168,7 @@ static inline ast_t* TUPLE_02(Allocator &al, Location &l, Vec elts) { } #define TUPLE_01(elts, l) TUPLE_02(p.m_a, l, elts) #define TUPLE_03(elts, l) make_Tuple_t(p.m_a, l, \ - EXPRS(elts), elts.size(), expr_contextType::Load); + EXPRS(elts), elts.size(), expr_contextType::Load) #define TUPLE_EMPTY(l) make_Tuple_t(p.m_a, l, \ nullptr, 0, expr_contextType::Load) @@ -280,17 +277,17 @@ static inline char *extract_type_comment(LFortran::Parser &p, } #define FOR_01(target, iter, stmts, l) make_For_t(p.m_a, l, \ - EXPR(SET_EXPR_CTX_01(SET_STORE_01(target), Store)), EXPR(iter), \ + EXPR(SET_EXPR_CTX_01(SET_CTX_01(target, Store), Store)), EXPR(iter), \ STMTS(stmts), stmts.size(), nullptr, 0, nullptr) #define FOR_02(target, iter, stmts, orelse, l) make_For_t(p.m_a, l, \ - EXPR(SET_EXPR_CTX_01(SET_STORE_01(target), Store)), EXPR(iter), \ + EXPR(SET_EXPR_CTX_01(SET_CTX_01(target, Store), Store)), EXPR(iter), \ STMTS(stmts), stmts.size(), STMTS(orelse), orelse.size(), nullptr) #define FOR_03(target, iter, type_comment, stmts, l) make_For_t(p.m_a, l, \ - EXPR(SET_EXPR_CTX_01(SET_STORE_01(target), Store)), EXPR(iter), \ + EXPR(SET_EXPR_CTX_01(SET_CTX_01(target, Store), Store)), EXPR(iter), \ STMTS(stmts), stmts.size(), nullptr, 0, \ extract_type_comment(p, l, type_comment)) #define FOR_04(target, iter, stmts, orelse, type_comment, l) make_For_t(p.m_a, l, \ - EXPR(SET_EXPR_CTX_01(SET_STORE_01(target), Store)), EXPR(iter), \ + EXPR(SET_EXPR_CTX_01(SET_CTX_01(target, Store), Store)), EXPR(iter), \ STMTS(stmts), stmts.size(), STMTS(orelse), orelse.size(), \ extract_type_comment(p, l, type_comment)) @@ -328,12 +325,31 @@ static inline withitem_t *WITH_ITEM(Allocator &al, Location &l, return r; } -#define WITH_ITEM_01(expr, l) WITH_ITEM(p.m_a, l, EXPR(expr), nullptr) -#define WITH_ITEM_02(expr, vars, l) WITH_ITEM(p.m_a, l, \ +static inline Vec convert_exprlist_to_withitem(Allocator &al, + Location &l, Vec &expr_list) { + Vec v; + v.reserve(al, expr_list.size()); + for (size_t i=0; i elts) { if(is_a(*elts[0]) && elts.size() == 1) { return (ast_t*) SET_EXPR_CTX_01(elts[0], Store); } - return make_Tuple_t(al, l, EXPRS(SET_EXPR_CTX_02(SET_STORE_02(elts), Store)), + return make_Tuple_t(al, l, EXPRS(SET_EXPR_CTX_02(SET_CTX_02(elts, Store), Store)), elts.size(), expr_contextType::Store); } #define ID_TUPLE_01(elts, l) ID_TUPLE_02(p.m_a, l, elts) #define ID_TUPLE_03(elts, l) make_Tuple_t(p.m_a, l, \ - EXPRS(SET_EXPR_CTX_02(SET_STORE_02(elts), Store)), elts.size(), \ + EXPRS(SET_EXPR_CTX_02(SET_CTX_02(elts, Store), Store)), elts.size(), \ expr_contextType::Store); #define LIST_COMP_1(expr, generators, l) make_ListComp_t(p.m_a, l, \ diff --git a/tests/parser/tuple1.py b/tests/parser/tuple1.py new file mode 100644 index 0000000000..f525524d3a --- /dev/null +++ b/tests/parser/tuple1.py @@ -0,0 +1,29 @@ +a = (1, ) + 4 +a = 3 * (1, 2) + 4 + +f((x, y)) +f((x, )) + +a = len((1, 2, 3)) +a4 = ((1, 2, 3), (4, 5, 6)) + +(1, 2, 3,) +(1, 2) +(1, 2) * 3 + +print("%s%s%s" % (a, b, c)) +print("%s%s%s" % (10 + x, y, z + 20)) +if sys.version_info >= (3, 9): + pass + +NDArray = _GenericAlias(np.ndarray, (Any, _DType)) + +@pytest.mark.parametrize("shape", [(5), (3, 3, 3)]) +def test(): + pass + +_promotion_table = { (int8, int8): int8 } + +# TODO +# 1, 2, +# 1, 2 diff --git a/tests/reference/ast_new-tuple1-29c08af.json b/tests/reference/ast_new-tuple1-29c08af.json new file mode 100644 index 0000000000..e30ed57db2 --- /dev/null +++ b/tests/reference/ast_new-tuple1-29c08af.json @@ -0,0 +1,13 @@ +{ + "basename": "ast_new-tuple1-29c08af", + "cmd": "lpython --show-ast --new-parser --no-color {infile} -o {outfile}", + "infile": "tests/parser/tuple1.py", + "infile_hash": "c6b5d261e80e336d87a78b4f378c30c43eb12b145c9ca6e731ce527c", + "outfile": null, + "outfile_hash": null, + "stdout": "ast_new-tuple1-29c08af.stdout", + "stdout_hash": "32eba4e6e55f98c5125966bc8d1d0873d249f96d8f3a32afb27f1eeb", + "stderr": null, + "stderr_hash": null, + "returncode": 0 +} \ No newline at end of file diff --git a/tests/reference/ast_new-tuple1-29c08af.stdout b/tests/reference/ast_new-tuple1-29c08af.stdout new file mode 100644 index 0000000000..c2e9022138 --- /dev/null +++ b/tests/reference/ast_new-tuple1-29c08af.stdout @@ -0,0 +1 @@ +(Module [(Assign [(Name a Store)] (BinOp (Tuple [(ConstantInt 1 ())] Load) Add (ConstantInt 4 ())) ()) (Assign [(Name a Store)] (BinOp (BinOp (ConstantInt 3 ()) Mult (Tuple [(ConstantInt 1 ()) (ConstantInt 2 ())] Load)) Add (ConstantInt 4 ())) ()) (Expr (Call (Name f Load) [(Tuple [(Name x Load) (Name y Load)] Load)] [])) (Expr (Call (Name f Load) [(Tuple [(Name x Load)] Load)] [])) (Assign [(Name a Store)] (Call (Name len Load) [(Tuple [(ConstantInt 1 ()) (ConstantInt 2 ()) (ConstantInt 3 ())] Load)] []) ()) (Assign [(Name a4 Store)] (Tuple [(Tuple [(ConstantInt 1 ()) (ConstantInt 2 ()) (ConstantInt 3 ())] Load) (Tuple [(ConstantInt 4 ()) (ConstantInt 5 ()) (ConstantInt 6 ())] Load)] Load) ()) (Expr (Tuple [(ConstantInt 1 ()) (ConstantInt 2 ()) (ConstantInt 3 ())] Load)) (Expr (Tuple [(ConstantInt 1 ()) (ConstantInt 2 ())] Load)) (Expr (BinOp (Tuple [(ConstantInt 1 ()) (ConstantInt 2 ())] Load) Mult (ConstantInt 3 ()))) (Expr (Call (Name print Load) [(BinOp (ConstantStr "%s%s%s" ()) Mod (Tuple [(Name a Load) (Name b Load) (Name c Load)] Load))] [])) (Expr (Call (Name print Load) [(BinOp (ConstantStr "%s%s%s" ()) Mod (Tuple [(BinOp (ConstantInt 10 ()) Add (Name x Load)) (Name y Load) (BinOp (Name z Load) Add (ConstantInt 20 ()))] Load))] [])) (If (Compare (Attribute (Name sys Load) version_info Load) GtE [(Tuple [(ConstantInt 3 ()) (ConstantInt 9 ())] Load)]) [(Pass)] []) (Assign [(Name NDArray Store)] (Call (Name _GenericAlias Load) [(Attribute (Name np Load) ndarray Load) (Tuple [(Name Any Load) (Name _DType Load)] Load)] []) ()) (FunctionDef test ([] [] [] [] [] [] []) [(Pass)] [(Call (Attribute (Attribute (Name pytest Load) mark Load) parametrize Load) [(ConstantStr "shape" ()) (List [(ConstantInt 5 ()) (Tuple [(ConstantInt 3 ()) (ConstantInt 3 ()) (ConstantInt 3 ())] Load)] Load)] [])] () ()) (Assign [(Name _promotion_table Store)] (Dict [(Tuple [(Name int8 Load) (Name int8 Load)] Load)] [(Name int8 Load)]) ())] []) diff --git a/tests/tests.toml b/tests/tests.toml index 613d48064a..750404bb61 100644 --- a/tests/tests.toml +++ b/tests/tests.toml @@ -508,6 +508,10 @@ ast_new = true filename = "parser/lambda1.py" ast_new = true +[[test]] +filename = "parser/tuple1.py" +ast_new = true + # tests/errors [[test]]