scratch work
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
% @doc
|
||||
% helper functions for grabbing collections of tokens
|
||||
% off the token stream
|
||||
%
|
||||
% generally assume no whitespace/comment tokens in
|
||||
% input stream
|
||||
-module(sfc_token_chunks).
|
||||
|
||||
-export_type([
|
||||
]).
|
||||
|
||||
-export([
|
||||
barf/2
|
||||
]).
|
||||
|
||||
% $sfc_include is so c() works from sfp eshell
|
||||
-include("$sfc_include/sfc.hrl").
|
||||
|
||||
%------------------------------------------
|
||||
% Types
|
||||
%------------------------------------------
|
||||
|
||||
-type chunk_shape()
|
||||
:: block
|
||||
| block_item
|
||||
| {block_item, Level :: pos_integer()}
|
||||
.
|
||||
|
||||
% FIXME
|
||||
-type choke_reason() :: any().
|
||||
|
||||
|
||||
-spec barf(ChunkShape, SigTokens) -> Perhaps
|
||||
when ChunkShape :: chunk_shape(),
|
||||
SigTokens :: Tokens,
|
||||
Perhaps :: {barf, Taken, Rest}
|
||||
| {choke, Reason},
|
||||
Taken :: Tokens,
|
||||
Rest :: Tokens,
|
||||
Reason :: choke_reason(),
|
||||
Tokens :: [sfc_token()].
|
||||
|
||||
% @doc
|
||||
% slurp/barf terminology comes from paredit mode in
|
||||
% emacs
|
||||
%
|
||||
% slurp ~= accepting input
|
||||
% barf ~= separating input
|
||||
%
|
||||
% slurp: (foo bar) baz ~> (foo bar baz)
|
||||
% barf : (foo bar baz) ~> foo (bar baz)
|
||||
|
||||
barf(_, []) ->
|
||||
{barf, [], []};
|
||||
barf(block, [H = #sfc_token{pos = {_, BlkCol}} | T]) ->
|
||||
Take =
|
||||
fun(#sfc_token{pos = {_, TkCol}}) ->
|
||||
BlkCol =< TkCol
|
||||
end,
|
||||
{A, B} = tw(Take, T),
|
||||
{barf, [H | A], B};
|
||||
barf(block_item, [H = #sfc_token{pos = {_, BlkCol}} | T]) ->
|
||||
Take =
|
||||
fun(#sfc_token{pos = {_, TkCol}}) ->
|
||||
BlkCol < TkCol
|
||||
end,
|
||||
{A, B} = tw(Take, T),
|
||||
{barf, [H | A], B}.
|
||||
barf({block_item, Level}, Tokens = [#sfc_token{pos = {_, StartLevel}} | _]) ->
|
||||
case Level =:= StartLevel of
|
||||
false -> {barf, [], Tokens};
|
||||
true -> barf(block_item, Tokens)
|
||||
end.
|
||||
barf(_, _) ->
|
||||
{choke, #sfc_err_nyi{}}.
|
||||
|
||||
|
||||
% takewhile but returns {Taken, Rest}
|
||||
tw(Pred, List) ->
|
||||
tw(Pred, [], List).
|
||||
|
||||
tw(Pred, Stk, [X | Xs]) ->
|
||||
case Pred(X) of
|
||||
true -> tw(Pred, [X | Stk], Xs);
|
||||
false -> {lists:reverse(Stk), [X | Xs]}
|
||||
end;
|
||||
tw(_, Stk, []) ->
|
||||
{lists:reverse(Stk), []}.
|
||||
|
||||
|
||||
%-spec consume_delist_round(Tokens) -> Result
|
||||
% when Tokens :: [sfc_token()],
|
||||
% Result :: {ok, {Delist, NewTokens}}
|
||||
% | {error, sfc_err()},
|
||||
% Delist :: Tokens,
|
||||
% NewTokens :: Tokens.
|
||||
%
|
||||
%consume_delist_round(Tokens = [#sfc_token{type = punct, string = "("} | _]) ->
|
||||
% consume_delist(Tokens);
|
||||
%consume_delist_round(Tokens) ->
|
||||
% {ok, {[], Tokens}}.
|
||||
%
|
||||
%
|
||||
%
|
||||
%-spec consume_delist_square(Tokens) -> Result
|
||||
% when Tokens :: [sfc_token()],
|
||||
% Result :: {ok, {Delist, NewTokens}}
|
||||
% | {error, sfc_err()},
|
||||
% Delist :: Tokens,
|
||||
% NewTokens :: Tokens.
|
||||
%
|
||||
%consume_delist_square(Tokens = [#sfc_token{type = punct, string = "["} | _]) ->
|
||||
% consume_delist(Tokens);
|
||||
%consume_delist_square(Tokens) ->
|
||||
% {ok, {[], Tokens}}.
|
||||
%
|
||||
%
|
||||
%
|
||||
%-spec consume_delist_curly(Tokens) -> Result
|
||||
% when Tokens :: [sfc_token()],
|
||||
% Result :: {ok, {Delist, NewTokens}}
|
||||
% | {error, sfc_err()},
|
||||
% Delist :: Tokens,
|
||||
% NewTokens :: Tokens.
|
||||
%
|
||||
%consume_delist_curly(Tokens = [#sfc_token{type = punct, string = "{"} | _]) ->
|
||||
% consume_delist(Tokens);
|
||||
%consume_delist_curly(Tokens) ->
|
||||
% {ok, {[], Tokens}}.
|
||||
%
|
||||
%
|
||||
%
|
||||
%-spec consume_delist(Tokens) -> Result
|
||||
% when Tokens :: [sfc_token()],
|
||||
% Result :: {ok, {Delist, NewTokens}}
|
||||
% | {error, sfc_err()},
|
||||
% Delist :: Tokens,
|
||||
% NewTokens :: Tokens.
|
||||
%
|
||||
%consume_delist([Head | Tail]) ->
|
||||
% case Head of
|
||||
% #sfc_token{type = punct, string = OpenStr = "("} ->
|
||||
% CloseStr = ")",
|
||||
% delist_verb(1, {OpenStr, CloseStr}, [Head], Tail);
|
||||
% #sfc_token{type = punct, string = OpenStr = "["} ->
|
||||
% CloseStr = "]",
|
||||
% delist_verb(1, {OpenStr, CloseStr}, [Head], Tail);
|
||||
% #sfc_token{type = punct, string = OpenStr = "{"} ->
|
||||
% CloseStr = "}",
|
||||
% delist_verb(1, {OpenStr, CloseStr}, [Head], Tail);
|
||||
% _ ->
|
||||
% {ok, {[], [Head | Tail]}}
|
||||
% end;
|
||||
%consume_delist([]) ->
|
||||
% {ok, {[], []}}.
|
||||
%
|
||||
%
|
||||
%% happy path: have a token and we are in the depth of the list
|
||||
%delist_verb(Depth, {OpenStr, CloseStr}, Stack, [Tok | Rest]) when Depth >= 1 ->
|
||||
% NewDepth =
|
||||
% case Tok of
|
||||
% % open token -> increase depth
|
||||
% #sfc_token{type = punct, string = Open} when Open =:= OpenStr ->
|
||||
% Depth + 1;
|
||||
% % close token -> decrease depth
|
||||
% #sfc_token{type = punct, string = Close} when Close =:= CloseStr ->
|
||||
% Depth - 1;
|
||||
% _ ->
|
||||
% Depth
|
||||
% end,
|
||||
% delist_verb(NewDepth, {OpenStr, CloseStr}, [Tok | Stack], Rest);
|
||||
%% we've hit end of available input before a close token
|
||||
%delist_verb(Depth, {OpenStr, _CloseStr}, _Stack, []) when Depth >= 1 ->
|
||||
% {error, #sfc_err{atom = unclosed_delimiter,
|
||||
% string = io_lib:format("unclosed open delimiter: ~p", [OpenStr])}};
|
||||
%% we've popped back out of the list, we're done
|
||||
%delist_verb(_Depth = 0, {_OpenStr, _CloseStr}, Stack, Tokens) ->
|
||||
% {ok, {lists:reverse(Stack), Tokens}}.
|
||||
Reference in New Issue
Block a user