Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trailing comma support implemented #1272

Merged
merged 6 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions jac/jaclang/compiler/jac.lark
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ from_path: (DOT | ELLIPSIS)* import_path
| (DOT | ELLIPSIS)+

import_path: named_ref (DOT named_ref)* (KW_AS NAME)?
import_items: (import_item COMMA)* import_item
import_items: (import_item COMMA)* import_item COMMA?
import_item: named_ref (KW_AS NAME)?
sub_name: COLON NAME
include_stmt: KW_INCLUDE sub_name? import_path SEMI
Expand Down Expand Up @@ -63,7 +63,7 @@ enum: decorators? enum_decl

enum_decl: KW_ENUM access_tag? STRING? NAME inherited_archs? (enum_block | SEMI)
enum_def: arch_to_enum_chain enum_block
enum_block: LBRACE ((enum_stmt COMMA)* enum_stmt)? RBRACE
enum_block: LBRACE ((enum_stmt COMMA)* enum_stmt COMMA?)? RBRACE

enum_stmt: NAME (COLON STRING)? EQ expression
| NAME (COLON STRING)?
Expand All @@ -83,7 +83,7 @@ abstract_ability: KW_OVERRIDE? KW_STATIC? KW_CAN access_tag? STRING? named_ref (
genai_ability: KW_OVERRIDE? KW_STATIC? KW_CAN access_tag? STRING? named_ref (func_decl) KW_BY atomic_call SEMI
event_clause: KW_WITH expression? (KW_EXIT | KW_ENTRY) (STRING? RETURN_HINT expression)?
func_decl: (LPAREN func_decl_params? RPAREN)? (RETURN_HINT (STRING COLON)? expression)?
func_decl_params: (param_var COMMA)* param_var
func_decl_params: (param_var COMMA)* param_var COMMA?
param_var: (STAR_POW | STAR_MUL)? NAME (COLON STRING)? type_tag (EQ expression)?

// Global variables
Expand Down Expand Up @@ -364,9 +364,9 @@ index_slice: LSQUARE expression? COLON expression? (COLON expression?)? RSQUARE
// Function calls
atomic_call: atomic_chain LPAREN param_list? (KW_BY atomic_call)? RPAREN

param_list: expr_list COMMA kw_expr_list
| kw_expr_list
| expr_list
param_list: expr_list COMMA kw_expr_list COMMA?
| kw_expr_list COMMA?
| expr_list COMMA?

// Atom
atom: named_ref
Expand Down Expand Up @@ -412,20 +412,20 @@ set_compr: LBRACE expression inner_compr+ RBRACE
dict_compr: LBRACE kv_pair inner_compr+ RBRACE
inner_compr: KW_ASYNC? KW_FOR atomic_chain KW_IN pipe_call (KW_IF walrus_assign)*

dict_val: LBRACE ((kv_pair COMMA)* kv_pair)? RBRACE
list_val: LSQUARE expr_list? RSQUARE
dict_val: LBRACE ((kv_pair COMMA)* kv_pair COMMA?)? RBRACE
list_val: LSQUARE (expr_list COMMA?)? RSQUARE
tuple_val: LPAREN tuple_list? RPAREN
set_val: LBRACE expr_list RBRACE
set_val: LBRACE expr_list COMMA? RBRACE

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
Expand Down Expand Up @@ -662,4 +662,4 @@ FSTR_BESC.1: /{{|}}/
COMMENT: /#\*(.|\n|\r)*?\*#|#.*/
WS.-2: /[ \t\f\r\n]/+
%ignore COMMENT
%ignore WS
%ignore WS
128 changes: 70 additions & 58 deletions jac/jaclang/compiler/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ def import_items(
) -> ast.SubNodeList[ast.ModuleItem]:
"""Grammar rule.

import_items: (import_item COMMA)* import_item
import_items: (import_item COMMA)* import_item COMMA?
"""
ret = ast.SubNodeList[ast.ModuleItem](
items=[i for i in kid if isinstance(i, ast.ModuleItem)],
Expand Down Expand Up @@ -693,7 +693,7 @@ def enum_block(
) -> ast.SubNodeList[ast.EnumBlockStmt]:
"""Grammar rule.

enum_block: LBRACE ((enum_stmt COMMA)* enum_stmt)? RBRACE
enum_block: LBRACE ((enum_stmt COMMA)* enum_stmt COMMA?)? RBRACE
"""
ret = ast.SubNodeList[ast.EnumBlockStmt](items=[], delim=Tok.COMMA, kid=kid)
ret.items = [i for i in kid if isinstance(i, ast.EnumBlockStmt)]
Expand Down Expand Up @@ -1022,7 +1022,7 @@ def func_decl_params(
) -> ast.SubNodeList[ast.ParamVar]:
"""Grammar rule.

func_decl_params: (param_var COMMA)* param_var
func_decl_params: (param_var COMMA)* param_var COMMA?
"""
ret = ast.SubNodeList[ast.ParamVar](
items=[i for i in kid if isinstance(i, ast.ParamVar)],
Expand Down Expand Up @@ -1267,29 +1267,30 @@ def code_block(
def statement(self, kid: list[ast.AstNode]) -> ast.CodeBlockStmt:
"""Grammar rule.

statement: py_code_block
| walker_stmt
| return_stmt SEMI
| report_stmt SEMI
| delete_stmt SEMI
| ctrl_stmt SEMI
| assert_stmt SEMI
| raise_stmt SEMI
| with_stmt
statement: import_stmt
| ability
| architype
| if_stmt
| while_stmt
| for_stmt
| try_stmt
| if_stmt
| expression SEMI
| (yield_expr | KW_YIELD) SEMI
| static_assignment
| assignment SEMI
| match_stmt
| with_stmt
| global_ref SEMI
| nonlocal_ref SEMI
| typed_ctx_block
| ability
| architype
| import_stmt
| return_stmt SEMI
| (yield_expr | KW_YIELD) SEMI
| raise_stmt SEMI
| assert_stmt SEMI
| check_stmt SEMI
| assignment SEMI
| delete_stmt SEMI
| report_stmt SEMI
| expression SEMI
| ctrl_stmt SEMI
| py_code_block
| walker_stmt
| SEMI
"""
if isinstance(kid[0], ast.CodeBlockStmt) and len(kid) < 2:
Expand Down Expand Up @@ -2180,30 +2181,21 @@ def cmp_op(self, kid: list[ast.AstNode]) -> ast.Token:
def arithmetic(self, kid: list[ast.AstNode]) -> ast.Expr:
"""Grammar rule.

arithmetic: term MINUS arithmetic
| term PLUS arithmetic
| term
arithmetic: (arithmetic (MINUS | PLUS))? term
"""
return self.binary_expr_unwind(kid)

def term(self, kid: list[ast.AstNode]) -> ast.Expr:
"""Grammar rule.

term: factor MOD term
| factor DIV term
| factor FLOOR_DIV term
| factor STAR_MUL term
| factor
term: (term (MOD | DIV | FLOOR_DIV | STAR_MUL | DECOR_OP))? power
"""
return self.binary_expr_unwind(kid)

def factor(self, kid: list[ast.AstNode]) -> ast.Expr:
"""Grammar rule.

factor: power
| BW_NOT factor
| MINUS factor
| PLUS factor
factor: (BW_NOT | MINUS | PLUS) factor | connect
"""
if len(kid) == 2:
if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.Expr):
Expand All @@ -2221,8 +2213,7 @@ def factor(self, kid: list[ast.AstNode]) -> ast.Expr:
def power(self, kid: list[ast.AstNode]) -> ast.Expr:
"""Grammar rule.

power: connect STAR_POW power
| connect
power: (power STAR_POW)? factor
"""
return self.binary_expr_unwind(kid)

Expand Down Expand Up @@ -2513,8 +2504,7 @@ def atom(self, kid: list[ast.AstNode]) -> ast.Expr:
def yield_expr(self, kid: list[ast.AstNode]) -> ast.YieldExpr:
"""Grammar rule.

yield_expr:
| KW_YIELD KW_FROM? expression
yield_expr: KW_YIELD KW_FROM? expression
"""
if isinstance(kid[-1], ast.Expr):
return self.nu(
Expand Down Expand Up @@ -2565,7 +2555,7 @@ def atom_collection(self, kid: list[ast.AstNode]) -> ast.AtomExpr:
def multistring(self, kid: list[ast.AstNode]) -> ast.AtomExpr:
"""Grammar rule.

multistring: (fstring | STRING)+
multistring: (fstring | STRING | DOC_STRING)+
"""
valid_strs = [i for i in kid if isinstance(i, (ast.String, ast.FString))]
if len(valid_strs) == len(kid):
Expand All @@ -2582,6 +2572,7 @@ def fstring(self, kid: list[ast.AstNode]) -> ast.FString:
"""Grammar rule.

fstring: FSTR_START fstr_parts FSTR_END
| FSTR_SQ_START fstr_sq_parts FSTR_SQ_END
"""
if len(kid) == 2:
return self.nu(
Expand All @@ -2605,7 +2596,7 @@ def fstr_parts(
) -> ast.SubNodeList[ast.String | ast.ExprStmt]:
"""Grammar rule.

fstr_parts: (FSTR_PIECE | FSTR_BESC | LBRACE expression RBRACE | fstring)*
fstr_parts: (FSTR_PIECE | FSTR_BESC | LBRACE expression RBRACE )*
"""
valid_parts: list[ast.String | ast.ExprStmt] = [
(
Expand Down Expand Up @@ -2651,7 +2642,7 @@ def fstr_sq_parts(
def list_val(self, kid: list[ast.AstNode]) -> ast.ListVal:
"""Grammar rule.

list_val: LSQUARE expr_list? RSQUARE
list_val: LSQUARE (expr_list COMMA?)? RSQUARE
"""
if len(kid) == 2:
return self.nu(
Expand Down Expand Up @@ -2695,7 +2686,7 @@ def tuple_val(self, kid: list[ast.AstNode]) -> ast.TupleVal:
def set_val(self, kid: list[ast.AstNode]) -> ast.SetVal:
"""Grammar rule.

set_val: LBRACE expr_list RBRACE
set_val: LBRACE expr_list COMMA? RBRACE
"""
if len(kid) == 2:
return self.nu(
Expand Down Expand Up @@ -2822,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))]
Expand All @@ -2855,7 +2858,7 @@ def tuple_list(
def dict_val(self, kid: list[ast.AstNode]) -> ast.DictVal:
"""Grammar rule.

dict_val: LBRACE ((kv_pair COMMA)* kv_pair)? RBRACE
dict_val: LBRACE ((kv_pair COMMA)* kv_pair COMMA?)? RBRACE
"""
ret = ast.DictVal(
kv_pairs=[],
Expand Down Expand Up @@ -2912,7 +2915,7 @@ def list_compr(self, kid: list[ast.AstNode]) -> ast.ListCompr:
def gen_compr(self, kid: list[ast.AstNode]) -> ast.GenCompr:
"""Grammar rule.

gen_compr: LSQUARE expression inner_compr+ RSQUARE
gen_compr: LPAREN expression inner_compr+ RPAREN
"""
comprs = [i for i in kid if isinstance(i, ast.InnerCompr)]
if isinstance(kid[1], ast.Expr):
Expand All @@ -2929,7 +2932,7 @@ def gen_compr(self, kid: list[ast.AstNode]) -> ast.GenCompr:
def set_compr(self, kid: list[ast.AstNode]) -> ast.SetCompr:
"""Grammar rule.

set_compr: LSQUARE expression inner_compr+ RSQUARE
set_compr: LBRACE expression inner_compr+ RBRACE
"""
comprs = [i for i in kid if isinstance(i, ast.InnerCompr)]
if isinstance(kid[1], ast.Expr) and isinstance(kid[2], ast.InnerCompr):
Expand Down Expand Up @@ -2993,12 +2996,21 @@ def param_list(
) -> ast.SubNodeList[ast.Expr | ast.KWPair]:
"""Grammar rule.

param_list: expr_list COMMA kw_expr_list
| kw_expr_list
| expr_list
param_list: expr_list COMMA kw_expr_list COMMA?
| kw_expr_list COMMA?
| expr_list COMMA?
"""
if len(kid) == 1:
ends_with_comma = (
len(kid) > 1
and isinstance(kid[-1], ast.Token)
and kid[-1].name == "COMMA"
)
if len(kid) == 1 or (len(kid) == 2 and ends_with_comma):
if isinstance(kid[0], ast.SubNodeList):
if (
ends_with_comma
): # Append the trailing comma to the subnode list.
kid[0].kid.append(kid[1])
return self.nu(kid[0])
else:
raise self.ice()
Expand Down Expand Up @@ -3146,7 +3158,7 @@ def object_ref(self, kid: list[ast.AstNode]) -> ast.ArchRef:
def type_ref(self, kid: list[ast.AstNode]) -> ast.ArchRef:
"""Grammar rule.

type_ref: TYPE_OP name_ref
type_ref: TYPE_OP (named_ref | builtin_type)
"""
if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.NameAtom):
return self.nu(
Expand Down
4 changes: 3 additions & 1 deletion jac/jaclang/compiler/passes/tool/jac_formatter_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,9 @@ def exit_func_call(self, node: ast.FuncCall) -> None:
indented = True
for count, j in enumerate(i.kid):
if j.gen.jac == ",":
if i.kid[count + 1].gen.jac.startswith("#"):
if len(i.kid) > count + 1 and i.kid[
count + 1
].gen.jac.startswith("#"):
self.indent_level -= 1
self.emit(node, f"{j.gen.jac} ")
self.indent_level += 1
Expand Down
Loading
Loading