use super::*;
pub fn parse_feature_prefix_modifiers<P: KerMLParser>(p: &mut P) {
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,
SyntaxKind::VARIATION_KW,
SyntaxKind::READONLY_KW,
SyntaxKind::REF_KW,
]) {
p.bump();
p.skip_trivia();
}
while p.at(SyntaxKind::HASH) {
parse_prefix_metadata(p);
p.skip_trivia();
}
}
fn parse_optional_feature_keyword<P: KerMLParser>(p: &mut P) -> bool {
if p.at(SyntaxKind::INV_KW) {
p.bump();
p.skip_trivia();
if p.at(SyntaxKind::NOT_KW) {
p.bump();
p.skip_trivia();
}
true
} else if p.at_any(&[
SyntaxKind::FEATURE_KW,
SyntaxKind::STEP_KW,
SyntaxKind::EXPR_KW,
]) {
p.bump();
true
} else if p.at(SyntaxKind::IDENT) {
if let Some(text) = p.current_token_text() {
if text == "feature" || text == "step" || text == "expr" {
p.bump();
true
} else {
false
}
} else {
false
}
} else {
false
}
}
fn parse_usage_name_or_shorthand<P: KerMLParser>(p: &mut P) {
if p.at(SyntaxKind::REDEFINES_KW)
|| p.at(SyntaxKind::COLON_GT_GT)
|| p.at(SyntaxKind::SUBSETS_KW)
|| p.at(SyntaxKind::COLON_GT)
{
p.start_node(SyntaxKind::SPECIALIZATION);
bump_and_skip(p);
parse_optional_qualified_name(p);
p.finish_node();
while p.at(SyntaxKind::COMMA) {
bump_and_skip(p);
p.start_node(SyntaxKind::SPECIALIZATION);
parse_qualified_name_and_skip(p);
p.finish_node();
}
} else if p.at_name_token() || p.at(SyntaxKind::LT) {
if p.at(SyntaxKind::IDENT) {
let peek1 = p.peek_kind(1);
if peek1 == SyntaxKind::IDENT || peek1 == SyntaxKind::LT {
p.start_node(SyntaxKind::TYPING);
p.bump(); p.skip_trivia();
p.finish_node();
p.parse_identification();
return;
}
}
p.parse_identification();
}
}
fn parse_usage_details<P: KerMLParser>(p: &mut P) {
p.skip_trivia();
parse_optional_multiplicity(p);
parse_optional_typing(p);
parse_optional_multiplicity(p);
parse_ordering_modifiers(p);
parse_specializations(p);
p.skip_trivia();
parse_optional_multiplicity(p);
parse_ordering_modifiers(p);
parse_feature_relationships(p);
p.skip_trivia();
}
fn parse_ordering_modifiers<P: KerMLParser>(p: &mut P) {
while p.at(SyntaxKind::ORDERED_KW) || p.at(SyntaxKind::NONUNIQUE_KW) {
bump_and_skip(p);
}
}
fn parse_optional_default_value<P: KerMLParser>(p: &mut P) {
if p.at(SyntaxKind::EQ) || p.at(SyntaxKind::COLON_EQ) || p.at(SyntaxKind::DEFAULT_KW) {
bump_and_skip(p);
super::kerml_expressions::parse_expression(p);
p.skip_trivia();
}
}
pub fn parse_usage_impl<P: KerMLParser>(p: &mut P) {
p.start_node(SyntaxKind::USAGE);
parse_feature_prefix_modifiers(p);
let _consumed_feature_keyword = parse_optional_feature_keyword(p);
p.skip_trivia();
if p.at(SyntaxKind::ALL_KW) {
p.bump();
p.skip_trivia();
}
parse_usage_name_or_shorthand(p);
parse_usage_details(p);
parse_optional_default_value(p);
p.parse_body();
p.finish_node();
}
pub fn parse_invariant<P: KerMLParser>(p: &mut P) {
p.start_node(SyntaxKind::USAGE);
p.expect(SyntaxKind::INV_KW);
p.skip_trivia();
if p.at(SyntaxKind::NOT_KW) {
p.bump();
p.skip_trivia();
}
if p.at_name_token() || p.at(SyntaxKind::LT) {
p.parse_identification();
p.skip_trivia();
}
if p.at(SyntaxKind::L_BRACE) {
p.start_node(SyntaxKind::NAMESPACE_BODY);
p.bump(); p.skip_trivia();
if p.at(SyntaxKind::DOC_KW) || p.at(SyntaxKind::COMMENT_KW) {
parse_annotation(p);
p.skip_trivia();
}
if !p.at(SyntaxKind::R_BRACE) {
super::kerml_expressions::parse_expression(p);
}
p.skip_trivia();
p.expect(SyntaxKind::R_BRACE);
p.finish_node();
} else {
p.parse_body();
}
p.finish_node();
}
pub fn parse_parameter_impl<P: KerMLParser>(p: &mut P) {
p.start_node(SyntaxKind::USAGE);
if p.at_any(&[
SyntaxKind::IN_KW,
SyntaxKind::OUT_KW,
SyntaxKind::INOUT_KW,
SyntaxKind::END_KW,
SyntaxKind::RETURN_KW,
]) {
p.bump();
}
p.skip_trivia();
parse_feature_prefix_modifiers(p);
if p.at_any(&[
SyntaxKind::ATTRIBUTE_KW,
SyntaxKind::PART_KW,
SyntaxKind::ITEM_KW,
SyntaxKind::CALC_KW,
SyntaxKind::ACTION_KW,
SyntaxKind::STATE_KW,
SyntaxKind::PORT_KW,
SyntaxKind::FEATURE_KW,
SyntaxKind::STEP_KW,
SyntaxKind::EXPR_KW,
]) {
bump_and_skip(p);
}
if p.at(SyntaxKind::IDENT) {
let peek1 = p.peek_kind(1);
if peek1 == SyntaxKind::IDENT {
p.bump();
p.skip_trivia();
if p.at_name_token() {
p.parse_identification();
}
} else {
parse_usage_name_or_shorthand(p);
}
} else {
parse_usage_name_or_shorthand(p);
}
parse_usage_details(p);
parse_optional_default_value(p);
p.parse_body();
p.finish_node();
}
fn parse_multiplicity_with_ordering<P: KerMLParser>(p: &mut P) {
if p.at(SyntaxKind::L_BRACKET) {
parse_multiplicity(p);
p.skip_trivia();
while p.at(SyntaxKind::ORDERED_KW) || p.at(SyntaxKind::NONUNIQUE_KW) {
bump_and_skip(p);
}
}
}
fn parse_prefix_modifiers<P: KerMLParser>(p: &mut P) {
while p.at_any(&[
SyntaxKind::REF_KW,
SyntaxKind::READONLY_KW,
SyntaxKind::DERIVED_KW,
SyntaxKind::ABSTRACT_KW,
SyntaxKind::VARIATION_KW,
SyntaxKind::VAR_KW,
SyntaxKind::COMPOSITE_KW,
SyntaxKind::PORTION_KW,
SyntaxKind::INDIVIDUAL_KW,
]) {
bump_and_skip(p);
}
}
fn parse_optional_sysml_usage_keyword<P: KerMLParser>(p: &mut P) {
if p.at_any(&[
SyntaxKind::ITEM_KW,
SyntaxKind::PART_KW,
SyntaxKind::ACTION_KW,
SyntaxKind::STATE_KW,
SyntaxKind::ATTRIBUTE_KW,
SyntaxKind::PORT_KW,
]) {
bump_and_skip(p);
}
}
fn parse_end_feature_prefix<P: KerMLParser>(p: &mut P) {
while p.at(SyntaxKind::HASH) {
parse_prefix_metadata(p);
p.skip_trivia();
}
parse_prefix_modifiers(p);
parse_multiplicity_with_ordering(p);
parse_optional_sysml_usage_keyword(p);
}
fn parse_feature_details<P: KerMLParser>(p: &mut P, parse_id: bool) {
if parse_id {
parse_optional_identification(p);
}
parse_multiplicity_with_ordering(p);
parse_optional_typing(p);
parse_specializations(p);
p.skip_trivia();
parse_feature_relationships(p);
p.skip_trivia();
}
fn parse_end_feature_with_keyword<P: KerMLParser>(p: &mut P) {
bump_and_skip(p);
if p.at(SyntaxKind::REDEFINES_KW)
|| p.at(SyntaxKind::COLON_GT_GT)
|| p.at(SyntaxKind::SUBSETS_KW)
|| p.at(SyntaxKind::COLON_GT)
|| p.at(SyntaxKind::REFERENCES_KW)
|| p.at(SyntaxKind::COLON_COLON_GT)
{
parse_feature_details(p, false);
} else {
parse_feature_details(p, true);
}
}
fn parse_typing_and_relationships<P: KerMLParser>(p: &mut P) {
parse_optional_typing(p);
parse_specializations(p);
p.skip_trivia();
parse_feature_relationships(p);
p.skip_trivia();
}
fn parse_end_feature_with_name<P: KerMLParser>(p: &mut P) {
parse_identification_and_skip(p);
parse_multiplicity_with_ordering(p);
parse_specializations(p);
p.skip_trivia();
parse_feature_relationships(p);
p.skip_trivia();
if p.at(SyntaxKind::FEATURE_KW) {
bump_and_skip(p);
parse_feature_details(p, true);
} else {
parse_typing_and_relationships(p);
}
}
fn parse_end_feature_minimal<P: KerMLParser>(p: &mut P) {
parse_multiplicity_with_ordering(p);
parse_specializations(p);
p.skip_trivia();
if p.at(SyntaxKind::FEATURE_KW) {
bump_and_skip(p);
parse_feature_details(p, true);
}
}
pub fn parse_end_feature_or_parameter<P: KerMLParser>(p: &mut P) {
p.start_node(SyntaxKind::USAGE);
consume_if(p, SyntaxKind::CONST_KW);
expect_and_skip(p, SyntaxKind::END_KW);
parse_end_feature_prefix(p);
if p.at(SyntaxKind::FEATURE_KW) {
parse_end_feature_with_keyword(p);
} else if p.at_name_token() || p.at(SyntaxKind::LT) {
if p.at(SyntaxKind::IDENT) {
let peek1 = p.peek_kind(1);
if peek1 == SyntaxKind::IDENT || peek1 == SyntaxKind::LT {
p.start_node(SyntaxKind::TYPING);
p.bump(); p.skip_trivia();
p.finish_node();
p.parse_identification();
parse_multiplicity_with_ordering(p);
parse_specializations(p);
p.skip_trivia();
parse_feature_relationships(p);
p.skip_trivia();
} else {
parse_end_feature_with_name(p);
}
} else {
parse_end_feature_with_name(p);
}
} else {
parse_end_feature_minimal(p);
}
parse_optional_default_value(p);
p.parse_body();
p.finish_node();
}