diff --git a/jac/jaclang/compiler/jac.lark b/jac/jaclang/compiler/jac.lark index 174a832b47..39b7db6c53 100644 --- a/jac/jaclang/compiler/jac.lark +++ b/jac/jaclang/compiler/jac.lark @@ -421,11 +421,11 @@ kv_pair: expression COLON expression | STAR_POW expression expr_list: (expr_list COMMA)? expression // Tuples and Jac Tuples -tuple_list: expression COMMA expr_list COMMA kw_expr_list - | expression COMMA kw_expr_list - | expression COMMA expr_list +tuple_list: expression COMMA expr_list COMMA kw_expr_list COMMA? + | expression COMMA kw_expr_list COMMA? + | expression COMMA expr_list COMMA? | expression COMMA - | kw_expr_list + | kw_expr_list COMMA? kw_expr_list: (kw_expr_list COMMA)? kw_expr kw_expr: named_ref EQ expression | STAR_POW expression diff --git a/jac/jaclang/compiler/parser.py b/jac/jaclang/compiler/parser.py index dc04951255..11cd4dfd52 100644 --- a/jac/jaclang/compiler/parser.py +++ b/jac/jaclang/compiler/parser.py @@ -2813,25 +2813,37 @@ def tuple_list( ) -> ast.SubNodeList[ast.Expr | ast.KWPair]: """Grammar rule. - tuple_list: expression COMMA expr_list COMMA kw_expr_list - | expression COMMA kw_expr_list - | expression COMMA expr_list - | expression COMMA - | kw_expr_list + tuple_list: expression COMMA expr_list COMMA kw_expr_list COMMA? + | expression COMMA kw_expr_list COMMA? + | expression COMMA expr_list COMMA? + | expression COMMA + | kw_expr_list COMMA? """ chomp = [*kid] first_expr = None if isinstance(chomp[0], ast.SubNodeList): + # The chomp will be like this: + # kw_expr_list, [COMMA] + if len(chomp) > 1: + # Add the comma to the subnode list if it exists, otherwise the last comma will not be a part of + # the ast, we need it for formatting. + chomp[0].kid.append(chomp[1]) return self.nu(chomp[0]) else: - first_expr = chomp[0] - chomp = chomp[2:] + # The chomp will be like this: + # expression, COMMA, [subnode_list, [COMMA, [kw_expr_list, [COMMA]]]] + # Pop the first expression from chomp. + first_expr = chomp[0] # Get the first expression. + chomp = chomp[2:] # Get rid of expr and comma. + + # The chomp will be like this: + # [subnode_list, [COMMA, [kw_expr_list, [COMMA]]]] expr_list = [] if len(chomp): - expr_list = chomp[0].kid - chomp = chomp[1:] + expr_list = chomp[0].kid # Get the kids subnode list. + chomp = chomp[2:] # Get rid of the subnode list and a comma if exists. if len(chomp): - chomp = chomp[1:] + # The chomp will be like this: [kw_expr_list, [COMMA]] expr_list = [*expr_list, *chomp[0].kid] expr_list = [first_expr, *expr_list] valid_kid = [i for i in expr_list if isinstance(i, (ast.Expr, ast.KWPair))]