anchor.diff:  bool_and_expr -> comp_expr bool_andalso_op bool_and_expr : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
   bool_and_expr -> comp_expr                               : '$1'.
   
  -comp_expr -> concat_expr comp_op concat_expr    : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  -comp_expr -> concat_expr                        : '$1'.
  -
  -concat_expr -> add_expr concat_op concat_expr   : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  -concat_expr -> add_expr                         : '$1'.
  -
  -add_expr -> add_expr add_op mul_expr         : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  -add_expr -> add_expr or_op mul_expr          : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  -add_expr -> add_expr bool_or_op mul_expr     : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  -add_expr -> add_expr shift_op mul_expr       : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  -add_expr -> mul_expr                         : '$1'.
  -
  -mul_expr -> mul_expr mul_op block_expr       : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  -mul_expr -> mul_expr and_op block_expr       : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  -mul_expr -> mul_expr bool_and_op block_expr  : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  -mul_expr -> block_expr                       : '$1'.
  +comp_expr -> concat_expr comp_op concat_expr : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  +comp_expr -> concat_expr                     : '$1'.
  +
  +concat_expr -> add_expr concat_op concat_expr : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  +concat_expr -> add_expr                       : '$1'.
  +
  +add_expr -> add_expr add_op mul_expr     : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  +add_expr -> add_expr or_op mul_expr      : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  +add_expr -> add_expr bool_or_op mul_expr : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  +add_expr -> add_expr shift_op mul_expr   : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  +add_expr -> mul_expr                     : '$1'.
  +
  +mul_expr -> mul_expr mul_op block_expr      : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  +mul_expr -> mul_expr and_op block_expr      : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  +mul_expr -> mul_expr bool_and_op block_expr : {op, line('$2'), op(unwrap('$2')), '$1', '$3'}.
  +mul_expr -> block_expr                      : '$1'.
   
   signed_integer -> add_op integer : {op, line('$2'), unwrap('$1'), '$2'}.
   
   signed_integer -> integer : '$1'.
   
  -block_expr -> if_expr           : '$1'.
  -block_expr -> for_expr          : '$1'.
  -block_expr -> when_expr         : '$1'.
  -block_expr -> arrow_expr        : '$1'.
  -block_expr -> case_expr         : '$1'.
  -block_expr -> try_expr          : '$1'.
  -block_expr -> recv_expr         : '$1'.
  -block_expr -> fun_def           : '$1'.
  +block_expr -> if_expr    : '$1'.
  +block_expr -> for_expr   : '$1'.
  +block_expr -> when_expr  : '$1'.
  +block_expr -> arrow_expr : '$1'.
  +block_expr -> case_expr  : '$1'.
  +block_expr -> try_expr   : '$1'.
  +block_expr -> recv_expr  : '$1'.
  +block_expr -> fun_def    : '$1'.
   
   % when expression
  -when_expr  -> when when_patterns      : {'if', line('$1'), '$2'}.
  +when_expr  -> when when_patterns : {'if', line('$1'), '$2'}.
   
   when_patterns -> when_pattern else fn_block :
       ['$1'|[{clause, line('$2'), [], [[{atom, line('$2'), true}]], '$3'}]].
   
  -when_patterns -> when_pattern else when when_patterns          : ['$1'|'$4'].
  -when_patterns -> when_pattern                              : ['$1'].
  -when_pattern  -> bool_expr fn_block                      : {clause, line('$1'), [], [['$1']], '$2'}.
  +when_patterns -> when_pattern else when when_patterns : ['$1'|'$4'].
  +when_patterns -> when_pattern                         : ['$1'].
  +when_pattern  -> bool_expr fn_block                   : {clause, line('$1'), [], [['$1']], '$2'}.
   
   % if expression
   
  -if_expr     -> if bool_expr fn_block :
  +if_expr -> if bool_expr fn_block :
        {'case', line('$1'), '$2', [{clause, line('$3'), [{atom, line('$3'), true}], [], '$3'}]}.
   
  -if_expr     -> if bool_expr fn_block else if_expr :
  +if_expr -> if bool_expr fn_block else if_expr :
        {'case', line('$1'), '$2',
            [{clause, line('$3'), [{atom, line('$3'), true}], [], '$3'},
             {clause, line('$3'), [{atom, line('$3'), false}], [], ['$5']}]}.
   
  -if_expr     -> if bool_expr fn_block else fn_block:
  +if_expr -> if bool_expr fn_block else fn_block:
        {'case', line('$1'), '$2',
            [{clause, line('$3'), [{atom, line('$3'), true}], [], '$3'},
             {clause, line('$3'), [{atom, line('$3'), false}], [], '$5'}]}.
  
positive.code: 
  % binary
  
  binary -> open_bin binary_items close_bin : {'bin', line('$1'), '$2'}.
  binary -> open_bin close_bin : {'bin', line('$1'), []}.
  
  binary_items -> binary_item sep binary_items : ['$1'|'$3'].
  binary_items -> binary_item : ['$1'].
  
  binary_item -> literal split_op integer mul_op bin_type_def :
      assert_atom('$4', '/'),
      {bin_element, line('$1'), '$1', '$3', '$5'}.
  
  binary_item -> literal mul_op bin_type_def :
      assert_atom('$2', '/'),
      {bin_element, line('$1'), '$1', default, '$3'}.
  
  binary_item -> literal split_op integer :
      {bin_element, line('$1'), '$1', '$3', default}.
  
  binary_item -> literal : {bin_element, line('$1'), '$1', default, default}.
  
  % used in @type
  
  
negative.code: 
  % function call
  
  fun_call -> atom fn_parameters: {call, line('$1'), '$1', '$2'}.
  fun_call -> var fn_parameters : {call, line('$1'), '$1', '$2'}.
  fun_call -> atom dot atom fn_parameters:
      {call, line('$2'), {remote, line('$2'), '$1', '$3'}, '$4'}.
  fun_call -> atom dot var fn_parameters:
      {call, line('$2'), {remote, line('$2'), '$1', '$3'}, '$4'}.
  fun_call -> var dot atom fn_parameters:
      {call, line('$2'), {remote, line('$2'), '$1', '$3'}, '$4'}.
  fun_call -> var dot var fn_parameters:
      {call, line('$2'), {remote, line('$2'), '$1', '$3'}, '$4'}.
  fun_call -> fun_call fn_parameters: {call, line('$1'), '$1', '$2'}.
  
  % function arity
  
  farity -> fn atom split_op integer:
      {'fun', line('$1'), {function, unwrap('$2'), unwrap('$4')}}.
  
  farity -> fn atom dot atom split_op integer:
      {'fun', line('$1'), {function, unwrap('$2'), unwrap('$4'), unwrap('$6')}}.
  
  % list comprehension
  