
%nonassoc catch
%right '='
%right '!'
%left add_op
%left mult_op
%nonassoc prefix_op

%%

add_op :	'+'	
	|	'-'
	|	T_bor
	|	T_bxor
	|	T_bsl
	|	T_bsr

comp_op :	T_equal
	|	T_notequal
	|	T_le
	|	T_lt
	|	T_ge
	|	T_gt
	|	T_exactequals

mult_op	:	'*'
	|	'/'
	|	T_div
	|	T_rem
	|	T_band

prefix_op :	'+'
	|	'-'
	|	T_bnot

basic_type :	T_atom
	|	T_number
	|	T_string
	|	T_var
	|	T_true

pattern :	basic_type
	|	pattern_list
	|	pattern_tuple

pattern_list :	'[' ']'
	|	'[' pattern pattern_tail ']'

pattern_tail :	'|' pattern
	|	',' pattern pattern_tail
	|	/* empty */
	;

pattern_tuple :	'{' '}'
	| 	'{' patterns '}'

patterns :	pattern
	| 	pattern ',' patterns

expr :		basic_type
	|	list
	|	tuple
	|	function_call
	|	expr add_op expr
	|	expr mult_op expr
	|	prefix_op expr
	|	'(' expr ')'
	|	T_begin exprs T_end
	|	T_catch expr
	|	case_expr
	|	if_expr
	|	receive_expr
	|	match_expr
	|	send_expr

list :		'[' ']'
	| 	'[' expr expr_tail ']'

expr_tail :	'|' expr
	| 	',' expr expr_tail
	|	/* empty */
	;

tuple :		'{' '}'
	|	'{' exprs '}'

function_call : T_atom '(' parameter_list ')'
	|  	T_atom ':' T_atom  '(' parameter_list ')'

parameter_list : exprs
	| 	/* empty */
	;

case_expr :	T_case expr T_of cr_clauses T_end
	
cr_clause : 	pattern clause_guard clause_body

cr_clauses : 	cr_clause
	| 	cr_clause ';' cr_clauses

if_expr : 	T_if if_clauses T_end

if_clause : 	guard clause_body

if_clauses :	if_clause
	| 	if_clause ';' if_clauses

receive_expr : 	T_receive T_after expr clause_body T_end
	| 	T_receive cr_clauses T_end
	| 	T_receive cr_clauses T_after expr clause_body T_end

match_expr : 	expr '=' expr

send_expr : 	expr '!' expr

exprs :		expr
	|	expr ',' exprs

guard_expr :	basic_type
	|	guard_expr_list
	|	guard_expr_tuple
	|	guard_call
	|	'(' guard_expr ')'
	|	guard_expr add_op guard_expr
	| 	guard_expr mult_op guard_expr
	|	prefix_op guard_expr

guard_expr_list : '[' ']'
	| '[' guard_expr guard_expr_tail ']'

guard_expr_tail : '|' guard_expr
	|	',' guard_expr guard_expr_tail
	| 	/* empty */
	;

guard_expr_tuple : '{' '}'
	| '{' guard_exprs '}'

guard_exprs :	guard_expr
	|	guard_expr ',' guard_exprs

guard_call :	T_atom '(' guard_parameter_list ')'

guard_parameter_list : guard_exprs
	|	/* empty */
	;

bif_test :	T_atom '(' guard_parameter_list ')'

guard_test : 	bif_test
	| 	guard_expr comp_op guard_expr

guard_tests : 	guard_test
	|	guard_test ',' guard_tests

guard :		T_true
	|	guard_tests

function_clause : clause_head clause_guard clause_body

clause_head :	T_atom '(' formal_parameter_list ')'

formal_parameter_list : /* empty */
	|	patterns

clause_guard : 	/* empty */	
	|	T_when guard
	
clause_body : T_arrow exprs

function :	function_clause
	| 	function_clause ';' function

attribute :	pattern
	| 	'[' farity_list ']'
	|	T_atom ',' '[' farity_list ']'

farity_list : 	farity
	|	farity ',' farity_list

farity :	T_atom '/' T_number

form :		'-' T_atom '(' attribute ')'
	|	function





