akhamoth/src/akh_source_map.erl

42 lines
1.1 KiB
Erlang

-module(akh_source_map).
-moduledoc """
The source map translates the byte offsets returned by the lexer into lines and
columns for display. Internally, it uses the balanced binary tree from
`m:gb_trees` to avoid linear lookup times.
""".
-export([
new/0,
insert/2,
location/2
]).
-export_type([source_map/0]).
-opaque source_map() :: {gb_trees:tree(non_neg_integer(), pos_integer()), Line :: pos_integer()}.
-type location() :: {Line :: pos_integer(), Column :: pos_integer()}.
-doc """
Returns a new source map.
""".
-spec new() -> source_map().
new() -> {gb_trees:empty(), 1}.
-doc """
Insert the next line break at byte offset `Offset`.
""".
-spec insert(Offset :: non_neg_integer(), SourceMap :: source_map()) -> source_map().
insert(Offset, {Tree, Line}) -> {gb_trees:insert(Offset - 1, Line + 1, Tree), Line + 1}.
-doc """
Get line and column info for byte offset `Offset`.
""".
-spec location(Offset :: non_neg_integer(), SourceMap :: source_map()) -> location().
location(Offset, {Tree, _}) ->
case gb_trees:smaller(Offset, Tree) of
{Start, Line} ->
{Line, Offset - Start};
none ->
{1, Offset}
end.