Current section
Files
Jump to
Current section
Files
src/dtu_walk.erl
-module(dtu_walk).
-export([walk/2,
walk/4,
new_state/0,
compose/1,
add_warning/3,
add_error/3,
get_errors/1,
get_warnings/1]).
new_state() ->
#{errors => [], warnings => [], state => #{}}.
add_warning(State = #{warnings := Warns}, Node, Msg) ->
State#{warnings := [{Node, Msg} | Warns]}.
add_error(State = #{errors := Errors}, Node, Msg) ->
State#{errors := [{Node, Msg} | Errors]}.
get_errors(#{errors := Errors}) ->
Errors.
get_warnings(#{warnings := Warns}) ->
Warns.
run_fns(State0, _Path, Node, []) ->
{State0, Node};
run_fns(State0, Path, Node, [Fn | Fns]) ->
{State1, Node1} = Fn(State0, Path, Node),
run_fns(State1, Path, Node1, Fns).
compose(Fns) ->
fun (State0, Path, Node) ->
run_fns(State0, Path, Node, Fns)
end.
walk(Fn, Node) ->
walk(new_state(), Fn, [], Node).
walk(State0, Fn, Path, {node, Line, {Id, Seq, Child}}) ->
Path1 = [node | Path],
{State1, Id1} = walk(State0, Fn, Path1, Id),
{State2, Seq1} = walk(State1, Fn, Path1, Seq),
{State3, Child1} = walk(State2, Fn, Path1, Child),
Fn(State3, Path, {node, Line, {Id1, Seq1, Child1}});
walk(State0, Fn, Path, {seq, Line, {Type, Items}}) ->
Path1 = [seq | Path],
{State1, Items1} = walk_items(State0, Fn, Path1, Items),
Fn(State1, Path, {seq, Line, {Type, Items1}});
walk(State0, Fn, Path, {op, Line, {Symbol, Left, Right}}) ->
Path1 = [op | Path],
{State1, Left1} = walk(State0, Fn, Path1, Left),
{State2, Right1} = walk(State1, Fn, Path1, Right),
Fn(State2, Path, {op, Line, {Symbol, Left1, Right1}});
walk(State0, Fn, Path, {uop, Line, {Symbol, Right}}) ->
Path1 = [uop | Path],
{State1, Right1} = walk(State0, Fn, Path1, Right),
Fn(State1, Path, {uop, Line, {Symbol, Right1}});
walk(State0, Fn, Path, {alt, Line, {Type, Items}}) ->
Path1 = [alt | Path],
{State1, Items1} = walk_items(State0, Fn, Path1, Items),
Fn(State1, Path, {alt, Line, {Type, Items1}});
walk(State0, Fn, Path, {pair, Line, {Left, Right}}) ->
Path1 = [pair | Path],
{State1, Left1} = walk(State0, Fn, Path1, Left),
{State2, Right1} = walk(State1, Fn, Path1, Right),
Fn(State2, Path, {pair, Line, {Left1, Right1}});
walk(State0, Fn, Path, {tag, Line, {Tag, Val}}) ->
Path1 = [tag | Path],
{State1, Val1} = walk(State0, Fn, Path1, Val),
Fn(State1, Path, {tag, Line, {Tag, Val1}});
walk(State0, Fn, Path, {anno, Line, {Val, Anno}}) ->
Path1 = [anno | Path],
{State1, Val1} = walk(State0, Fn, Path1, Val),
{State2, Anno1} = walk(State1, Fn, Path1, Anno),
Fn(State2, Path, {anno, Line, {Val1, Anno1}});
walk(State0, Fn, Path, {attr, Line, {Key, Args}}) ->
Path1 = [attr | Path],
{State1, Args1} = walk_items(State0, Fn, Path1, Args),
Fn(State1, Path, {attr, Line, {Key, Args1}});
walk(State0, Fn, Path, {attrs, Line, {Attrs, Node}}) ->
Path1 = [attrs | Path],
{State1, Attrs1} = walk_items(State0, Fn, Path1, Attrs),
{State2, Node1} = walk(State1, Fn, Path1, Node),
Fn(State2, Path, {attrs, Line, {Attrs1, Node1}});
walk(State0, Fn, Path, Node) ->
Fn(State0, Path, Node).
walk_items(State0, Fn, Path, Items) ->
walk_items(State0, Fn, Path, Items, []).
walk_items(State0, _Fn, _Path, [], Accum) ->
{State0, lists:reverse(Accum)};
walk_items(State0, Fn, Path, [H | T], Accum) ->
{State1, H1} = walk(State0, Fn, Path, H),
walk_items(State1, Fn, Path, T, [H1 | Accum]).