anchor.diff:          false -> list_string
         end,
         tokenize(Line, Rest, [{Kind,Line,unescape_tokens(Parts)}|Tokens])
  -  end;
  -
  -% Strings
  -
  -tokenize(Line, [H|T], Tokens) when ?is_quote(H) ->
  +  end.
  +
  +handle_strings(Line, H, T, Tokens) ->
     case elixir_interpolation:extract(Line, true, T, H) of
       { NewLine, Parts, [$:|Rest] } ->
         case Parts of
  
positive.code: tokenize(Line, "..." ++ Rest, Tokens) ->
    tokenize(Line, Rest, [tokenize_call_identifier(identifier, Line, '...', Rest)|Tokens]);
  
  % Dot call
  
  % ## Exception for .( as it needs to be treated specially in the parser
  
negative.code:     Else -> Else
    end;
  
  % Heredocs
  
  tokenize(Line, "\"\"\"" ++ T, Tokens) -> handle_heredocs(Line, $", T, Tokens);
  tokenize(Line, "'''" ++ T, Tokens)    -> handle_heredocs(Line, $', T, Tokens);
  
  % Strings
  
  tokenize(Line, [$"|T], Tokens) -> handle_strings(Line, $", T, Tokens);
  tokenize(Line, [$'|T], Tokens) -> handle_strings(Line, $', T, Tokens);
  
  % Atoms
  
  tokenize(Line, [$:,T|String], Tokens) when ?is_upcase(T); ?is_downcase(T); T == $_ ->
    { Rest, Atom } = tokenize_atom([T|String], []),
    tokenize(Line, Rest, [{atom,Line,[Atom]}|Tokens]);
  
  tokenize(Line, [$:,H|T], Tokens) when ?is_quote(H) ->
    case elixir_interpolation:extract(Line, true, T, H) of
      { NewLine, Parts, Rest } -> tokenize(NewLine, Rest, [{atom,Line,unescape_tokens(Parts)}|Tokens]);
      Else -> Else
    end;
  
  % Atom operators
  
  % ## Containers
  tokenize(Line, ":<<>>" ++ Rest, Tokens) ->
    tokenize(Line, Rest, [{atom,Line,['<<>>']}|Tokens]);
  
  tokenize(Line, [$:,T1,T2|Rest], Tokens) when ?container2(T1, T2) ->
    tokenize(Line, Rest, [{atom,Line,[list_to_atom([T1,T2])]}|Tokens]);
  
  % ## Three Token Operators
  tokenize(Line, [$:,T1,T2,T3|Rest], Tokens) when ?comp3(T1, T2, T3) ->
    tokenize(Line, Rest, [{atom,Line,[list_to_atom([T1,T2,T3])]}|Tokens]);
  
  % ## Two Token Operators
  tokenize(Line, [$:,T1,T2|Rest], Tokens) when ?comp2(T1, T2); ?op2(T1, T2) ->
    tokenize(Line, Rest, [{atom,Line,[list_to_atom([T1,T2])]}|Tokens]);
  
  % ## Single Token Operators
  tokenize(Line, [$:,T|Rest], Tokens) when ?comp1(T); ?op1(T); T == $&; T == $. ->
    tokenize(Line, Rest, [{atom,Line,[list_to_atom([T])]}|Tokens]);
  
  % End of line
  
  tokenize(Line, ";" ++ Rest, []) ->
    tokenize(Line, Rest, eol(Line, []));
  
  tokenize(Line, ";" ++ Rest, [Top|Tokens]) when element(1, Top) /= eol ->
    tokenize(Line, Rest, eol(Line, [Top|Tokens]));
  
  tokenize(Line, "\\\n" ++ Rest, Tokens) ->
    tokenize(Line + 1, Rest, Tokens);
  
  tokenize(Line, "\\\r\n" ++ Rest, Tokens) ->
    tokenize(Line + 1, Rest, Tokens);
  
  tokenize(Line, "\n" ++ Rest, Tokens) ->
    tokenize(Line + 1, Rest, eol(Line, Tokens));
  
  tokenize(Line, "\r\n" ++ Rest, Tokens) ->
    tokenize(Line + 1, Rest, eol(Line, Tokens));
  
  % Stand-alone tokens
  
  % ## &
  tokenize(Line, [$&,H|Rest], Tokens) when ?is_digit(H) ->
    tokenize(Line, Rest, [{'&', Line, [list_to_integer([H])]}|Tokens]);
  
  % ## Containers + punctuation tokens
  
  tokenize(Line, [T,T|Rest], Tokens) when T == $<; T == $>; T == $. ->
    tokenize(Line, Rest, [{list_to_atom([T,T]), Line}|Tokens]);
  
  tokenize(Line, [T|Rest], Tokens) when T == $(;
    T == ${; T == $}; T == $[; T == $]; T == $);
    T == $,; T == $. ->
    tokenize(Line, Rest, [{list_to_atom([T]), Line}|Tokens]);
  
  % ## Comparison three token operators
  tokenize(Line, [T1,T2,T3|Rest], Tokens) when ?comp3(T1, T2, T3) ->
    handle_comp_op(Line, list_to_atom([T1,T2,T3]), Rest, Tokens);
  
  % ## Three token operators - none yet
  
  % ## Comparison two token operators
  tokenize(Line, [T1,T2|Rest], Tokens) when ?comp2(T1, T2) ->
    handle_comp_op(Line, list_to_atom([T1,T2]), Rest, Tokens);
  
  % ## Two Token Operators
  tokenize(Line, [T1,T2|Rest], Tokens) when ?op2(T1, T2) ->
    handle_op(Line, list_to_atom([T1,T2]), Rest, Tokens);
  
  % ## Comparison single token operators
  tokenize(Line, [T|Rest], Tokens) when ?comp1(T) ->
    handle_comp_op(Line, list_to_atom([T]), Rest, Tokens);
  
  % ## Single Token Operators
  tokenize(Line, [T|Rest], Tokens) when ?op1(T) ->
    handle_op(Line, list_to_atom([T]), Rest, Tokens);
  
  % Integers and floats
  
  tokenize(Line, [H|_] = String, Tokens) when ?is_digit(H) ->
    { Rest, Number } = tokenize_number(String, [], false),
    tokenize(Line, Rest, [{number,Line,Number}|Tokens]);
  
  % Aliases
  
  tokenize(Line, [H|_] = String, Tokens) when ?is_upcase(H) ->
    { Rest, Alias } = tokenize_identifier(String, [], false),
    tokenize(Line, Rest, [{'__aliases__',Line,[list_to_atom(Alias)]}|Tokens]);
  
  % Identifier
  
  tokenize(Line, [H|_] = String, Tokens) when ?is_downcase(H); H == $_ ->
    { Rest, { Kind, _, Identifier } } = tokenize_any_identifier(Line, String, []),
    case keyword(Line, Kind, Identifier) of
      false ->
        tokenize(Line, Rest, [{Kind,Line,Identifier}|Tokens]);
      Else  ->
        tokenize(Line, Rest, [Else|Tokens])
    end;
  
  % Ambiguous unary/binary operators tokens
  
  tokenize(Line, [Space,Sign,NotMarker|T], [{Identifier,_,_} = H|Tokens]) when Sign == $+ orelse Sign == $-,
    Space == $\s orelse Space == $\t, NotMarker /= $\s, NotMarker /= $\t,
    NotMarker /= $\n, NotMarker /= $:, NotMarker /= $(,
    NotMarker /= $+, NotMarker /= $-, NotMarker /= $>,
    Identifier == identifier orelse Identifier == punctuated_identifier ->
    Rest = [NotMarker|T],
    tokenize(Line, Rest, [{list_to_atom([Sign]),Line},setelement(1, H, op_identifier)|Tokens]);
  
  % Spaces
  
  tokenize(Line, [T|Rest], Tokens) when T == $ ; T == $\r; T == $\t ->
    tokenize(Line, Rest, Tokens);
  
  tokenize(_, [{line,Line}|Rest], Tokens) ->
    tokenize(Line, Rest, Tokens);
  
  tokenize(Line, T, _) ->
    { error, { Line, "invalid token: ", T } }.
  
  %% Handlers
  
  handle_heredocs(Line, H, T, Tokens) ->
    case extract_heredoc_with_interpolation(Line, true, T, H) of
      { error, _ } = Error ->
        Error;
  