use super::*;
fn parse_connector_name_or_specialization<P: KerMLParser>(
p: &mut P,
looks_like_direct_endpoint: bool,
) {
if p.at(SyntaxKind::COLON_GT)
|| p.at(SyntaxKind::COLON_GT_GT)
|| p.at(SyntaxKind::SUBSETS_KW)
|| p.at(SyntaxKind::SPECIALIZES_KW)
|| p.at(SyntaxKind::REDEFINES_KW)
{
parse_specializations(p);
p.skip_trivia();
} else if p.at(SyntaxKind::EQ) {
bump_and_skip(p);
parse_optional_qualified_name(p);
} else if !looks_like_direct_endpoint && (p.at_name_token() || p.at(SyntaxKind::LT)) {
parse_identification_and_skip(p);
if p.at(SyntaxKind::EQ) {
bump_and_skip(p);
parse_optional_qualified_name(p);
} else {
parse_specializations(p);
p.skip_trivia();
}
}
}
fn parse_nary_connector_endpoints<P: KerMLParser>(p: &mut P) -> bool {
if !p.at(SyntaxKind::L_PAREN) {
return false;
}
p.bump(); p.skip_trivia();
if p.at_name_token() || p.at(SyntaxKind::L_BRACKET) {
parse_connection_end(p);
p.skip_trivia();
}
while p.at(SyntaxKind::COMMA) {
p.bump(); p.skip_trivia();
if p.at_name_token() || p.at(SyntaxKind::L_BRACKET) {
parse_connection_end(p);
p.skip_trivia();
}
}
if p.at(SyntaxKind::R_PAREN) {
p.bump(); p.skip_trivia();
}
true
}
fn parse_binary_connector_endpoints<P: KerMLParser>(p: &mut P) {
if p.at(SyntaxKind::FROM_KW) {
p.bump();
p.skip_trivia();
parse_connection_end(p);
p.skip_trivia();
} else if !p.at(SyntaxKind::TO_KW) && (p.at_name_token() || p.at(SyntaxKind::L_PAREN)) {
parse_connection_end(p);
p.skip_trivia();
}
if p.at(SyntaxKind::TO_KW) {
p.bump();
p.skip_trivia();
parse_connection_end(p);
p.skip_trivia();
}
}
pub fn parse_connector_usage<P: KerMLParser>(p: &mut P) {
p.start_node(SyntaxKind::CONNECTOR);
while p.at_any(&[
SyntaxKind::VAR_KW,
SyntaxKind::COMPOSITE_KW,
SyntaxKind::PORTION_KW,
SyntaxKind::MEMBER_KW,
SyntaxKind::ABSTRACT_KW,
SyntaxKind::DERIVED_KW,
SyntaxKind::CONST_KW,
SyntaxKind::END_KW,
]) {
bump_and_skip(p);
}
if p.at_any(&[
SyntaxKind::BINDING_KW,
SyntaxKind::SUCCESSION_KW,
SyntaxKind::FIRST_KW,
]) {
parse_binding_or_succession_impl(p);
return;
}
expect_and_skip(p, SyntaxKind::CONNECTOR_KW);
consume_if(p, SyntaxKind::ALL_KW);
if p.at(SyntaxKind::FEATURED_KW) {
parse_feature_relationships(p);
p.skip_trivia();
parse_binary_connector_endpoints(p);
p.parse_body();
p.finish_node();
return;
}
let looks_like_direct =
looks_like_qualified_name_before(p, &[SyntaxKind::TO_KW, SyntaxKind::FROM_KW]);
parse_connector_name_or_specialization(p, looks_like_direct);
parse_optional_typing(p);
parse_optional_multiplicity(p);
parse_feature_relationships(p);
p.skip_trivia();
if parse_nary_connector_endpoints(p) {
p.parse_body();
p.finish_node();
return;
}
parse_binary_connector_endpoints(p);
p.parse_body();
p.finish_node();
}
fn parse_connection_end<P: KerMLParser>(p: &mut P) {
p.start_node(SyntaxKind::CONNECTION_END);
if p.at(SyntaxKind::L_BRACKET) {
parse_multiplicity(p);
p.skip_trivia();
}
if p.at_name_token() {
let _checkpoint_pos = p.get_pos();
p.parse_qualified_name();
p.skip_trivia();
if p.at(SyntaxKind::REFERENCES_KW) || p.at(SyntaxKind::COLON_COLON_GT) {
p.bump();
p.skip_trivia();
if p.at_name_token() {
p.parse_qualified_name();
}
}
}
p.finish_node();
}
fn parse_binding_succession_prefix<P: KerMLParser>(
p: &mut P,
looks_like_direct_endpoint: bool,
) -> bool {
let mut parsed_name = false;
if p.at(SyntaxKind::REDEFINES_KW) || p.at(SyntaxKind::COLON_GT_GT) {
p.start_node(SyntaxKind::SPECIALIZATION);
p.bump();
p.skip_trivia();
if p.at_name_token() {
p.parse_qualified_name();
p.skip_trivia();
parsed_name = true;
}
p.finish_node();
} else if !looks_like_direct_endpoint && (p.at_name_token() || p.at(SyntaxKind::LT)) {
p.parse_identification();
p.skip_trivia();
parsed_name = true;
}
parsed_name
}
fn parse_succession_modifiers<P: KerMLParser>(p: &mut P) {
if p.at(SyntaxKind::COLON) {
parse_typing(p);
p.skip_trivia();
}
if p.at(SyntaxKind::L_BRACKET) {
parse_multiplicity(p);
p.skip_trivia();
}
}
fn parse_succession_first_pattern<P: KerMLParser>(p: &mut P) {
p.bump(); p.skip_trivia();
if p.at(SyntaxKind::L_BRACKET) {
parse_multiplicity(p);
p.skip_trivia();
}
p.parse_qualified_name();
p.skip_trivia();
if p.at(SyntaxKind::THEN_KW) {
p.bump();
p.skip_trivia();
if p.at(SyntaxKind::L_BRACKET) {
parse_multiplicity(p);
p.skip_trivia();
}
p.parse_qualified_name();
}
}
fn parse_endpoint_references<P: KerMLParser>(p: &mut P, parsed_name: bool) {
if p.at(SyntaxKind::L_BRACKET) {
parse_multiplicity(p);
p.skip_trivia();
}
if !parsed_name && p.at_name_token() {
p.parse_qualified_name();
p.skip_trivia();
}
if p.at(SyntaxKind::EQ) || p.at(SyntaxKind::THEN_KW) {
p.bump();
p.skip_trivia();
if p.at(SyntaxKind::L_BRACKET) {
parse_multiplicity(p);
p.skip_trivia();
}
if p.at_name_token() {
p.parse_qualified_name();
}
}
}
fn parse_binding_of_clause<P: KerMLParser>(p: &mut P) {
if p.at(SyntaxKind::OF_KW) {
p.bump();
p.skip_trivia();
if p.at(SyntaxKind::L_BRACKET) {
parse_multiplicity(p);
p.skip_trivia();
}
if p.at_name_token() {
parse_feature_chain_or_qualified_name(p);
p.skip_trivia();
}
if p.at(SyntaxKind::EQ) {
p.bump();
p.skip_trivia();
if p.at(SyntaxKind::L_BRACKET) {
parse_multiplicity(p);
p.skip_trivia();
}
if p.at_name_token() {
parse_feature_chain_or_qualified_name(p);
p.skip_trivia();
}
}
}
}
fn should_parse_first_pattern<P: KerMLParser>(p: &P, is_succession: bool) -> bool {
is_succession && p.at(SyntaxKind::FIRST_KW)
}
fn parse_binding_or_succession_impl<P: KerMLParser>(p: &mut P) {
let is_succession = p.at(SyntaxKind::SUCCESSION_KW) || p.at(SyntaxKind::FIRST_KW);
let is_shorthand_first = p.at(SyntaxKind::FIRST_KW);
if !is_shorthand_first {
bump_and_skip(p);
}
consume_if(p, SyntaxKind::ALL_KW);
let parsed_name = if should_parse_first_pattern(p, is_succession) {
false } else {
let looks_like_direct = if is_succession {
let next_after_name = p.peek_kind(1);
next_after_name == SyntaxKind::THEN_KW
} else {
looks_like_name_then(p, SyntaxKind::EQ)
};
parse_binding_succession_prefix(p, looks_like_direct)
};
if p.at(SyntaxKind::L_BRACKET) {
parse_multiplicity(p);
p.skip_trivia();
}
if !is_succession {
parse_binding_of_clause(p);
}
if is_succession {
parse_succession_modifiers(p);
}
parse_specializations(p);
p.skip_trivia();
if should_parse_first_pattern(p, is_succession) {
parse_succession_first_pattern(p);
} else {
parse_endpoint_references(p, parsed_name);
}
p.skip_trivia();
p.parse_body();
p.finish_node();
}
pub fn parse_flow_usage<P: KerMLParser>(p: &mut P) {
p.start_node(SyntaxKind::USAGE);
consume_if(p, SyntaxKind::ABSTRACT_KW);
consume_if(p, SyntaxKind::SUCCESSION_KW);
expect_and_skip(p, SyntaxKind::FLOW_KW);
let starts_with_all = consume_if(p, SyntaxKind::ALL_KW);
let looks_like_direct = starts_with_all || {
if p.at_name_token() {
let next = p.peek_kind(1);
matches!(next, SyntaxKind::DOT | SyntaxKind::TO_KW)
} else {
false
}
};
if looks_like_direct {
parse_flow_direct_pattern(p);
} else {
parse_flow_declaration_pattern(p);
}
p.skip_trivia();
parse_body(p);
p.finish_node();
}
fn parse_flow_direct_pattern<P: KerMLParser>(p: &mut P) {
super::kerml_expressions::parse_expression(p);
p.skip_trivia();
if p.at(SyntaxKind::TO_KW) {
bump_and_skip(p);
super::kerml_expressions::parse_expression(p);
p.skip_trivia();
}
}
fn parse_flow_declaration_pattern<P: KerMLParser>(p: &mut P) {
parse_optional_identification(p);
parse_optional_multiplicity(p);
parse_optional_typing(p);
parse_specializations(p);
p.skip_trivia();
if p.at(SyntaxKind::OF_KW) {
bump_and_skip(p);
parse_qualified_name_and_skip(p);
}
if p.at(SyntaxKind::FROM_KW) {
bump_and_skip(p);
super::kerml_expressions::parse_expression(p);
p.skip_trivia();
}
if p.at(SyntaxKind::TO_KW) {
bump_and_skip(p);
super::kerml_expressions::parse_expression(p);
p.skip_trivia();
}
}