-module(gsc_ntree). -export_type([ ntree/2, ntree/0, nforest/2, nforest/0, nt/2, nt/0, nf/2, nf/0 ]). -export([ nstem/2, meta/1, kids/1, flatten_tree/1, flatten_forest/1 ]). -include("$gsc_include/gsc.hrl"). %%===================================================== %% API: types %%===================================================== % @doc stem record -record(ns, {meta :: any(), kids :: list(any())}). % @doc `ntree(S, L)' is a "node tree" (meaning stems % have values and children) % % for the purposes of the compiler, the key observation % is that a flat list of tokens is already a forest -type ntree(S, L) :: #ns{meta :: S, kids :: [ntree(S, L)]} | L. % @doc forest is just a list of trees -type nforest(S, L) :: [ntree(S, L)]. % aliases -type nt(S, L) :: ntree(S, L). -type nf(S, L) :: nforest(S, L). -type ntree() :: ntree(any(), any()). -type nforest() :: [ntree()]. -type nt() :: ntree(). -type nf() :: nforest(). %%===================================================== %% API: functions %%===================================================== -spec nstem(Root, Forest) -> Tree when Root :: S, Forest :: nforest(S, L), Tree :: ntree(S, L), S :: any(), L :: any(). nstem(Root, List) -> {ns, Root, List}. meta(#ns{meta = M}) -> M. kids(#ns{kids = K}) -> K. -spec flatten_tree(Tree) -> Leafs when Tree :: ntree(_, L), Leafs :: [L], L :: any(). flatten_tree(T) -> lists:flatten(ft(T)). -spec flatten_forest(Forest) -> Leafs when Forest :: nforest(_, L), Leafs :: [L], L :: any(). flatten_forest(F) -> lists:flatten(ff(F)). ft(#ns{kids = F}) -> ff(F); ft(Leaf) -> [Leaf]. ff(F) -> [ft(T) || T <- F].