anchor.diff:  %% Unary operators
   unary_op -> '+'   : '$1'.
   unary_op -> '-'   : '$1'.
  -unary_op -> 'not' : '$1'.
  -
  -%% Declarations
  -declaration -> module_decl : '$1'.
  -declaration -> class_decl : '$1'.
  -
  -%% Module declaration
  -module_decl -> module constant eol functions 'end' : {module, line('$1'), '$2', '$4'}.
  -
  -%% Class declaration
  -class_decl -> class constant eol functions 'end' : {class, line('$1'), '$2', '$4'}.
  -class_decl -> class constant '<' constant eol functions 'end' : {class, line('$1'), '$2', '$4', '$6'}.
  -
  -%% Functions
  -functions -> function : ['$1'].
  -functions -> function eol : ['$1'].
  -functions -> eol functions : '$2'.
  -functions -> function eol functions : ['$1'|'$3'].
  -
  -%% Function definitions
  -function -> def function_identifier eol expr_list 'end' : {function, line('$1'), '$2', [], {nil, line('$2')}, '$4'}.
  -function -> def function_identifier '(' ')' eol expr_list 'end' : {function, line('$1'), '$2', [], {nil, line('$2')}, '$6'}.
  -function -> def function_identifier '(' exprs ')' eol expr_list 'end' : {function, line('$1'), '$2', '$4', {nil, line('$2')}, '$7'}.
  -
  -%% Function definitions with block arguments
  -function -> def function_identifier '(' '&' identifier ')' eol expr_list 'end' : {function, line('$1'), '$2', [], '$5', '$8'}.
  -function -> def function_identifier '(' function_params '&' identifier ')' eol expr_list 'end' : {function, line('$1'), '$2', '$4', '$6', '$9'}.
  -
  -%% FIXME: workaround for shift/reduce conflicts involving ',' and block args
  -%% Doesn't handle newlines properly
  -function_params -> expr ',' : ['$1'].
  -function_params -> expr ',' function_params : ['$1'|'$3'].
  -
  -%% Function identifiers
  -function_identifier -> identifier : function_identifier('$1').
  -function_identifier -> punctuated_identifier : function_identifier('$1').
  -function_identifier -> class : function_identifier('$1').
  -
  -%% Function references
  -funref -> funcall_expr '.' function_identifier : {funref, line('$2'), '$1', '$3'}.
  -
  -%% Local function calls
  -funcall -> function_identifier '(' ')' : {funcall, line('$2'), '$1', [], {atom, line('$2'), nil}}.
  -funcall -> function_identifier '(' exprs ')' : {funcall, line('$2'), '$1', '$3', {atom, line('$2'), nil}}.
  -
  -%% Remote function calls
  -funcall -> funcall_expr '.' function_identifier '(' ')' : {funcall, line('$2'), '$1', '$3', [], {atom, line('$2'), nil}}.
  -funcall -> funcall_expr '.' function_identifier '(' exprs ')' : {funcall, line('$2'), '$1', '$3', '$5', {atom, line('$2'), nil}}.
  -funcall -> funcall_expr '[' expr ']' : {funcall, line('$2'), '$1', {identifier, line('$2'), '[]'}, ['$3'], {atom, line('$2'), nil}}.
  -funcall -> funcall_expr '.' function_identifier '[' expr ']' : {funcall, line('$2'), {funcall, line('$2'), '$1', '$3', [], {atom, line('$2'), nil}}, {identifier, line('$2'), '[]'}, ['$5'], {atom, line('$2'), nil}}.
  -
  -%% Async function calls
  -funcall -> funcall_expr '<-' function_identifier '(' ')' : {cast, line('$2'), '$1', '$3', [], {atom, line('$2'), nil}}.
  -funcall -> funcall_expr '<-' function_identifier '(' exprs ')' : {cast, line('$2'), '$1', '$3', '$5', {atom, line('$2'), nil}}.
  -
  -%% Local function calls with blocks
  -funcall -> function_identifier block : {funcall, line('$2'), '$1', [], '$2'}.
  -funcall -> function_identifier '(' ')' block : {funcall, line('$2'), '$1', [], '$4'}.
  -funcall -> function_identifier '(' exprs ')' block : {funcall, line('$2'), '$1', '$3', '$5'}.
  -
  -%% Remote function calls with blocks
  -funcall -> funcall_expr '.' function_identifier block : {funcall, line('$2'), '$1', '$3', [], '$4'}.
  -funcall -> funcall_expr '.' function_identifier '(' ')' block : {funcall, line('$2'), '$1', '$3', [], '$6'}.
  -funcall -> funcall_expr '.' function_identifier '(' exprs ')' block : {funcall, line('$2'), '$1', '$3', '$5', '$7'}.
  -
  -% Async function calls with blocks
  -funcall -> funcall_expr '<-' function_identifier block : {cast, line('$2'), '$1', '$3', [], '$4'}.
  -funcall -> funcall_expr '<-' function_identifier '(' ')' block : {cast, line('$2'), '$1', '$3', [], '$6'}.
  -funcall -> funcall_expr '<-' function_identifier '(' exprs ')' block : {cast, line('$2'), '$1', '$3', '$5', '$7'}.
  -
  -%% Local function calls with lambdas passed as blocks
  -funcall -> function_identifier '(' '&' identifier ')' : {funcall, line('$2'), '$1', [], '$4'}.
  -funcall -> function_identifier '(' function_params '&' identifier ')' : {funcall, line('$2'), '$1', '$3', '$5'}.
  -
  -% Remote function calls with lambdas passed as blocks
  -funcall -> funcall_expr '.' function_identifier '(' '&' identifier ')' : {funcall, line('$2'), '$1', '$3', [], '$6'}.
  -funcall -> funcall_expr '.' function_identifier '(' function_params '&' identifier ')' : {funcall, line('$2'), '$1', '$3', '$5', '$7'}.
  -
  -% Async function calls with lambdas passed as blocks
  -funcall -> funcall_expr '<-' function_identifier '(' '&' identifier ')' : {cast, line('$2'), '$1', '$3', [], '$6'}.
  -funcall -> funcall_expr '<-' function_identifier '(' function_params '&' identifier ')' : {cast, line('$2'), '$1', '$3', '$5', '$7'}.
  -
  -%% Class instantiations
  -class_inst -> constant '(' ')' : {class_inst, line('$2'), '$1', []}.
  -class_inst -> constant '(' exprs ')' : {class_inst, line('$2'), '$1', '$3'}.
  -
  -%% Class instantiations with blocks
  -class_inst -> constant block : {funcall, line('$2'), '$1', [], '$2'}.
  -class_inst -> constant '(' ')' block : {funcall, line('$2'), '$1', [], '$4'}.
  -class_inst -> constant '(' exprs ')' block : {funcall, line('$2'), '$1', '$3', '$5'}.
  -
  -%% Blocks
  -
  -block -> '{' expr_list '}' : {lambda, line('$1'), [], '$2'}.
  -block -> '{' '|' exprs '|' expr_list '}' : {lambda, line('$1'), '$3', '$5'}.
  -
  -block -> do expr_list 'end' : {lambda, line('$1'), [], '$2'}.
  -block -> do '|' exprs '|' expr_list 'end' : {lambda, line('$1'), '$3', '$5'}.
  -
  -%% Erlang function calls
  -erl_funcall -> identifier '::' identifier '(' ')' : {erl_funcall, line('$2'), '$1', '$3', []}.
  -erl_funcall -> identifier '::' identifier '(' exprs ')' : {erl_funcall, line('$2'), '$1', '$3', '$5'}.
   
   %% Numbers
   number -> float : '$1'.
   number -> integer : '$1'.
  -
  -%% Lists
  -list -> '[' ']' : {list, line('$1'), []}.
  -list -> '[' exprs ']' : {list, line('$1'), '$2'}.
  -
  -%% Tuples
  -tuple -> '(' ')' : {tuple, line('$1'), []}.
  -tuple -> '(' expr ',' ')' : {tuple, line('$1'), ['$2']}.
  -tuple -> '(' expr ',' exprs ')': {tuple, line('$1'), ['$2'|'$4']}.
  -
  -%% Dicts
  -dict -> '{' '}' : {dict, line('$1'), []}.
  -dict -> '{' dict_entries '}' : {dict, line('$1'), '$2'}.
  -
  -dict_entries -> bool_expr '=>' expr : [{'$1','$3'}].
  -dict_entries -> bool_expr '=>' expr ',' dict_entries : [{'$1','$3'}|'$5'].
  -
  -%% Binaries
  -binary -> '<<' string '>>' : {binary, line('$1'), '$2'}.
  -
  -%% Lambdas
  -lambda -> fun '{' expr_list '}' : {lambda, line('$1'), [], '$3'}.
  -lambda -> fun '(' ')' '{' expr_list '}' : {lambda, line('$1'), [], '$5'}.
  -lambda -> fun '(' exprs ')' '{' expr_list '}' : {lambda, line('$1'), '$3', '$6'}.
  -lambda -> fun do expr_list 'end' : {lambda, line('$1'), [], '$3'}.
  -lambda -> fun '(' ')' do expr_list 'end' : {lambda, line('$1'), [], '$5'}.
  -lambda -> fun '(' exprs ')' do expr_list 'end' : {lambda, line('$1'), '$3', '$6'}.
  -  
  -%% List comprehensions
  -list_comprehension -> '[' expr '|' lc_exprs ']' : {lc, line('$1'), '$2', '$4'}.
  -
  -lc_exprs -> lc_expr : ['$1'].
  -lc_exprs -> lc_expr ',' lc_exprs: ['$1'|'$3'].
  -
  -lc_expr -> expr : '$1'.
  -lc_expr -> expr 'in' expr : {generate, line('$2'), '$1', '$3'}.
   
   Erlang code.
   
  
positive.code: expr_list -> eol expr_list : '$2'.
  expr_list -> expr eol expr_list : ['$1'|'$3'].
  
  %% Expressions (comma delimited)
  exprs -> expr : ['$1'].
  exprs -> expr eol : ['$1'].
  exprs -> eol exprs : '$2'.
  exprs -> expr ',' exprs : ['$1'|'$3'].
  
  expr -> inline_if_expr : '$1'.
  
  inline_if_expr -> match_expr 'if' match_expr : {'if', line('$2'), [{clause, line('$2'), '$3', ['$1']}]}.
  inline_if_expr -> match_expr 'unless' match_expr : {'if', line('$2'), [{clause, line('$2'), {op, line('$2'), 'not', '$3'}, ['$1']}]}.
  inline_if_expr -> match_expr : '$1'.
  
  match_expr -> send_expr '=' match_expr : {match, line('$2'), '$1', '$3'}.
  match_expr -> send_expr : '$1'.
  
  send_expr -> bool_expr '!' send_expr : {send, line('$2'), '$1', '$3'}.
  send_expr -> bool_expr : '$1'.
  
  bool_expr -> comp_expr bool_op bool_expr : {op, line('$1'), op('$2'), '$1', '$3'}.
  bool_expr -> comp_expr : '$1'.
  
  comp_expr -> range_expr comp_op range_expr : {op, line('$1'), op('$2'), '$1', '$3'}.
  comp_expr -> range_expr : '$1'.
  
  range_expr -> add_expr '..' range_expr : {range, line('$2'), '$1', '$3'}.
  range_expr -> add_expr : '$1'.
  
  add_expr -> mult_expr add_op add_expr : {op, line('$1'), op('$2'), '$1', '$3'}.
  add_expr -> mult_expr : '$1'.
  
negative.code: Nonterminals
    grammar
    expr_list
    expr
    add_expr
    mult_expr
    pow_expr
    unary_expr
    terminal_expr
    add_op
    mult_op
    pow_op
    unary_op
    number
    .
    
  Terminals
    eol '(' ')'
    float integer
    '+' '-' '*' '/' '%' '**'
    .
  
  Rootsymbol grammar.
  