Current section
Files
Jump to
Current section
Files
src/glance.erl
-module(glance).
-compile([no_auto_import, nowarn_unused_vars]).
-export([precedence/1, module/1]).
-export_type([definition/1, attribute/0, module_/0, external_function/0, function_/0, statement/0, assignment_kind/0, pattern/0, expression/0, clause/0, bit_string_segment_option/1, binary_operator/0, fn_parameter/0, function_parameter/0, assignment_name/0, import/0, constant/0, unqualified_import/0, publicity/0, type_alias/0, custom_type/0, external_type/0, variant/0, field/1, type/0, error/0]).
-type definition(FUS) :: {definition, list(attribute()), FUS}.
-type attribute() :: {attribute, binary(), list(expression())}.
-type module_() :: {module,
list(definition(import())),
list(definition(custom_type())),
list(definition(type_alias())),
list(definition(constant())),
list(definition(external_type())),
list(definition(external_function())),
list(definition(function_()))}.
-type external_function() :: {external_function,
binary(),
publicity(),
list(field(type())),
type(),
binary(),
binary()}.
-type function_() :: {function,
binary(),
publicity(),
list(function_parameter()),
gleam@option:option(type()),
list(statement())}.
-type statement() :: {use, list(pattern()), expression()} |
{assignment,
assignment_kind(),
pattern(),
gleam@option:option(type()),
expression()} |
{expression, expression()}.
-type assignment_kind() :: 'let' | assert.
-type pattern() :: {pattern_int, binary()} |
{pattern_float, binary()} |
{pattern_string, binary()} |
{pattern_discard, binary()} |
{pattern_variable, binary()} |
{pattern_tuple, list(pattern())} |
{pattern_list, list(pattern()), gleam@option:option(pattern())} |
{pattern_assignment, pattern(), binary()} |
{pattern_concatenate, binary(), assignment_name()} |
{pattern_bit_string,
list({pattern(), list(bit_string_segment_option(pattern()))})} |
{pattern_constructor,
gleam@option:option(binary()),
binary(),
list(field(pattern())),
boolean()}.
-type expression() :: panic |
{int, binary()} |
{float, binary()} |
{string, binary()} |
{variable, binary()} |
{negate_int, expression()} |
{negate_bool, expression()} |
{block, list(statement())} |
{todo, gleam@option:option(binary())} |
{tuple, list(expression())} |
{list, list(expression()), gleam@option:option(expression())} |
{fn, list(fn_parameter()), gleam@option:option(type()), list(statement())} |
{record_update,
gleam@option:option(binary()),
binary(),
expression(),
list({binary(), expression()})} |
{field_access, expression(), binary()} |
{call, expression(), list(field(expression()))} |
{tuple_index, expression(), integer()} |
{fn_capture,
expression(),
list(field(expression())),
list(field(expression()))} |
{bit_string,
list({expression(), list(bit_string_segment_option(expression()))})} |
{'case', list(expression()), list(clause())} |
{binary_operator, binary_operator(), expression(), expression()}.
-type clause() :: {clause,
list(list(pattern())),
gleam@option:option(expression()),
expression()}.
-type bit_string_segment_option(FUT) :: binary_option |
int_option |
float_option |
bit_string_option |
utf8_option |
utf16_option |
utf32_option |
utf8_codepoint_option |
utf16_codepoint_option |
utf32_codepoint_option |
signed_option |
unsigned_option |
big_option |
little_option |
native_option |
{size_value_option, FUT} |
{size_option, integer()} |
{unit_option, integer()}.
-type binary_operator() :: 'and' |
'or' |
eq |
not_eq |
lt_int |
lt_eq_int |
lt_float |
lt_eq_float |
gt_eq_int |
gt_int |
gt_eq_float |
gt_float |
pipe |
add_int |
add_float |
sub_int |
sub_float |
mult_int |
mult_float |
div_int |
div_float |
remainder_int |
concatenate.
-type fn_parameter() :: {fn_parameter,
assignment_name(),
gleam@option:option(type())}.
-type function_parameter() :: {function_parameter,
gleam@option:option(binary()),
assignment_name(),
gleam@option:option(type())}.
-type assignment_name() :: {named, binary()} | {discarded, binary()}.
-type import() :: {import,
binary(),
gleam@option:option(binary()),
list(unqualified_import())}.
-type constant() :: {constant,
binary(),
publicity(),
gleam@option:option(type()),
expression()}.
-type unqualified_import() :: {unqualified_import,
binary(),
gleam@option:option(binary())}.
-type publicity() :: public | private.
-type type_alias() :: {type_alias,
binary(),
publicity(),
list(binary()),
type()}.
-type custom_type() :: {custom_type,
binary(),
publicity(),
boolean(),
list(binary()),
list(variant())}.
-type external_type() :: {external_type, binary(), publicity(), list(binary())}.
-type variant() :: {variant, binary(), list(field(type()))}.
-type field(FUU) :: {field, gleam@option:option(binary()), FUU}.
-type type() :: {named_type,
binary(),
gleam@option:option(binary()),
list(type())} |
{tuple_type, list(type())} |
{function_type, list(type()), type()} |
{variable_type, binary()}.
-type error() :: unexpected_end_of_input |
{unexpected_token, glexer@token:token(), glexer:position()}.
-spec precedence(binary_operator()) -> integer().
precedence(Operator) ->
case Operator of
'or' ->
1;
'and' ->
2;
eq ->
3;
not_eq ->
3;
lt_int ->
4;
lt_eq_int ->
4;
lt_float ->
4;
lt_eq_float ->
4;
gt_eq_int ->
4;
gt_int ->
4;
gt_eq_float ->
4;
gt_float ->
4;
concatenate ->
5;
pipe ->
6;
add_int ->
7;
add_float ->
7;
sub_int ->
7;
sub_float ->
7;
mult_int ->
8;
mult_float ->
8;
div_int ->
8;
div_float ->
8;
remainder_int ->
8
end.
-spec is_whitespace(glexer@token:token()) -> boolean().
is_whitespace(Token) ->
case Token of
empty_line ->
true;
comment_normal ->
true;
comment_module ->
true;
{comment_doc, _} ->
true;
_ ->
false
end.
-spec push_variant(custom_type(), variant()) -> custom_type().
push_variant(Custom_type, Variant) ->
erlang:setelement(
6,
Custom_type,
[Variant | erlang:element(6, Custom_type)]
).
-spec expect(
glexer@token:token(),
list({glexer@token:token(), glexer:position()}),
fun((glexer:position(), list({glexer@token:token(), glexer:position()})) -> {ok,
FVE} |
{error, error()})
) -> {ok, FVE} | {error, error()}.
expect(Expected, Tokens, Next) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{Token, Position} | Tokens@1] when Token =:= Expected ->
Next(Position, Tokens@1);
[{Other, Position@1} | _] ->
{error, {unexpected_token, Other, Position@1}}
end.
-spec expect_upper_name(
list({glexer@token:token(), glexer:position()}),
fun((binary(), list({glexer@token:token(), glexer:position()})) -> {ok, FVJ} |
{error, error()})
) -> {ok, FVJ} | {error, error()}.
expect_upper_name(Tokens, Next) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{{upper_name, Name}, _} | Tokens@1] ->
Next(Name, Tokens@1);
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end.
-spec expect_name(
list({glexer@token:token(), glexer:position()}),
fun((binary(), list({glexer@token:token(), glexer:position()})) -> {ok, FVO} |
{error, error()})
) -> {ok, FVO} | {error, error()}.
expect_name(Tokens, Next) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{{name, Name}, _} | Tokens@1] ->
Next(Name, Tokens@1);
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end.
-spec expect_string(
list({glexer@token:token(), glexer:position()}),
fun((binary(), list({glexer@token:token(), glexer:position()})) -> {ok, FVT} |
{error, error()})
) -> {ok, FVT} | {error, error()}.
expect_string(Tokens, Next) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{{string, S}, _} | Tokens@1] ->
Next(S, Tokens@1);
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end.
-spec optional_module_alias(list({glexer@token:token(), glexer:position()})) -> {gleam@option:option(binary()),
list({glexer@token:token(), glexer:position()})}.
optional_module_alias(Tokens) ->
case Tokens of
[{as, _}, {{name, Alias}, _} | Tokens@1] ->
{{some, Alias}, Tokens@1};
_ ->
{none, Tokens}
end.
-spec unexpected_error(list({glexer@token:token(), glexer:position()})) -> {ok,
any()} |
{error, error()}.
unexpected_error(Tokens) ->
case Tokens of
[{Token, Position} | _] ->
{error, {unexpected_token, Token, Position}};
[] ->
{error, unexpected_end_of_input}
end.
-spec binary_operator(glexer@token:token()) -> {ok, binary_operator()} |
{error, nil}.
binary_operator(Token) ->
case Token of
amper_amper ->
{ok, 'and'};
equal_equal ->
{ok, eq};
greater ->
{ok, gt_int};
greater_dot ->
{ok, gt_float};
greater_equal ->
{ok, gt_eq_int};
greater_equal_dot ->
{ok, gt_eq_float};
less ->
{ok, lt_int};
less_dot ->
{ok, lt_float};
less_equal ->
{ok, lt_eq_int};
less_equal_dot ->
{ok, lt_eq_float};
less_greater ->
{ok, concatenate};
minus ->
{ok, sub_int};
minus_dot ->
{ok, sub_float};
not_equal ->
{ok, not_eq};
percent ->
{ok, remainder_int};
v_bar ->
{ok, 'or'};
pipe ->
{ok, pipe};
plus ->
{ok, add_int};
plus_dot ->
{ok, add_float};
slash ->
{ok, div_int};
slash_dot ->
{ok, div_float};
star ->
{ok, mult_int};
star_dot ->
{ok, mult_float};
_ ->
{error, nil}
end.
-spec pop_binary_operator(list({glexer@token:token(), glexer:position()})) -> {ok,
{binary_operator(), list({glexer@token:token(), glexer:position()})}} |
{error, nil}.
pop_binary_operator(Tokens) ->
case Tokens of
[{Token, _} | Tokens@1] ->
gleam@result:map(
binary_operator(Token),
fun(Op) -> {Op, Tokens@1} end
);
[] ->
{error, nil}
end.
-spec name(list({glexer@token:token(), glexer:position()})) -> {ok,
{binary(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
name(Tokens) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{{name, Name}, _} | Tokens@1] ->
{ok, {Name, Tokens@1}};
[{Token, Position} | _] ->
{error, {unexpected_token, Token, Position}}
end.
-spec field(
list({glexer@token:token(), glexer:position()}),
fun((list({glexer@token:token(), glexer:position()})) -> {ok,
{GDT, list({glexer@token:token(), glexer:position()})}} |
{error, error()})
) -> {ok, {field(GDT), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
field(Tokens, Parser) ->
case Tokens of
[{{name, Name}, _}, {colon, _} | Tokens@1] ->
gleam@result:'try'(
Parser(Tokens@1),
fun(_use0) ->
{T, Tokens@2} = _use0,
{ok, {{field, {some, Name}, T}, Tokens@2}}
end
);
_ ->
gleam@result:'try'(
Parser(Tokens),
fun(_use0@1) ->
{T@1, Tokens@3} = _use0@1,
{ok, {{field, none, T@1}, Tokens@3}}
end
)
end.
-spec list(
fun((list({glexer@token:token(), glexer:position()})) -> {ok,
{GBI, list({glexer@token:token(), glexer:position()})}} |
{error, error()}),
gleam@option:option(GBI),
list(GBI),
list({glexer@token:token(), glexer:position()})
) -> {ok,
{list(GBI),
gleam@option:option(GBI),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
list(Parser, Discard, Acc, Tokens) ->
case Tokens of
[{right_square, _} | Tokens@1] ->
{ok, {gleam@list:reverse(Acc), none, Tokens@1}};
[{comma, _}, {right_square, _} | Tokens@2] when Acc =/= [] ->
{ok, {gleam@list:reverse(Acc), none, Tokens@2}};
_ ->
gleam@result:'try'(
Parser(Tokens),
fun(_use0) ->
{Element, Tokens@3} = _use0,
Acc@1 = [Element | Acc],
case Tokens@3 of
[{right_square, _} | Tokens@4] ->
{ok, {gleam@list:reverse(Acc@1), none, Tokens@4}};
[{comma, _}, {right_square, _} | Tokens@4] ->
{ok, {gleam@list:reverse(Acc@1), none, Tokens@4}};
[{comma, _},
{dot_dot, _},
{right_square, _} = Close |
Tokens@5] ->
case Discard of
none ->
unexpected_error([Close | Tokens@5]);
{some, Discard@1} ->
{ok,
{gleam@list:reverse(Acc@1),
{some, Discard@1},
Tokens@5}}
end;
[{comma, _}, {dot_dot, _} | Tokens@6] ->
gleam@result:'try'(
Parser(Tokens@6),
fun(_use0@1) ->
{Rest, Tokens@7} = _use0@1,
expect(
right_square,
Tokens@7,
fun(_, Tokens@8) ->
{ok,
{gleam@list:reverse(Acc@1),
{some, Rest},
Tokens@8}}
end
)
end
);
[{comma, _} | Tokens@9] ->
list(Parser, Discard, Acc@1, Tokens@9);
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}};
[] ->
{error, unexpected_end_of_input}
end
end
)
end.
-spec push_constant(module_(), list(attribute()), constant()) -> module_().
push_constant(Module, Attributes, Constant) ->
erlang:setelement(
5,
Module,
[{definition, gleam@list:reverse(Attributes), Constant} |
erlang:element(5, Module)]
).
-spec push_external_function(module_(), list(attribute()), external_function()) -> module_().
push_external_function(Module, Attributes, External_function) ->
erlang:setelement(
7,
Module,
[{definition, gleam@list:reverse(Attributes), External_function} |
erlang:element(7, Module)]
).
-spec push_function(module_(), list(attribute()), function_()) -> module_().
push_function(Module, Attributes, Function) ->
erlang:setelement(
8,
Module,
[{definition, gleam@list:reverse(Attributes), Function} |
erlang:element(8, Module)]
).
-spec push_external_type(module_(), list(attribute()), external_type()) -> module_().
push_external_type(Module, Attributes, External_type) ->
erlang:setelement(
6,
Module,
[{definition, gleam@list:reverse(Attributes), External_type} |
erlang:element(6, Module)]
).
-spec push_custom_type(module_(), list(attribute()), custom_type()) -> module_().
push_custom_type(Module, Attributes, Custom_type) ->
Custom_type@1 = erlang:setelement(
6,
Custom_type,
gleam@list:reverse(erlang:element(6, Custom_type))
),
erlang:setelement(
3,
Module,
[{definition, gleam@list:reverse(Attributes), Custom_type@1} |
erlang:element(3, Module)]
).
-spec push_type_alias(module_(), list(attribute()), type_alias()) -> module_().
push_type_alias(Module, Attributes, Type_alias) ->
erlang:setelement(
4,
Module,
[{definition, gleam@list:reverse(Attributes), Type_alias} |
erlang:element(4, Module)]
).
-spec slurp(
module_(),
list(attribute()),
list({glexer@token:token(), glexer:position()})
) -> {ok, module_()} | {error, error()}.
slurp(Module, Attributes, Tokens) ->
case Tokens of
[{at, _} | Tokens@1] ->
gleam@result:'try'(
attribute(Tokens@1),
fun(_use0) ->
{Attribute, Tokens@2} = _use0,
slurp(Module, [Attribute | Attributes], Tokens@2)
end
);
[{import, _} | Tokens@3] ->
Result = import_statement(Module, Attributes, Tokens@3),
gleam@result:'try'(
Result,
fun(_use0@1) ->
{Module@1, Tokens@4} = _use0@1,
slurp(Module@1, [], Tokens@4)
end
);
[{pub, _}, {type, _} | Tokens@5] ->
Result@1 = type_definition(
Module,
Attributes,
public,
false,
Tokens@5
),
gleam@result:'try'(
Result@1,
fun(_use0@2) ->
{Module@2, Tokens@6} = _use0@2,
slurp(Module@2, [], Tokens@6)
end
);
[{pub, _}, {opaque, _}, {type, _} | Tokens@7] ->
Result@2 = type_definition(
Module,
Attributes,
public,
true,
Tokens@7
),
gleam@result:'try'(
Result@2,
fun(_use0@3) ->
{Module@3, Tokens@8} = _use0@3,
slurp(Module@3, [], Tokens@8)
end
);
[{type, _} | Tokens@9] ->
Result@3 = type_definition(
Module,
Attributes,
private,
false,
Tokens@9
),
gleam@result:'try'(
Result@3,
fun(_use0@4) ->
{Module@4, Tokens@10} = _use0@4,
slurp(Module@4, [], Tokens@10)
end
);
[{pub, _}, {const, _} | Tokens@11] ->
Result@4 = const_definition(Module, Attributes, public, Tokens@11),
gleam@result:'try'(
Result@4,
fun(_use0@5) ->
{Module@5, Tokens@12} = _use0@5,
slurp(Module@5, [], Tokens@12)
end
);
[{const, _} | Tokens@13] ->
Result@5 = const_definition(Module, Attributes, private, Tokens@13),
gleam@result:'try'(
Result@5,
fun(_use0@6) ->
{Module@6, Tokens@14} = _use0@6,
slurp(Module@6, [], Tokens@14)
end
);
[{pub, _}, {external, _}, {fn, _} | Tokens@15] ->
Result@6 = external_fn_definition(
Module,
Attributes,
public,
Tokens@15
),
gleam@result:'try'(
Result@6,
fun(_use0@7) ->
{Module@7, Tokens@16} = _use0@7,
slurp(Module@7, [], Tokens@16)
end
);
[{external, _}, {fn, _} | Tokens@17] ->
Result@7 = external_fn_definition(
Module,
Attributes,
private,
Tokens@17
),
gleam@result:'try'(
Result@7,
fun(_use0@8) ->
{Module@8, Tokens@18} = _use0@8,
slurp(Module@8, [], Tokens@18)
end
);
[{pub, _}, {fn, _}, {{name, Name}, _} | Tokens@19] ->
Result@8 = function_definition(
Module,
Attributes,
public,
Name,
Tokens@19
),
gleam@result:'try'(
Result@8,
fun(_use0@9) ->
{Module@9, Tokens@20} = _use0@9,
slurp(Module@9, [], Tokens@20)
end
);
[{fn, _}, {{name, Name@1}, _} | Tokens@21] ->
Result@9 = function_definition(
Module,
Attributes,
private,
Name@1,
Tokens@21
),
gleam@result:'try'(
Result@9,
fun(_use0@10) ->
{Module@10, Tokens@22} = _use0@10,
slurp(Module@10, [], Tokens@22)
end
);
[{pub, _}, {external, _}, {type, _} | Tokens@23] ->
Result@10 = external_type_definition(
Module,
Attributes,
public,
Tokens@23
),
gleam@result:'try'(
Result@10,
fun(_use0@11) ->
{Module@11, Tokens@24} = _use0@11,
slurp(Module@11, [], Tokens@24)
end
);
[{external, _}, {type, _} | Tokens@25] ->
Result@11 = external_type_definition(
Module,
Attributes,
private,
Tokens@25
),
gleam@result:'try'(
Result@11,
fun(_use0@12) ->
{Module@12, Tokens@26} = _use0@12,
slurp(Module@12, [], Tokens@26)
end
);
[] ->
{ok, Module};
Tokens@27 ->
unexpected_error(Tokens@27)
end.
-spec module(binary()) -> {ok, module_()} | {error, error()}.
module(Src) ->
_pipe = glexer:new(Src),
_pipe@1 = glexer:lex(_pipe),
_pipe@2 = gleam@list:filter(
_pipe@1,
fun(Pair) -> not is_whitespace(erlang:element(1, Pair)) end
),
slurp({module, [], [], [], [], [], [], []}, [], _pipe@2).
-spec until(
glexer@token:token(),
FVY,
list({glexer@token:token(), glexer:position()}),
fun((FVY, list({glexer@token:token(), glexer:position()})) -> {ok,
{FVY, list({glexer@token:token(), glexer:position()})}} |
{error, error()})
) -> {ok, {FVY, list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
until(Limit, Acc, Tokens, Callback) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{Token, _} | Tokens@1] when Token =:= Limit ->
{ok, {Acc, Tokens@1}};
[_ | _] ->
case Callback(Acc, Tokens) of
{ok, {Acc@1, Tokens@2}} ->
until(Limit, Acc@1, Tokens@2, Callback);
{error, Error} ->
{error, Error}
end
end.
-spec comma_delimited(
list(GCH),
list({glexer@token:token(), glexer:position()}),
fun((list({glexer@token:token(), glexer:position()})) -> {ok,
{GCH, list({glexer@token:token(), glexer:position()})}} |
{error, error()}),
glexer@token:token()
) -> {ok, {list(GCH), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
comma_delimited(Items, Tokens, Parser, Final) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{Token, _} | Tokens@1] when Token =:= Final ->
{ok, {gleam@list:reverse(Items), Tokens@1}};
_ ->
gleam@result:'try'(
Parser(Tokens),
fun(_use0) ->
{Element, Tokens@2} = _use0,
case Tokens@2 of
[{comma, _} | Tokens@3] ->
comma_delimited(
[Element | Items],
Tokens@3,
Parser,
Final
);
[{Token@1, _} | Tokens@4] when Token@1 =:= Final ->
{ok,
{gleam@list:reverse([Element | Items]),
Tokens@4}};
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end
end
)
end.
-spec optional_type_parameters(list({glexer@token:token(), glexer:position()})) -> {ok,
{list(binary()), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
optional_type_parameters(Tokens) ->
case Tokens of
[{left_paren, _} | Tokens@1] ->
comma_delimited([], Tokens@1, fun name/1, right_paren);
_ ->
{ok, {[], Tokens}}
end.
-spec external_type_definition(
module_(),
list(attribute()),
publicity(),
list({glexer@token:token(), glexer:position()})
) -> {ok, {module_(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
external_type_definition(Module, Attributes, Publicity, Tokens) ->
expect_upper_name(
Tokens,
fun(Name, Tokens@1) ->
gleam@result:'try'(
optional_type_parameters(Tokens@1),
fun(_use0) ->
{Parameters, Tokens@2} = _use0,
External_type = {external_type, Name, Publicity, Parameters},
Module@1 = push_external_type(
Module,
Attributes,
External_type
),
{ok, {Module@1, Tokens@2}}
end
)
end
).
-spec expression_loop(
list({glexer@token:token(), glexer:position()}),
list(binary_operator()),
list(expression())
) -> {ok, {expression(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
expression_loop(Tokens, Operators, Values) ->
gleam@result:'try'(
expression_unit(Tokens),
fun(_use0) ->
{Expression, Tokens@1} = _use0,
case Expression of
none ->
unexpected_error(Tokens@1);
{some, E} ->
Values@1 = [E | Values],
case pop_binary_operator(Tokens@1) of
{ok, {Operator, Tokens@2}} ->
case handle_operator(
{some, Operator},
Operators,
Values@1
) of
{{some, Expression@1}, _, _} ->
{ok, {Expression@1, Tokens@2}};
{none, Operators@1, Values@2} ->
expression_loop(
Tokens@2,
Operators@1,
Values@2
)
end;
_ ->
case erlang:element(
1,
handle_operator(none, Operators, Values@1)
) of
none ->
unexpected_error(Tokens@1);
{some, Expression@2} ->
{ok, {Expression@2, Tokens@1}}
end
end
end
end
).
-spec expression(list({glexer@token:token(), glexer:position()})) -> {ok,
{expression(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
expression(Tokens) ->
expression_loop(Tokens, [], []).
-spec attribute(list({glexer@token:token(), glexer:position()})) -> {ok,
{attribute(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
attribute(Tokens) ->
expect_name(
Tokens,
fun(Name, Tokens@1) ->
expect(
left_paren,
Tokens@1,
fun(_, Tokens@2) ->
Result = comma_delimited(
[],
Tokens@2,
fun expression/1,
right_paren
),
gleam@result:'try'(
Result,
fun(_use0) ->
{Parameters, Tokens@3} = _use0,
{ok, {{attribute, Name, Parameters}, Tokens@3}}
end
)
end
)
end
).
-spec record_update_field(list({glexer@token:token(), glexer:position()})) -> {ok,
{{binary(), expression()},
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
record_update_field(Tokens) ->
case Tokens of
[{{name, Name}, _}, {colon, _} | Tokens@1] ->
gleam@result:'try'(
expression(Tokens@1),
fun(_use0) ->
{Expression, Tokens@2} = _use0,
{ok, {{Name, Expression}, Tokens@2}}
end
);
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}};
[] ->
{error, unexpected_end_of_input}
end.
-spec record_update(
gleam@option:option(binary()),
binary(),
list({glexer@token:token(), glexer:position()})
) -> {ok,
{gleam@option:option(expression()),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
record_update(Module, Constructor, Tokens) ->
gleam@result:'try'(
expression(Tokens),
fun(_use0) ->
{Record, Tokens@1} = _use0,
case Tokens@1 of
[{right_paren, _} | Tokens@2] ->
{ok,
{{some,
{record_update, Module, Constructor, Record, []}},
Tokens@2}};
[{comma, _} | Tokens@3] ->
Result = comma_delimited(
[],
Tokens@3,
fun record_update_field/1,
right_paren
),
gleam@result:'try'(
Result,
fun(_use0@1) ->
{Fields, Tokens@4} = _use0@1,
{ok,
{{some,
{record_update,
Module,
Constructor,
Record,
Fields}},
Tokens@4}}
end
);
_ ->
{ok, {none, Tokens@1}}
end
end
).
-spec optional_clause_guard(list({glexer@token:token(), glexer:position()})) -> {ok,
{gleam@option:option(expression()),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
optional_clause_guard(Tokens) ->
case Tokens of
[{'if', _} | Tokens@1] ->
gleam@result:'try'(
expression(Tokens@1),
fun(_use0) ->
{Expression, Tokens@2} = _use0,
{ok, {{some, Expression}, Tokens@2}}
end
);
_ ->
{ok, {none, Tokens}}
end.
-spec module_name(binary(), list({glexer@token:token(), glexer:position()})) -> {ok,
{binary(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
module_name(Name, Tokens) ->
case Tokens of
[{slash, _}, {{name, S}, _} | Tokens@1] when Name =/= <<""/utf8>> ->
module_name(
<<<<Name/binary, "/"/utf8>>/binary, S/binary>>,
Tokens@1
);
[{{name, S@1}, _} | Tokens@2] when Name =:= <<""/utf8>> ->
module_name(S@1, Tokens@2);
[] when Name =:= <<""/utf8>> ->
{error, unexpected_end_of_input};
[{Other, Position} | _] when Name =:= <<""/utf8>> ->
{error, {unexpected_token, Other, Position}};
_ ->
{ok, {Name, Tokens}}
end.
-spec unqualified_imports(
list(unqualified_import()),
list({glexer@token:token(), glexer:position()})
) -> {ok,
{list(unqualified_import()),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
unqualified_imports(Items, Tokens) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{right_brace, _} | Tokens@1] ->
{ok, {gleam@list:reverse(Items), Tokens@1}};
[{{upper_name, Name}, _},
{as, _},
{{upper_name, Alias}, _},
{comma, _} |
Tokens@2] ->
Import_ = {unqualified_import, Name, {some, Alias}},
unqualified_imports([Import_ | Items], Tokens@2);
[{{name, Name}, _}, {as, _}, {{name, Alias}, _}, {comma, _} | Tokens@2] ->
Import_ = {unqualified_import, Name, {some, Alias}},
unqualified_imports([Import_ | Items], Tokens@2);
[{{upper_name, Name@1}, _},
{as, _},
{{upper_name, Alias@1}, _},
{right_brace, _} |
Tokens@3] ->
Import_@1 = {unqualified_import, Name@1, {some, Alias@1}},
{ok, {gleam@list:reverse([Import_@1 | Items]), Tokens@3}};
[{{name, Name@1}, _},
{as, _},
{{name, Alias@1}, _},
{right_brace, _} |
Tokens@3] ->
Import_@1 = {unqualified_import, Name@1, {some, Alias@1}},
{ok, {gleam@list:reverse([Import_@1 | Items]), Tokens@3}};
[{{upper_name, Name@2}, _}, {comma, _} | Tokens@4] ->
Import_@2 = {unqualified_import, Name@2, none},
unqualified_imports([Import_@2 | Items], Tokens@4);
[{{name, Name@2}, _}, {comma, _} | Tokens@4] ->
Import_@2 = {unqualified_import, Name@2, none},
unqualified_imports([Import_@2 | Items], Tokens@4);
[{{upper_name, Name@3}, _}, {right_brace, _} | Tokens@5] ->
Import_@3 = {unqualified_import, Name@3, none},
{ok, {gleam@list:reverse([Import_@3 | Items]), Tokens@5}};
[{{name, Name@3}, _}, {right_brace, _} | Tokens@5] ->
Import_@3 = {unqualified_import, Name@3, none},
{ok, {gleam@list:reverse([Import_@3 | Items]), Tokens@5}};
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end.
-spec optional_unqualified_imports(
list({glexer@token:token(), glexer:position()})
) -> {ok,
{list(unqualified_import()),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
optional_unqualified_imports(Tokens) ->
case Tokens of
[{dot, _}, {left_brace, _} | Tokens@1] ->
unqualified_imports([], Tokens@1);
_ ->
{ok, {[], Tokens}}
end.
-spec import_statement(
module_(),
list(attribute()),
list({glexer@token:token(), glexer:position()})
) -> {ok, {module_(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
import_statement(Module, Attributes, Tokens) ->
gleam@result:'try'(
module_name(<<""/utf8>>, Tokens),
fun(_use0) ->
{Module_name, Tokens@1} = _use0,
gleam@result:'try'(
optional_unqualified_imports(Tokens@1),
fun(_use0@1) ->
{Unqualified, Tokens@2} = _use0@1,
{Alias, Tokens@3} = optional_module_alias(Tokens@2),
Import_ = {import, Module_name, Alias, Unqualified},
Definition = {definition,
gleam@list:reverse(Attributes),
Import_},
Module@1 = erlang:setelement(
2,
Module,
[Definition | erlang:element(2, Module)]
),
{ok, {Module@1, Tokens@3}}
end
)
end
).
-spec statements(
list(statement()),
list({glexer@token:token(), glexer:position()})
) -> {ok, {list(statement()), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
statements(Acc, Tokens) ->
case Tokens of
[{right_brace, _} | Tokens@1] ->
{ok, {gleam@list:reverse(Acc), Tokens@1}};
_ ->
gleam@result:'try'(
statement(Tokens),
fun(_use0) ->
{Statement, Tokens@2} = _use0,
statements([Statement | Acc], Tokens@2)
end
)
end.
-spec pattern(list({glexer@token:token(), glexer:position()})) -> {ok,
{pattern(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
pattern(Tokens) ->
gleam@result:'try'(case Tokens of
[{{upper_name, Name}, _} | Tokens@1] ->
pattern_constructor(none, Name, Tokens@1);
[{{name, Module}, _},
{dot, _},
{{upper_name, Name@1}, _} |
Tokens@2] ->
pattern_constructor({some, Module}, Name@1, Tokens@2);
[{{string, V}, _}, {less_greater, _}, {{name, N}, _} | Tokens@3] ->
{ok, {{pattern_concatenate, V, {named, N}}, Tokens@3}};
[{{string, V@1}, _},
{less_greater, _},
{{discard_name, N@1}, _} |
Tokens@4] ->
{ok, {{pattern_concatenate, V@1, {discarded, N@1}}, Tokens@4}};
[{{int, Value}, _} | Tokens@5] ->
{ok, {{pattern_int, Value}, Tokens@5}};
[{{float, Value@1}, _} | Tokens@6] ->
{ok, {{pattern_float, Value@1}, Tokens@6}};
[{{string, Value@2}, _} | Tokens@7] ->
{ok, {{pattern_string, Value@2}, Tokens@7}};
[{{discard_name, Name@2}, _} | Tokens@8] ->
{ok, {{pattern_discard, Name@2}, Tokens@8}};
[{{name, Name@3}, _} | Tokens@9] ->
{ok, {{pattern_variable, Name@3}, Tokens@9}};
[{left_square, _} | Tokens@10] ->
Result = list(
fun pattern/1,
{some, {pattern_discard, <<""/utf8>>}},
[],
Tokens@10
),
gleam@result:map(
Result,
fun(_use0) ->
{Elements, Rest, Tokens@11} = _use0,
{{pattern_list, Elements, Rest}, Tokens@11}
end
);
[{hash, _}, {left_paren, _} | Tokens@12] ->
Result@1 = comma_delimited(
[],
Tokens@12,
fun pattern/1,
right_paren
),
gleam@result:'try'(
Result@1,
fun(_use0@1) ->
{Patterns, Tokens@13} = _use0@1,
{ok, {{pattern_tuple, Patterns}, Tokens@13}}
end
);
[{less_less, _} | Tokens@14] ->
Parser = fun(_capture) ->
bit_string_segment(fun pattern/1, _capture)
end,
Result@2 = comma_delimited(
[],
Tokens@14,
Parser,
greater_greater
),
gleam@result:'try'(
Result@2,
fun(_use0@2) ->
{Segments, Tokens@15} = _use0@2,
{ok, {{pattern_bit_string, Segments}, Tokens@15}}
end
);
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}};
[] ->
{error, unexpected_end_of_input}
end, fun(_use0@3) ->
{Pattern, Tokens@16} = _use0@3,
case Tokens@16 of
[{as, _}, {{name, Name@4}, _} | Tokens@17] ->
{ok, {{pattern_assignment, Pattern, Name@4}, Tokens@17}};
_ ->
{ok, {Pattern, Tokens@16}}
end
end).
-spec delimited(
list(GAY),
list({glexer@token:token(), glexer:position()}),
fun((list({glexer@token:token(), glexer:position()})) -> {ok,
{GAY, list({glexer@token:token(), glexer:position()})}} |
{error, error()}),
glexer@token:token()
) -> {ok, {list(GAY), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
delimited(Acc, Tokens, Parser, Delimeter) ->
gleam@result:'try'(
Parser(Tokens),
fun(_use0) ->
{T, Tokens@1} = _use0,
Acc@1 = [T | Acc],
case Tokens@1 of
[{Token, _} | Tokens@2] when Token =:= Delimeter ->
delimited(Acc@1, Tokens@2, Parser, Delimeter);
_ ->
{ok, {gleam@list:reverse(Acc@1), Tokens@1}}
end
end
).
-spec use_(list({glexer@token:token(), glexer:position()})) -> {ok,
{statement(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
use_(Tokens) ->
gleam@result:'try'(
delimited([], Tokens, fun pattern/1, comma),
fun(_use0) ->
{Patterns, Tokens@1} = _use0,
expect(
left_arrow,
Tokens@1,
fun(_, Tokens@2) ->
gleam@result:'try'(
expression(Tokens@2),
fun(_use0@1) ->
{Function, Tokens@3} = _use0@1,
{ok, {{use, Patterns, Function}, Tokens@3}}
end
)
end
)
end
).
-spec case_clause(list({glexer@token:token(), glexer:position()})) -> {ok,
{clause(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
case_clause(Tokens) ->
Multipatterns = fun(_capture) ->
delimited([], _capture, fun pattern/1, comma)
end,
Result = delimited([], Tokens, Multipatterns, v_bar),
gleam@result:'try'(
Result,
fun(_use0) ->
{Patterns, Tokens@1} = _use0,
gleam@result:'try'(
optional_clause_guard(Tokens@1),
fun(_use0@1) ->
{Guard, Tokens@2} = _use0@1,
expect(
right_arrow,
Tokens@2,
fun(_, Tokens@3) ->
gleam@result:map(
expression(Tokens@3),
fun(_use0@2) ->
{Expression, Tokens@4} = _use0@2,
{{clause, Patterns, Guard, Expression},
Tokens@4}
end
)
end
)
end
)
end
).
-spec pattern_constructor_arguments(
list(field(pattern())),
list({glexer@token:token(), glexer:position()})
) -> {ok,
{list(field(pattern())),
boolean(),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
pattern_constructor_arguments(Arguments, Tokens) ->
case Tokens of
[{right_paren, _} | Tokens@1] ->
{ok, {Arguments, false, Tokens@1}};
[{dot_dot, _}, {right_paren, _} | Tokens@2] ->
{ok, {Arguments, true, Tokens@2}};
Tokens@3 ->
gleam@result:'try'(
field(Tokens@3, fun pattern/1),
fun(_use0) ->
{Pattern, Tokens@4} = _use0,
Arguments@1 = [Pattern | Arguments],
case Tokens@4 of
[{right_paren, _} | Tokens@5] ->
{ok, {Arguments@1, false, Tokens@5}};
[{comma, _}, {dot_dot, _}, {right_paren, _} | Tokens@6] ->
{ok, {Arguments@1, true, Tokens@6}};
[{comma, _} | Tokens@7] ->
pattern_constructor_arguments(Arguments@1, Tokens@7);
[{Token, Position} | _] ->
{error, {unexpected_token, Token, Position}};
[] ->
{error, unexpected_end_of_input}
end
end
)
end.
-spec pattern_constructor(
gleam@option:option(binary()),
binary(),
list({glexer@token:token(), glexer:position()})
) -> {ok, {pattern(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
pattern_constructor(Module, Constructor, Tokens) ->
case Tokens of
[{left_paren, _} | Tokens@1] ->
Result = pattern_constructor_arguments([], Tokens@1),
gleam@result:'try'(
Result,
fun(_use0) ->
{Patterns, Spread, Tokens@2} = _use0,
Arguments = gleam@list:reverse(Patterns),
Pattern = {pattern_constructor,
Module,
Constructor,
Arguments,
Spread},
{ok, {Pattern, Tokens@2}}
end
);
_ ->
Pattern@1 = {pattern_constructor, Module, Constructor, [], false},
{ok, {Pattern@1, Tokens}}
end.
-spec handle_operator(
gleam@option:option(binary_operator()),
list(binary_operator()),
list(expression())
) -> {gleam@option:option(expression()),
list(binary_operator()),
list(expression())}.
handle_operator(Next, Operators, Values) ->
case {Next, Operators, Values} of
{{some, Operator}, [], _} ->
{none, [Operator | Operators], Values};
{{some, Next@1}, [Previous | Operators@1], [A, B | Rest_values]} ->
case precedence(Previous) >= precedence(Next@1) of
true ->
Values@1 = [{binary_operator, Previous, B, A} | Rest_values],
handle_operator({some, Next@1}, Operators@1, Values@1);
false ->
{none, [Next@1, Previous | Operators@1], Values}
end;
{none, [Operator@1 | Operators@2], [A@1, B@1 | Values@2]} ->
Values@3 = [{binary_operator, Operator@1, B@1, A@1} | Values@2],
handle_operator(none, Operators@2, Values@3);
{none, [], [Expression]} ->
{{some, Expression}, Operators, Values};
{none, [], []} ->
{none, Operators, Values};
{none, [], _} ->
erlang:error(#{gleam_error => panic,
message => <<"panic expression evaluated"/utf8>>,
module => <<"glance"/utf8>>,
function => <<"handle_operator"/utf8>>,
line => 955})
end.
-spec case_subjects(
list(expression()),
list({glexer@token:token(), glexer:position()})
) -> {ok, {list(expression()), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
case_subjects(Subjects, Tokens) ->
gleam@result:'try'(
expression(Tokens),
fun(_use0) ->
{Subject, Tokens@1} = _use0,
Subjects@1 = [Subject | Subjects],
case Tokens@1 of
[{comma, _} | Tokens@2] ->
case_subjects(Subjects@1, Tokens@2);
_ ->
{ok, {gleam@list:reverse(Subjects@1), Tokens@1}}
end
end
).
-spec case_clauses(
list(clause()),
list({glexer@token:token(), glexer:position()})
) -> {ok, {list(clause()), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
case_clauses(Clauses, Tokens) ->
gleam@result:'try'(
case_clause(Tokens),
fun(_use0) ->
{Clause, Tokens@1} = _use0,
Clauses@1 = [Clause | Clauses],
case Tokens@1 of
[{right_brace, _} | Tokens@2] ->
{ok, {gleam@list:reverse(Clauses@1), Tokens@2}};
_ ->
case_clauses(Clauses@1, Tokens@1)
end
end
).
-spec case_(list({glexer@token:token(), glexer:position()})) -> {ok,
{gleam@option:option(expression()),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
case_(Tokens) ->
gleam@result:'try'(
case_subjects([], Tokens),
fun(_use0) ->
{Subjects, Tokens@1} = _use0,
expect(
left_brace,
Tokens@1,
fun(_, Tokens@2) ->
gleam@result:'try'(
case_clauses([], Tokens@2),
fun(_use0@1) ->
{Clauses, Tokens@3} = _use0@1,
{ok,
{{some, {'case', Subjects, Clauses}}, Tokens@3}}
end
)
end
)
end
).
-spec bit_string_segment_options(
fun((list({glexer@token:token(), glexer:position()})) -> {ok,
{FZH, list({glexer@token:token(), glexer:position()})}} |
{error, error()}),
list(bit_string_segment_option(FZH)),
list({glexer@token:token(), glexer:position()})
) -> {ok,
{list(bit_string_segment_option(FZH)),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
bit_string_segment_options(Parser, Options, Tokens) ->
gleam@result:'try'(case Tokens of
[{{int, I}, Position} | Tokens@1] ->
case gleam@int:parse(I) of
{ok, I@1} ->
{ok, {{size_option, I@1}, Tokens@1}};
{error, _} ->
{error, {unexpected_token, {int, I}, Position}}
end;
[{{name, <<"size"/utf8>>}, _}, {left_paren, _} | Tokens@2] ->
gleam@result:'try'(
Parser(Tokens@2),
fun(_use0) ->
{Value, Tokens@3} = _use0,
expect(
right_paren,
Tokens@3,
fun(_, Tokens@4) ->
{ok, {{size_value_option, Value}, Tokens@4}}
end
)
end
);
[{{name, <<"unit"/utf8>>}, Position@1},
{left_paren, _},
{{int, I@2}, _},
{right_paren, _} |
Tokens@5] ->
case gleam@int:parse(I@2) of
{ok, I@3} ->
{ok, {{unit_option, I@3}, Tokens@5}};
{error, _} ->
{error, {unexpected_token, {int, I@2}, Position@1}}
end;
[{{name, <<"binary"/utf8>>}, _} | Tokens@6] ->
{ok, {binary_option, Tokens@6}};
[{{name, <<"int"/utf8>>}, _} | Tokens@7] ->
{ok, {int_option, Tokens@7}};
[{{name, <<"float"/utf8>>}, _} | Tokens@8] ->
{ok, {float_option, Tokens@8}};
[{{name, <<"bit_string"/utf8>>}, _} | Tokens@9] ->
{ok, {bit_string_option, Tokens@9}};
[{{name, <<"utf8"/utf8>>}, _} | Tokens@10] ->
{ok, {utf8_option, Tokens@10}};
[{{name, <<"utf16"/utf8>>}, _} | Tokens@11] ->
{ok, {utf16_option, Tokens@11}};
[{{name, <<"utf32"/utf8>>}, _} | Tokens@12] ->
{ok, {utf32_option, Tokens@12}};
[{{name, <<"utf8_codepoint"/utf8>>}, _} | Tokens@13] ->
{ok, {utf8_codepoint_option, Tokens@13}};
[{{name, <<"utf16_codepoint"/utf8>>}, _} | Tokens@14] ->
{ok, {utf16_codepoint_option, Tokens@14}};
[{{name, <<"utf32_codepoint"/utf8>>}, _} | Tokens@15] ->
{ok, {utf32_codepoint_option, Tokens@15}};
[{{name, <<"signed"/utf8>>}, _} | Tokens@16] ->
{ok, {signed_option, Tokens@16}};
[{{name, <<"unsigned"/utf8>>}, _} | Tokens@17] ->
{ok, {unsigned_option, Tokens@17}};
[{{name, <<"big"/utf8>>}, _} | Tokens@18] ->
{ok, {big_option, Tokens@18}};
[{{name, <<"little"/utf8>>}, _} | Tokens@19] ->
{ok, {little_option, Tokens@19}};
[{{name, <<"native"/utf8>>}, _} | Tokens@20] ->
{ok, {native_option, Tokens@20}};
[{Other, Position@2} | _] ->
{error, {unexpected_token, Other, Position@2}};
[] ->
{error, unexpected_end_of_input}
end, fun(_use0@1) ->
{Option, Tokens@21} = _use0@1,
Options@1 = [Option | Options],
case Tokens@21 of
[{minus, _} | Tokens@22] ->
bit_string_segment_options(Parser, Options@1, Tokens@22);
_ ->
{ok, {gleam@list:reverse(Options@1), Tokens@21}}
end
end).
-spec optional_bit_string_segment_options(
fun((list({glexer@token:token(), glexer:position()})) -> {ok,
{FZA, list({glexer@token:token(), glexer:position()})}} |
{error, error()}),
list({glexer@token:token(), glexer:position()})
) -> {ok,
{list(bit_string_segment_option(FZA)),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
optional_bit_string_segment_options(Parser, Tokens) ->
case Tokens of
[{colon, _} | Tokens@1] ->
bit_string_segment_options(Parser, [], Tokens@1);
_ ->
{ok, {[], Tokens}}
end.
-spec bit_string_segment(
fun((list({glexer@token:token(), glexer:position()})) -> {ok,
{FYT, list({glexer@token:token(), glexer:position()})}} |
{error, error()}),
list({glexer@token:token(), glexer:position()})
) -> {ok,
{{FYT, list(bit_string_segment_option(FYT))},
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
bit_string_segment(Parser, Tokens) ->
gleam@result:'try'(
Parser(Tokens),
fun(_use0) ->
{Value, Tokens@1} = _use0,
Result = optional_bit_string_segment_options(Parser, Tokens@1),
gleam@result:'try'(
Result,
fun(_use0@1) ->
{Options, Tokens@2} = _use0@1,
{ok, {{Value, Options}, Tokens@2}}
end
)
end
).
-spec after_expression(
expression(),
list({glexer@token:token(), glexer:position()})
) -> {ok, {expression(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
after_expression(Parsed, Tokens) ->
case Tokens of
[{dot, _}, {{name, Label}, _} | Tokens@1] ->
after_expression({field_access, Parsed, Label}, Tokens@1);
[{dot, _}, {{upper_name, Label}, _} | Tokens@1] ->
after_expression({field_access, Parsed, Label}, Tokens@1);
[{dot, _}, {{int, Value} = Token, Position} | Tokens@2] ->
case gleam@int:parse(Value) of
{ok, I} ->
after_expression({tuple_index, Parsed, I}, Tokens@2);
{error, _} ->
{error, {unexpected_token, Token, Position}}
end;
[{left_paren, _} | Tokens@3] ->
call([], Parsed, Tokens@3);
_ ->
{ok, {Parsed, Tokens}}
end.
-spec call(
list(field(expression())),
expression(),
list({glexer@token:token(), glexer:position()})
) -> {ok, {expression(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
call(Arguments, Function, Tokens) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{right_paren, _} | Tokens@1] ->
Call = {call, Function, gleam@list:reverse(Arguments)},
after_expression(Call, Tokens@1);
[{{discard_name, <<""/utf8>>}, _},
{comma, _},
{right_paren, _} |
Tokens@2] ->
Capture = {fn_capture, Function, gleam@list:reverse(Arguments), []},
after_expression(Capture, Tokens@2);
[{{discard_name, <<""/utf8>>}, _}, {right_paren, _} | Tokens@2] ->
Capture = {fn_capture, Function, gleam@list:reverse(Arguments), []},
after_expression(Capture, Tokens@2);
[{{discard_name, <<""/utf8>>}, _}, {comma, _} | Tokens@3] ->
fn_capture(Function, gleam@list:reverse(Arguments), [], Tokens@3);
[{{discard_name, <<""/utf8>>}, _} | Tokens@3] ->
fn_capture(Function, gleam@list:reverse(Arguments), [], Tokens@3);
_ ->
gleam@result:'try'(
field(Tokens, fun expression/1),
fun(_use0) ->
{Argument, Tokens@4} = _use0,
Arguments@1 = [Argument | Arguments],
case Tokens@4 of
[{comma, _} | Tokens@5] ->
call(Arguments@1, Function, Tokens@5);
[{right_paren, _} | Tokens@6] ->
Call@1 = {call,
Function,
gleam@list:reverse(Arguments@1)},
after_expression(Call@1, Tokens@6);
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end
end
)
end.
-spec fn_capture(
expression(),
list(field(expression())),
list(field(expression())),
list({glexer@token:token(), glexer:position()})
) -> {ok, {expression(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
fn_capture(Function, Before, After, Tokens) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{right_paren, _} | Tokens@1] ->
Capture = {fn_capture, Function, Before, gleam@list:reverse(After)},
after_expression(Capture, Tokens@1);
_ ->
gleam@result:'try'(
field(Tokens, fun expression/1),
fun(_use0) ->
{Argument, Tokens@2} = _use0,
After@1 = [Argument | After],
case Tokens@2 of
[{comma, _} | Tokens@3] ->
fn_capture(Function, Before, After@1, Tokens@3);
[{right_paren, _} | Tokens@4] ->
Call = {fn_capture,
Function,
Before,
gleam@list:reverse(After@1)},
after_expression(Call, Tokens@4);
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}}
end
end
)
end.
-spec named_type(
binary(),
gleam@option:option(binary()),
list({glexer@token:token(), glexer:position()})
) -> {ok, {type(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
named_type(Name, Module, Tokens) ->
gleam@result:'try'(case Tokens of
[{left_paren, _} | Tokens@1] ->
comma_delimited([], Tokens@1, fun type_/1, right_paren);
_ ->
{ok, {[], Tokens}}
end, fun(_use0) ->
{Parameters, Tokens@2} = _use0,
T = {named_type, Name, Module, Parameters},
{ok, {T, Tokens@2}}
end).
-spec type_(list({glexer@token:token(), glexer:position()})) -> {ok,
{type(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
type_(Tokens) ->
case Tokens of
[] ->
{error, unexpected_end_of_input};
[{fn, _}, {left_paren, _} | Tokens@1] ->
fn_type(Tokens@1);
[{hash, _}, {left_paren, _} | Tokens@2] ->
tuple_type(Tokens@2);
[{{name, Module}, _}, {dot, _}, {{upper_name, Name}, _} | Tokens@3] ->
named_type(Name, {some, Module}, Tokens@3);
[{{upper_name, Name@1}, _} | Tokens@4] ->
named_type(Name@1, none, Tokens@4);
[{{name, Name@2}, _} | Tokens@5] ->
{ok, {{variable_type, Name@2}, Tokens@5}};
[{Token, Position} | _] ->
{error, {unexpected_token, Token, Position}}
end.
-spec optional_return_annotation(
list({glexer@token:token(), glexer:position()})
) -> {ok,
{gleam@option:option(type()),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
optional_return_annotation(Tokens) ->
case Tokens of
[{right_arrow, _} | Tokens@1] ->
gleam@result:'try'(
type_(Tokens@1),
fun(_use0) ->
{Return_type, Tokens@2} = _use0,
{ok, {{some, Return_type}, Tokens@2}}
end
);
_ ->
{ok, {none, Tokens}}
end.
-spec external_fn_definition(
module_(),
list(attribute()),
publicity(),
list({glexer@token:token(), glexer:position()})
) -> {ok, {module_(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
external_fn_definition(Module, Attributes, Publicity, Tokens) ->
expect_name(
Tokens,
fun(Name, Tokens@1) ->
expect(
left_paren,
Tokens@1,
fun(_, Tokens@2) ->
Parser = fun(_capture) -> field(_capture, fun type_/1) end,
Result = comma_delimited([], Tokens@2, Parser, right_paren),
gleam@result:'try'(
Result,
fun(_use0) ->
{Parameters, Tokens@3} = _use0,
expect(
right_arrow,
Tokens@3,
fun(_, Tokens@4) ->
gleam@result:'try'(
type_(Tokens@4),
fun(_use0@1) ->
{Return_type, Tokens@5} = _use0@1,
expect(
equal,
Tokens@5,
fun(_, Tokens@6) ->
expect_string(
Tokens@6,
fun(Mod, Tokens@7) ->
expect_string(
Tokens@7,
fun(F, Tokens@8) ->
Extern = {external_function,
Name,
Publicity,
Parameters,
Return_type,
Mod,
F},
Module@1 = push_external_function(
Module,
Attributes,
Extern
),
{ok,
{Module@1,
Tokens@8}}
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-spec optional_type_annotation(list({glexer@token:token(), glexer:position()})) -> {ok,
{gleam@option:option(type()),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
optional_type_annotation(Tokens) ->
case Tokens of
[{colon, _} | Tokens@1] ->
gleam@result:map(
type_(Tokens@1),
fun(_use0) ->
{Annotation, Tokens@2} = _use0,
{{some, Annotation}, Tokens@2}
end
);
_ ->
{ok, {none, Tokens}}
end.
-spec assignment(
assignment_kind(),
list({glexer@token:token(), glexer:position()})
) -> {ok, {statement(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
assignment(Kind, Tokens) ->
gleam@result:'try'(
pattern(Tokens),
fun(_use0) ->
{Pattern, Tokens@1} = _use0,
expect(
equal,
Tokens@1,
fun(_, Tokens@2) ->
gleam@result:'try'(
optional_type_annotation(Tokens@2),
fun(_use0@1) ->
{Annotation, Tokens@3} = _use0@1,
gleam@result:'try'(
expression(Tokens@3),
fun(_use0@2) ->
{Expression, Tokens@4} = _use0@2,
Statement = {assignment,
Kind,
Pattern,
Annotation,
Expression},
{ok, {Statement, Tokens@4}}
end
)
end
)
end
)
end
).
-spec statement(list({glexer@token:token(), glexer:position()})) -> {ok,
{statement(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
statement(Tokens) ->
case Tokens of
[{'let', _}, {assert, _} | Tokens@1] ->
assignment(assert, Tokens@1);
[{'let', _} | Tokens@2] ->
assignment('let', Tokens@2);
[{use, _} | Tokens@3] ->
use_(Tokens@3);
Tokens@4 ->
gleam@result:'try'(
expression(Tokens@4),
fun(_use0) ->
{Expression, Tokens@5} = _use0,
{ok, {{expression, Expression}, Tokens@5}}
end
)
end.
-spec fn_parameter(list({glexer@token:token(), glexer:position()})) -> {ok,
{fn_parameter(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
fn_parameter(Tokens) ->
gleam@result:'try'(case Tokens of
[{{name, Name}, _} | Tokens@1] ->
{ok, {{named, Name}, Tokens@1}};
[{{discard_name, Name@1}, _} | Tokens@2] ->
{ok, {{discarded, Name@1}, Tokens@2}};
[{Other, Position} | _] ->
{error, {unexpected_token, Other, Position}};
[] ->
{error, unexpected_end_of_input}
end, fun(_use0) ->
{Name@2, Tokens@3} = _use0,
gleam@result:'try'(
optional_type_annotation(Tokens@3),
fun(_use0@1) ->
{Type_, Tokens@4} = _use0@1,
{ok, {{fn_parameter, Name@2, Type_}, Tokens@4}}
end
)
end).
-spec fn_(list({glexer@token:token(), glexer:position()})) -> {ok,
{gleam@option:option(expression()),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
fn_(Tokens) ->
expect(
left_paren,
Tokens,
fun(_, Tokens@1) ->
Result = comma_delimited(
[],
Tokens@1,
fun fn_parameter/1,
right_paren
),
gleam@result:'try'(
Result,
fun(_use0) ->
{Parameters, Tokens@2} = _use0,
gleam@result:'try'(
optional_return_annotation(Tokens@2),
fun(_use0@1) ->
{Return, Tokens@3} = _use0@1,
expect(
left_brace,
Tokens@3,
fun(_, Tokens@4) ->
gleam@result:'try'(
statements([], Tokens@4),
fun(_use0@2) ->
{Body, Tokens@5} = _use0@2,
{ok,
{{some,
{fn,
Parameters,
Return,
Body}},
Tokens@5}}
end
)
end
)
end
)
end
)
end
).
-spec expression_unit(list({glexer@token:token(), glexer:position()})) -> {ok,
{gleam@option:option(expression()),
list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
expression_unit(Tokens) ->
gleam@result:'try'(case Tokens of
[{{name, Module}, _},
{dot, _},
{{upper_name, Constructor}, _},
{left_paren, _},
{dot_dot, _} |
Tokens@1] ->
record_update({some, Module}, Constructor, Tokens@1);
[{{upper_name, Constructor@1}, _},
{left_paren, _},
{dot_dot, _} |
Tokens@2] ->
record_update(none, Constructor@1, Tokens@2);
[{{upper_name, Name}, _} | Tokens@3] ->
{ok, {{some, {variable, Name}}, Tokens@3}};
[{panic, _} | Tokens@4] ->
{ok, {{some, panic}, Tokens@4}};
[{{int, Value}, _} | Tokens@5] ->
{ok, {{some, {int, Value}}, Tokens@5}};
[{{float, Value@1}, _} | Tokens@6] ->
{ok, {{some, {float, Value@1}}, Tokens@6}};
[{{string, Value@2}, _} | Tokens@7] ->
{ok, {{some, {string, Value@2}}, Tokens@7}};
[{{name, Name@1}, _} | Tokens@8] ->
{ok, {{some, {variable, Name@1}}, Tokens@8}};
[{fn, _} | Tokens@9] ->
fn_(Tokens@9);
[{'case', _} | Tokens@10] ->
case_(Tokens@10);
[{todo, _},
{left_paren, _},
{{string, Value@3}, _},
{right_paren, _} |
Tokens@11] ->
{ok, {{some, {todo, {some, Value@3}}}, Tokens@11}};
[{todo, _} | Tokens@12] ->
{ok, {{some, {todo, none}}, Tokens@12}};
[{left_square, _} | Tokens@13] ->
Result = list(fun expression/1, none, [], Tokens@13),
gleam@result:map(
Result,
fun(_use0) ->
{Elements, Rest, Tokens@14} = _use0,
{{some, {list, Elements, Rest}}, Tokens@14}
end
);
[{hash, _}, {left_paren, _} | Tokens@15] ->
Result@1 = comma_delimited(
[],
Tokens@15,
fun expression/1,
right_paren
),
gleam@result:map(
Result@1,
fun(_use0@1) ->
{Expressions, Tokens@16} = _use0@1,
{{some, {tuple, Expressions}}, Tokens@16}
end
);
[{bang, _} | Tokens@17] ->
gleam@result:map(
expression(Tokens@17),
fun(_use0@2) ->
{Expression, Tokens@18} = _use0@2,
{{some, {negate_bool, Expression}}, Tokens@18}
end
);
[{minus, _} | Tokens@19] ->
gleam@result:map(
expression(Tokens@19),
fun(_use0@3) ->
{Expression@1, Tokens@20} = _use0@3,
{{some, {negate_int, Expression@1}}, Tokens@20}
end
);
[{left_brace, _} | Tokens@21] ->
gleam@result:map(
statements([], Tokens@21),
fun(_use0@4) ->
{Statements, Tokens@22} = _use0@4,
{{some, {block, Statements}}, Tokens@22}
end
);
[{less_less, _} | Tokens@23] ->
Parser = fun(_capture) ->
bit_string_segment(fun expression/1, _capture)
end,
Result@2 = comma_delimited(
[],
Tokens@23,
Parser,
greater_greater
),
gleam@result:map(
Result@2,
fun(_use0@5) ->
{Segments, Tokens@24} = _use0@5,
{{some, {bit_string, Segments}}, Tokens@24}
end
);
_ ->
{ok, {none, Tokens}}
end, fun(_use0@6) ->
{Parsed, Tokens@25} = _use0@6,
case Parsed of
{some, Expression@2} ->
case after_expression(Expression@2, Tokens@25) of
{ok, {Expression@3, Tokens@26}} ->
{ok, {{some, Expression@3}, Tokens@26}};
{error, Error} ->
{error, Error}
end;
none ->
{ok, {none, Tokens@25}}
end
end).
-spec function_parameter(list({glexer@token:token(), glexer:position()})) -> {ok,
{function_parameter(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
function_parameter(Tokens) ->
gleam@result:'try'(case Tokens of
[] ->
{error, unexpected_end_of_input};
[{{name, Label}, _}, {{discard_name, Name}, _} | Tokens@1] ->
{ok, {{some, Label}, {discarded, Name}, Tokens@1}};
[{{discard_name, Name@1}, _} | Tokens@2] ->
{ok, {none, {discarded, Name@1}, Tokens@2}};
[{{name, Label@1}, _}, {{name, Name@2}, _} | Tokens@3] ->
{ok, {{some, Label@1}, {named, Name@2}, Tokens@3}};
[{{name, Name@3}, _} | Tokens@4] ->
{ok, {none, {named, Name@3}, Tokens@4}};
[{Token, Position} | _] ->
{error, {unexpected_token, Token, Position}}
end, fun(_use0) ->
{Label@2, Parameter, Tokens@5} = _use0,
gleam@result:'try'(
optional_type_annotation(Tokens@5),
fun(_use0@1) ->
{Type_, Tokens@6} = _use0@1,
{ok,
{{function_parameter, Label@2, Parameter, Type_},
Tokens@6}}
end
)
end).
-spec function_definition(
module_(),
list(attribute()),
publicity(),
binary(),
list({glexer@token:token(), glexer:position()})
) -> {ok, {module_(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
function_definition(Module, Attributes, Publicity, Name, Tokens) ->
expect(
left_paren,
Tokens,
fun(_, Tokens@1) ->
Result = comma_delimited(
[],
Tokens@1,
fun function_parameter/1,
right_paren
),
gleam@result:'try'(
Result,
fun(_use0) ->
{Parameters, Tokens@2} = _use0,
gleam@result:'try'(
optional_return_annotation(Tokens@2),
fun(_use0@1) ->
{Return_type, Tokens@3} = _use0@1,
expect(
left_brace,
Tokens@3,
fun(_, Tokens@4) ->
gleam@result:'try'(
statements([], Tokens@4),
fun(_use0@2) ->
{Statements, Tokens@5} = _use0@2,
Function = {function,
Name,
Publicity,
Parameters,
Return_type,
Statements},
Module@1 = push_function(
Module,
Attributes,
Function
),
{ok, {Module@1, Tokens@5}}
end
)
end
)
end
)
end
)
end
).
-spec const_definition(
module_(),
list(attribute()),
publicity(),
list({glexer@token:token(), glexer:position()})
) -> {ok, {module_(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
const_definition(Module, Attributes, Publicity, Tokens) ->
expect_name(
Tokens,
fun(Name, Tokens@1) ->
gleam@result:'try'(
optional_type_annotation(Tokens@1),
fun(_use0) ->
{Annotation, Tokens@2} = _use0,
expect(
equal,
Tokens@2,
fun(_, Tokens@3) ->
gleam@result:'try'(
expression(Tokens@3),
fun(_use0@1) ->
{Expression, Tokens@4} = _use0@1,
Constant = {constant,
Name,
Publicity,
Annotation,
Expression},
Module@1 = push_constant(
Module,
Attributes,
Constant
),
{ok, {Module@1, Tokens@4}}
end
)
end
)
end
)
end
).
-spec type_alias(
module_(),
list(attribute()),
binary(),
list(binary()),
publicity(),
list({glexer@token:token(), glexer:position()})
) -> {ok, {module_(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
type_alias(Module, Attributes, Name, Parameters, Publicity, Tokens) ->
gleam@result:'try'(
type_(Tokens),
fun(_use0) ->
{Type_, Tokens@1} = _use0,
Alias = {type_alias, Name, Publicity, Parameters, Type_},
Module@1 = push_type_alias(Module, Attributes, Alias),
{ok, {Module@1, Tokens@1}}
end
).
-spec fn_type(list({glexer@token:token(), glexer:position()})) -> {ok,
{type(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
fn_type(Tokens) ->
Result = comma_delimited([], Tokens, fun type_/1, right_paren),
gleam@result:'try'(
Result,
fun(_use0) ->
{Parameters, Tokens@1} = _use0,
expect(
right_arrow,
Tokens@1,
fun(_, Tokens@2) ->
gleam@result:'try'(
type_(Tokens@2),
fun(_use0@1) ->
{Return, Tokens@3} = _use0@1,
{ok,
{{function_type, Parameters, Return}, Tokens@3}}
end
)
end
)
end
).
-spec tuple_type(list({glexer@token:token(), glexer:position()})) -> {ok,
{type(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
tuple_type(Tokens) ->
Result = comma_delimited([], Tokens, fun type_/1, right_paren),
gleam@result:'try'(
Result,
fun(_use0) ->
{Types, Tokens@1} = _use0,
{ok, {{tuple_type, Types}, Tokens@1}}
end
).
-spec optional_variant_fields(list({glexer@token:token(), glexer:position()})) -> {ok,
{list(field(type())), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
optional_variant_fields(Tokens) ->
case Tokens of
[{left_paren, _}, {right_paren, _} | Tokens@1] ->
{ok, {[], Tokens@1}};
[{left_paren, _} | Tokens@2] ->
comma_delimited(
[],
Tokens@2,
fun(_capture) -> field(_capture, fun type_/1) end,
right_paren
);
_ ->
{ok, {[], Tokens}}
end.
-spec variants(custom_type(), list({glexer@token:token(), glexer:position()})) -> {ok,
{custom_type(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
variants(Ct, Tokens) ->
until(
right_brace,
Ct,
Tokens,
fun(Ct@1, Tokens@1) ->
expect_upper_name(
Tokens@1,
fun(Name, Tokens@2) ->
gleam@result:'try'(
optional_variant_fields(Tokens@2),
fun(_use0) ->
{Parameters, Tokens@3} = _use0,
Ct@2 = push_variant(
Ct@1,
{variant, Name, Parameters}
),
{ok, {Ct@2, Tokens@3}}
end
)
end
)
end
).
-spec custom_type(
module_(),
list(attribute()),
binary(),
list(binary()),
publicity(),
boolean(),
list({glexer@token:token(), glexer:position()})
) -> {ok, {module_(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
custom_type(Module, Attributes, Name, Parameters, Publicity, Opaque_, Tokens) ->
Ct = {custom_type, Name, Publicity, Opaque_, Parameters, []},
gleam@result:'try'(
variants(Ct, Tokens),
fun(_use0) ->
{Ct@1, Tokens@1} = _use0,
Module@1 = push_custom_type(Module, Attributes, Ct@1),
{ok, {Module@1, Tokens@1}}
end
).
-spec type_definition(
module_(),
list(attribute()),
publicity(),
boolean(),
list({glexer@token:token(), glexer:position()})
) -> {ok, {module_(), list({glexer@token:token(), glexer:position()})}} |
{error, error()}.
type_definition(Module, Attributes, Publicity, Opaque_, Tokens) ->
expect_upper_name(
Tokens,
fun(Name, Tokens@1) ->
gleam@result:'try'(
optional_type_parameters(Tokens@1),
fun(_use0) ->
{Parameters, Tokens@2} = _use0,
case Tokens@2 of
[] ->
{error, unexpected_end_of_input};
[{equal, _} | Tokens@3] ->
type_alias(
Module,
Attributes,
Name,
Parameters,
Publicity,
Tokens@3
);
[{left_brace, _} | Tokens@4] ->
_pipe = Module,
custom_type(
_pipe,
Attributes,
Name,
Parameters,
Publicity,
Opaque_,
Tokens@4
)
end
end
)
end
).