wip name cleanups
This commit is contained in:
+35
-51
@@ -1,20 +1,10 @@
|
|||||||
% This is a header file that contains sfc's record types
|
% This is a header file that contains gsc's record types
|
||||||
%
|
%
|
||||||
% This is in order to
|
% This is in order to
|
||||||
% 1. share records across modules; and,
|
% 1. share records across modules; and,
|
||||||
% 2. allow external modules to just use the sfc records
|
% 2. allow external modules to just use the gsc records
|
||||||
|
|
||||||
%-------------------------------------------------------
|
-type tk_shape()
|
||||||
% API Types: sfc internal token representation
|
|
||||||
%
|
|
||||||
% -export_type([
|
|
||||||
% sf_token_type/0
|
|
||||||
% sf_token/0
|
|
||||||
% ]).
|
|
||||||
%-------------------------------------------------------
|
|
||||||
|
|
||||||
%
|
|
||||||
-type sfc_token_type()
|
|
||||||
:: bcom % /* ... */
|
:: bcom % /* ... */
|
||||||
| lcom % //
|
| lcom % //
|
||||||
| ws % whitespace
|
| ws % whitespace
|
||||||
@@ -50,14 +40,14 @@
|
|||||||
.
|
.
|
||||||
|
|
||||||
|
|
||||||
-type sfc_pos() :: {Line :: pos_integer(), Col :: pos_integer()}.
|
-type tk_pos() :: {Line :: pos_integer(), Col :: pos_integer()}.
|
||||||
|
|
||||||
-record(sfc_token,
|
-record(tk,
|
||||||
{type :: sfc_token_type(),
|
{shape :: tk_shape(),
|
||||||
pos :: sfc_pos(),
|
pos :: tk_pos(),
|
||||||
string :: string()}).
|
str :: string()}).
|
||||||
|
|
||||||
-type sfc_token() :: #sfc_token{}.
|
-type tk() :: #tk{}.
|
||||||
|
|
||||||
|
|
||||||
% tokens are in essence the "chunk boundaries" of
|
% tokens are in essence the "chunk boundaries" of
|
||||||
@@ -93,15 +83,15 @@
|
|||||||
% lists = (_, _, _)
|
% lists = (_, _, _)
|
||||||
% | [_, _, _]
|
% | [_, _, _]
|
||||||
% | {_, _, _}
|
% | {_, _, _}
|
||||||
%-record(sfc_ast1_block,
|
%-record(gsc_ast1_block,
|
||||||
% {indent = none :: none | pos_integer(),
|
% {indent = none :: none | pos_integer(),
|
||||||
% decls = none :: [sfc_ast1_decl()]}).
|
% decls = none :: [gsc_ast1_decl()]}).
|
||||||
%
|
%
|
||||||
%-type sfc_ast() ::
|
%-type gsc_ast() ::
|
||||||
%
|
%
|
||||||
%-type sfc_list_group() :: {'(', [sfc_token()], ')'}
|
%-type gsc_list_group() :: {'(', [tk()], ')'}
|
||||||
% | {'[', [sfc_token()], ']'}
|
% | {'[', [tk()], ']'}
|
||||||
% | {'{', [sfc_token()], '}'}
|
% | {'{', [tk()], '}'}
|
||||||
% | {proof,
|
% | {proof,
|
||||||
% .
|
% .
|
||||||
|
|
||||||
@@ -112,50 +102,44 @@
|
|||||||
% record type: unterminated block comments at the end
|
% record type: unterminated block comments at the end
|
||||||
% of files. these are ok in legacy sophia, so we have to
|
% of files. these are ok in legacy sophia, so we have to
|
||||||
% specifically account for this error
|
% specifically account for this error
|
||||||
-record(sfc_err_bcom_unterminated,
|
-record(gsc_err_bcom_unterminated,
|
||||||
{prev_tokens :: [sfc_token()],
|
{prev_tokens :: [tk()],
|
||||||
break_pos :: sfc_pos(),
|
break_pos :: gsc_pos(),
|
||||||
rest :: string()}).
|
rest :: string()}).
|
||||||
|
|
||||||
-record(sfc_err_no_tokmatch,
|
-record(gsc_err_no_tokmatch,
|
||||||
{prev_tokens :: [sfc_token()],
|
{prev_tokens :: [tk()],
|
||||||
break_pos :: sfc_pos(),
|
break_pos :: gsc_pos(),
|
||||||
rest :: string()}).
|
rest :: string()}).
|
||||||
|
|
||||||
|
|
||||||
-record(sfc_err_delims,
|
-record(gsc_err_delims,
|
||||||
{past :: [sfc_token()],
|
{past :: [tk()],
|
||||||
open_stack :: [sfc_token()],
|
open_stack :: [tk()],
|
||||||
bad_close :: sfc_token(),
|
bad_close :: tk(),
|
||||||
future :: [sfc_token()]}).
|
future :: [tk()]}).
|
||||||
% FIXME
|
% FIXME
|
||||||
-record(sfc_err_nyi, {}).
|
-record(gsc_err_nyi, {}).
|
||||||
-record(sfc_err_empty_file, {}).
|
-record(gsc_err_empty_file, {}).
|
||||||
|
|
||||||
%-record(src_parse_error,
|
%-record(src_parse_error,
|
||||||
% {atom = none :: none | atom(),
|
% {atom = none :: none | atom(),
|
||||||
% string =
|
% string =
|
||||||
|
|
||||||
%j-record(sfc_err_gulp_ct,
|
%j-record(gsc_err_gulp_ct,
|
||||||
%j {gulped ::
|
%j {gulped ::
|
||||||
|
|
||||||
% @doc
|
% @doc
|
||||||
% generic placeholder error for now
|
% generic placeholder error for now
|
||||||
-record(sfc_err,
|
-record(gsc_err,
|
||||||
{atom :: atom(),
|
{atom :: atom(),
|
||||||
string = none :: none | iolist(),
|
string = none :: none | iolist(),
|
||||||
extra = none :: none | any()}).
|
extra = none :: none | any()}).
|
||||||
|
|
||||||
% @doc all errors SFC can return conveniently listed in
|
% @doc all errors SFC can return conveniently listed in
|
||||||
% one place
|
% one place
|
||||||
-type sfc_err() :: #sfc_err_bcom_unterminated{}
|
-type gsc_err() :: #gsc_err_bcom_unterminated{}
|
||||||
| #sfc_err_no_tokmatch{}
|
| #gsc_err_no_tokmatch{}
|
||||||
| #sfc_err_nyi{}
|
| #gsc_err_nyi{}
|
||||||
| #sfc_err_empty_file{}
|
| #gsc_err_empty_file{}
|
||||||
| #sfc_err{}.
|
| #gsc_err{}.
|
||||||
|
|
||||||
|
|
||||||
%% FIXME
|
|
||||||
-type sfc_ast() :: any().
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,199 @@
|
|||||||
|
% @doc
|
||||||
|
% File ::= Block(TopDecl)
|
||||||
|
-record(ast_file,
|
||||||
|
{top_decls = none :: none | [top_decl()]}).
|
||||||
|
|
||||||
|
|
||||||
|
-type ast() :: #ast_file{}
|
||||||
|
| top_decl()
|
||||||
|
| #ast_nyi{}
|
||||||
|
.
|
||||||
|
|
||||||
|
%% Decl ::= 'type' Id ['(' TVar* ')'] '=' TypeAlias
|
||||||
|
%% | 'record' Id ['(' TVar* ')'] '=' RecordType
|
||||||
|
%% | 'datatype' Id ['(' TVar* ')'] '=' DataType
|
||||||
|
%% | 'let' Id [':' Type] '=' Expr
|
||||||
|
%% | (EModifier* 'entrypoint' | FModifier* 'function') Block(FunDecl)
|
||||||
|
%% | Using
|
||||||
|
%-record(ast_type_alias,
|
||||||
|
% {name = none :: none | string(),
|
||||||
|
% tvars = none :: none | [string()],
|
||||||
|
% rewrites_to = none :: none | ast_type()}).
|
||||||
|
|
||||||
|
|
||||||
|
-type gulp_target()
|
||||||
|
:: ast_file
|
||||||
|
| top_decl
|
||||||
|
| ast_ct
|
||||||
|
| ast_nyi
|
||||||
|
.
|
||||||
|
|
||||||
|
% gulp means it must consume all input
|
||||||
|
-spec gulp(AstTarget, SigTokens) -> Perhaps
|
||||||
|
when AstTarget :: gulp_target(),
|
||||||
|
SigTokens :: [sfc_token()],
|
||||||
|
Perhaps :: {gulp, ast()}
|
||||||
|
| {error, sfc_err()}.
|
||||||
|
|
||||||
|
gulp(ast_file, Tokens) ->
|
||||||
|
gulp_file(Tokens);
|
||||||
|
gulp(top_decl, Tokens) ->
|
||||||
|
Targets = [ast_ct,
|
||||||
|
ast_nyi],
|
||||||
|
gulp_oneof(Targets, Tokens);
|
||||||
|
gulp(ast_ct, Tokens) ->
|
||||||
|
gulp_ct(#ast_ct{}, Tokens);
|
||||||
|
gulp(ast_nyi, Tokens) ->
|
||||||
|
{gulp, #ast_nyi{tokens = Tokens}};
|
||||||
|
gulp({block_of, X}, Tokens) ->
|
||||||
|
{barf, ItemChunks, []} = sfc_token_chunks:barf(block_as_items, Tokens),
|
||||||
|
gulp_block_of(X, ItemChunks);
|
||||||
|
gulp(Nyi, Tokens) ->
|
||||||
|
Msg = io_lib:format("sfc_ast:gulp/2: unknown target: ~p", [Nyi]),
|
||||||
|
Err = #sfc_err{atom = gulp_nyi,
|
||||||
|
string = Msg,
|
||||||
|
extra = [{target, Nyi}, {tokens, Tokens}]},
|
||||||
|
{error, Err}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% FIXME: payable and main need to be in that order i think
|
||||||
|
gulp_ct(Ast = #ast_ct{payable = none}, Tokens) ->
|
||||||
|
case Tokens of
|
||||||
|
[#sfc_token{string = "payable", type = kwd} | NewTokens] ->
|
||||||
|
gulp_ct(Ast#ast_ct{payable = payable}, NewTokens);
|
||||||
|
_ ->
|
||||||
|
gulp_ct(Ast#ast_ct{payable = false}, Tokens)
|
||||||
|
end;
|
||||||
|
gulp_ct(Ast = #ast_ct{main = none}, Tokens) ->
|
||||||
|
case Tokens of
|
||||||
|
[#sfc_token{string = "main", type = kwd} | NewTokens] ->
|
||||||
|
gulp_ct(Ast#ast_ct{main = main}, NewTokens);
|
||||||
|
_ ->
|
||||||
|
gulp_ct(Ast#ast_ct{main = false}, Tokens)
|
||||||
|
end;
|
||||||
|
gulp_ct(Ast = #ast_ct{contract = none}, Tokens) ->
|
||||||
|
case Tokens of
|
||||||
|
[#sfc_token{string = "contract", type = kwd} | NewTokens] ->
|
||||||
|
gulp_ct(Ast#ast_ct{contract = contract}, NewTokens);
|
||||||
|
% FIXME: reject logic applies to choice of branch, therefore
|
||||||
|
% should be contained in branchpoint code
|
||||||
|
_ ->
|
||||||
|
reject
|
||||||
|
%[#sfc_token{pos = P, string = S} | _] ->
|
||||||
|
% {error, #sfc_err{atom = no_kwd_contract,
|
||||||
|
% extra = [{pos, P},
|
||||||
|
% {expecting, "contract"},
|
||||||
|
% {got, S},
|
||||||
|
% {ast, Ast},
|
||||||
|
% {tokens, Tokens}]}};
|
||||||
|
%[] ->
|
||||||
|
% {error, #sfc_err{atom = no_kwd_contract,
|
||||||
|
% extra = [{pos, none},
|
||||||
|
% {expecting, "contract"},
|
||||||
|
% {got, eof},
|
||||||
|
% {ast, Ast},
|
||||||
|
% {tokens, Tokens}]}}
|
||||||
|
end;
|
||||||
|
gulp_ct(Ast = #ast_ct{name = none}, Tokens) ->
|
||||||
|
case Tokens of
|
||||||
|
[#sfc_token{string = Name, type = con} | NewTokens] ->
|
||||||
|
gulp_ct(Ast#ast_ct{name = Name}, NewTokens);
|
||||||
|
_ ->
|
||||||
|
reject
|
||||||
|
end;
|
||||||
|
gulp_ct(Ast = #ast_ct{implements = none}, Tokens) ->
|
||||||
|
case slurp_ct_impls(Tokens) of
|
||||||
|
{slurp, Names, NewTokens} ->
|
||||||
|
gulp_ct(Ast#ast_ct{implements = {':', Names}}, NewTokens);
|
||||||
|
reject ->
|
||||||
|
gulp_ct(Ast#ast_ct{implements = {':', []}}, Tokens);
|
||||||
|
Poison -> Poison
|
||||||
|
end;
|
||||||
|
gulp_ct(Ast = #ast_ct{eq = none}, Tokens) ->
|
||||||
|
case Tokens of
|
||||||
|
[#sfc_token{string = "=", type = op} | NewTokens] ->
|
||||||
|
gulp_ct(Ast#ast_ct{eq = '='}, NewTokens);
|
||||||
|
_ ->
|
||||||
|
{error, #sfc_err{atom = no_eq}}
|
||||||
|
end;
|
||||||
|
gulp_ct(Ast = #ast_ct{decls = none}, Tokens) ->
|
||||||
|
Decls = [gulp(decl, Item) || Item <- sfc_token_chunks:unsafe_block_to_items(Tokens)],
|
||||||
|
{gulp, Ast#ast_ct{decls = Decls}};
|
||||||
|
gulp_ct(_, _) ->
|
||||||
|
reject.
|
||||||
|
|
||||||
|
|
||||||
|
slurp_ct_impls([#sfc_token{string = ":", type = op},
|
||||||
|
#sfc_token{string = Con1, type = con}
|
||||||
|
| Rest]) ->
|
||||||
|
slurp_ct_impls2(Rest, [Con1]);
|
||||||
|
slurp_ct_impls(_) ->
|
||||||
|
reject.
|
||||||
|
|
||||||
|
slurp_ct_impls2([#sfc_token{string = ",", type = punct},
|
||||||
|
#sfc_token{string = Con1, type = con}
|
||||||
|
| Rest],
|
||||||
|
Acc) ->
|
||||||
|
slurp_ct_impls2(Rest, [Con1 | Acc]);
|
||||||
|
slurp_ct_impls2(Rest, Names) ->
|
||||||
|
{slurp, lists:reverse(Names), Rest}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-spec gulp_file(SigTokens) -> Perhaps
|
||||||
|
when SigTokens :: [sfc_token()],
|
||||||
|
Perhaps :: {gulp, #ast_file{}}
|
||||||
|
| {error, sfc_err()}.
|
||||||
|
% @private
|
||||||
|
% `file` enforces that the entire SigTokens is one
|
||||||
|
% block, chokes otherwise
|
||||||
|
|
||||||
|
gulp_file([]) ->
|
||||||
|
{error, #sfc_err{atom = empty_file}};
|
||||||
|
gulp_file(FileTokens = [#sfc_token{pos = FilePos} | _]) ->
|
||||||
|
case sfc_token_chunks:barf(block, FileTokens) of
|
||||||
|
% happy path: got the whole file back
|
||||||
|
{barf, FileTokens, []} ->
|
||||||
|
gulp_full_file(FileTokens);
|
||||||
|
% sad path: block terminated
|
||||||
|
{barf, _, [#sfc_token{pos = EndPos}]} ->
|
||||||
|
Msg = io_lib:format("block starting at ~p ends at ~p instead of EOF",
|
||||||
|
[FilePos, EndPos]),
|
||||||
|
{error, #sfc_err{atom = bad_file,
|
||||||
|
string = Msg}};
|
||||||
|
Nyi ->
|
||||||
|
{error, #sfc_err{atom = bad_file_nyi, extra = Nyi}}
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
% FIXME: need to rethink types here in order to handle syntax errors
|
||||||
|
% from different blocks independently.
|
||||||
|
|
||||||
|
% file = block(top_decl)
|
||||||
|
gulp_full_file(BlockTokens) ->
|
||||||
|
ItemChunks = sfc_token_chunks:unsafe_block_to_items(BlockTokens),
|
||||||
|
gulp_file_decls([], [], ItemChunks).
|
||||||
|
|
||||||
|
|
||||||
|
gulp_file_decls(Decls, Errs, [DeclTokens | Rest]) ->
|
||||||
|
case gulp(top_decl, DeclTokens) of
|
||||||
|
{gulp, NewDecl} ->
|
||||||
|
gulp_file_decls([NewDecl | Decls], Errs, Rest);
|
||||||
|
reject ->
|
||||||
|
ErrPos = sfc_token_chunks:start_pos(DeclTokens),
|
||||||
|
NewErr = #sfc_err{atom = bad_top_decl,
|
||||||
|
extra = [{tokens, DeclTokens},
|
||||||
|
{pos, ErrPos}]},
|
||||||
|
gulp_file_decls(Decls, [NewErr | Errs], Rest);
|
||||||
|
Poison ->
|
||||||
|
gulp_file_decls(Decls, [Poison | Errs], Rest)
|
||||||
|
end;
|
||||||
|
% end of block
|
||||||
|
gulp_file_decls(Decls, _Errs = [], _Input = []) ->
|
||||||
|
{gulp, #ast_file{top_decls = lists:reverse(Decls)}};
|
||||||
|
gulp_file_decls(_Decls, Errs, _Input = []) ->
|
||||||
|
{error, #sfc_err{atom = many,
|
||||||
|
extra = Errs}}.
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
% @doc
|
||||||
|
% working out infix parsing bullshit on toy arith language
|
||||||
|
%
|
||||||
|
% our operators for now are
|
||||||
|
%
|
||||||
|
% [+, *, ^] in outer->inner order
|
||||||
|
-module(ifarith).
|
||||||
|
|
||||||
|
-export([main/0]).
|
||||||
|
|
||||||
|
test_str() ->
|
||||||
|
"1 + 2 + 3"
|
||||||
|
|
||||||
|
main() ->
|
||||||
|
% first going to tokenize
|
||||||
|
Tokens = tokens(test_str()).
|
||||||
|
|
||||||
|
-record(tk,
|
||||||
|
{type = none :: int | op | noise,
|
||||||
|
str = none :: none | string(),
|
||||||
|
val = none :: none | integer() | atom()}).
|
||||||
|
|
||||||
|
tokens(Stk, []) ->
|
||||||
|
lists:reverse(Stk).
|
||||||
|
% [+*^] op token
|
||||||
|
tokens(Stk, [Char | Rest]) ->
|
||||||
|
case Char of
|
||||||
|
Op when $+ =:= Op; $* =:= Op; $^ =:= Op ->
|
||||||
|
Tk = #tk{type = op, str = [Op], val = list_to_tuple([Op])},
|
||||||
|
tokens([Tk | Stk], Rest);
|
||||||
|
D when $0 =< D, D =< $9 ->
|
||||||
|
{Tk, NewSrcStr} = tk_int([D], [D], Rest),
|
||||||
|
tokens([Tk | Stk], NewSrcStr).
|
||||||
|
_ ->
|
||||||
|
tokens(Stk, Rest)
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
% tokens for now are
|
||||||
|
-spec tk_int(DigitStack, CharStack, SrcStr) -> Result when
|
||||||
|
DigitStack :: string(),
|
||||||
|
CharStack :: string(),
|
||||||
|
SrcStr :: string(),
|
||||||
|
Result :: {Token, NewSrcStr},
|
||||||
|
Token :: #tk{},
|
||||||
|
NewSrcStr :: string().
|
||||||
|
|
||||||
|
tk_int(DigitStack, CharStack, SrcStr) ->
|
||||||
|
case SrcStr of
|
||||||
|
% cases when still consuming the int
|
||||||
|
% [0-9]
|
||||||
|
[D | NewSrcStr] when $0 =< D, D =< $9 ->
|
||||||
|
tk_int([D | DigitStack], [D | CharStack], NewSrcStr);
|
||||||
|
[$_ | NewSrcStr] ->
|
||||||
|
tk_int(DigitStack, [D | CharStack], NewSrcStr);
|
||||||
|
% otherwise done
|
||||||
|
_ ->
|
||||||
|
Digits =
|
||||||
|
end.
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
-type ifx_tree_() :: any().
|
||||||
|
|
||||||
|
%% placeholders
|
||||||
|
-type ast_() :: any().
|
||||||
|
-type ast_type_expr_() :: any().
|
||||||
|
-type ast_te_() :: any().
|
||||||
|
|
||||||
|
|
||||||
|
% @doc
|
||||||
|
% product type: foo * bar * baz
|
||||||
|
%
|
||||||
|
% stupid weird implication from bad syntax foresight trying to be
|
||||||
|
% fancy and overload what parens do is products must always have at
|
||||||
|
% least two operands; probably this is because `(foo)` is always the
|
||||||
|
% same as `foo`
|
||||||
|
%
|
||||||
|
% - 0-tuple -> `unit`
|
||||||
|
% - 1-tuple -> type itself
|
||||||
|
% - 2+ -> here
|
||||||
|
-record(ast_te_prod2,
|
||||||
|
{types = none :: none | [ast_te_()]}).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% @doc
|
||||||
|
% function type: (string, string) => string
|
||||||
|
-record(ast_te_ts_to_t,
|
||||||
|
{dom = none :: none | [ast_te_()],
|
||||||
|
codom = none :: none | ast_te_()}).
|
||||||
|
|
||||||
|
|
||||||
|
% @doc
|
||||||
|
% application type: map(string, int)
|
||||||
|
-record(ast_te_t_of_ts,
|
||||||
|
{fn = none :: none | ast_te_(),
|
||||||
|
args = none :: none | [ast_te_()]}).
|
||||||
|
|
||||||
|
|
||||||
|
% @doc
|
||||||
|
% node for a type name
|
||||||
|
% token type id : string int unit
|
||||||
|
% qid : Foo.Bar.baz
|
||||||
|
% tvar : 'a
|
||||||
|
-record(ast_te_name,
|
||||||
|
{name = none :: none | sfc_token()}).
|
||||||
|
|
||||||
|
|
||||||
|
% @doc
|
||||||
|
% placeholder
|
||||||
|
-record(ast_te_nyi,
|
||||||
|
{tokens = none :: none | [sfc_token()]}).
|
||||||
|
-type ast_te_nyi() :: #ast_nyi{}.
|
||||||
|
|
||||||
|
|
||||||
|
-type ast_type_expr()
|
||||||
|
:: #ast_te_ts_to_t{} % function (string, string) => string
|
||||||
|
| #ast_te_t_of_ts{} % application map(string, int)
|
||||||
|
| #ast_te_prod2{} % product foo * bar * baz
|
||||||
|
| #ast_te_tkid{} % token string int 'a Foo.Bar.baz
|
||||||
|
| #ast_te_nyi{}.
|
||||||
|
-type ast_te() :: ast_type_expr().
|
||||||
|
|
||||||
|
|
||||||
|
-record(ifx_stem_op,
|
||||||
|
{left = none :: none | [ifx_tree_()],
|
||||||
|
op = none :: none | infix_op(),
|
||||||
|
op_token = none :: none | {value, sfc_token()},
|
||||||
|
right = none :: none | [ifx_tree_()]}).
|
||||||
|
|
||||||
|
-record(ifx_stem_plist,
|
||||||
|
{items :: [any()]}).
|
||||||
|
|
||||||
|
-record(ifx_leaf_idtk,
|
||||||
|
{token :: sfc_token()}).
|
||||||
|
|
||||||
|
-type ifx_tree()
|
||||||
|
:: #ifx_stem_op{}
|
||||||
|
| #ifx_stem_plist{}
|
||||||
|
| #ifx_leaf_idtk{}.
|
||||||
|
|
||||||
|
|
||||||
|
-spec slurp_ifx_tree(Tokens) -> SlurpedIfxTree when
|
||||||
|
Tokens :: [sfc_token()],
|
||||||
|
SlurpedIfxNode :: slurped(ifx_tree()).
|
||||||
|
|
||||||
|
slurp_ifx_tree(Tokens) ->
|
||||||
|
case take_until_ifx_op(Tokens) of
|
||||||
|
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
% @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([
|
||||||
|
% chunk_shape/0,
|
||||||
|
% choke_reason/0
|
||||||
|
%]).
|
||||||
|
%
|
||||||
|
%-export([
|
||||||
|
% take/2,
|
||||||
|
% unsafe_block_to_items/1,
|
||||||
|
% barf/2,
|
||||||
|
% start_pos/1,
|
||||||
|
% end_pos/1
|
||||||
|
%]).
|
||||||
|
%
|
||||||
|
%% $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()}
|
||||||
|
% | block_as_items
|
||||||
|
% .
|
||||||
|
%
|
||||||
|
%% FIXME
|
||||||
|
%-type choke_reason() :: any().
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%%------------------------------------------
|
||||||
|
%% functions
|
||||||
|
%%------------------------------------------
|
||||||
|
%
|
||||||
|
%% take = just split
|
||||||
|
%
|
||||||
|
%take(block, []) ->
|
||||||
|
% {[], []};
|
||||||
|
%take(block, [Hd = #sfc_token{pos = {_, BCol}} | Tl]) ->
|
||||||
|
% tw(fun(#sfc_token{pos = {_, TkCol}}) -> BCol =< TkCol end, [Hd], Tl);
|
||||||
|
%take(block_item, []) ->
|
||||||
|
% {[], []};
|
||||||
|
%take(block_item, [Hd = #sfc_token{pos = {_, ICol}} | Tl]) ->
|
||||||
|
% tw(fun(#sfc_token{pos = {_, TkCol}}) -> ICol < TkCol end, Tl).
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%-spec start_pos([sfc_token()]) -> {value, sfc_pos()} | none.
|
||||||
|
%
|
||||||
|
%start_pos([#sfc_token{pos = P}]) -> {value, P};
|
||||||
|
%start_pos([]) -> none.
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%-spec end_pos([sfc_token()]) -> {value, sfc_pos()} | none.
|
||||||
|
%
|
||||||
|
%end_pos([#sfc_token{pos = Pos, string = Str}]) ->
|
||||||
|
% {value, sfc_tokens:new_pos(Pos, Str)};
|
||||||
|
%end_pos([_ | T]) ->
|
||||||
|
% end_pos(T);
|
||||||
|
%end_pos([]) ->
|
||||||
|
% none.
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%-spec barf(ChunkShape, SigTokens) -> Perhaps
|
||||||
|
% when ChunkShape :: chunk_shape(),
|
||||||
|
% SigTokens :: [Token],
|
||||||
|
% Perhaps :: {barf, Chunk, Rest}
|
||||||
|
% | {choke, Reason},
|
||||||
|
% Chunk :: [Token] % most
|
||||||
|
% | [[Token]], % block_as_items
|
||||||
|
% Rest :: [Token],
|
||||||
|
% Reason :: choke_reason(),
|
||||||
|
% Token :: 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};
|
||||||
|
%% not needed for our case, future-proofing. see unsafe_block_to_items
|
||||||
|
%% for details
|
||||||
|
%barf({block_item, Level}, Tokens = [#sfc_token{pos = {_, StartLevel}} | _]) ->
|
||||||
|
% case Level =:= StartLevel of
|
||||||
|
% false -> {barf, [], Tokens};
|
||||||
|
% true -> barf(block_item, Tokens)
|
||||||
|
% end;
|
||||||
|
%% this has a fancy name in Haskell like Lens . lift ^. mapM_
|
||||||
|
%%
|
||||||
|
%% i think it's `sequence` actually, but not looking it up
|
||||||
|
%%
|
||||||
|
%% this barfs a block, and then uses unsafe_block_to_items/1 to split
|
||||||
|
%% the block tokens into individual items
|
||||||
|
%barf(block_as_items, Tokens) ->
|
||||||
|
% {barf, BlockTokens, Rest} = barf(block, Tokens),
|
||||||
|
% {barf, unsafe_block_to_items(BlockTokens), Rest};
|
||||||
|
%barf(_, _) ->
|
||||||
|
% {choke, #sfc_err_nyi{}}.
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%-spec unsafe_block_to_items([Token]) -> [[Token]]
|
||||||
|
% when Token :: sfc_token().
|
||||||
|
%
|
||||||
|
%% @doc
|
||||||
|
%% PITFALL: this ASSUMES that the given list of tokens has the
|
||||||
|
%% property that all indent levels are >= that of the head... i.e. the
|
||||||
|
%% input to this is assumed to be the output of (e.g.) barf(block, _)
|
||||||
|
%%
|
||||||
|
%% the danger case is something my intuition is pointing to as a
|
||||||
|
%% possibility perhaps if you're doing some incremental parallel
|
||||||
|
%% stream parsing voodoo, naively parsing a block by greedily pulling
|
||||||
|
%% block items off the head of the list
|
||||||
|
%%
|
||||||
|
%% with the current way things work, we actually do not need to check
|
||||||
|
%% the indent level of each block item and make sure they're all the
|
||||||
|
%% same
|
||||||
|
%%
|
||||||
|
%% BLOCK =
|
||||||
|
%% foo
|
||||||
|
%% ...
|
||||||
|
%% bar
|
||||||
|
%% ...
|
||||||
|
%% baz
|
||||||
|
%% ...
|
||||||
|
%%
|
||||||
|
%% BLOCK_ITEM =
|
||||||
|
%% foo
|
||||||
|
%% ...
|
||||||
|
%%
|
||||||
|
%%
|
||||||
|
%% very important property of blocks is that each list item starts at
|
||||||
|
%% the same indent level.
|
||||||
|
%%
|
||||||
|
%% a concern would be that when we go to grab the bar item that
|
||||||
|
%% BarIndentLevel is somehow different from FooIndentLevel.
|
||||||
|
%%
|
||||||
|
%% let us reason through why it must be the case that FooIndentLevel
|
||||||
|
%% =:= BarIndentLevel
|
||||||
|
%%
|
||||||
|
%% 1. not (BarIndentLevel < FooIndentLevel); i.e.
|
||||||
|
%%
|
||||||
|
%% // impossible by call path:
|
||||||
|
%% foo ...
|
||||||
|
%% bar ...
|
||||||
|
%%
|
||||||
|
%% This is impossible because the call path ensures that all tokens
|
||||||
|
%% in BlkItems have indent level >= FooIndentLevel
|
||||||
|
%%
|
||||||
|
%% 2. not (FooIndentLevel < BarIndentLevel),
|
||||||
|
%%
|
||||||
|
%% // impossible because bar would get
|
||||||
|
%% // consumed by the foo block
|
||||||
|
%% foo ...
|
||||||
|
%% bar ...
|
||||||
|
%
|
||||||
|
%unsafe_block_to_items([]) ->
|
||||||
|
% [];
|
||||||
|
%unsafe_block_to_items(BlockTks) ->
|
||||||
|
% {barf, ItemTks, NewBlockTks} = barf(block_item, BlockTks),
|
||||||
|
% [ItemTks | unsafe_block_to_items(NewBlockTks)].
|
||||||
+25
-25
@@ -4,15 +4,15 @@
|
|||||||
% based on original sophia compiler
|
% based on original sophia compiler
|
||||||
%
|
%
|
||||||
% parse layers:
|
% parse layers:
|
||||||
% 1. sfc_tokenizer: SrcStr -> (Tokens | SigTokens)
|
% 1. gsc_tokenizer: SrcStr -> (Tokens | SigTokens)
|
||||||
%
|
%
|
||||||
% SigTokens = not comment/whitespace
|
% SigTokens = not comment/whitespace
|
||||||
%
|
%
|
||||||
% layers:
|
% layers:
|
||||||
% a. sfc_strmatch : matches string shapes
|
% a. gsc_strmatch : matches string shapes
|
||||||
% b. sfc_so_scan : converts to so_scan shapes
|
% b. gsc_so_scan : converts to so_scan shapes
|
||||||
%
|
%
|
||||||
% 2. sfc_ast: SigTokens -> AST
|
% 2. gsc_ast: SigTokens -> AST
|
||||||
%
|
%
|
||||||
% terminology:
|
% terminology:
|
||||||
%
|
%
|
||||||
@@ -36,8 +36,8 @@
|
|||||||
% - too fuzzy right now
|
% - too fuzzy right now
|
||||||
% - possibly:
|
% - possibly:
|
||||||
% - rename parser layers sequentially:
|
% - rename parser layers sequentially:
|
||||||
% - sfc_
|
% - gsc_
|
||||||
-module(sfc).
|
-module(gsc).
|
||||||
|
|
||||||
|
|
||||||
-export_type([
|
-export_type([
|
||||||
@@ -54,13 +54,13 @@
|
|||||||
ast_from_tokens/1
|
ast_from_tokens/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("$sfc_include/sfc.hrl").
|
-include("$gsc_include/gsc.hrl").
|
||||||
|
|
||||||
%-----------------------------------------
|
%-----------------------------------------
|
||||||
% types
|
% types
|
||||||
%-----------------------------------------
|
%-----------------------------------------
|
||||||
|
|
||||||
-type token() :: sfc_token().
|
-type token() :: tk().
|
||||||
|
|
||||||
%-----------------------------------------
|
%-----------------------------------------
|
||||||
% functions
|
% functions
|
||||||
@@ -68,13 +68,13 @@
|
|||||||
|
|
||||||
sigtokens_from_file(X) ->
|
sigtokens_from_file(X) ->
|
||||||
case tokens_from_file(X) of
|
case tokens_from_file(X) of
|
||||||
{ok, Y} -> {ok, sfc_tokens:filter_significant(Y)};
|
{ok, Y} -> {ok, gsc_tokens:filter_significant(Y)};
|
||||||
Err -> Err
|
Err -> Err
|
||||||
end.
|
end.
|
||||||
|
|
||||||
sigtokens_from_string(X) ->
|
sigtokens_from_string(X) ->
|
||||||
case tokens_from_string(X) of
|
case tokens_from_string(X) of
|
||||||
{ok, Y} -> {ok, sfc_tokens:filter_significant(Y)};
|
{ok, Y} -> {ok, gsc_tokens:filter_significant(Y)};
|
||||||
Err -> Err
|
Err -> Err
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@@ -82,8 +82,8 @@ sigtokens_from_string(X) ->
|
|||||||
-spec tokens_from_file(FilePath) -> Perhaps
|
-spec tokens_from_file(FilePath) -> Perhaps
|
||||||
when FilePath :: string(),
|
when FilePath :: string(),
|
||||||
Perhaps :: {ok, Tokens}
|
Perhaps :: {ok, Tokens}
|
||||||
| {error, sfc_err() | any()},
|
| {error, gsc_err() | any()},
|
||||||
Tokens :: [sfc_token()].
|
Tokens :: [tk()].
|
||||||
|
|
||||||
tokens_from_file(FilePath) ->
|
tokens_from_file(FilePath) ->
|
||||||
case file:read_file(FilePath) of
|
case file:read_file(FilePath) of
|
||||||
@@ -97,18 +97,18 @@ tokens_from_file(FilePath) ->
|
|||||||
-spec tokens_from_string(SrcStr) -> Result
|
-spec tokens_from_string(SrcStr) -> Result
|
||||||
when SrcStr :: string(),
|
when SrcStr :: string(),
|
||||||
Result :: {ok, Tokens}
|
Result :: {ok, Tokens}
|
||||||
| {error, sfc_err()},
|
| {error, gsc_err()},
|
||||||
Tokens :: [sfc_token()].
|
Tokens :: [tk()].
|
||||||
|
|
||||||
tokens_from_string(SrcStr) ->
|
tokens_from_string(SrcStr) ->
|
||||||
sfc_tokens:tokens(SrcStr).
|
gsc_tokens:tokens(SrcStr).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-spec ast_from_file(FilePath) -> Perhaps
|
-spec ast_from_file(FilePath) -> Perhaps
|
||||||
when FilePath :: string(),
|
when FilePath :: string(),
|
||||||
Perhaps :: {ok, AST} | {error, sfc_err()},
|
Perhaps :: {ok, AST} | {error, gsc_err()},
|
||||||
AST :: sfc_ast().
|
AST :: gsc_ast().
|
||||||
|
|
||||||
ast_from_file(FilePath) ->
|
ast_from_file(FilePath) ->
|
||||||
case file:read_file(FilePath) of
|
case file:read_file(FilePath) of
|
||||||
@@ -120,11 +120,11 @@ ast_from_file(FilePath) ->
|
|||||||
|
|
||||||
-spec ast_from_string(SrcStr) -> Perhaps
|
-spec ast_from_string(SrcStr) -> Perhaps
|
||||||
when SrcStr :: string(),
|
when SrcStr :: string(),
|
||||||
Perhaps :: {ok, AST} | {error, sfc_err()},
|
Perhaps :: {ok, AST} | {error, gsc_err()},
|
||||||
AST :: sfc_ast().
|
AST :: gsc_ast().
|
||||||
|
|
||||||
ast_from_string(SrcStr) ->
|
ast_from_string(SrcStr) ->
|
||||||
case sfc_tokens:significant_tokens(SrcStr) of
|
case gsc_tokens:significant_tokens(SrcStr) of
|
||||||
{ok, SigTks} -> ast_from_tokens(SigTks);
|
{ok, SigTks} -> ast_from_tokens(SigTks);
|
||||||
Error -> Error
|
Error -> Error
|
||||||
end.
|
end.
|
||||||
@@ -132,13 +132,13 @@ ast_from_string(SrcStr) ->
|
|||||||
|
|
||||||
|
|
||||||
-spec ast_from_tokens(SrcTokens) -> Perhaps
|
-spec ast_from_tokens(SrcTokens) -> Perhaps
|
||||||
when SrcTokens :: [sfc_token()],
|
when SrcTokens :: [tk()],
|
||||||
Perhaps :: {ok, AST} | {error, sfc_err()},
|
Perhaps :: {ok, AST} | {error, gsc_err()},
|
||||||
AST :: sfc_ast().
|
AST :: gsc_ast().
|
||||||
|
|
||||||
ast_from_tokens(Tks) ->
|
ast_from_tokens(Tks) ->
|
||||||
SigTks = sfc_tokens:filter_significant(Tks),
|
SigTks = gsc_tokens:filter_significant(Tks),
|
||||||
case sfc_ast:gulp_file(SigTks) of
|
case gsc_ast:gulp_file(SigTks) of
|
||||||
{gulp, AST} -> {ok, AST};
|
{gulp, AST} -> {ok, AST};
|
||||||
Error -> Error
|
Error -> Error
|
||||||
end.
|
end.
|
||||||
|
|||||||
+54
-54
@@ -56,7 +56,7 @@
|
|||||||
% Domain ::= Type // Single argument
|
% Domain ::= Type // Single argument
|
||||||
% | '(' Sep(Type, ',') ')' // Multiple arguments
|
% | '(' Sep(Type, ',') ')' // Multiple arguments
|
||||||
% ```
|
% ```
|
||||||
-module(sfc_ast).
|
-module(gsc_ast).
|
||||||
|
|
||||||
%-compile([export_all,nowarn_export_all]).
|
%-compile([export_all,nowarn_export_all]).
|
||||||
%
|
%
|
||||||
@@ -71,16 +71,16 @@
|
|||||||
% gulp_file/1
|
% gulp_file/1
|
||||||
%]).
|
%]).
|
||||||
%
|
%
|
||||||
%-include("$sfc_include/sfc.hrl").
|
%-include("$gsc_include/gsc.hrl").
|
||||||
%
|
%
|
||||||
%%%-----------------------------
|
%%%-----------------------------
|
||||||
%%% TYPES: sfc_ast
|
%%% TYPES: gsc_ast
|
||||||
%%%-----------------------------
|
%%%-----------------------------
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
%% % placeholders
|
%% % placeholders
|
||||||
%-type ast_() :: any().
|
%-type ast_() :: any().
|
||||||
%-record(ast_nyi, {tokens = none :: [sfc_token()]}).
|
%-record(ast_nyi, {tokens = none :: [tk()]}).
|
||||||
%-type ast_nyi() :: #ast_nyi{}.
|
%-type ast_nyi() :: #ast_nyi{}.
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
@@ -109,8 +109,8 @@
|
|||||||
%% ta = type alias
|
%% ta = type alias
|
||||||
%% 'type' Id ['(' TVar* ')'] '=' TypeAlias
|
%% 'type' Id ['(' TVar* ')'] '=' TypeAlias
|
||||||
%-record(ast_ta,
|
%-record(ast_ta,
|
||||||
% {alias = none :: none | sfc_token(),
|
% {alias = none :: none | tk(),
|
||||||
% tvars = none :: none | [sfc_token()],
|
% tvars = none :: none | [tk()],
|
||||||
% points_to = none :: none | ast_type_expr()}).
|
% points_to = none :: none | ast_type_expr()}).
|
||||||
%
|
%
|
||||||
%% Decl ::= 'type' Id ['(' TVar* ')'] '=' TypeAlias
|
%% Decl ::= 'type' Id ['(' TVar* ')'] '=' TypeAlias
|
||||||
@@ -126,8 +126,8 @@
|
|||||||
%-record(ast_ct,
|
%-record(ast_ct,
|
||||||
% {payable = none :: none | boolean(),
|
% {payable = none :: none | boolean(),
|
||||||
% main = none :: none | boolean(),
|
% main = none :: none | boolean(),
|
||||||
% name = none :: none | sfc_token(),
|
% name = none :: none | tk(),
|
||||||
% impls = none :: none | [sfc_token()],
|
% impls = none :: none | [tk()],
|
||||||
% decls = none :: none | [decl()]}).
|
% decls = none :: none | [decl()]}).
|
||||||
%
|
%
|
||||||
%-record(ast_td_iface,{}).
|
%-record(ast_td_iface,{}).
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
%
|
%
|
||||||
%-type parse_error_() :: any().
|
%-type parse_error_() :: any().
|
||||||
%-record(parse_error,
|
%-record(parse_error,
|
||||||
% {pos = none :: none | sfc_pos(),
|
% {pos = none :: none | gsc_pos(),
|
||||||
% msg = "" :: string(),
|
% msg = "" :: string(),
|
||||||
% subs = [] :: [parse_error_()],
|
% subs = [] :: [parse_error_()],
|
||||||
% extra = none :: any()}).
|
% extra = none :: any()}).
|
||||||
@@ -189,20 +189,20 @@
|
|||||||
%%%-----------------------------
|
%%%-----------------------------
|
||||||
%
|
%
|
||||||
%-spec gulp_file(Tokens) -> Perhaps
|
%-spec gulp_file(Tokens) -> Perhaps
|
||||||
% when Tokens :: [sfc_token()],
|
% when Tokens :: [tk()],
|
||||||
% Perhaps :: {gulp, #ast_file{}}
|
% Perhaps :: {gulp, #ast_file{}}
|
||||||
% | {error, #parse_error{}}.
|
% | {error, #parse_error{}}.
|
||||||
%
|
%
|
||||||
%gulp_file([]) ->
|
%gulp_file([]) ->
|
||||||
% {error, empty_file};
|
% {error, empty_file};
|
||||||
%gulp_file(Tokens) ->
|
%gulp_file(Tokens) ->
|
||||||
% case sfc_tokens:take_block(Tokens) of
|
% case gsc_tokens:take_block(Tokens) of
|
||||||
% {Tokens, []} ->
|
% {Tokens, []} ->
|
||||||
% gulp_block(fun gulp_top_decl/1, Tokens);
|
% gulp_block(fun gulp_top_decl/1, Tokens);
|
||||||
% %gulp_file2([], [], Tokens);
|
% %gulp_file2([], [], Tokens);
|
||||||
% {A, B} ->
|
% {A, B} ->
|
||||||
% StartPos = sfc_tokens:start_pos(A),
|
% StartPos = gsc_tokens:start_pos(A),
|
||||||
% ErrPos = sfc_tokens:start_pos(B),
|
% ErrPos = gsc_tokens:start_pos(B),
|
||||||
% Msg = efmt("gulp_file: block starting at ~p ends at ~p instead of EOF",
|
% Msg = efmt("gulp_file: block starting at ~p ends at ~p instead of EOF",
|
||||||
% [StartPos, ErrPos]),
|
% [StartPos, ErrPos]),
|
||||||
% {error, #parse_error{pos = ErrPos, msg = Msg}}
|
% {error, #parse_error{pos = ErrPos, msg = Msg}}
|
||||||
@@ -212,7 +212,7 @@
|
|||||||
%
|
%
|
||||||
%%gulp_file2(AccOks, AccErrs, Tokens = [_ | _]) ->
|
%%gulp_file2(AccOks, AccErrs, Tokens = [_ | _]) ->
|
||||||
%% % ItemTokens will be nonempty
|
%% % ItemTokens will be nonempty
|
||||||
%% {ItemTokens, NewTokens} = sfc_tokens:take_block_item(Tokens),
|
%% {ItemTokens, NewTokens} = gsc_tokens:take_block_item(Tokens),
|
||||||
%% case gulp_top_decl(ItemTokens) of
|
%% case gulp_top_decl(ItemTokens) of
|
||||||
%% {gulp, Ok} -> gulp_file2([Ok | AccOks], AccErrs, NewTokens);
|
%% {gulp, Ok} -> gulp_file2([Ok | AccOks], AccErrs, NewTokens);
|
||||||
%% Err -> gulp_file2(AccOks, [Err | AccErrs], NewTokens)
|
%% Err -> gulp_file2(AccOks, [Err | AccErrs], NewTokens)
|
||||||
@@ -227,7 +227,7 @@
|
|||||||
%
|
%
|
||||||
%-spec gulp_block(GulpItem, Tokens) -> GulpedItems
|
%-spec gulp_block(GulpItem, Tokens) -> GulpedItems
|
||||||
% when GulpItem :: fun((ItemTokens) -> GulpedItem),
|
% when GulpItem :: fun((ItemTokens) -> GulpedItem),
|
||||||
% Tokens :: [sfc_token()],
|
% Tokens :: [tk()],
|
||||||
% ItemTokens :: Tokens,
|
% ItemTokens :: Tokens,
|
||||||
% GulpedItem :: {gulp, Item} | {error, Reason},
|
% GulpedItem :: {gulp, Item} | {error, Reason},
|
||||||
% GulpedItems :: {gulp, Items} | {error, Reason},
|
% GulpedItems :: {gulp, Items} | {error, Reason},
|
||||||
@@ -258,7 +258,7 @@
|
|||||||
%
|
%
|
||||||
%gulp_block(GulpItem, AccOks, AccErrs, Tokens = [_ | _]) ->
|
%gulp_block(GulpItem, AccOks, AccErrs, Tokens = [_ | _]) ->
|
||||||
% % ItemTokens will be nonempty
|
% % ItemTokens will be nonempty
|
||||||
% {ItemTokens, NewTokens} = sfc_tokens:take_block_item(Tokens),
|
% {ItemTokens, NewTokens} = gsc_tokens:take_block_item(Tokens),
|
||||||
% case GulpItem(ItemTokens) of
|
% case GulpItem(ItemTokens) of
|
||||||
% {gulp, Ok} -> gulp_block(GulpItem, [Ok | AccOks], AccErrs, NewTokens);
|
% {gulp, Ok} -> gulp_block(GulpItem, [Ok | AccOks], AccErrs, NewTokens);
|
||||||
% Err -> gulp_block(GulpItem, AccOks, [Err | AccErrs], NewTokens)
|
% Err -> gulp_block(GulpItem, AccOks, [Err | AccErrs], NewTokens)
|
||||||
@@ -272,7 +272,7 @@
|
|||||||
%
|
%
|
||||||
%
|
%
|
||||||
%-spec gulp_top_decl(DeclTokens) -> Result
|
%-spec gulp_top_decl(DeclTokens) -> Result
|
||||||
% when DeclTokens :: [sfc_token()],
|
% when DeclTokens :: [tk()],
|
||||||
% Result :: {gulp, ast()} | {error, any()}.
|
% Result :: {gulp, ast()} | {error, any()}.
|
||||||
%
|
%
|
||||||
%% @doc
|
%% @doc
|
||||||
@@ -284,7 +284,7 @@
|
|||||||
%% | Using
|
%% | Using
|
||||||
%% @end
|
%% @end
|
||||||
%gulp_top_decl(DeclTokens) ->
|
%gulp_top_decl(DeclTokens) ->
|
||||||
% case sfc_tokens:strings(3, DeclTokens) of
|
% case gsc_tokens:strings(3, DeclTokens) of
|
||||||
% ["payable", "contract", "interface"] ->
|
% ["payable", "contract", "interface"] ->
|
||||||
% gulp_nyi(DeclTokens);
|
% gulp_nyi(DeclTokens);
|
||||||
% ["contract", "interface" | _] ->
|
% ["contract", "interface" | _] ->
|
||||||
@@ -311,7 +311,7 @@
|
|||||||
% gulp_nyi(DeclTokens);
|
% gulp_nyi(DeclTokens);
|
||||||
% _ ->
|
% _ ->
|
||||||
% % decl tokens will always be nonempty
|
% % decl tokens will always be nonempty
|
||||||
% [H = #sfc_token{pos = ErrPos} | _] = DeclTokens,
|
% [H = #tk{pos = ErrPos} | _] = DeclTokens,
|
||||||
% EMsg = efmt("gulp_top_decl: bad token: ~p; "
|
% EMsg = efmt("gulp_top_decl: bad token: ~p; "
|
||||||
% "expecting one of: [payable, main, contract, namespace, @compiler, include, using]",
|
% "expecting one of: [payable, main, contract, namespace, @compiler, include, using]",
|
||||||
% [H]),
|
% [H]),
|
||||||
@@ -320,7 +320,7 @@
|
|||||||
% end.
|
% end.
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
%gulp_ct2(Ast, Tokens = [#sfc_token{pos = Pos} | _]) ->
|
%gulp_ct2(Ast, Tokens = [#tk{pos = Pos} | _]) ->
|
||||||
% % need to pass through pos for error messages on premature end of
|
% % need to pass through pos for error messages on premature end of
|
||||||
% % input... for now it's a fixme thing
|
% % input... for now it's a fixme thing
|
||||||
% gulp_ct3(Ast, Tokens, Pos).
|
% gulp_ct3(Ast, Tokens, Pos).
|
||||||
@@ -331,7 +331,7 @@
|
|||||||
%gulp_ct3(Ast = #ast_ct{name = none}, Tokens, Pos) ->
|
%gulp_ct3(Ast = #ast_ct{name = none}, Tokens, Pos) ->
|
||||||
% NewPos = Pos, %% fixme
|
% NewPos = Pos, %% fixme
|
||||||
% case Tokens of
|
% case Tokens of
|
||||||
% [Name = #sfc_token{type = con} | NewTokens] ->
|
% [Name = #tk{type = con} | NewTokens] ->
|
||||||
% NewAst = Ast#ast_ct{name = Name},
|
% NewAst = Ast#ast_ct{name = Name},
|
||||||
% gulp_ct3(NewAst, NewTokens, NewPos);
|
% gulp_ct3(NewAst, NewTokens, NewPos);
|
||||||
% [Name | _] ->
|
% [Name | _] ->
|
||||||
@@ -355,7 +355,7 @@
|
|||||||
%% contract X : Y, Z, W = <block>
|
%% contract X : Y, Z, W = <block>
|
||||||
%% ^
|
%% ^
|
||||||
%gulp_ct3(Ast = #ast_ct{decls = none},
|
%gulp_ct3(Ast = #ast_ct{decls = none},
|
||||||
% [#sfc_token{string = "="} | Tokens],
|
% [#tk{string = "="} | Tokens],
|
||||||
% _Pos) ->
|
% _Pos) ->
|
||||||
% case gulp_block(fun gulp_decl/1, Tokens) of
|
% case gulp_block(fun gulp_decl/1, Tokens) of
|
||||||
% {gulp, Decls} ->
|
% {gulp, Decls} ->
|
||||||
@@ -370,7 +370,7 @@
|
|||||||
%
|
%
|
||||||
%
|
%
|
||||||
%-spec slurp_ct_impls(Tokens) -> Slurped
|
%-spec slurp_ct_impls(Tokens) -> Slurped
|
||||||
% when Tokens :: [sfc_token()],
|
% when Tokens :: [tk()],
|
||||||
% Slurped :: {slurp, Impls, NewTokens}
|
% Slurped :: {slurp, Impls, NewTokens}
|
||||||
% | {error, Reason},
|
% | {error, Reason},
|
||||||
% Impls :: Tokens,
|
% Impls :: Tokens,
|
||||||
@@ -380,11 +380,11 @@
|
|||||||
%
|
%
|
||||||
%% FIXME: this should be a restructured a tiny bit for better error
|
%% FIXME: this should be a restructured a tiny bit for better error
|
||||||
%% handling
|
%% handling
|
||||||
%slurp_ct_impls([_ = #sfc_token{string = ":"},
|
%slurp_ct_impls([_ = #tk{string = ":"},
|
||||||
% Con = #sfc_token{type = con}
|
% Con = #tk{type = con}
|
||||||
% | NewTokens]) ->
|
% | NewTokens]) ->
|
||||||
% slurp_ct_impls2([Con], NewTokens);
|
% slurp_ct_impls2([Con], NewTokens);
|
||||||
%slurp_ct_impls(NewTokens = [#sfc_token{string = "="} | _]) ->
|
%slurp_ct_impls(NewTokens = [#tk{string = "="} | _]) ->
|
||||||
% {slurp, [], NewTokens};
|
% {slurp, [], NewTokens};
|
||||||
%slurp_ct_impls([BadToken | _]) ->
|
%slurp_ct_impls([BadToken | _]) ->
|
||||||
% Msg = efmt("slurp_ct_impls: expecting (: Con | =), got ~p", [BadToken]),
|
% Msg = efmt("slurp_ct_impls: expecting (: Con | =), got ~p", [BadToken]),
|
||||||
@@ -393,11 +393,11 @@
|
|||||||
% {error, {fixme, "expecting : or =, got end-of-input"}}.
|
% {error, {fixme, "expecting : or =, got end-of-input"}}.
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
%slurp_ct_impls2(Stk, [_ = #sfc_token{string = ","},
|
%slurp_ct_impls2(Stk, [_ = #tk{string = ","},
|
||||||
% Con = #sfc_token{type = con}
|
% Con = #tk{type = con}
|
||||||
% | NewTokens]) ->
|
% | NewTokens]) ->
|
||||||
% slurp_ct_impls2([Con | Stk], NewTokens);
|
% slurp_ct_impls2([Con | Stk], NewTokens);
|
||||||
%slurp_ct_impls2(Stk, NewTokens = [#sfc_token{string = "="} | _]) ->
|
%slurp_ct_impls2(Stk, NewTokens = [#tk{string = "="} | _]) ->
|
||||||
% {slurp, lists:reverse(Stk), NewTokens};
|
% {slurp, lists:reverse(Stk), NewTokens};
|
||||||
%slurp_ct_impls2(Stk, BadTokens) ->
|
%slurp_ct_impls2(Stk, BadTokens) ->
|
||||||
% {error, {fixme, nyi, slurp_ct_impls2, [Stk, BadTokens]}}.
|
% {error, {fixme, nyi, slurp_ct_impls2, [Stk, BadTokens]}}.
|
||||||
@@ -410,7 +410,7 @@
|
|||||||
%% | (EModifier* 'entrypoint' | FModifier* 'function') Block(FunDecl)
|
%% | (EModifier* 'entrypoint' | FModifier* 'function') Block(FunDecl)
|
||||||
%% | Using
|
%% | Using
|
||||||
%gulp_decl(Tokens) ->
|
%gulp_decl(Tokens) ->
|
||||||
% case sfc_tokens:strings(1, Tokens) of
|
% case gsc_tokens:strings(1, Tokens) of
|
||||||
% ["type"] -> gulp_type_alias(Tokens);
|
% ["type"] -> gulp_type_alias(Tokens);
|
||||||
% _ -> gulp_nyi(Tokens)
|
% _ -> gulp_nyi(Tokens)
|
||||||
% end.
|
% end.
|
||||||
@@ -423,7 +423,7 @@
|
|||||||
%% 'type' Id ['(' TVar* ')'] '=' TypeAlias
|
%% 'type' Id ['(' TVar* ')'] '=' TypeAlias
|
||||||
%% ^
|
%% ^
|
||||||
%gulp_ta(Ast = #ast_ta{alias = none},
|
%gulp_ta(Ast = #ast_ta{alias = none},
|
||||||
% _ = [#sfc_token{string = "type"}, Alias = #sfc_token{type = id}
|
% _ = [#tk{string = "type"}, Alias = #tk{type = id}
|
||||||
% | NewTokens]) ->
|
% | NewTokens]) ->
|
||||||
% NewAst = Ast#ast_ta{alias = Alias},
|
% NewAst = Ast#ast_ta{alias = Alias},
|
||||||
% gulp_ta(NewAst, NewTokens);
|
% gulp_ta(NewAst, NewTokens);
|
||||||
@@ -440,7 +440,7 @@
|
|||||||
%% 'type' Id ['(' TVar* ')'] '=' TypeAlias
|
%% 'type' Id ['(' TVar* ')'] '=' TypeAlias
|
||||||
%% ^
|
%% ^
|
||||||
%gulp_ta(Ast = #ast_ta{points_to = none},
|
%gulp_ta(Ast = #ast_ta{points_to = none},
|
||||||
% _ = [#sfc_token{string = "="} | NewTokens]) ->
|
% _ = [#tk{string = "="} | NewTokens]) ->
|
||||||
% case gulp_type_expr(NewTokens) of
|
% case gulp_type_expr(NewTokens) of
|
||||||
% {gulp, TypeExpr} ->
|
% {gulp, TypeExpr} ->
|
||||||
% Result = Ast#ast_ta{points_to = TypeExpr},
|
% Result = Ast#ast_ta{points_to = TypeExpr},
|
||||||
@@ -455,25 +455,25 @@
|
|||||||
%% ^
|
%% ^
|
||||||
%%
|
%%
|
||||||
%% "(bar, baz) = ..." ~> {slurp, [bar, baz], "= ..."}
|
%% "(bar, baz) = ..." ~> {slurp, [bar, baz], "= ..."}
|
||||||
%slurp_ta_tvars(Tks = [#sfc_token{string = "="} | _]) ->
|
%slurp_ta_tvars(Tks = [#tk{string = "="} | _]) ->
|
||||||
% {slurp, [], Tks};
|
% {slurp, [], Tks};
|
||||||
%slurp_ta_tvars([#sfc_token{string = "("},
|
%slurp_ta_tvars([#tk{string = "("},
|
||||||
% #sfc_token{string = ")"}
|
% #tk{string = ")"}
|
||||||
% | NewTokens]) ->
|
% | NewTokens]) ->
|
||||||
% {slurp, [], NewTokens};
|
% {slurp, [], NewTokens};
|
||||||
%slurp_ta_tvars([_ = #sfc_token{string = "("},
|
%slurp_ta_tvars([_ = #tk{string = "("},
|
||||||
% TVar = #sfc_token{type = tvar}
|
% TVar = #tk{type = tvar}
|
||||||
% | NewTokens]) ->
|
% | NewTokens]) ->
|
||||||
% slurp_tavars([TVar], NewTokens).
|
% slurp_tavars([TVar], NewTokens).
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
%slurp_tavars(Stk,
|
%slurp_tavars(Stk,
|
||||||
% [_ = #sfc_token{string = ","},
|
% [_ = #tk{string = ","},
|
||||||
% TVar = #sfc_token{type = tvar}
|
% TVar = #tk{type = tvar}
|
||||||
% | NewTks]) ->
|
% | NewTks]) ->
|
||||||
% slurp_tavars([TVar | Stk], NewTks);
|
% slurp_tavars([TVar | Stk], NewTks);
|
||||||
%slurp_tavars(Stk,
|
%slurp_tavars(Stk,
|
||||||
% [#sfc_token{string = ")"}
|
% [#tk{string = ")"}
|
||||||
% | NewTks]) ->
|
% | NewTks]) ->
|
||||||
% {slurp, lists:reverse(Stk), NewTks}.
|
% {slurp, lists:reverse(Stk), NewTks}.
|
||||||
%
|
%
|
||||||
@@ -536,7 +536,7 @@
|
|||||||
%% (X) // legal, equiv to X
|
%% (X) // legal, equiv to X
|
||||||
%% (X, Y) // illegal, should be X * Y
|
%% (X, Y) // illegal, should be X * Y
|
||||||
%%
|
%%
|
||||||
%slurp_type_expr(Tks = [#sfc_token{pos = Pos} | _]) ->
|
%slurp_type_expr(Tks = [#tk{pos = Pos} | _]) ->
|
||||||
% case slurp_type1(Tks) of
|
% case slurp_type1(Tks) of
|
||||||
% % plist cases
|
% % plist cases
|
||||||
% % function types _ => _
|
% % function types _ => _
|
||||||
@@ -546,7 +546,7 @@
|
|||||||
% % () => _
|
% % () => _
|
||||||
% % (_) => _
|
% % (_) => _
|
||||||
% % (_, _) => _
|
% % (_, _) => _
|
||||||
% {DomainType, [#sfc_token{string = "=>"} | After]} ->
|
% {DomainType, [#tk{string = "=>"} | After]} ->
|
||||||
% case slurp_type_expr(After) of
|
% case slurp_type_expr(After) of
|
||||||
% {slurp, CodomainType, NewTks} ->
|
% {slurp, CodomainType, NewTks} ->
|
||||||
% TypeExpr = #ast_te_fn{dom = DomainType,
|
% TypeExpr = #ast_te_fn{dom = DomainType,
|
||||||
@@ -572,7 +572,7 @@
|
|||||||
% {slurp, {token, Tk}, NewTks} ->
|
% {slurp, {token, Tk}, NewTks} ->
|
||||||
% case NewTks of
|
% case NewTks of
|
||||||
% % foo => bar is fine, normalized to (foo) => bar
|
% % foo => bar is fine, normalized to (foo) => bar
|
||||||
% [#sfc_token{string = "=>"} | After] ->
|
% [#tk{string = "=>"} | After] ->
|
||||||
% case slurp_type_expr(After) of
|
% case slurp_type_expr(After) of
|
||||||
% {slurp, Codom, NewAfter} ->
|
% {slurp, Codom, NewAfter} ->
|
||||||
% ArgType = #ast_te_tk{token = ArgTypeTk},
|
% ArgType = #ast_te_tk{token = ArgTypeTk},
|
||||||
@@ -600,7 +600,7 @@
|
|||||||
% % ["("] -> error(nyi);
|
% % ["("] -> error(nyi);
|
||||||
% % ["*"] -> error(nyi);
|
% % ["*"] -> error(nyi);
|
||||||
% %case After of
|
% %case After of
|
||||||
% % [#sfc_token{string = "("} | _] ->
|
% % [#tk{string = "("} | _] ->
|
||||||
% % case slurp_type1_II(After) of
|
% % case slurp_type1_II(After) of
|
||||||
% % {slurp, {plist, ArgTypes}, NewAfter} ->
|
% % {slurp, {plist, ArgTypes}, NewAfter} ->
|
||||||
% % {slurp, #ast_te_ap{fn = FirstType
|
% % {slurp, #ast_te_ap{fn = FirstType
|
||||||
@@ -609,12 +609,12 @@
|
|||||||
%
|
%
|
||||||
%
|
%
|
||||||
%% Type1 = {plist, Types} () (foo) (foo, bar)
|
%% Type1 = {plist, Types} () (foo) (foo, bar)
|
||||||
%% | {token, #sfc_token{}} foo Bar.baz 'quux
|
%% | {token, #tk{}} foo Bar.baz 'quux
|
||||||
%slurp_type1(Tks) ->
|
%slurp_type1(Tks) ->
|
||||||
% case sfc_tokens:slurp_plist(Tks) of
|
% case gsc_tokens:slurp_plist(Tks) of
|
||||||
% % head token is NOT open paren -> must be id/qid/tvar
|
% % head token is NOT open paren -> must be id/qid/tvar
|
||||||
% {slurp, [], [Tk | NewTks]} ->
|
% {slurp, [], [Tk | NewTks]} ->
|
||||||
% TkType = Tk#sfc_token.type,
|
% TkType = Tk#tk.type,
|
||||||
% case TkType of
|
% case TkType of
|
||||||
% id -> {slurp, {token, Tk}, NewTks};
|
% id -> {slurp, {token, Tk}, NewTks};
|
||||||
% qid -> {slurp, {token, Tk}, NewTks};
|
% qid -> {slurp, {token, Tk}, NewTks};
|
||||||
@@ -633,10 +633,10 @@
|
|||||||
%
|
%
|
||||||
%
|
%
|
||||||
%%slurp_type_expr_plist(Tks) ->
|
%%slurp_type_expr_plist(Tks) ->
|
||||||
%% case sfc_tokens:slurp_plist(Tks) of
|
%% case gsc_tokens:slurp_plist(Tks) of
|
||||||
%% % head token is NOT open paren -> must be id/qid/tvar
|
%% % head token is NOT open paren -> must be id/qid/tvar
|
||||||
%% {slurp, [], [Tk | NewTks]} ->
|
%% {slurp, [], [Tk | NewTks]} ->
|
||||||
%% TkType = Tk#sfc_token.type,
|
%% TkType = Tk#tk.type,
|
||||||
%% case TkType of
|
%% case TkType of
|
||||||
%% id -> {slurp, {token, Tk}, NewTks};
|
%% id -> {slurp, {token, Tk}, NewTks};
|
||||||
%% qid -> {slurp, {token, Tk}, NewTks};
|
%% qid -> {slurp, {token, Tk}, NewTks};
|
||||||
@@ -653,23 +653,23 @@
|
|||||||
%% Error = {error, _} -> Error
|
%% Error = {error, _} -> Error
|
||||||
%% end.
|
%% end.
|
||||||
%
|
%
|
||||||
%gulp_ptype1([#sfc_token{string = "("}, #sfc_token{string = ")"}]) ->
|
%gulp_ptype1([#tk{string = "("}, #tk{string = ")"}]) ->
|
||||||
% {gulp, []};
|
% {gulp, []};
|
||||||
%gulp_ptype1([#sfc_token{string = "("} | Tail]) ->
|
%gulp_ptype1([#tk{string = "("} | Tail]) ->
|
||||||
% gulp_ptype1_II([], Tail).
|
% gulp_ptype1_II([], Tail).
|
||||||
%
|
%
|
||||||
%gulp_ptype1_II(Stk, Tks) ->
|
%gulp_ptype1_II(Stk, Tks) ->
|
||||||
% case slurp_type_expr(Tks) of
|
% case slurp_type_expr(Tks) of
|
||||||
% {slurp, NewType, [#sfc_token{string = ")"}]} ->
|
% {slurp, NewType, [#tk{string = ")"}]} ->
|
||||||
% {gulp, lists:reverse([NewType | Stk])};
|
% {gulp, lists:reverse([NewType | Stk])};
|
||||||
% {slurp, NewType, [#sfc_token{string = ","} | NewTks]} ->
|
% {slurp, NewType, [#tk{string = ","} | NewTks]} ->
|
||||||
% gulp_ptype1_II([NewType | Stk], NewTks);
|
% gulp_ptype1_II([NewType | Stk], NewTks);
|
||||||
% Error = {error, _} ->
|
% Error = {error, _} ->
|
||||||
% Error
|
% Error
|
||||||
% end.
|
% end.
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
%%gulp_te_tk([Tk = #sfc_token{type = TkType}])
|
%%gulp_te_tk([Tk = #tk{type = TkType}])
|
||||||
%% when id =:= TkType;
|
%% when id =:= TkType;
|
||||||
%% qid =:= TkType;
|
%% qid =:= TkType;
|
||||||
%% tvar =:= TkType ->
|
%% tvar =:= TkType ->
|
||||||
|
|||||||
+5
-5
@@ -1,5 +1,5 @@
|
|||||||
% @doc
|
% @doc
|
||||||
% sfc_bst = ast second attempt but prefix so tab complete
|
% gsc_bst = ast second attempt but prefix so tab complete
|
||||||
%
|
%
|
||||||
% from docs/sophia/so_syntax.md:
|
% from docs/sophia/so_syntax.md:
|
||||||
%
|
%
|
||||||
@@ -38,12 +38,12 @@
|
|||||||
% FModifier ::= 'stateful' | 'private'
|
% FModifier ::= 'stateful' | 'private'
|
||||||
%
|
%
|
||||||
% Args ::= '(' Sep(Pattern, ',') ')'
|
% Args ::= '(' Sep(Pattern, ',') ')'
|
||||||
-module(sfc_bst).
|
-module(gsc_bst).
|
||||||
|
|
||||||
-compile([export_all, nowarn_export_all]).
|
-compile([export_all, nowarn_export_all]).
|
||||||
-include("$sfc_include/sfc.hrl").
|
-include("$gsc_include/gsc.hrl").
|
||||||
|
|
||||||
%-record(bst_nyi, {tokens :: [sfc_token()]).
|
%-record(bst_nyi, {tokens :: [tk()]).
|
||||||
%
|
%
|
||||||
%% ['payable'] ['main'] 'contract' Con [Implement] '=' Block(Decl)
|
%% ['payable'] ['main'] 'contract' Con [Implement] '=' Block(Decl)
|
||||||
%-record(bst_ct,
|
%-record(bst_ct,
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
%% | '@compiler' PragmaOp Version
|
%% | '@compiler' PragmaOp Version
|
||||||
%% | 'include' String
|
%% | 'include' String
|
||||||
%% | Using
|
%% | Using
|
||||||
%gulp(top_decl, [#sfc_token{string = S} | Rest]) ->
|
%gulp(top_decl, [#tk{string = S} | Rest]) ->
|
||||||
% case strings(3, Tokens) of
|
% case strings(3, Tokens) of
|
||||||
% ["payable", "contract", "interface"] ->
|
% ["payable", "contract", "interface"] ->
|
||||||
% gulp_ct(#bst_iface{payable = true, main = true}, drop(3, Tokens));
|
% gulp_ct(#bst_iface{payable = true, main = true}, drop(3, Tokens));
|
||||||
|
|||||||
+23
-23
@@ -1,4 +1,4 @@
|
|||||||
-module(sfc_parse_type_expr).
|
-module(gsc_parse_type_expr).
|
||||||
|
|
||||||
-export_type([
|
-export_type([
|
||||||
]).
|
]).
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
take_until_ifx_op/1
|
take_until_ifx_op/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("$sfc_include/sfc.hrl").
|
-include("$gsc_include/gsc.hrl").
|
||||||
|
|
||||||
|
|
||||||
%------------------------------------------------------
|
%------------------------------------------------------
|
||||||
@@ -17,18 +17,18 @@
|
|||||||
%------------------------------------------------------
|
%------------------------------------------------------
|
||||||
|
|
||||||
-type vtk_ifx_op() :: vtk_apply_to
|
-type vtk_ifx_op() :: vtk_apply_to
|
||||||
| {'vtk_*', sfc_token()}
|
| {'vtk_*', tk()}
|
||||||
| {'vtk_=>', sfc_token()}.
|
| {'vtk_=>', tk()}.
|
||||||
|
|
||||||
-type vtk() :: sfc_token()
|
-type vtk() :: tk()
|
||||||
| {vtk_plist, [sfc_token()]}
|
| {vtk_plist, [tk()]}
|
||||||
| vtk_ifx_op().
|
| vtk_ifx_op().
|
||||||
|
|
||||||
|
|
||||||
-type gulped(X) :: {gulp, X}
|
-type gulped(X) :: {gulp, X}
|
||||||
| {error, any()}.
|
| {error, any()}.
|
||||||
|
|
||||||
-type slurped(X) :: {slurp, X, Rest :: [sfc_token()]}
|
-type slurped(X) :: {slurp, X, Rest :: [tk()]}
|
||||||
| {error, any()}.
|
| {error, any()}.
|
||||||
|
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
% @doc for testing
|
% @doc for testing
|
||||||
unsafe_vtks_from_string(S) ->
|
unsafe_vtks_from_string(S) ->
|
||||||
{ok, SigTks} = sfc_tokens:significant_tokens(S),
|
{ok, SigTks} = gsc_tokens:significant_tokens(S),
|
||||||
{gulp, Vtks} = gulp_vtks(SigTks),
|
{gulp, Vtks} = gulp_vtks(SigTks),
|
||||||
Vtks.
|
Vtks.
|
||||||
|
|
||||||
@@ -79,9 +79,9 @@ unsafe_vtks_from_string(S) ->
|
|||||||
|
|
||||||
|
|
||||||
-record(ast_parens,
|
-record(ast_parens,
|
||||||
{open = none :: none | sfc_token(),
|
{open = none :: none | tk(),
|
||||||
inner = none :: none | [sfc_token()],
|
inner = none :: none | [tk()],
|
||||||
close = none :: none | sfc_token()}).
|
close = none :: none | tk()}).
|
||||||
|
|
||||||
chunk_by(Strategy, Tokens) ->
|
chunk_by(Strategy, Tokens) ->
|
||||||
chunk_by(Strategy, [], Tokens).
|
chunk_by(Strategy, [], Tokens).
|
||||||
@@ -91,7 +91,7 @@ chunk_by(Strategy, Tokens) ->
|
|||||||
Strategy :: chunk_strategy(),
|
Strategy :: chunk_strategy(),
|
||||||
Oks :: [any()],
|
Oks :: [any()],
|
||||||
Errs :: [{error, Reason :: any()}],
|
Errs :: [{error, Reason :: any()}],
|
||||||
Tokens :: [sfc_token()],
|
Tokens :: [tk()],
|
||||||
Result :: {ok,
|
Result :: {ok,
|
||||||
|
|
||||||
gulp_chunks_by(_, Stk, [], []) ->
|
gulp_chunks_by(_, Stk, [], []) ->
|
||||||
@@ -109,8 +109,8 @@ gulp_chunks_by(plist, Stk, Errs, Tokens) ->
|
|||||||
gulp_chunks_by(plist, Stk, [Error | Errs], Tokens);
|
gulp_chunks_by(plist, Stk, [Error | Errs], Tokens);
|
||||||
end.
|
end.
|
||||||
|
|
||||||
slurp_plist_rec(Tokens = [#sfc_token{string = "(" | _]) ->
|
slurp_plist_rec(Tokens = [#tk{string = "(" | _]) ->
|
||||||
case sfc_tokens:slurp_plist(Tokens) of
|
case gsc_tokens:slurp_plist(Tokens) of
|
||||||
{slurp, [], _} ->
|
{slurp, [], _} ->
|
||||||
barf;
|
barf;
|
||||||
{slurp, PTokens, NewTokens} ->
|
{slurp, PTokens, NewTokens} ->
|
||||||
@@ -118,18 +118,18 @@ slurp_plist_rec(Tokens = [#sfc_token{string = "(" | _]) ->
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
%-spec gulp_ifx_tree(Tokens) -> gulped(IfxTree) when
|
%-spec gulp_ifx_tree(Tokens) -> gulped(IfxTree) when
|
||||||
% Tokens :: [sfc_token()],
|
% Tokens :: [tk()],
|
||||||
% IfxTree :: ifx_tree().
|
% IfxTree :: ifx_tree().
|
||||||
%
|
%
|
||||||
%-spec chunk_by(ChunkStrategy, Tokens) -> Result when
|
%-spec chunk_by(ChunkStrategy, Tokens) -> Result when
|
||||||
% ChunkStrategy :: chunk_strategy(),
|
% ChunkStrategy :: chunk_strategy(),
|
||||||
% Tokens :: [sfc_token()],
|
% Tokens :: [tk()],
|
||||||
% Result :: {ChunkStrategy,
|
% Result :: {ChunkStrategy,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-spec gulp_vtks(Tokens) -> Result when
|
-spec gulp_vtks(Tokens) -> Result when
|
||||||
Tokens :: [sfc_token()],
|
Tokens :: [tk()],
|
||||||
Result :: gulped(VirtualTokens),
|
Result :: gulped(VirtualTokens),
|
||||||
VirtualTokens :: [vtk()].
|
VirtualTokens :: [vtk()].
|
||||||
|
|
||||||
@@ -155,8 +155,8 @@ gulp_vtks(Acc, Tks0) ->
|
|||||||
% ~> [..., foo, {plist, "(bar, baz)"}, ...]
|
% ~> [..., foo, {plist, "(bar, baz)"}, ...]
|
||||||
{_Pfx = Tks1_BeforeOpen,
|
{_Pfx = Tks1_BeforeOpen,
|
||||||
_Sfx = Tks2_OpenNAfter
|
_Sfx = Tks2_OpenNAfter
|
||||||
= [#sfc_token{string = "("} | _]} ->
|
= [#tk{string = "("} | _]} ->
|
||||||
case sfc_tokens:slurp_plist(Tks2_OpenNAfter) of
|
case gsc_tokens:slurp_plist(Tks2_OpenNAfter) of
|
||||||
{slurp, Tks2A_OpenToClose, Tks2B_AfterClose} ->
|
{slurp, Tks2A_OpenToClose, Tks2B_AfterClose} ->
|
||||||
NewAcc = [Acc,
|
NewAcc = [Acc,
|
||||||
Tks1_BeforeOpen,
|
Tks1_BeforeOpen,
|
||||||
@@ -168,7 +168,7 @@ gulp_vtks(Acc, Tks0) ->
|
|||||||
end;
|
end;
|
||||||
% product
|
% product
|
||||||
{_Pfx = Tks0_BeforeTimes,
|
{_Pfx = Tks0_BeforeTimes,
|
||||||
_Sfx = [ Tk1A_Times = #sfc_token{string = "*"}
|
_Sfx = [ Tk1A_Times = #tk{string = "*"}
|
||||||
| Tks1B_AfterTimes]} ->
|
| Tks1B_AfterTimes]} ->
|
||||||
NewAcc = [Acc,
|
NewAcc = [Acc,
|
||||||
Tks0_BeforeTimes,
|
Tks0_BeforeTimes,
|
||||||
@@ -176,7 +176,7 @@ gulp_vtks(Acc, Tks0) ->
|
|||||||
gulp_vtks(NewAcc, Tks1B_AfterTimes);
|
gulp_vtks(NewAcc, Tks1B_AfterTimes);
|
||||||
% funType
|
% funType
|
||||||
{_Pfx = Tks0_BeforeOp,
|
{_Pfx = Tks0_BeforeOp,
|
||||||
_Sfx = [ Tk1A_Op = #sfc_token{string = "=>"}
|
_Sfx = [ Tk1A_Op = #tk{string = "=>"}
|
||||||
| Tks1B_AfterOp]} ->
|
| Tks1B_AfterOp]} ->
|
||||||
NewAcc = [Acc,
|
NewAcc = [Acc,
|
||||||
Tks0_BeforeOp,
|
Tks0_BeforeOp,
|
||||||
@@ -187,7 +187,7 @@ gulp_vtks(Acc, Tks0) ->
|
|||||||
|
|
||||||
|
|
||||||
-spec take_until_ifx_op(Tokens) -> Result when
|
-spec take_until_ifx_op(Tokens) -> Result when
|
||||||
Tokens :: [sfc_token()],
|
Tokens :: [tk()],
|
||||||
Result :: {Taken, NewTokens},
|
Result :: {Taken, NewTokens},
|
||||||
Taken :: Tokens,
|
Taken :: Tokens,
|
||||||
NewTokens :: Tokens.
|
NewTokens :: Tokens.
|
||||||
@@ -200,7 +200,7 @@ take_until_ifx_op(Tks) ->
|
|||||||
take_until_ifx_op(Stack, []) ->
|
take_until_ifx_op(Stack, []) ->
|
||||||
{lists:reverse(Stack), []};
|
{lists:reverse(Stack), []};
|
||||||
take_until_ifx_op(Stack, Tokens = [Token | NewTokens]) ->
|
take_until_ifx_op(Stack, Tokens = [Token | NewTokens]) ->
|
||||||
TokStr = Token#sfc_token.string,
|
TokStr = Token#tk.string,
|
||||||
Continue =
|
Continue =
|
||||||
case TokStr of
|
case TokStr of
|
||||||
% exit cases
|
% exit cases
|
||||||
|
|||||||
@@ -65,12 +65,12 @@
|
|||||||
% KW = string:join(Keywords, "|"),
|
% KW = string:join(Keywords, "|"),
|
||||||
%
|
%
|
||||||
% There is a lot going on in that code. This is purely the part that matches
|
% There is a lot going on in that code. This is purely the part that matches
|
||||||
% strings specifically, . The *tokenizer* (sfc_tokenizer) knows the hierarchy
|
% strings specifically, . The *tokenizer* (gsc_tokenizer) knows the hierarchy
|
||||||
% of sophia tokens (e.g. it knows to match keywords before identifiers, so that
|
% of sophia tokens (e.g. it knows to match keywords before identifiers, so that
|
||||||
% `contract` gets tokenized as a keyword and not a variable name), and then
|
% `contract` gets tokenized as a keyword and not a variable name), and then
|
||||||
% calls into this module in order to match the string shape it's looking for.
|
% calls into this module in order to match the string shape it's looking for.
|
||||||
% @end
|
% @end
|
||||||
-module(sfc_strmatch).
|
-module(gsc_strmatch).
|
||||||
|
|
||||||
%-compile([export_all, nowarn_export_all]).
|
%-compile([export_all, nowarn_export_all]).
|
||||||
|
|
||||||
|
|||||||
+94
-94
@@ -7,16 +7,16 @@
|
|||||||
% For MVP it mimics the behavior of so_scan exactly, in terms of like what its
|
% For MVP it mimics the behavior of so_scan exactly, in terms of like what its
|
||||||
% definition of a token is and so on.
|
% definition of a token is and so on.
|
||||||
%
|
%
|
||||||
% sfc_so_scan.erl contains a compatibility layer that should agree with so_scan
|
% gsc_so_scan.erl contains a compatibility layer that should agree with so_scan
|
||||||
% exactly. It converts the data types here to the shapes that so_scan outputs.
|
% exactly. It converts the data types here to the shapes that so_scan outputs.
|
||||||
%
|
%
|
||||||
% This is for two reasons:
|
% This is for two reasons:
|
||||||
%
|
%
|
||||||
% 1. in order to enable testing the two modules against each other, and
|
% 1. in order to enable testing the two modules against each other, and
|
||||||
% 2. to future-proof in case we decide to incrementally incorporate the sfc
|
% 2. to future-proof in case we decide to incrementally incorporate the gsc
|
||||||
% code into the legacy sophia compiler
|
% code into the legacy sophia compiler
|
||||||
% @end
|
% @end
|
||||||
-module(sfc_tokens).
|
-module(gsc_tokens).
|
||||||
|
|
||||||
% meta
|
% meta
|
||||||
-export([
|
-export([
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
new_pos/2
|
new_pos/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("$sfc_include/sfc.hrl").
|
-include("$gsc_include/gsc.hrl").
|
||||||
|
|
||||||
|
|
||||||
%=======================================================
|
%=======================================================
|
||||||
@@ -55,11 +55,11 @@
|
|||||||
|
|
||||||
-spec strings(N, Tokens) -> AtMostNStrings
|
-spec strings(N, Tokens) -> AtMostNStrings
|
||||||
when N :: non_neg_integer(),
|
when N :: non_neg_integer(),
|
||||||
Tokens :: [sfc_token()],
|
Tokens :: [tk()],
|
||||||
AtMostNStrings :: [string()].
|
AtMostNStrings :: [string()].
|
||||||
% @doc return the strings of the first N tokens
|
% @doc return the strings of the first N tokens
|
||||||
|
|
||||||
strings(N, [#sfc_token{string = S} | Rest]) when is_integer(N), N >= 1 ->
|
strings(N, [#tk{string = S} | Rest]) when is_integer(N), N >= 1 ->
|
||||||
[S | strings(N-1, Rest)];
|
[S | strings(N-1, Rest)];
|
||||||
strings(_, []) ->
|
strings(_, []) ->
|
||||||
[];
|
[];
|
||||||
@@ -84,16 +84,16 @@ strings(0, _) ->
|
|||||||
% ...
|
% ...
|
||||||
|
|
||||||
-spec take_block(Tokens) -> {BlockTokens, Rest}
|
-spec take_block(Tokens) -> {BlockTokens, Rest}
|
||||||
when Tokens :: [sfc_token()],
|
when Tokens :: [tk()],
|
||||||
BlockTokens :: Tokens,
|
BlockTokens :: Tokens,
|
||||||
Rest :: Tokens.
|
Rest :: Tokens.
|
||||||
% @doc
|
% @doc
|
||||||
% takes all tokens whose column position is >= the column position of
|
% takes all tokens whose column position is >= the column position of
|
||||||
% the head token
|
% the head token
|
||||||
|
|
||||||
take_block([H = #sfc_token{pos = {_, BlkCol}} | T]) ->
|
take_block([H = #tk{pos = {_, BlkCol}} | T]) ->
|
||||||
TokenInBlock =
|
TokenInBlock =
|
||||||
fun(#sfc_token{pos = {_, TkCol}}) ->
|
fun(#tk{pos = {_, TkCol}}) ->
|
||||||
BlkCol =< TkCol
|
BlkCol =< TkCol
|
||||||
end,
|
end,
|
||||||
take_while(TokenInBlock, [H], T);
|
take_while(TokenInBlock, [H], T);
|
||||||
@@ -103,16 +103,16 @@ take_block([]) ->
|
|||||||
|
|
||||||
|
|
||||||
-spec take_block_item(Tokens) -> {ItemTokens, Rest}
|
-spec take_block_item(Tokens) -> {ItemTokens, Rest}
|
||||||
when Tokens :: [sfc_token()],
|
when Tokens :: [tk()],
|
||||||
ItemTokens :: Tokens,
|
ItemTokens :: Tokens,
|
||||||
Rest :: Tokens.
|
Rest :: Tokens.
|
||||||
% @doc
|
% @doc
|
||||||
% takes all tokens whose column position is > the column position of
|
% takes all tokens whose column position is > the column position of
|
||||||
% the head token
|
% the head token
|
||||||
|
|
||||||
take_block_item([H = #sfc_token{pos = {_, ItemCol}} | T]) ->
|
take_block_item([H = #tk{pos = {_, ItemCol}} | T]) ->
|
||||||
TokenInItem =
|
TokenInItem =
|
||||||
fun(#sfc_token{pos = {_, TkCol}}) ->
|
fun(#tk{pos = {_, TkCol}}) ->
|
||||||
ItemCol < TkCol
|
ItemCol < TkCol
|
||||||
end,
|
end,
|
||||||
take_while(TokenInItem, [H], T);
|
take_while(TokenInItem, [H], T);
|
||||||
@@ -128,7 +128,7 @@ take_block_item([]) ->
|
|||||||
Mismatch :: {fixme, mismatch, OpenStack, ClosedBy},
|
Mismatch :: {fixme, mismatch, OpenStack, ClosedBy},
|
||||||
OpenStack :: Tokens,
|
OpenStack :: Tokens,
|
||||||
ClosedBy :: none | {value, Token},
|
ClosedBy :: none | {value, Token},
|
||||||
Token :: sfc_token().
|
Token :: tk().
|
||||||
|
|
||||||
% @doc
|
% @doc
|
||||||
% the verbiage here is `slurp' rather than `take' because we insist on
|
% the verbiage here is `slurp' rather than `take' because we insist on
|
||||||
@@ -159,7 +159,7 @@ take_block_item([]) ->
|
|||||||
% counterintuitive to end-users (who are programmers, entirely
|
% counterintuitive to end-users (who are programmers, entirely
|
||||||
% unfamiliar with notions like stacks and open/close delimiters)
|
% unfamiliar with notions like stacks and open/close delimiters)
|
||||||
|
|
||||||
slurp_plist([Hd = #sfc_token{string = "("} | Tl]) ->
|
slurp_plist([Hd = #tk{string = "("} | Tl]) ->
|
||||||
slurp_dlist([Hd], [Hd], Tl);
|
slurp_dlist([Hd], [Hd], Tl);
|
||||||
slurp_plist(Tks) ->
|
slurp_plist(Tks) ->
|
||||||
{slurp, [], Tks}.
|
{slurp, [], Tks}.
|
||||||
@@ -170,30 +170,30 @@ slurp_dlist(All, [], NewTokens) ->
|
|||||||
{slurp, lists:reverse(All), NewTokens};
|
{slurp, lists:reverse(All), NewTokens};
|
||||||
% WMA stack is nonempty
|
% WMA stack is nonempty
|
||||||
% happy cases of opens getting popped
|
% happy cases of opens getting popped
|
||||||
slurp_dlist(All, [#sfc_token{string = "("} | NewOpen],
|
slurp_dlist(All, [#tk{string = "("} | NewOpen],
|
||||||
[#sfc_token{string = ")"} = Tk | NewTks]) ->
|
[#tk{string = ")"} = Tk | NewTks]) ->
|
||||||
slurp_dlist([Tk | All], NewOpen, NewTks);
|
slurp_dlist([Tk | All], NewOpen, NewTks);
|
||||||
slurp_dlist(All, [#sfc_token{string = "["} | NewOpen],
|
slurp_dlist(All, [#tk{string = "["} | NewOpen],
|
||||||
[#sfc_token{string = "]"} = Tk | NewTks]) ->
|
[#tk{string = "]"} = Tk | NewTks]) ->
|
||||||
slurp_dlist([Tk | All], NewOpen, NewTks);
|
slurp_dlist([Tk | All], NewOpen, NewTks);
|
||||||
slurp_dlist(All, [#sfc_token{string = "{"} | NewOpen],
|
slurp_dlist(All, [#tk{string = "{"} | NewOpen],
|
||||||
[#sfc_token{string = "}"} = Tk | NewTks]) ->
|
[#tk{string = "}"} = Tk | NewTks]) ->
|
||||||
slurp_dlist([Tk | All], NewOpen, NewTks);
|
slurp_dlist([Tk | All], NewOpen, NewTks);
|
||||||
% happy: open delimiters getting pushed
|
% happy: open delimiters getting pushed
|
||||||
slurp_dlist(All, Opens, [#sfc_token{string = "("} = Tk | NewTks]) ->
|
slurp_dlist(All, Opens, [#tk{string = "("} = Tk | NewTks]) ->
|
||||||
slurp_dlist([Tk | All], [Tk | Opens], NewTks);
|
slurp_dlist([Tk | All], [Tk | Opens], NewTks);
|
||||||
slurp_dlist(All, Opens, [#sfc_token{string = "["} = Tk | NewTks]) ->
|
slurp_dlist(All, Opens, [#tk{string = "["} = Tk | NewTks]) ->
|
||||||
slurp_dlist([Tk | All], [Tk | Opens], NewTks);
|
slurp_dlist([Tk | All], [Tk | Opens], NewTks);
|
||||||
slurp_dlist(All, Opens, [#sfc_token{string = "{"} = Tk | NewTks]) ->
|
slurp_dlist(All, Opens, [#tk{string = "{"} = Tk | NewTks]) ->
|
||||||
slurp_dlist([Tk | All], [Tk | Opens], NewTks);
|
slurp_dlist([Tk | All], [Tk | Opens], NewTks);
|
||||||
% sad: mismatch cases
|
% sad: mismatch cases
|
||||||
slurp_dlist(All, Opens, []) ->
|
slurp_dlist(All, Opens, []) ->
|
||||||
{error, {fixme, mismatch, Opens, none}};
|
{error, {fixme, mismatch, Opens, none}};
|
||||||
slurp_dlist(All, Opens, [#sfc_token{string = "}"} = BadClose | _]) ->
|
slurp_dlist(All, Opens, [#tk{string = "}"} = BadClose | _]) ->
|
||||||
{error, {fixme, mismatch, Opens, {value, BadClose}}};
|
{error, {fixme, mismatch, Opens, {value, BadClose}}};
|
||||||
slurp_dlist(All, Opens, [#sfc_token{string = "]"} = BadClose | _]) ->
|
slurp_dlist(All, Opens, [#tk{string = "]"} = BadClose | _]) ->
|
||||||
{error, {fixme, mismatch, Opens, {value, BadClose}}};
|
{error, {fixme, mismatch, Opens, {value, BadClose}}};
|
||||||
slurp_dlist(All, Opens, [#sfc_token{string = ")"} = BadClose | _]) ->
|
slurp_dlist(All, Opens, [#tk{string = ")"} = BadClose | _]) ->
|
||||||
{error, {fixme, mismatch, Opens, {value, BadClose}}};
|
{error, {fixme, mismatch, Opens, {value, BadClose}}};
|
||||||
% general case: non-terminal token gets pushed
|
% general case: non-terminal token gets pushed
|
||||||
slurp_dlist(All, Opens, [Tk | NewTks]) ->
|
slurp_dlist(All, Opens, [Tk | NewTks]) ->
|
||||||
@@ -211,7 +211,7 @@ slurp_dlist(All, Opens, [Tk | NewTks]) ->
|
|||||||
% ]).
|
% ]).
|
||||||
%-------------------------------------------------------
|
%-------------------------------------------------------
|
||||||
|
|
||||||
-spec token_types_parse_order() -> [sfc_token_type()].
|
-spec token_types_parse_order() -> [gsc_token_type()].
|
||||||
% @doc
|
% @doc
|
||||||
% list of sophia tokens in parse order (if an earlier type matches, the later
|
% list of sophia tokens in parse order (if an earlier type matches, the later
|
||||||
% type isn't even checked)
|
% type isn't even checked)
|
||||||
@@ -288,9 +288,9 @@ kwds() ->
|
|||||||
%-------------------------------------------------------
|
%-------------------------------------------------------
|
||||||
|
|
||||||
% Token accessors
|
% Token accessors
|
||||||
-spec indent_level(sfc_token()) -> pos_integer().
|
-spec indent_level(tk()) -> pos_integer().
|
||||||
|
|
||||||
indent_level(#sfc_token{pos = {_, IndentLevel}}) ->
|
indent_level(#tk{pos = {_, IndentLevel}}) ->
|
||||||
IndentLevel.
|
IndentLevel.
|
||||||
|
|
||||||
|
|
||||||
@@ -298,8 +298,8 @@ indent_level(#sfc_token{pos = {_, IndentLevel}}) ->
|
|||||||
-spec significant_tokens(SrcStr) -> Result
|
-spec significant_tokens(SrcStr) -> Result
|
||||||
when SrcStr :: iolist(),
|
when SrcStr :: iolist(),
|
||||||
Result :: {ok, Tokens}
|
Result :: {ok, Tokens}
|
||||||
| {error, sfc_err()},
|
| {error, gsc_err()},
|
||||||
Tokens :: [sfc_token()].
|
Tokens :: [tk()].
|
||||||
|
|
||||||
significant_tokens(SrcStr) ->
|
significant_tokens(SrcStr) ->
|
||||||
case tokens(SrcStr) of
|
case tokens(SrcStr) of
|
||||||
@@ -312,7 +312,7 @@ significant_tokens(SrcStr) ->
|
|||||||
|
|
||||||
|
|
||||||
-spec filter_significant(Tokens) -> SignificantTokens
|
-spec filter_significant(Tokens) -> SignificantTokens
|
||||||
when Tokens :: [sfc_token()],
|
when Tokens :: [tk()],
|
||||||
SignificantTokens :: Tokens.
|
SignificantTokens :: Tokens.
|
||||||
|
|
||||||
filter_significant(Tokens) ->
|
filter_significant(Tokens) ->
|
||||||
@@ -321,19 +321,19 @@ filter_significant(Tokens) ->
|
|||||||
|
|
||||||
|
|
||||||
-spec is_significant(Token) -> boolean()
|
-spec is_significant(Token) -> boolean()
|
||||||
when Token :: sfc_token().
|
when Token :: tk().
|
||||||
|
|
||||||
is_significant(#sfc_token{type = bcom}) -> false;
|
is_significant(#tk{type = bcom}) -> false;
|
||||||
is_significant(#sfc_token{type = lcom}) -> false;
|
is_significant(#tk{type = lcom}) -> false;
|
||||||
is_significant(#sfc_token{type = ws}) -> false;
|
is_significant(#tk{type = ws}) -> false;
|
||||||
is_significant(_) -> true.
|
is_significant(_) -> true.
|
||||||
|
|
||||||
|
|
||||||
-spec tokens(SrcStr) -> Result
|
-spec tokens(SrcStr) -> Result
|
||||||
when SrcStr :: iolist(),
|
when SrcStr :: iolist(),
|
||||||
Result :: {ok, Tokens}
|
Result :: {ok, Tokens}
|
||||||
| {error, sfc_err()},
|
| {error, gsc_err()},
|
||||||
Tokens :: [sfc_token()].
|
Tokens :: [tk()].
|
||||||
% @doc
|
% @doc
|
||||||
% Recursively parse all tokens off the front end of the string. `Rest' is
|
% Recursively parse all tokens off the front end of the string. `Rest' is
|
||||||
% the first tail of the string for which no token parser succeeds.
|
% the first tail of the string for which no token parser succeeds.
|
||||||
@@ -349,13 +349,13 @@ tokens(Stack, _FinalPos, "") ->
|
|||||||
{ok, lists:reverse(Stack)};
|
{ok, lists:reverse(Stack)};
|
||||||
tokens(Stack, Pos, SrcStr) ->
|
tokens(Stack, Pos, SrcStr) ->
|
||||||
case slurp_token(Pos, SrcStr) of
|
case slurp_token(Pos, SrcStr) of
|
||||||
{tokmatch, NewToken = #sfc_token{string = TokStr},
|
{tokmatch, NewToken = #tk{string = TokStr},
|
||||||
NewSrcStr} ->
|
NewSrcStr} ->
|
||||||
NewPos = new_pos(Pos, TokStr),
|
NewPos = new_pos(Pos, TokStr),
|
||||||
tokens([NewToken | Stack], NewPos, NewSrcStr);
|
tokens([NewToken | Stack], NewPos, NewSrcStr);
|
||||||
no_tokmatch ->
|
no_tokmatch ->
|
||||||
PrevTokens = lists:reverse(Stack),
|
PrevTokens = lists:reverse(Stack),
|
||||||
Err = #sfc_err_no_tokmatch{prev_tokens = PrevTokens,
|
Err = #gsc_err_no_tokmatch{prev_tokens = PrevTokens,
|
||||||
break_pos = Pos,
|
break_pos = Pos,
|
||||||
rest = SrcStr},
|
rest = SrcStr},
|
||||||
{error, Err};
|
{error, Err};
|
||||||
@@ -367,7 +367,7 @@ tokens(Stack, Pos, SrcStr) ->
|
|||||||
% for now we're just going to agree with so_scan
|
% for now we're just going to agree with so_scan
|
||||||
{ierr, unterminated_block_comment} ->
|
{ierr, unterminated_block_comment} ->
|
||||||
PrevTokens = lists:reverse(Stack),
|
PrevTokens = lists:reverse(Stack),
|
||||||
Err = #sfc_err_bcom_unterminated{prev_tokens = PrevTokens,
|
Err = #gsc_err_bcom_unterminated{prev_tokens = PrevTokens,
|
||||||
break_pos = Pos,
|
break_pos = Pos,
|
||||||
rest = SrcStr},
|
rest = SrcStr},
|
||||||
{error, Err};
|
{error, Err};
|
||||||
@@ -455,13 +455,13 @@ next_tabstop8(Col0) when Col0 >= 0 ->
|
|||||||
|
|
||||||
|
|
||||||
-spec slurp_token(Pos, SrcStr) -> Result
|
-spec slurp_token(Pos, SrcStr) -> Result
|
||||||
when Pos :: sfc_pos(),
|
when Pos :: gsc_pos(),
|
||||||
SrcStr :: string(),
|
SrcStr :: string(),
|
||||||
Result :: {tokmatch, Token, Rest}
|
Result :: {tokmatch, Token, Rest}
|
||||||
| no_tokmatch
|
| no_tokmatch
|
||||||
| {error, sfc_err()}
|
| {error, gsc_err()}
|
||||||
| {ierr, unterminated_block_comment},
|
| {ierr, unterminated_block_comment},
|
||||||
Token :: sfc_token(),
|
Token :: tk(),
|
||||||
Rest :: string().
|
Rest :: string().
|
||||||
% @doc
|
% @doc
|
||||||
% grab a single token off the front of the string according to
|
% grab a single token off the front of the string according to
|
||||||
@@ -474,14 +474,14 @@ slurp_token(Pos, SrcStr) ->
|
|||||||
|
|
||||||
|
|
||||||
-spec slurp_token_types(ParseOrder, Pos, SrcStr) -> Result
|
-spec slurp_token_types(ParseOrder, Pos, SrcStr) -> Result
|
||||||
when ParseOrder :: [sfc_token_type()],
|
when ParseOrder :: [gsc_token_type()],
|
||||||
Pos :: sfc_pos(),
|
Pos :: gsc_pos(),
|
||||||
SrcStr :: string(),
|
SrcStr :: string(),
|
||||||
Result :: {tokmatch, Token, Rest}
|
Result :: {tokmatch, Token, Rest}
|
||||||
| no_tokmatch
|
| no_tokmatch
|
||||||
| {error, sfc_err()}
|
| {error, gsc_err()}
|
||||||
| {ierr, unterminated_block_comment},
|
| {ierr, unterminated_block_comment},
|
||||||
Token :: sfc_token(),
|
Token :: tk(),
|
||||||
Rest :: string().
|
Rest :: string().
|
||||||
% @doc
|
% @doc
|
||||||
% grab a single token off the front of the string according to
|
% grab a single token off the front of the string according to
|
||||||
@@ -499,14 +499,14 @@ slurp_token_types([], _Pos, _SrcStr) ->
|
|||||||
|
|
||||||
|
|
||||||
-spec slurp_token_of_type(TokenType, Pos, SrcStr) -> MaybeToken
|
-spec slurp_token_of_type(TokenType, Pos, SrcStr) -> MaybeToken
|
||||||
when TokenType :: sfc_token_type(),
|
when TokenType :: gsc_token_type(),
|
||||||
Pos :: sfc_pos(),
|
Pos :: gsc_pos(),
|
||||||
SrcStr :: string(),
|
SrcStr :: string(),
|
||||||
MaybeToken :: {tokmatch, Token, Rest}
|
MaybeToken :: {tokmatch, Token, Rest}
|
||||||
| no_tokmatch
|
| no_tokmatch
|
||||||
| {error, sfc_err()}
|
| {error, gsc_err()}
|
||||||
| {ierr, unterminated_block_comment},
|
| {ierr, unterminated_block_comment},
|
||||||
Token :: sfc_token(),
|
Token :: tk(),
|
||||||
Rest :: string().
|
Rest :: string().
|
||||||
% @doc
|
% @doc
|
||||||
% match a sophia token of a given type off the front of the string
|
% match a sophia token of a given type off the front of the string
|
||||||
@@ -522,7 +522,7 @@ slurp_token_of_type(lcom, Pos, SrcStr) ->
|
|||||||
case SrcStr of
|
case SrcStr of
|
||||||
"//" ++ _ ->
|
"//" ++ _ ->
|
||||||
{Line, Rest} = takeline("", SrcStr),
|
{Line, Rest} = takeline("", SrcStr),
|
||||||
Token = #sfc_token{type = lcom,
|
Token = #tk{type = lcom,
|
||||||
pos = Pos,
|
pos = Pos,
|
||||||
string = Line},
|
string = Line},
|
||||||
{tokmatch, Token, Rest};
|
{tokmatch, Token, Rest};
|
||||||
@@ -536,7 +536,7 @@ slurp_token_of_type(bcom, Pos, SrcStr0) ->
|
|||||||
"/*" ++ SrcStr1 ->
|
"/*" ++ SrcStr1 ->
|
||||||
case bcom("/*", 1, SrcStr1) of
|
case bcom("/*", 1, SrcStr1) of
|
||||||
{ok, CommentStr, SrcStr2} ->
|
{ok, CommentStr, SrcStr2} ->
|
||||||
Token = #sfc_token{type = bcom,
|
Token = #tk{type = bcom,
|
||||||
pos = Pos,
|
pos = Pos,
|
||||||
string = CommentStr},
|
string = CommentStr},
|
||||||
{tokmatch, Token, SrcStr2};
|
{tokmatch, Token, SrcStr2};
|
||||||
@@ -547,12 +547,12 @@ slurp_token_of_type(bcom, Pos, SrcStr0) ->
|
|||||||
no_tokmatch
|
no_tokmatch
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(ws, Pos, SrcStr) ->
|
slurp_token_of_type(ws, Pos, SrcStr) ->
|
||||||
WhitespaceMatcher = sfc_strmatch:smr_sf_ws(),
|
WhitespaceMatcher = gsc_strmatch:smr_sf_ws(),
|
||||||
case sfc_strmatch:match(WhitespaceMatcher, SrcStr) of
|
case gsc_strmatch:match(WhitespaceMatcher, SrcStr) of
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch;
|
no_tokmatch;
|
||||||
{strmatch, WS, Rest} ->
|
{strmatch, WS, Rest} ->
|
||||||
Token = #sfc_token{type = ws,
|
Token = #tk{type = ws,
|
||||||
pos = Pos,
|
pos = Pos,
|
||||||
string = WS},
|
string = WS},
|
||||||
{tokmatch, Token, Rest}
|
{tokmatch, Token, Rest}
|
||||||
@@ -570,86 +570,86 @@ slurp_token_of_type(ws, Pos, SrcStr) ->
|
|||||||
% of the kwds
|
% of the kwds
|
||||||
slurp_token_of_type(kwd, Pos, SrcStr) ->
|
slurp_token_of_type(kwd, Pos, SrcStr) ->
|
||||||
case slurp_token_of_type(id, Pos, SrcStr) of
|
case slurp_token_of_type(id, Pos, SrcStr) of
|
||||||
{tokmatch, IdTok = #sfc_token{string = IdStr}, Rest} ->
|
{tokmatch, IdTok = #tk{string = IdStr}, Rest} ->
|
||||||
case lists:member(IdStr, kwds()) of
|
case lists:member(IdStr, kwds()) of
|
||||||
false ->
|
false ->
|
||||||
no_tokmatch;
|
no_tokmatch;
|
||||||
true ->
|
true ->
|
||||||
KwTok = IdTok#sfc_token{type = kwd},
|
KwTok = IdTok#tk{type = kwd},
|
||||||
{tokmatch, KwTok, Rest}
|
{tokmatch, KwTok, Rest}
|
||||||
end;
|
end;
|
||||||
no_tokmatch ->
|
no_tokmatch ->
|
||||||
no_tokmatch
|
no_tokmatch
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(op, Pos, SrcStr) ->
|
slurp_token_of_type(op, Pos, SrcStr) ->
|
||||||
case sfc_strmatch:match(sfc_strmatch:smr_sf_op(), SrcStr) of
|
case gsc_strmatch:match(gsc_strmatch:smr_sf_op(), SrcStr) of
|
||||||
{strmatch, Str, Rest} ->
|
{strmatch, Str, Rest} ->
|
||||||
Token = #sfc_token{type = op, pos = Pos, string = Str},
|
Token = #tk{type = op, pos = Pos, string = Str},
|
||||||
{tokmatch, Token, Rest};
|
{tokmatch, Token, Rest};
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch
|
no_tokmatch
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(punct, Pos, SrcStr) ->
|
slurp_token_of_type(punct, Pos, SrcStr) ->
|
||||||
case sfc_strmatch:match(sfc_strmatch:smr_sf_punct(), SrcStr) of
|
case gsc_strmatch:match(gsc_strmatch:smr_sf_punct(), SrcStr) of
|
||||||
{strmatch, Str, Rest} ->
|
{strmatch, Str, Rest} ->
|
||||||
Token = #sfc_token{type = punct, pos = Pos, string = Str},
|
Token = #tk{type = punct, pos = Pos, string = Str},
|
||||||
{tokmatch, Token, Rest};
|
{tokmatch, Token, Rest};
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch
|
no_tokmatch
|
||||||
end;
|
end;
|
||||||
% SOPHIA VARIABLE NAMES: id, con, qid, qcon, tvar
|
% SOPHIA VARIABLE NAMES: id, con, qid, qcon, tvar
|
||||||
slurp_token_of_type(id, Pos, SrcStr) ->
|
slurp_token_of_type(id, Pos, SrcStr) ->
|
||||||
case sfc_strmatch:match(sfc_strmatch:smr_sf_id(), SrcStr) of
|
case gsc_strmatch:match(gsc_strmatch:smr_sf_id(), SrcStr) of
|
||||||
{strmatch, IdStr, Rest} ->
|
{strmatch, IdStr, Rest} ->
|
||||||
Token = #sfc_token{type = id, pos = Pos, string = IdStr},
|
Token = #tk{type = id, pos = Pos, string = IdStr},
|
||||||
{tokmatch, Token, Rest};
|
{tokmatch, Token, Rest};
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch
|
no_tokmatch
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(con, Pos, SrcStr) ->
|
slurp_token_of_type(con, Pos, SrcStr) ->
|
||||||
case sfc_strmatch:match(sfc_strmatch:smr_sf_con(), SrcStr) of
|
case gsc_strmatch:match(gsc_strmatch:smr_sf_con(), SrcStr) of
|
||||||
{strmatch, Str, Rest} ->
|
{strmatch, Str, Rest} ->
|
||||||
Token = #sfc_token{type = con, pos = Pos, string = Str},
|
Token = #tk{type = con, pos = Pos, string = Str},
|
||||||
{tokmatch, Token, Rest};
|
{tokmatch, Token, Rest};
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch
|
no_tokmatch
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(qid, Pos, SrcStr) ->
|
slurp_token_of_type(qid, Pos, SrcStr) ->
|
||||||
case sfc_strmatch:match(sfc_strmatch:smr_sf_qid(), SrcStr) of
|
case gsc_strmatch:match(gsc_strmatch:smr_sf_qid(), SrcStr) of
|
||||||
{strmatch, Str, Rest} ->
|
{strmatch, Str, Rest} ->
|
||||||
Token = #sfc_token{type = qid, pos = Pos, string = Str},
|
Token = #tk{type = qid, pos = Pos, string = Str},
|
||||||
{tokmatch, Token, Rest};
|
{tokmatch, Token, Rest};
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch
|
no_tokmatch
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(qcon, Pos, SrcStr) ->
|
slurp_token_of_type(qcon, Pos, SrcStr) ->
|
||||||
case sfc_strmatch:match(sfc_strmatch:smr_sf_qcon(), SrcStr) of
|
case gsc_strmatch:match(gsc_strmatch:smr_sf_qcon(), SrcStr) of
|
||||||
{strmatch, Str, Rest} ->
|
{strmatch, Str, Rest} ->
|
||||||
Token = #sfc_token{type = qcon, pos = Pos, string = Str},
|
Token = #tk{type = qcon, pos = Pos, string = Str},
|
||||||
{tokmatch, Token, Rest};
|
{tokmatch, Token, Rest};
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch
|
no_tokmatch
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(tvar, Pos, SrcStr) ->
|
slurp_token_of_type(tvar, Pos, SrcStr) ->
|
||||||
case sfc_strmatch:match(sfc_strmatch:smr_sf_tvar(), SrcStr) of
|
case gsc_strmatch:match(gsc_strmatch:smr_sf_tvar(), SrcStr) of
|
||||||
{strmatch, Str, Rest} ->
|
{strmatch, Str, Rest} ->
|
||||||
Token = #sfc_token{type = tvar, pos = Pos, string = Str},
|
Token = #tk{type = tvar, pos = Pos, string = Str},
|
||||||
{tokmatch, Token, Rest};
|
{tokmatch, Token, Rest};
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch
|
no_tokmatch
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(int16, Pos, SrcStr) ->
|
slurp_token_of_type(int16, Pos, SrcStr) ->
|
||||||
case sfc_strmatch:match(sfc_strmatch:smr_sf_int16(), SrcStr) of
|
case gsc_strmatch:match(gsc_strmatch:smr_sf_int16(), SrcStr) of
|
||||||
{strmatch, Str, Rest} ->
|
{strmatch, Str, Rest} ->
|
||||||
Token = #sfc_token{type = int16, pos = Pos, string = Str},
|
Token = #tk{type = int16, pos = Pos, string = Str},
|
||||||
{tokmatch, Token, Rest};
|
{tokmatch, Token, Rest};
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch
|
no_tokmatch
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(int10, Pos, SrcStr) ->
|
slurp_token_of_type(int10, Pos, SrcStr) ->
|
||||||
case sfc_strmatch:match(sfc_strmatch:smr_sf_int10(), SrcStr) of
|
case gsc_strmatch:match(gsc_strmatch:smr_sf_int10(), SrcStr) of
|
||||||
{strmatch, Str, Rest} ->
|
{strmatch, Str, Rest} ->
|
||||||
Token = #sfc_token{type = int10, pos = Pos, string = Str},
|
Token = #tk{type = int10, pos = Pos, string = Str},
|
||||||
{tokmatch, Token, Rest};
|
{tokmatch, Token, Rest};
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch
|
no_tokmatch
|
||||||
@@ -659,60 +659,60 @@ slurp_token_of_type(int10, Pos, SrcStr) ->
|
|||||||
%
|
%
|
||||||
% char: sophia char literal
|
% char: sophia char literal
|
||||||
slurp_token_of_type(ak, Pos, SrcStr) ->
|
slurp_token_of_type(ak, Pos, SrcStr) ->
|
||||||
StringMatcher = sfc_strmatch:smr_sf_ak(),
|
StringMatcher = gsc_strmatch:smr_sf_ak(),
|
||||||
case sfc_strmatch:match(StringMatcher, SrcStr) of
|
case gsc_strmatch:match(StringMatcher, SrcStr) of
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch;
|
no_tokmatch;
|
||||||
{strmatch, TokenStr, Rest} ->
|
{strmatch, TokenStr, Rest} ->
|
||||||
Token = #sfc_token{type = ak, pos = Pos, string = TokenStr},
|
Token = #tk{type = ak, pos = Pos, string = TokenStr},
|
||||||
{tokmatch, Token, Rest}
|
{tokmatch, Token, Rest}
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(ct, Pos, SrcStr) ->
|
slurp_token_of_type(ct, Pos, SrcStr) ->
|
||||||
StringMatcher = sfc_strmatch:smr_sf_ct(),
|
StringMatcher = gsc_strmatch:smr_sf_ct(),
|
||||||
case sfc_strmatch:match(StringMatcher, SrcStr) of
|
case gsc_strmatch:match(StringMatcher, SrcStr) of
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch;
|
no_tokmatch;
|
||||||
{strmatch, TokenStr, Rest} ->
|
{strmatch, TokenStr, Rest} ->
|
||||||
Token = #sfc_token{type = ct, pos = Pos, string = TokenStr},
|
Token = #tk{type = ct, pos = Pos, string = TokenStr},
|
||||||
{tokmatch, Token, Rest}
|
{tokmatch, Token, Rest}
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(sg, Pos, SrcStr) ->
|
slurp_token_of_type(sg, Pos, SrcStr) ->
|
||||||
StringMatcher = sfc_strmatch:smr_sf_sg(),
|
StringMatcher = gsc_strmatch:smr_sf_sg(),
|
||||||
case sfc_strmatch:match(StringMatcher, SrcStr) of
|
case gsc_strmatch:match(StringMatcher, SrcStr) of
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch;
|
no_tokmatch;
|
||||||
{strmatch, TokenStr, Rest} ->
|
{strmatch, TokenStr, Rest} ->
|
||||||
Token = #sfc_token{type = sg, pos = Pos, string = TokenStr},
|
Token = #tk{type = sg, pos = Pos, string = TokenStr},
|
||||||
{tokmatch, Token, Rest}
|
{tokmatch, Token, Rest}
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(char, Pos, SrcStr) ->
|
slurp_token_of_type(char, Pos, SrcStr) ->
|
||||||
StringMatcher = sfc_strmatch:smr_sf_char(),
|
StringMatcher = gsc_strmatch:smr_sf_char(),
|
||||||
case sfc_strmatch:match(StringMatcher, SrcStr) of
|
case gsc_strmatch:match(StringMatcher, SrcStr) of
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch;
|
no_tokmatch;
|
||||||
{strmatch, TokenStr, Rest} ->
|
{strmatch, TokenStr, Rest} ->
|
||||||
Token = #sfc_token{type = char, pos = Pos, string = TokenStr},
|
Token = #tk{type = char, pos = Pos, string = TokenStr},
|
||||||
{tokmatch, Token, Rest}
|
{tokmatch, Token, Rest}
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(string, Pos, SrcStr) ->
|
slurp_token_of_type(string, Pos, SrcStr) ->
|
||||||
case sfc_strmatch:match(sfc_strmatch:smr_sf_str(), SrcStr) of
|
case gsc_strmatch:match(gsc_strmatch:smr_sf_str(), SrcStr) of
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch;
|
no_tokmatch;
|
||||||
{strmatch, TokenStr, Rest} ->
|
{strmatch, TokenStr, Rest} ->
|
||||||
Token = #sfc_token{type = string, pos = Pos, string = TokenStr},
|
Token = #tk{type = string, pos = Pos, string = TokenStr},
|
||||||
{tokmatch, Token, Rest}
|
{tokmatch, Token, Rest}
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(bytes, Pos, SrcStr) ->
|
slurp_token_of_type(bytes, Pos, SrcStr) ->
|
||||||
case sfc_strmatch:match(sfc_strmatch:smr_sf_bytes(), SrcStr) of
|
case gsc_strmatch:match(gsc_strmatch:smr_sf_bytes(), SrcStr) of
|
||||||
no_strmatch ->
|
no_strmatch ->
|
||||||
no_tokmatch;
|
no_tokmatch;
|
||||||
{strmatch, TokenStr, Rest} ->
|
{strmatch, TokenStr, Rest} ->
|
||||||
Token = #sfc_token{type = bytes, pos = Pos, string = TokenStr},
|
Token = #tk{type = bytes, pos = Pos, string = TokenStr},
|
||||||
{tokmatch, Token, Rest}
|
{tokmatch, Token, Rest}
|
||||||
end;
|
end;
|
||||||
slurp_token_of_type(NyiType, Pos, SrcStr) ->
|
slurp_token_of_type(NyiType, Pos, SrcStr) ->
|
||||||
Message = io_lib:format("cannot slurp token of type: ~p", [NyiType]),
|
Message = io_lib:format("cannot slurp token of type: ~p", [NyiType]),
|
||||||
error(#sfc_err{atom = nyi,
|
error(#gsc_err{atom = nyi,
|
||||||
string = Message,
|
string = Message,
|
||||||
extra = [{token_type, NyiType},
|
extra = [{token_type, NyiType},
|
||||||
{pos, Pos},
|
{pos, Pos},
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
% @doc compatibility layer to test against so_scan
|
% @doc compatibility layer to test against so_scan
|
||||||
%
|
%
|
||||||
% converts sfc_tokens data to so_scan tokens
|
% converts gsc_tokens data to so_scan tokens
|
||||||
%
|
%
|
||||||
% Ref: so_scan.erl
|
% Ref: so_scan.erl
|
||||||
-module(sfc_so_scan).
|
-module(gso_scan).
|
||||||
|
|
||||||
-export_type([
|
-export_type([
|
||||||
so_kwd/0,
|
so_kwd/0,
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
ken_barson_rises/2
|
ken_barson_rises/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-include("$sfc_include/sfc.hrl").
|
-include("$gsc_include/gsc.hrl").
|
||||||
|
|
||||||
%================================
|
%================================
|
||||||
% API: types
|
% API: types
|
||||||
@@ -76,14 +76,14 @@
|
|||||||
-type so_symbol() :: so_kwd() | so_special_char() | atom().
|
-type so_symbol() :: so_kwd() | so_special_char() | atom().
|
||||||
|
|
||||||
-type so_token2() :: {Symbol :: so_symbol(),
|
-type so_token2() :: {Symbol :: so_symbol(),
|
||||||
Location :: sfc_pos()}.
|
Location :: gsc_pos()}.
|
||||||
|
|
||||||
% FIXME
|
% FIXME
|
||||||
% this is 'id', 'con', qid
|
% this is 'id', 'con', qid
|
||||||
-type so_tk3type() :: char | string | hex | int | bytes | qid | qcon | tvar | id | con.
|
-type so_tk3type() :: char | string | hex | int | bytes | qid | qcon | tvar | id | con.
|
||||||
|
|
||||||
-type so_token3() :: {TokenType :: so_tk3type(),
|
-type so_token3() :: {TokenType :: so_tk3type(),
|
||||||
Location :: sfc_pos(),
|
Location :: gsc_pos(),
|
||||||
TokenValue :: term()}.
|
TokenValue :: term()}.
|
||||||
|
|
||||||
-type so_token() :: so_token2() | so_token3().
|
-type so_token() :: so_token2() | so_token3().
|
||||||
@@ -93,23 +93,23 @@
|
|||||||
% API: functions
|
% API: functions
|
||||||
%================================
|
%================================
|
||||||
|
|
||||||
-spec scan(SrcStr) -> {ok, SoTokens} | {error, sfc_err()}
|
-spec scan(SrcStr) -> {ok, SoTokens} | {error, gsc_err()}
|
||||||
when SrcStr :: iolist(),
|
when SrcStr :: iolist(),
|
||||||
SoTokens :: [so_token()].
|
SoTokens :: [so_token()].
|
||||||
% @doc
|
% @doc
|
||||||
% this is meant to agree with so_scan:scan/1 in all cases
|
% this is meant to agree with so_scan:scan/1 in all cases
|
||||||
%
|
%
|
||||||
% this converts sfc's internal representation of tokens into the format that
|
% this converts gsc's internal representation of tokens into the format that
|
||||||
% so_scan outputs
|
% so_scan outputs
|
||||||
% @end
|
% @end
|
||||||
|
|
||||||
scan(SrcStr) ->
|
scan(SrcStr) ->
|
||||||
case sfc_tokens:tokens(SrcStr) of
|
case gsc_tokens:tokens(SrcStr) of
|
||||||
{ok, SfLTokens} ->
|
{ok, SfLTokens} ->
|
||||||
SoTokens = to_so_tokens(SfLTokens),
|
SoTokens = to_so_tokens(SfLTokens),
|
||||||
{ok, SoTokens};
|
{ok, SoTokens};
|
||||||
% fucking stupid
|
% fucking stupid
|
||||||
{error, #sfc_err_bcom_unterminated{prev_tokens = SfcTokens}} ->
|
{error, #gsc_err_bcom_unterminated{prev_tokens = SfcTokens}} ->
|
||||||
{ok, to_so_tokens(SfcTokens)};
|
{ok, to_so_tokens(SfcTokens)};
|
||||||
Error ->
|
Error ->
|
||||||
Error
|
Error
|
||||||
@@ -118,11 +118,11 @@ scan(SrcStr) ->
|
|||||||
|
|
||||||
|
|
||||||
-spec to_so_tokens(SfcTokens) -> SoTokens
|
-spec to_so_tokens(SfcTokens) -> SoTokens
|
||||||
when SfcTokens :: [sfc_token()],
|
when SfcTokens :: [tk()],
|
||||||
SoTokens :: [so_token()].
|
SoTokens :: [so_token()].
|
||||||
|
|
||||||
% @doc
|
% @doc
|
||||||
% most sfc tokens map 1-to-1 with so_tokens. the
|
% most gsc tokens map 1-to-1 with so_tokens. the
|
||||||
% exception is ak/ct/sg literals. this is a
|
% exception is ak/ct/sg literals. this is a
|
||||||
% many-to-one-mapping, and therefore ak, sg, ct need to
|
% many-to-one-mapping, and therefore ak, sg, ct need to
|
||||||
% be handled at the list level.
|
% be handled at the list level.
|
||||||
@@ -133,7 +133,7 @@ scan(SrcStr) ->
|
|||||||
% stage computes the pubkey that corresponds to.
|
% stage computes the pubkey that corresponds to.
|
||||||
%
|
%
|
||||||
% as a result, if we have ak_GHI, I is not a valid
|
% as a result, if we have ak_GHI, I is not a valid
|
||||||
% base58 char, so WE (sfc) end up lexing that as
|
% base58 char, so WE (gsc) end up lexing that as
|
||||||
%
|
%
|
||||||
% [{ak, "ak_GH"}, {con, "I"}]
|
% [{ak, "ak_GH"}, {con, "I"}]
|
||||||
%
|
%
|
||||||
@@ -151,12 +151,12 @@ scan(SrcStr) ->
|
|||||||
%
|
%
|
||||||
% so if we see an ak/ct/sg token, we summon evil ben
|
% so if we see an ak/ct/sg token, we summon evil ben
|
||||||
% carson to reconjoin the unconjoined twins
|
% carson to reconjoin the unconjoined twins
|
||||||
to_so_tokens([ AkTok = #sfc_token{type = AkCtSg, pos = Pos}
|
to_so_tokens([ AkTok = #tk{type = AkCtSg, pos = Pos}
|
||||||
| Sheeit])
|
| Sheeit])
|
||||||
when ak =:= AkCtSg;
|
when ak =:= AkCtSg;
|
||||||
ct =:= AkCtSg;
|
ct =:= AkCtSg;
|
||||||
sg =:= AkCtSg ->
|
sg =:= AkCtSg ->
|
||||||
{#sfc_token{string = FinalAkStr}, NewSheeit}
|
{#tk{string = FinalAkStr}, NewSheeit}
|
||||||
= ken_barson_rises(AkTok, Sheeit),
|
= ken_barson_rises(AkTok, Sheeit),
|
||||||
[{id, Pos, FinalAkStr}| to_so_tokens(NewSheeit)];
|
[{id, Pos, FinalAkStr}| to_so_tokens(NewSheeit)];
|
||||||
% this part is just lists:filtermap
|
% this part is just lists:filtermap
|
||||||
@@ -171,8 +171,8 @@ to_so_tokens([]) ->
|
|||||||
|
|
||||||
|
|
||||||
-spec ken_barson_rises(InitApiToken, SfToks) -> {FinalApiToken, NewSfToks}
|
-spec ken_barson_rises(InitApiToken, SfToks) -> {FinalApiToken, NewSfToks}
|
||||||
when InitApiToken :: sfc_token(),
|
when InitApiToken :: tk(),
|
||||||
SfToks :: [sfc_token()],
|
SfToks :: [tk()],
|
||||||
FinalApiToken :: InitApiToken,
|
FinalApiToken :: InitApiToken,
|
||||||
NewSfToks :: SfToks.
|
NewSfToks :: SfToks.
|
||||||
% @doc
|
% @doc
|
||||||
@@ -252,15 +252,15 @@ to_so_tokens([]) ->
|
|||||||
%
|
%
|
||||||
% When any of these appear AFTER at least one valid
|
% When any of these appear AFTER at least one valid
|
||||||
% base58 char in a `ak_`/`ct_`/`sg_` prefixed
|
% base58 char in a `ak_`/`ct_`/`sg_` prefixed
|
||||||
% identifier, `sfc` splits what `so_scan` sees as one
|
% identifier, `gsc` splits what `so_scan` sees as one
|
||||||
% `id` token into 2+ sfc tokens.
|
% `id` token into 2+ gsc tokens.
|
||||||
%
|
%
|
||||||
% **No split if non-base58 char is immediately after
|
% **No split if non-base58 char is immediately after
|
||||||
% `_`**: `smr_plus` requires >=1 base58 char to
|
% `_`**: `smr_plus` requires >=1 base58 char to
|
||||||
% match; `ak_I`, `ak_0`, `ak__bar` all fall
|
% match; `ak_I`, `ak_0`, `ak__bar` all fall
|
||||||
% through to `id` and both tokenizers agree.
|
% through to `id` and both tokenizers agree.
|
||||||
ken_barson_rises(AkTokAcc = #sfc_token{string = AkStr},
|
ken_barson_rises(AkTokAcc = #tk{string = AkStr},
|
||||||
SrcTokens = [#sfc_token{type = CandidateType,
|
SrcTokens = [#tk{type = CandidateType,
|
||||||
string = CandidateString}
|
string = CandidateString}
|
||||||
| Rest]) ->
|
| Rest]) ->
|
||||||
% candidate:
|
% candidate:
|
||||||
@@ -273,7 +273,7 @@ ken_barson_rises(AkTokAcc = #sfc_token{string = AkStr},
|
|||||||
Smash ->
|
Smash ->
|
||||||
% dig out the token from LcTokApi
|
% dig out the token from LcTokApi
|
||||||
NewAkStr = AkStr ++ CandidateString,
|
NewAkStr = AkStr ++ CandidateString,
|
||||||
NewAkTokAcc = AkTokAcc#sfc_token{string = NewAkStr},
|
NewAkTokAcc = AkTokAcc#tk{string = NewAkStr},
|
||||||
ken_barson_rises(NewAkTokAcc, Rest);
|
ken_barson_rises(NewAkTokAcc, Rest);
|
||||||
Pass ->
|
Pass ->
|
||||||
{AkTokAcc, SrcTokens}
|
{AkTokAcc, SrcTokens}
|
||||||
@@ -310,7 +310,7 @@ pass_types() ->
|
|||||||
|
|
||||||
|
|
||||||
-spec to_so_token(SfcToken) -> MaybeSoToken
|
-spec to_so_token(SfcToken) -> MaybeSoToken
|
||||||
when SfcToken :: sfc_token(),
|
when SfcToken :: tk(),
|
||||||
MaybeSoToken :: {true, SoToken}
|
MaybeSoToken :: {true, SoToken}
|
||||||
| false,
|
| false,
|
||||||
SoToken :: so_token().
|
SoToken :: so_token().
|
||||||
@@ -320,7 +320,7 @@ pass_types() ->
|
|||||||
% follow-on tokens
|
% follow-on tokens
|
||||||
% @end
|
% @end
|
||||||
|
|
||||||
to_so_token(#sfc_token{type = SfTokenType,
|
to_so_token(#tk{type = SfTokenType,
|
||||||
pos = Pos,
|
pos = Pos,
|
||||||
string = SfTokenStr}) ->
|
string = SfTokenStr}) ->
|
||||||
case SfTokenType of
|
case SfTokenType of
|
||||||
@@ -369,8 +369,8 @@ to_so_token(#sfc_token{type = SfTokenType,
|
|||||||
int10 -> {true, {int, Pos, so_parse_int(SfTokenStr)}};
|
int10 -> {true, {int, Pos, so_parse_int(SfTokenStr)}};
|
||||||
bytes -> {true, {bytes, Pos, so_parse_bytes(SfTokenStr)}};
|
bytes -> {true, {bytes, Pos, so_parse_bytes(SfTokenStr)}};
|
||||||
NYI ->
|
NYI ->
|
||||||
Msg = io_lib:format("sfc_so_scan:to_so_token/1: unhandled token shape: ~p", [NYI]),
|
Msg = io_lib:format("gsc_so_scan:to_so_token/1: unhandled token shape: ~p", [NYI]),
|
||||||
error(#sfc_err{atom = nyi,
|
error(#gsc_err{atom = nyi,
|
||||||
string = Msg})
|
string = Msg})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@@ -392,7 +392,7 @@ so_parse_char([$' | Chars]) ->
|
|||||||
case unicode:characters_to_nfc_list(unescape($', Chars, [])) of
|
case unicode:characters_to_nfc_list(unescape($', Chars, [])) of
|
||||||
[Char] -> Char;
|
[Char] -> Char;
|
||||||
_Bad ->
|
_Bad ->
|
||||||
error(#sfc_err{atom = bad_token,
|
error(#gsc_err{atom = bad_token,
|
||||||
string = "Bad character literal: '" ++ Chars})
|
string = "Bad character literal: '" ++ Chars})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@@ -434,7 +434,7 @@ unescape(Delim, [$\\, Code | Chars], Acc) ->
|
|||||||
$r -> Ok($\r);
|
$r -> Ok($\r);
|
||||||
$t -> Ok($\t);
|
$t -> Ok($\t);
|
||||||
$v -> Ok($\v);
|
$v -> Ok($\v);
|
||||||
_ -> error(#sfc_err{atom = bad_escape_char,
|
_ -> error(#gsc_err{atom = bad_escape_char,
|
||||||
string = "Bad control sequence: \\" ++ [Code]}) %% TODO
|
string = "Bad control sequence: \\" ++ [Code]}) %% TODO
|
||||||
end;
|
end;
|
||||||
unescape(Delim, [C | Chars], Acc) ->
|
unescape(Delim, [C | Chars], Acc) ->
|
||||||
Reference in New Issue
Block a user