-module(prequel@internals@parser). -compile([no_auto_import, nowarn_unused_vars]). -export([parse/1]). -spec 'try'( {ok, {HYR, list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}, fun((HYR, list({prequel@internals@token:token(), prequel@span:span()})) -> {ok, {HYU, list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}) ) -> {ok, {HYU, list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. 'try'(Result, Do) -> case Result of {ok, {A, Tokens}} -> Do(A, Tokens); {error, Error} -> {error, Error} end. -spec fail(prequel@error@parse_error:parse_error()) -> {ok, {any(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. fail(Error) -> {error, Error}. -spec succeed(HYZ, list({prequel@internals@token:token(), prequel@span:span()})) -> {ok, {HYZ, list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. succeed(Result, Tokens) -> {ok, {Result, Tokens}}. -spec totality_from_string(binary()) -> {ok, prequel@ast:totality()} | {error, nil}. totality_from_string(String) -> case String of <<"total"/utf8>> -> {ok, total}; <<"partial"/utf8>> -> {ok, partial}; _ -> {error, nil} end. -spec overlapping_from_string(binary()) -> {ok, prequel@ast:overlapping()} | {error, nil}. overlapping_from_string(String) -> case String of <<"overlapped"/utf8>> -> {ok, overlapped}; <<"disjoint"/utf8>> -> {ok, disjoint}; _ -> {error, nil} end. -spec parse_attribute_type( list({prequel@internals@token:token(), prequel@span:span()}) ) -> {ok, {prequel@ast:type(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_attribute_type(Tokens) -> _pipe = no_type, succeed(_pipe, Tokens). -spec parse_number(binary(), prequel@span:span(), prequel@span:span()) -> {ok, integer()} | {error, prequel@error@parse_error:parse_error()}. parse_number(Raw_number, Raw_number_span, Enclosing_span) -> _pipe = gleam@int:parse(Raw_number), gleam@result:replace_error( _pipe, {internal_error, {some, <<"TODO: add hint"/utf8>>}, {some, Enclosing_span}, Raw_number_span, <<"This was assumed to be a number"/utf8>>} ). -spec parse_cardinality( list({prequel@internals@token:token(), prequel@span:span()}), boolean(), prequel@span:span(), prequel@span:span() ) -> {ok, {prequel@ast:cardinality(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_cardinality(Tokens, Lenient, Enclosing_span, Preceding_span) -> case Tokens of [{open_parens, Start}, {{number, Raw_lower}, Raw_lower_span}, {minus, _}, {{number, Raw_upper}, Raw_upper_span}, {close_parens, End} | Tokens@1] -> Result = parse_number(Raw_lower, Raw_lower_span, Enclosing_span), gleam@result:'try'( Result, fun(Lower) -> Result@1 = parse_number( Raw_upper, Raw_upper_span, Enclosing_span ), gleam@result:'try'( Result@1, fun(Upper) -> _pipe = {bounded, prequel@span:merge(Start, End), Lower, Upper}, succeed(_pipe, Tokens@1) end ) end ); [{open_parens, Start@1}, {{number, Raw_lower@1}, Raw_lower_span@1}, {minus, _}, {{word, <<"N"/utf8>>}, _}, {close_parens, End@1} | Tokens@2] -> Result@2 = parse_number( Raw_lower@1, Raw_lower_span@1, Enclosing_span ), gleam@result:'try'( Result@2, fun(Lower@1) -> _pipe@1 = {unbounded, prequel@span:merge(Start@1, End@1), Lower@1}, succeed(_pipe@1, Tokens@2) end ); [{open_parens, _}, {{number, _}, _}, {minus, _}, {{word, _}, Span}, {close_parens, _} | _] -> _pipe@2 = {wrong_letter_in_unbounded_cardinality, {some, <<"TODO: add hint"/utf8>>}, Enclosing_span, Span}, fail(_pipe@2); [{open_parens, Start@2}, {{number, _}, _}, {minus, _}, {{number, _}, End@2} | _] -> _pipe@3 = {incomplete_cardinality, {some, <<"TODO: add hint"/utf8>>}, Enclosing_span, prequel@span:merge(Start@2, End@2), <<"a closed parentheses"/utf8>>}, fail(_pipe@3); [{open_parens, Start@2}, {{number, _}, _}, {minus, _}, {{word, _}, End@2} | _] -> _pipe@3 = {incomplete_cardinality, {some, <<"TODO: add hint"/utf8>>}, Enclosing_span, prequel@span:merge(Start@2, End@2), <<"a closed parentheses"/utf8>>}, fail(_pipe@3); [{open_parens, Start@3}, {{number, _}, _}, {minus, End@3} | _] -> _pipe@4 = {incomplete_cardinality, {some, <<"TODO: add hint"/utf8>>}, Enclosing_span, prequel@span:merge(Start@3, End@3), <<"an upper bound"/utf8>>}, fail(_pipe@4); [{open_parens, Start@4}, {{number, _}, End@4} | _] -> _pipe@5 = {incomplete_cardinality, {some, <<"TODO: add hint"/utf8>>}, Enclosing_span, prequel@span:merge(Start@4, End@4), <<"an upper bound"/utf8>>}, fail(_pipe@5); [{open_parens, Span@1} | _] -> _pipe@6 = {incomplete_cardinality, {some, <<"TODO: add hint"/utf8>>}, Enclosing_span, Span@1, <<"a lower bound"/utf8>>}, fail(_pipe@6); [{{number, _}, Span@2} | _] -> _pipe@7 = {incomplete_cardinality, {some, <<"TODO: add hint"/utf8>>}, Enclosing_span, Span@2, <<"an open parentheses"/utf8>>}, fail(_pipe@7); [_ | _] when Lenient -> _pipe@8 = {bounded, Preceding_span, 1, 1}, succeed(_pipe@8, Tokens); [{Token, Span@3} | _] -> _pipe@9 = {wrong_cardinality_annotation, {some, <<"TODO: add hint"/utf8>>}, Enclosing_span, Preceding_span, prequel@internals@token:to_string(Token), Span@3}, fail(_pipe@9); [] -> _pipe@10 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, {some, Enclosing_span}, Preceding_span, <<"the cardinality of this element"/utf8>>}, fail(_pipe@10) end. -spec parse_attribute( list({prequel@internals@token:token(), prequel@span:span()}), prequel@span:span(), prequel@span:span() ) -> {ok, {prequel@ast:attribute(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_attribute(Tokens, Enclosing_span, Lollipop_span) -> case Tokens of [{{word, Name}, Name_span}, {colon, Colon_span} | Tokens@1] -> 'try'( parse_attribute_type(Tokens@1), fun(Type_, Tokens@2) -> 'try'( parse_cardinality( Tokens@2, Type_ /= no_type, Enclosing_span, Colon_span ), fun(Cardinality, Tokens@3) -> _pipe = {attribute, Name_span, Name, Cardinality, Type_}, succeed(_pipe, Tokens@3) end ) end ); [{{word, Name@1}, Name_span@1} | Tokens@4] -> _pipe@1 = {attribute, Name_span@1, Name@1, {bounded, Name_span@1, 1, 1}, no_type}, succeed(_pipe@1, Tokens@4); [{Token, Span} | _] -> _pipe@2 = {wrong_attribute_name, {some, <<"TODO: add hint"/utf8>>}, Enclosing_span, Lollipop_span, prequel@internals@token:to_string(Token), Span}, fail(_pipe@2); [] -> _pipe@3 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, {some, Enclosing_span}, Lollipop_span, <<"this attribute"/utf8>>}, fail(_pipe@3) end. -spec parse_multi_attribute_key( list({prequel@internals@token:token(), prequel@span:span()}), prequel@span:span(), prequel@span:span(), prequel@span:span(), prequel@span:span(), list(binary()) ) -> {ok, {prequel@ast:key(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_multi_attribute_key( Tokens, Entity_span, Lollipop_span, Last_ampersand_span, First_word_span, Keys ) -> case Tokens of [{{word, Key}, _}, {ampersand, Last_ampersand_span@1} | Tokens@1] -> parse_multi_attribute_key( Tokens@1, Entity_span, Lollipop_span, Last_ampersand_span@1, First_word_span, [Key | Keys] ); [{{word, _}, Last_word_span}, {colon, Colon_span} | _] -> _pipe = {type_annotation_on_composed_key, {some, <<"TODO: add hint"/utf8>>}, Entity_span, prequel@span:merge(First_word_span, Last_word_span), Colon_span}, fail(_pipe); [{{word, Key@1}, Last_word_span@1} | Tokens@2] -> _pipe@1 = prequel@span:merge(First_word_span, Last_word_span@1), _pipe@2 = {composed_key, _pipe@1, non_empty_list:reverse(non_empty_list:new(Key@1, Keys))}, succeed(_pipe@2, Tokens@2); [{Token, Span} | _] -> _pipe@3 = {incomplete_composed_key, {some, <<"TODO: add hint"/utf8>>}, prequel@span:merge(Lollipop_span, Last_ampersand_span), Entity_span, prequel@internals@token:to_string(Token), Span}, fail(_pipe@3); [] -> _pipe@4 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Lollipop_span, <<"this key"/utf8>>}, fail(_pipe@4) end. -spec do_parse_key( list({prequel@internals@token:token(), prequel@span:span()}), prequel@span:span(), prequel@span:span() ) -> {ok, {prequel@ast:key(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. do_parse_key(Tokens, Entity_span, Lollipop_span) -> case Tokens of [{{word, Key}, First_word_span}, {ampersand, Last_ampersand_span} | Tokens@1] -> 'try'( parse_multi_attribute_key( Tokens@1, Entity_span, Lollipop_span, Last_ampersand_span, First_word_span, [Key] ), fun(Key@1, Tokens@2) -> succeed(Key@1, Tokens@2) end ); [{{word, Key@2}, Span}, {colon, _} | Tokens@3] -> 'try'( parse_attribute_type(Tokens@3), fun(Type_, Tokens@4) -> succeed({single_key, Span, Key@2, {some, Type_}}, Tokens@4) end ); [{{word, Key@3}, Span@1} | Tokens@5] -> succeed({single_key, Span@1, Key@3, none}, Tokens@5); [{Token, Span@2} | _] -> _pipe = {wrong_key_name, {some, <<"TODO: add hint"/utf8>>}, Entity_span, Lollipop_span, prequel@internals@token:to_string(Token), Span@2}, fail(_pipe); [] -> _pipe@1 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Lollipop_span, <<"this key"/utf8>>}, fail(_pipe@1) end. -spec parse_key( list({prequel@internals@token:token(), prequel@span:span()}), prequel@span:span(), prequel@span:span() ) -> {ok, {prequel@ast:key(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_key(Tokens, Entity_span, Lollipop_span) -> do_parse_key(Tokens, Entity_span, Lollipop_span). -spec do_parse_inner_relationship_body( list({prequel@internals@token:token(), prequel@span:span()}), prequel@span:span(), prequel@span:span(), list(prequel@ast:attribute()) ) -> {ok, {list(prequel@ast:attribute()), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. do_parse_inner_relationship_body( Tokens, Relationship_span, Entity_span, Attributes ) -> case Tokens of [{close_bracket, _} | Tokens@1] -> _pipe = gleam@list:reverse(Attributes), succeed(_pipe, Tokens@1); [{circle_lollipop, Span} | Tokens@2] -> 'try'( parse_attribute(Tokens@2, Relationship_span, Span), fun(Attribute, Tokens@3) -> do_parse_inner_relationship_body( Tokens@3, Relationship_span, Entity_span, [Attribute | Attributes] ) end ); [{star_lollipop, Lollipop_span} | _] -> _pipe@1 = {key_inside_relationship, {some, <<"TODO: add hint"/utf8>>}, Relationship_span, Lollipop_span}, fail(_pipe@1); [{minus, Minus_span}, {{word, <<"o"/utf8>>}, O_span} | _] -> _pipe@2 = {possible_circle_lollipop_typo, {some, <<"TODO: add hint"/utf8>>}, Relationship_span, prequel@span:merge(Minus_span, O_span)}, fail(_pipe@2); [{_, Token_span} | _] -> _pipe@3 = {unexpected_token_in_binary_relationship, {some, <<"TODO: add hint"/utf8>>}, Relationship_span, Token_span}, fail(_pipe@3); [] -> _pipe@4 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Relationship_span, <<"the body of this relationship"/utf8>>}, fail(_pipe@4) end. -spec parse_inner_relationship_body( list({prequel@internals@token:token(), prequel@span:span()}), prequel@span:span(), prequel@span:span() ) -> {ok, {list(prequel@ast:attribute()), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_inner_relationship_body(Tokens, Relationship_span, Entity_span) -> do_parse_inner_relationship_body(Tokens, Relationship_span, Entity_span, []). -spec parse_inner_relationship( list({prequel@internals@token:token(), prequel@span:span()}), binary(), prequel@span:span(), prequel@span:span() ) -> {ok, {prequel@ast:relationship(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_inner_relationship(Tokens, Entity_name, Entity_span, Lollipop_span) -> case Tokens of [{{word, Relationship_name}, Relationship_span}, {colon, Colon_span} | Tokens@1] -> 'try'( parse_cardinality(Tokens@1, false, Entity_span, Colon_span), fun(One_cardinality, Tokens@2) -> case Tokens@2 of [{{word, Other_name}, Other_name_span} | Tokens@3] -> 'try'( parse_cardinality( Tokens@3, false, Entity_span, Other_name_span ), fun(Other_cardinality, Tokens@4) -> One_entity = {relationship_entity, Entity_span, Entity_name, One_cardinality}, Other_entity = begin _pipe = {relationship_entity, Other_name_span, Other_name, Other_cardinality}, non_empty_list:single(_pipe) end, case Tokens@4 of [{open_bracket, _} | Tokens@5] -> 'try'( parse_inner_relationship_body( Tokens@5, Relationship_span, Entity_span ), fun(Attributes, Tokens@6) -> _pipe@1 = {relationship, Relationship_span, Relationship_name, One_entity, Other_entity, Attributes}, succeed(_pipe@1, Tokens@6) end ); _ -> _pipe@2 = Relationship_span, _pipe@3 = {relationship, _pipe@2, Relationship_name, One_entity, Other_entity, []}, succeed(_pipe@3, Tokens@4) end end ); [{Token, Span} | _] -> _pipe@4 = {wrong_entity_name, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, erlang:element(2, One_cardinality), prequel@internals@token:to_string(Token), Span, <<"the first cardinality annotation"/utf8>>}, fail(_pipe@4); [] -> _pipe@5 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Lollipop_span, <<"this relationship"/utf8>>}, fail(_pipe@5) end end ); [{{word, _}, Name_span} | _] -> _pipe@6 = {missing_cardinality_annotation, {some, <<"TODO: add hint"/utf8>>}, Entity_span, Name_span}, fail(_pipe@6); [{Token@1, Span@1} | _] -> _pipe@7 = {wrong_relationship_name, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Lollipop_span, prequel@internals@token:to_string(Token@1), Span@1}, fail(_pipe@7); [] -> _pipe@8 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Lollipop_span, <<"this relationship"/utf8>>}, fail(_pipe@8) end. -spec parse_relationship_entity( list({prequel@internals@token:token(), prequel@span:span()}), prequel@span:span(), prequel@span:span() ) -> {ok, {prequel@ast:relationship_entity(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_relationship_entity(Tokens, Relationship_span, Lollipop_span) -> case Tokens of [{{word, Name}, Name_span}, {colon, Colon_span} | Tokens@1] -> 'try'( parse_cardinality( Tokens@1, false, Relationship_span, Colon_span ), fun(Cardinality, Tokens@2) -> _pipe = {relationship_entity, Name_span, Name, Cardinality}, succeed(_pipe, Tokens@2) end ); [{{word, _}, Name_span@1} | _] -> _pipe@1 = {missing_cardinality_annotation, {some, <<"TODO: add hint"/utf8>>}, Relationship_span, Name_span@1}, fail(_pipe@1); [{Token, Span} | _] -> _pipe@2 = {wrong_entity_name, {some, <<"TODO: add hint"/utf8>>}, {some, Relationship_span}, Lollipop_span, prequel@internals@token:to_string(Token), Span, <<"the `->` lollipop"/utf8>>}, fail(_pipe@2); [] -> _pipe@3 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, {some, Relationship_span}, Lollipop_span, <<"this entity"/utf8>>}, fail(_pipe@3) end. -spec do_parse( list({prequel@internals@token:token(), prequel@span:span()}), list(prequel@ast:entity()), list(prequel@ast:relationship()) ) -> {ok, {prequel@ast:module_(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. do_parse(Tokens, Entities, Relationships) -> case Tokens of [] -> _pipe = {module, gleam@list:reverse(Entities), gleam@list:reverse(Relationships)}, succeed(_pipe, []); [{{word, <<"entity"/utf8>>}, Entity_keyword_span} | Tokens@1] -> 'try'( parse_entity(Tokens@1, Entity_keyword_span), fun(Entity, Tokens@2) -> do_parse(Tokens@2, [Entity | Entities], Relationships) end ); [{{word, <<"relationship"/utf8>>}, Relationship_span} | Tokens@3] -> 'try'( parse_relationship(Tokens@3, Relationship_span), fun(Relationship, Tokens@4) -> do_parse(Tokens@4, Entities, [Relationship | Relationships]) end ); [{_, Span} | _] -> _pipe@1 = {unexpected_token_in_top_level, {some, <<"TODO: add hint"/utf8>>}, Span}, fail(_pipe@1) end. -spec parse(list({prequel@internals@token:token(), prequel@span:span()})) -> {ok, prequel@ast:module_()} | {error, prequel@error@parse_error:parse_error()}. parse(Tokens) -> case do_parse(Tokens, [], []) of {ok, {Module, _}} -> {ok, Module}; {error, Error} -> {error, Error} end. -spec do_parse_entity_body( list({prequel@internals@token:token(), prequel@span:span()}), binary(), prequel@span:span(), list(prequel@ast:key()), list(prequel@ast:attribute()), list(prequel@ast:relationship()), gleam@option:option(prequel@ast:hierarchy()) ) -> {ok, {prequel@ast:entity(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. do_parse_entity_body( Tokens, Entity_name, Entity_span, Keys, Attributes, Inner_relationships, Children ) -> case Tokens of [{close_bracket, _} | Tokens@1] -> _pipe = {entity, Entity_span, Entity_name, gleam@list:reverse(Keys), gleam@list:reverse(Attributes), gleam@list:reverse(Inner_relationships), Children}, succeed(_pipe, Tokens@1); [{circle_lollipop, Lollipop_span} | Tokens@2] -> 'try'( parse_attribute(Tokens@2, Entity_span, Lollipop_span), fun(Attribute, Tokens@3) -> do_parse_entity_body( Tokens@3, Entity_name, Entity_span, Keys, [Attribute | Attributes], Inner_relationships, Children ) end ); [{star_lollipop, Lollipop_span@1} | Tokens@4] -> 'try'( parse_key(Tokens@4, Entity_span, Lollipop_span@1), fun(Key, Tokens@5) -> do_parse_entity_body( Tokens@5, Entity_name, Entity_span, [Key | Keys], Attributes, Inner_relationships, Children ) end ); [{arrow_lollipop, Lollipop_span@2} | Tokens@6] -> 'try'( parse_inner_relationship( Tokens@6, Entity_name, Entity_span, Lollipop_span@2 ), fun(Relationship, Tokens@7) -> do_parse_entity_body( Tokens@7, Entity_name, Entity_span, Keys, Attributes, [Relationship | Inner_relationships], Children ) end ); [{{word, <<"total"/utf8>> = Totality_string}, Totality_span} | Tokens@8] -> Error = {internal_error, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Totality_span, <<"A call to `totality_from_string` failed despite this being assumed a correct totality"/utf8>>}, Result = gleam@result:replace_error( totality_from_string(Totality_string), Error ), gleam@result:'try'( Result, fun(Totality) -> 'try'( parse_hierarchy( Tokens@8, Entity_span, Totality_span, Children, Totality ), fun(Hierarchy, Tokens@9) -> do_parse_entity_body( Tokens@9, Entity_name, Entity_span, Keys, Attributes, Inner_relationships, {some, Hierarchy} ) end ) end ); [{{word, <<"partial"/utf8>> = Totality_string}, Totality_span} | Tokens@8] -> Error = {internal_error, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Totality_span, <<"A call to `totality_from_string` failed despite this being assumed a correct totality"/utf8>>}, Result = gleam@result:replace_error( totality_from_string(Totality_string), Error ), gleam@result:'try'( Result, fun(Totality) -> 'try'( parse_hierarchy( Tokens@8, Entity_span, Totality_span, Children, Totality ), fun(Hierarchy, Tokens@9) -> do_parse_entity_body( Tokens@9, Entity_name, Entity_span, Keys, Attributes, Inner_relationships, {some, Hierarchy} ) end ) end ); [{minus, Minus_span}, {{word, <<"o"/utf8>>}, O_span} | _] -> _pipe@1 = {possible_circle_lollipop_typo, {some, <<"TODO: add hint"/utf8>>}, Entity_span, prequel@span:merge(Minus_span, O_span)}, fail(_pipe@1); [{minus, Minus_span@1}, {{word, <<"*"/utf8>>}, Star_span} | _] -> _pipe@2 = {possible_star_lollipop_typo, {some, <<"TODO: add hint"/utf8>>}, Entity_span, prequel@span:merge(Minus_span@1, Star_span)}, fail(_pipe@2); [{minus, Minus_span@2}, {{word, <<">"/utf8>>}, Arrow_span} | _] -> _pipe@3 = {possible_arrow_lollipop_typo, {some, <<"TODO: add hint"/utf8>>}, Entity_span, prequel@span:merge(Minus_span@2, Arrow_span)}, fail(_pipe@3); [{{word, First}, First_span}, {{word, Second}, Second_span} | _] when (((First =:= <<"overlapped"/utf8>>) orelse (First =:= <<"overlapping"/utf8>>)) orelse (First =:= <<"disjoint"/utf8>>)) andalso ((Second =:= <<"total"/utf8>>) orelse (Second =:= <<"partial"/utf8>>)) -> _pipe@4 = {wrong_order_of_hierarchy_qualifiers, {some, <<"TODO: add hint"/utf8>>}, Entity_span, prequel@span:merge(First_span, Second_span), First, Second}, fail(_pipe@4); [{{word, <<"hierarchy"/utf8>>}, Span} | _] -> _pipe@5 = {unqualified_hierarchy, {some, <<"TODO: add hint"/utf8>>}, Entity_span, Span}, fail(_pipe@5); [{_, Token_span} | _] -> _pipe@6 = {unexpected_token_in_entity_body, {some, <<"TODO: add hint"/utf8>>}, Entity_span, Token_span}, fail(_pipe@6); [] -> _pipe@7 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, none, Entity_span, <<"the body of this entity"/utf8>>}, fail(_pipe@7) end. -spec parse_entity_body( list({prequel@internals@token:token(), prequel@span:span()}), binary(), prequel@span:span() ) -> {ok, {prequel@ast:entity(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_entity_body(Tokens, Entity_name, Entity_span) -> do_parse_entity_body(Tokens, Entity_name, Entity_span, [], [], [], none). -spec parse_entity( list({prequel@internals@token:token(), prequel@span:span()}), prequel@span:span() ) -> {ok, {prequel@ast:entity(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_entity(Tokens, Entity_keyword_span) -> case Tokens of [{{word, Entity_name}, Entity_span}, {open_bracket, _} | Tokens@1] -> parse_entity_body(Tokens@1, Entity_name, Entity_span); [{{word, Entity_name@1}, Entity_span@1} | Tokens@2] -> _pipe = {entity, Entity_span@1, Entity_name@1, [], [], [], none}, succeed(_pipe, Tokens@2); [{Token, Span} | _] -> _pipe@1 = {wrong_entity_name, {some, <<"TODO: add hint"/utf8>>}, none, Entity_keyword_span, prequel@internals@token:to_string(Token), Span, <<"the `entity` keyword"/utf8>>}, fail(_pipe@1); [] -> _pipe@2 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, none, Entity_keyword_span, <<"this entity"/utf8>>}, fail(_pipe@2) end. -spec do_parse_hierarchy_body( list({prequel@internals@token:token(), prequel@span:span()}), list(prequel@ast:entity()), prequel@span:span(), prequel@span:span() ) -> {ok, {non_empty_list:non_empty_list(prequel@ast:entity()), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. do_parse_hierarchy_body(Tokens, Entities, Entity_span, Hierarchy_span) -> case Tokens of [{close_bracket, _} | Tokens@1] -> Error = {empty_hierarchy, {some, <<"TODO: add hint"/utf8>>}, Entity_span, Hierarchy_span}, _pipe = Entities, _pipe@1 = gleam@list:reverse(_pipe), _pipe@2 = non_empty_list:from_list(_pipe@1), _pipe@3 = gleam@result:replace_error(_pipe@2, Error), gleam@result:'try'( _pipe@3, fun(_capture) -> succeed(_capture, Tokens@1) end ); [{{word, <<"entity"/utf8>>}, Span} | Tokens@2] -> 'try'( parse_entity(Tokens@2, Span), fun(Entity, Tokens@3) -> do_parse_hierarchy_body( Tokens@3, [Entity | Entities], Entity_span, Hierarchy_span ) end ); [{_, Span@1} | _] -> _pipe@4 = {unexpected_token_in_hierarchy_body, {some, <<"TODO: add hint"/utf8>>}, Hierarchy_span, Span@1}, fail(_pipe@4); [] -> _pipe@5 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Hierarchy_span, <<"this hierarchy"/utf8>>}, fail(_pipe@5) end. -spec parse_hierarchy_body( list({prequel@internals@token:token(), prequel@span:span()}), prequel@span:span(), prequel@span:span() ) -> {ok, {non_empty_list:non_empty_list(prequel@ast:entity()), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_hierarchy_body(Tokens, Entity_span, Hierarchy_span) -> do_parse_hierarchy_body(Tokens, [], Entity_span, Hierarchy_span). -spec parse_hierarchy( list({prequel@internals@token:token(), prequel@span:span()}), prequel@span:span(), prequel@span:span(), gleam@option:option(prequel@ast:hierarchy()), prequel@ast:totality() ) -> {ok, {prequel@ast:hierarchy(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_hierarchy(Tokens, Entity_span, Totality_span, Entity_children, Totality) -> case Tokens of [{{word, <<"overlapped"/utf8>> = Word}, Word_span}, {{word, <<"hierarchy"/utf8>>}, Final_span}, {open_bracket, _} | Tokens@1] -> Error = {internal_error, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Word_span, <<"A call to `overlapping_from_string` failed despite this being assumed a correct overlapping"/utf8>>}, Result = gleam@result:replace_error( overlapping_from_string(Word), Error ), gleam@result:'try'( Result, fun(Overlapping) -> Hierarchy_span = prequel@span:merge( Totality_span, Final_span ), case Entity_children of {some, First_hierarchy} -> _pipe = {more_than_one_hierarchy, {some, <<"TODO: add hint"/utf8>>}, Entity_span, erlang:element(2, First_hierarchy), Hierarchy_span}, fail(_pipe); none -> 'try'( parse_hierarchy_body( Tokens@1, Entity_span, Hierarchy_span ), fun(Entities, Tokens@2) -> _pipe@1 = {hierarchy, Hierarchy_span, Overlapping, Totality, Entities}, succeed(_pipe@1, Tokens@2) end ) end end ); [{{word, <<"disjoint"/utf8>> = Word}, Word_span}, {{word, <<"hierarchy"/utf8>>}, Final_span}, {open_bracket, _} | Tokens@1] -> Error = {internal_error, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Word_span, <<"A call to `overlapping_from_string` failed despite this being assumed a correct overlapping"/utf8>>}, Result = gleam@result:replace_error( overlapping_from_string(Word), Error ), gleam@result:'try'( Result, fun(Overlapping) -> Hierarchy_span = prequel@span:merge( Totality_span, Final_span ), case Entity_children of {some, First_hierarchy} -> _pipe = {more_than_one_hierarchy, {some, <<"TODO: add hint"/utf8>>}, Entity_span, erlang:element(2, First_hierarchy), Hierarchy_span}, fail(_pipe); none -> 'try'( parse_hierarchy_body( Tokens@1, Entity_span, Hierarchy_span ), fun(Entities, Tokens@2) -> _pipe@1 = {hierarchy, Hierarchy_span, Overlapping, Totality, Entities}, succeed(_pipe@1, Tokens@2) end ) end end ); [{{word, <<"overlapped"/utf8>>}, _}, {{word, <<"hierarchy"/utf8>>}, Hierarchy_span@1} | _] -> _pipe@2 = {empty_hierarchy, {some, <<"TODO: add hint"/utf8>>}, Entity_span, prequel@span:merge(Totality_span, Hierarchy_span@1)}, fail(_pipe@2); [{{word, <<"disjoint"/utf8>>}, _}, {{word, <<"hierarchy"/utf8>>}, Hierarchy_span@1} | _] -> _pipe@2 = {empty_hierarchy, {some, <<"TODO: add hint"/utf8>>}, Entity_span, prequel@span:merge(Totality_span, Hierarchy_span@1)}, fail(_pipe@2); [{{word, <<"overlapped"/utf8>>}, Overlapping_span} | _] -> _pipe@3 = {missing_hierarchy_keyword, {some, <<"TODO: add hint"/utf8>>}, Entity_span, prequel@span:merge(Totality_span, Overlapping_span)}, fail(_pipe@3); [{{word, <<"disjoint"/utf8>>}, Overlapping_span} | _] -> _pipe@3 = {missing_hierarchy_keyword, {some, <<"TODO: add hint"/utf8>>}, Entity_span, prequel@span:merge(Totality_span, Overlapping_span)}, fail(_pipe@3); [{Token, Span} | _] -> _pipe@4 = {wrong_hierarchy_overlapping, {some, <<"TODO: add hint"/utf8>>}, Entity_span, Totality_span, prequel@internals@token:to_string(Token), Span}, fail(_pipe@4); [] -> _pipe@5 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, {some, Entity_span}, Totality_span, <<"this hierarchy"/utf8>>}, fail(_pipe@5) end. -spec do_parse_relationship_body( list({prequel@internals@token:token(), prequel@span:span()}), binary(), prequel@span:span(), list(prequel@ast:relationship_entity()), list(prequel@ast:attribute()) ) -> {ok, {prequel@ast:relationship(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. do_parse_relationship_body( Tokens, Relationship_name, Relationship_span, Entities, Attributes ) -> case Tokens of [{close_bracket, _} | Tokens@1] -> case Entities of [One_entity, Other_entity | Other_entities] -> _pipe = {relationship, Relationship_span, Relationship_name, One_entity, non_empty_list:new(Other_entity, Other_entities), Attributes}, succeed(_pipe, Tokens@1); [One_entity@1] -> _pipe@1 = {relationship_body_with_just_one_entity, {some, <<"TODO: add hint"/utf8>>}, Relationship_span, Relationship_name, erlang:element(2, One_entity@1)}, fail(_pipe@1); [] -> _pipe@2 = {relationship_body_with_no_entities, {some, <<"TODO: add hint"/utf8>>}, Relationship_span}, fail(_pipe@2) end; [{circle_lollipop, Lollipop_span} | Tokens@2] -> 'try'( parse_attribute(Tokens@2, Relationship_span, Lollipop_span), fun(Attribute, Tokens@3) -> do_parse_relationship_body( Tokens@3, Relationship_name, Relationship_span, Entities, [Attribute | Attributes] ) end ); [{arrow_lollipop, Lollipop_span@1} | Tokens@4] -> 'try'( parse_relationship_entity( Tokens@4, Relationship_span, Lollipop_span@1 ), fun(Entity, Tokens@5) -> do_parse_relationship_body( Tokens@5, Relationship_name, Relationship_span, [Entity | Entities], Attributes ) end ); [{star_lollipop, Lollipop_span@2} | _] -> _pipe@3 = {key_inside_relationship, {some, <<"TODO: add hint"/utf8>>}, Relationship_span, Lollipop_span@2}, fail(_pipe@3); [{minus, Minus_span}, {{word, <<"o"/utf8>>}, O_span} | _] -> _pipe@4 = {possible_circle_lollipop_typo, {some, <<"TODO: add hint"/utf8>>}, Relationship_span, prequel@span:merge(Minus_span, O_span)}, fail(_pipe@4); [{minus, Minus_span@1}, {{word, <<">"/utf8>>}, Arrow_span} | _] -> _pipe@5 = {possible_arrow_lollipop_typo, {some, <<"TODO: add hint"/utf8>>}, Relationship_span, prequel@span:merge(Minus_span@1, Arrow_span)}, fail(_pipe@5); [{_, Span} | _] -> _pipe@6 = {unexpected_token_in_relationship_body, {some, <<"TODO: add hint"/utf8>>}, Relationship_span, Span}, fail(_pipe@6); [] -> _pipe@7 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, none, Relationship_span, <<"this relationship"/utf8>>}, fail(_pipe@7) end. -spec parse_relationship_body( list({prequel@internals@token:token(), prequel@span:span()}), binary(), prequel@span:span() ) -> {ok, {prequel@ast:relationship(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_relationship_body(Tokens, Relationship_name, Name_span) -> do_parse_relationship_body(Tokens, Relationship_name, Name_span, [], []). -spec parse_relationship( list({prequel@internals@token:token(), prequel@span:span()}), prequel@span:span() ) -> {ok, {prequel@ast:relationship(), list({prequel@internals@token:token(), prequel@span:span()})}} | {error, prequel@error@parse_error:parse_error()}. parse_relationship(Tokens, Relationship_keyword_span) -> case Tokens of [{{word, Relationship_name}, Relationship_span}, {open_bracket, _} | Tokens@1] -> parse_relationship_body( Tokens@1, Relationship_name, Relationship_span ); [{{word, _}, Name_span} | _] -> _pipe = {relationship_body_with_no_entities, {some, <<"TODO: add hint"/utf8>>}, Name_span}, fail(_pipe); [{Token, Span} | _] -> _pipe@1 = {wrong_relationship_name, {some, <<"TODO: add hint"/utf8>>}, none, Relationship_keyword_span, prequel@internals@token:to_string(Token), Span}, fail(_pipe@1); [] -> _pipe@2 = {unexpected_end_of_file, {some, <<"TODO: add hint"/utf8>>}, none, Relationship_keyword_span, <<"this relationship"/utf8>>}, fail(_pipe@2) end.