anchor.diff:  %% @doc
   %% SAX parser for broken HTML
   %% missing:
  -%% * handle attributes in end-tag
  +%% * handle attributes in end-tag (?)
   %% @end
   
   -module('trane').
  
positive.code: %end.
  
  
  -define(M(X),<<X,_/binary>>). % match
  -define(m(X,B),<<X,B/binary>>). % match
  -define(d(X,B),<<X:8/integer,B/binary>>). % decompose
  -define(D1(X,B),<<X:8/integer,_/binary>> = B). % decompose
  -define(D2(Y,B),<<Y:2/binary,_/binary>> = B). % decompose
  
  -define(ok(X),$a=<X,X=<$z;$A=<X,X=<$Z;$0=<X,X=<$9;X==$_;X==$-;X==$:).
  -define(ws(X),X==$\s;X==$\r;X==$\n;X==$\t).
  -define(dq(X),X==$").
  -define(sq(X),X==$').
  
  -define(ev(X), ?ws(X); X==$>; X== <<"/>">>; X==$=).
  
  tokenize(Str) when is_integer(hd(Str))-> tokenize(list_to_binary(Str));
  tokenize(Str) when is_binary(Str) -> tokenize(tz(nil,Str));
  
negative.code: tokenize({TZ,Str,Token}) ->
    [{Token,{TZ,Str}}].
  
  tz(nil,?m("<",Str))                       -> {{tag,""},ws(Str)};
  tz(nil,?d(_,Str))                         -> {nil,Str};
  
  tz({tag,""},?m("!--",Str))                -> {{comm,""},Str};
  tz({tag,""},?m("!",Str))                  -> {{'!',""},ws(Str)};
  tz({tag,""},?m("?",Str))                  -> {{que,""},ws(Str)};
  tz({tag,""},?m("/",Str))                  -> {{end_tag,""},ws(Str)};
  tz({tag,Tag},?D(X,S))when ?ev(X)          -> {{attr,"",{Tag,[]}},ws(S)};
  tz({tag,Tag},?d(X,Str))when ?ok(X)        -> {{tag,Tag++[X]},Str};
  
  tz({'!',DT},?m(">",Str))                  -> {text,Str,{'!',dc(DT)}};
  tz({'!',DT},?d(X,Str))                    -> {{'!',DT++[X]},Str};
  
  tz({que,DT},?m("?>",Str))                 -> {text,Str,{'?',dc(DT)}};
  tz({que,DT},?d(X,Str))                    -> {{que,DT++[X]},Str};
  
  tz({comm,Comm},?m("-->",Str))         -> {text,Str,{comment,Comm}};
  tz({comm,Comm},?d(X,Str))                 -> {{comm,Comm++[X]},Str};
  
  tz({etag,Tag,Attrs},?m("/>",Str))         -> {text,Str,{sc,Tag,Attrs}};
  tz({etag,"script",Attrs},?m(">",Str))     -> {script,Str,{open,"script",Attrs}};
  tz({etag,"style",Attrs},?m(">",Str))      -> {style,Str,{open,"style",Attrs}};
  tz({etag,Tag,Attrs},?m(">",Str))          -> {text,Str,{open,Tag,Attrs}};
  
  tz({end_tag,Tag},?D(X,S))when ?ev(X)      -> {{end_tag,Tag,'>'},ws(S)};
  tz({end_tag,Tag,'>'},?m(">",Str))         -> {text,Str,{close,dc(Tag)}};
  tz({end_tag,Tag},?d(X,Str))               -> {{end_tag,Tag++[X]},Str};
  
  tz({attr,"",{Tag,As}},?D(X,S))when ?ev(X) -> {{etag,dc(Tag),As},S};
  tz({attr,"",{Tag,As}},?M("/>",S))         -> {{etag,dc(Tag),As},S};
  tz({attr,A,{T,As}},?D(X,S))when ?ev(X)    -> {{eatt,{dc(A),T,As}},ws(S)};
  tz({attr,A,{T,As}},?M("/>",S))            -> {{eatt,{dc(A),T,As}},ws(S)};
  tz({attr,A,TAs},?d(X,Str))when ?ok(X)     -> {{attr,A++[X],TAs},Str};
  
  tz({eatt,ATAs},?m("=",Str))               -> {{val,ATAs},ws(Str)};
  tz({eatt,{A,T,As}},S)                     -> {{attr,"",{T,As++[{A,""}]}},ws(S)};
  
  tz({val,ATAs},?m("'",Str))                -> {{sqval,"",ATAs},Str};%singlequoted
  tz({val,ATAs},?m("\"",Str))               -> {{dqval,"",ATAs},Str};%doublequoted
  tz({val,ATAs},Str)                        -> {{uqval,"",ATAs},Str};%unquoted
  
  tz({sqval,V,{A,T,As}},?m("'",S))          -> {{attr,"",{T,As++[{A,V}]}},ws(S)};
  tz({sqval,V,ATAs},?d(X,Str))              -> {{sqval,V++[X],ATAs},Str};
  
  tz({dqval,V,{A,T,As}},?m("\"",S))         -> {{attr,"",{T,As++[{A,V}]}},ws(S)};
  tz({dqval,V,ATAs},?d(X,Str))              -> {{dqval,V++[X],ATAs},Str};
  
  tz({uqval,V,{A,T,As}},?D(X,S))when ?ev(X) -> {{attr,"",{T,As++[{A,V}]}},ws(S)};
  tz({uqval,V,{A,T,As}},?M("/>",S))         -> {{attr,"",{T,As++[{A,V}]}},ws(S)};
  tz({uqval,V,ATAs},?d(X,Str))              -> {{uqval,V++[X],ATAs},Str};
  
  tz(script,Str)                            -> ff(script,Str);
  tz(style,Str)                             -> ff(style,Str);
  tz(text,Str)                              -> ff(text,Str);
  
  tz(X,"")                                  -> {X,"",eof}.
  
  ff(What,Str) ->
    case ff(Str,ff(What),[1,2]) of
  