use super::*;
pub(super) fn error_missing_body_terminator<P: SysMLParser>(p: &mut P, context: &str) {
let found = if let Some(text) = p.current_token_text() {
format!("'{}' ({})", text, p.current_kind().display_name())
} else {
"end of file".to_string()
};
p.error(format!(
"expected ';' to end {} or '{{' to start body, found {}",
context, found
));
}
pub(super) fn bump_keyword<P: SysMLParser>(p: &mut P) {
p.bump();
p.skip_trivia();
}
pub(super) fn expect_and_skip<P: SysMLParser>(p: &mut P, kind: SyntaxKind) {
p.expect(kind);
p.skip_trivia();
}
pub(super) fn consume_if<P: SysMLParser>(p: &mut P, kind: SyntaxKind) -> bool {
if p.at(kind) {
bump_keyword(p);
true
} else {
false
}
}
pub(super) fn skip_trivia_lookahead<P: SysMLParser>(p: &P, mut lookahead: usize) -> usize {
while matches!(
p.peek_kind(lookahead),
SyntaxKind::WHITESPACE | SyntaxKind::LINE_COMMENT | SyntaxKind::BLOCK_COMMENT
) {
lookahead += 1;
}
lookahead
}
pub(super) fn peek_past_name_for<P: SysMLParser>(p: &P, target: SyntaxKind) -> bool {
let mut lookahead = 0;
lookahead = skip_trivia_lookahead(p, lookahead);
if p.peek_kind(lookahead) == SyntaxKind::IDENT {
lookahead += 1;
} else {
return false;
}
loop {
lookahead = skip_trivia_lookahead(p, lookahead);
let next = p.peek_kind(lookahead);
if next == SyntaxKind::COLON_COLON || next == SyntaxKind::DOT {
lookahead += 1;
lookahead = skip_trivia_lookahead(p, lookahead);
if p.peek_kind(lookahead) == SyntaxKind::IDENT {
lookahead += 1;
} else {
break;
}
} else {
break;
}
}
lookahead = skip_trivia_lookahead(p, lookahead);
p.peek_kind(lookahead) == target
}
pub(super) fn peek_past_optional_name<P: SysMLParser>(
p: &P,
mut lookahead: usize,
) -> (usize, SyntaxKind) {
lookahead = skip_trivia_lookahead(p, lookahead);
let mut next = p.peek_kind(lookahead);
if next == SyntaxKind::IDENT {
lookahead += 1;
lookahead = skip_trivia_lookahead(p, lookahead);
next = p.peek_kind(lookahead);
}
(lookahead, next)
}
pub(super) fn parse_optional_identification<P: SysMLParser>(p: &mut P) {
if p.at_name_token() || p.at(SyntaxKind::LT) {
p.parse_identification();
p.skip_trivia();
}
}
pub(super) fn parse_optional_qualified_name<P: SysMLParser>(p: &mut P) {
if p.at_name_token() {
p.parse_qualified_name();
p.skip_trivia();
}
}
pub(super) fn parse_qualified_name_and_skip<P: SysMLParser>(p: &mut P) {
p.parse_qualified_name();
p.skip_trivia();
}
pub(super) fn parse_body_or_semicolon<P: SysMLParser>(p: &mut P) {
if p.at(SyntaxKind::L_BRACE) {
p.parse_body();
} else {
p.expect(SyntaxKind::SEMICOLON);
}
}
pub(super) fn parse_optional_default_value<P: SysMLParser>(p: &mut P) {
if p.at(SyntaxKind::DEFAULT_KW) {
bump_keyword(p);
if p.at(SyntaxKind::EQ) || p.at(SyntaxKind::COLON_EQ) {
bump_keyword(p);
}
if p.can_start_expression() {
parse_expression(p);
p.skip_trivia();
}
} else if p.at(SyntaxKind::EQ) || p.at(SyntaxKind::COLON_EQ) {
bump_keyword(p);
if p.can_start_expression() {
parse_expression(p);
p.skip_trivia();
}
}
}
pub(super) fn parse_optional_multiplicity<P: SysMLParser>(p: &mut P) {
if p.at(SyntaxKind::L_BRACKET) {
p.parse_multiplicity();
p.skip_trivia();
}
}
pub(super) fn parse_optional_typing<P: SysMLParser>(p: &mut P) {
if p.at(SyntaxKind::COLON) {
p.parse_typing();
p.skip_trivia();
}
}
pub(super) fn parse_specializations_with_skip<P: SysMLParser>(p: &mut P) {
parse_specializations(p);
p.skip_trivia();
}
pub(super) fn parse_optional_via<P: SysMLParser>(p: &mut P) {
if p.at(SyntaxKind::VIA_KW) {
bump_keyword(p);
if p.can_start_expression() {
parse_expression(p);
p.skip_trivia();
}
}
}
pub(super) fn parse_optional_to<P: SysMLParser>(p: &mut P) {
if p.at(SyntaxKind::TO_KW) {
bump_keyword(p);
if p.can_start_expression() {
parse_expression(p);
p.skip_trivia();
}
}
}
pub(super) fn parse_optional_from_to<P: SysMLParser>(p: &mut P) {
if p.at(SyntaxKind::FROM_KW) {
p.start_node(SyntaxKind::FROM_TO_CLAUSE);
p.bump(); p.skip_trivia();
if p.at_name_token() {
p.start_node(SyntaxKind::FROM_TO_SOURCE);
p.parse_qualified_name();
p.finish_node();
p.skip_trivia();
}
if p.at(SyntaxKind::TO_KW) {
p.bump(); p.skip_trivia();
if p.at_name_token() {
p.start_node(SyntaxKind::FROM_TO_TARGET);
p.parse_qualified_name();
p.finish_node();
p.skip_trivia();
}
}
p.finish_node(); }
}
#[allow(dead_code)]
pub(super) fn parse_comma_separated_list<P: SysMLParser, F>(p: &mut P, mut parse_item: F)
where
F: FnMut(&mut P),
{
parse_item(p);
while p.at(SyntaxKind::COMMA) {
bump_keyword(p);
parse_item(p);
}
}
pub(super) fn parse_inline_send_action<P: SysMLParser>(p: &mut P) {
p.start_node(SyntaxKind::SEND_ACTION_USAGE);
p.expect(SyntaxKind::SEND_KW);
p.skip_trivia();
if p.can_start_expression() {
parse_expression(p);
p.skip_trivia();
}
parse_optional_via(p);
parse_optional_to(p);
p.finish_node();
}
pub(super) fn parse_accept_trigger<P: SysMLParser>(p: &mut P) {
if (p.at_name_token() || p.at(SyntaxKind::LT))
&& !p.at(SyntaxKind::AT_KW)
&& !p.at(SyntaxKind::AFTER_KW)
&& !p.at(SyntaxKind::WHEN_KW)
&& !p.at(SyntaxKind::VIA_KW)
{
p.parse_identification();
p.skip_trivia();
}
if p.at(SyntaxKind::COLON) || p.at(SyntaxKind::COLON_GT) {
p.parse_typing();
p.skip_trivia();
}
if p.at(SyntaxKind::AT_KW) || p.at(SyntaxKind::AFTER_KW) || p.at(SyntaxKind::WHEN_KW) {
bump_keyword(p);
parse_expression(p);
p.skip_trivia();
}
if p.at(SyntaxKind::VIA_KW) {
bump_keyword(p);
p.parse_qualified_name();
p.skip_trivia();
}
}
pub(super) fn parse_inline_action<P: SysMLParser>(p: &mut P) {
p.start_node(SyntaxKind::USAGE);
p.expect(SyntaxKind::ACTION_KW);
p.skip_trivia();
if p.at_name_token() {
p.parse_identification();
p.skip_trivia();
}
parse_action_body(p);
p.finish_node();
}