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 2 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
14 changes: 7 additions & 7 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 @@ -412,10 +412,10 @@ 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
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
79 changes: 35 additions & 44 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 @@ -2855,7 +2846,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 +2903,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 +2920,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 @@ -3146,7 +3137,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
64 changes: 64 additions & 0 deletions jac/jaclang/tests/fixtures/trailing_comma.jac
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""
This test file is to ensure the valid syntax of jac lang.
Add new jac syntax here to test if it compile without any issue.
"""

# Import statement without trailing comma.
import:py from time {
sleep,
timezone,
tzname
}


# Import statement with trailing comma.
import:py from os {
path,
getenv,
getpid,
}


enum WithoutTrailComma {
FOO = "FOO",
BAR = "BAR"
}


enum WithTrailComma {
FOO = "FOO",
BAR = "BAR",
}


can without_trail_comma(a:int, b:int) {}

can with_trail_comma(
a:int,
b:int,
c:int,
) {}


with entry {

dict_without_trail_comma = { "key" : "value" };
dict_with_trail_comma = {
"key" : "val",
};

list_without_trail_comma = [ "foo", "bar" ];
list_with_trail_comma = [
"foo",
"bar",
];

set_without_trail_comma = { "foo", "bar" };
set_with_trail_comma = {
"foo",
"bar",
};

print("Code compiled and ran successfully!");
}

9 changes: 9 additions & 0 deletions jac/jaclang/tests/test_language.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,15 @@ def test_tuple_unpack(self) -> None:
self.assertIn("1", stdout_value[0])
self.assertIn("[2, 3, 4]", stdout_value[1])

def test_trailing_comma(self) -> None:
"""Test trailing comma."""
captured_output = io.StringIO()
sys.stdout = captured_output
jac_import("trailing_comma", base_path=self.fixture_abs_path("./"))
sys.stdout = sys.__stdout__
stdout_value = captured_output.getvalue()
self.assertIn("Code compiled and ran successfully!", stdout_value)

def test_try_finally(self) -> None:
"""Test try finally."""
captured_output = io.StringIO()
Expand Down
Loading