token whitespace = /[ \n\t]+/ [ skip ]; token upper_identifier = /[A-Z_][a-z_A-Z0-9]*/; token lower_identifier = /[a-z_][a-z_A-Z0-9]*/; token number = /[0-9]+/; token kw_data = /data/; token kw_type = /type/; token kw_defn = /defn/; token kw_let = /let/; token kw_letrec = /letrec/; token kw_in = /in/; token kw_case = /case/; token kw_of = /of/; token tkn_ocurly = /{/; token tkn_ccurly = /}/; token tkn_oparen = /\(/; token tkn_cparen = /\)/; token tkn_eq = /=/; token tkn_comma = /,/; token tkn_arrow = /->/; token op_add = /\+/; token op_sub = /-/; token op_mul = /\*/; token op_div = /\//; rule S = program; rule program = definition program? ; rule definition = kw_data upper_identifier tkn_eq data_body | kw_type upper_identifier tkn_eq type_body | kw_defn lower_identifier params? tkn_eq defn_body ; rule data_body = tkn_ocurly data_elems tkn_ccurly ; rule data_elems = data_elem | data_elem tkn_comma data_elems ; rule data_elem = upper_identifier | upper_identifier tkn_oparen data_elem_types tkn_cparen ; rule data_elem_types = type | type tkn_comma data_elem_types ; rule type_body = tkn_ocurly type tkn_ccurly ; rule params = lower_identifier params? ; rule defn_body = tkn_ocurly expr tkn_ccurly ; rule expr = expr_add | expr_let | expr_letrec | expr_case ; rule expr_add = expr_add op_add expr_mul | expr_add op_sub expr_mul | expr_mul ; rule expr_mul = expr_mul op_mul expr_app | expr_mul op_div expr_app | expr_app ; rule expr_app = expr_app? expr_app_bottom ; rule expr_app_bottom = lower_identifier | upper_identifier | number | tkn_oparen expr tkn_cparen ; rule expr_curly = tkn_ocurly expr tkn_ccurly ; rule expr_let = kw_let lower_identifier tkn_eq expr_curly kw_in expr_curly ; rule expr_letrec = kw_letrec lower_identifier tkn_eq expr_curly kw_in expr_curly ; rule expr_case = kw_case expr kw_of tkn_ocurly expr_case_branches tkn_ccurly ; rule expr_case_branches = expr_case_branch expr_case_branches? ; rule expr_case_branch = pattern tkn_arrow expr_curly ; rule pattern = lower_identifier | upper_identifier | upper_identifier tkn_oparen patterns tkn_cparen ; rule patterns = lower_identifier | lower_identifier tkn_comma patterns ; rule type = upper_identifier ;