use crate::io::traits::ISource;
use crate::parser::directives::DirectiveContext;
use crate::parser::lexer::Token;
use crate::parser::token_stream::TokenStream;
use crate::parser::utils::context::ParsingContext;
pub(crate) fn peek_ahead_for_mapping_key(
source: &mut dyn ISource,
directives: &DirectiveContext,
) -> bool {
if !source.more() {
return false;
}
let state = source.save_state();
let mut result = false;
if let Ok(mut stream) = TokenStream::new(source, directives, false) {
let mut flow_depth: i32 = 0;
while let Some(tok) = stream.current() {
match tok {
Token::Newline | Token::Eof => break,
Token::FlowSequenceStart | Token::FlowMappingStart => {
flow_depth += 1;
let _ = stream.next();
}
Token::FlowSequenceEnd | Token::FlowMappingEnd => {
flow_depth = std::cmp::max(0, flow_depth - 1);
let _ = stream.next();
}
Token::Colon => {
if flow_depth == 0 {
result = true;
break;
}
let _ = stream.next();
}
Token::Indent(_) | Token::Comment(_) => {
let _ = stream.next();
}
Token::Dash => {
if flow_depth == 0 {
result = false;
break;
} else {
let _ = stream.next();
}
}
_ => {
let _ = stream.next();
}
}
}
}
source.restore_state(state);
result
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum BlockHeadKind {
DocumentStartOrEnd,
Directive,
BlockSequence,
BlockMapping,
InlineMapping,
InlineSequence,
Alias,
Value,
CommentOrTrivia,
None,
}
pub(crate) fn classify_block_head(
source: &mut dyn ISource,
directives: &DirectiveContext,
_ctx: &ParsingContext,
) -> BlockHeadKind {
if !source.more() {
return BlockHeadKind::None;
}
let state = source.save_state();
let kind = if let Ok(stream) = TokenStream::new(source, directives, false) {
match stream.current() {
Some(Token::DocumentStart) | Some(Token::DocumentEnd) => {
BlockHeadKind::DocumentStartOrEnd
}
Some(Token::Directive(_)) => BlockHeadKind::Directive,
Some(Token::Dash) => BlockHeadKind::BlockSequence,
Some(Token::FlowMappingStart) => BlockHeadKind::InlineMapping,
Some(Token::FlowSequenceStart) => BlockHeadKind::InlineSequence,
Some(Token::Alias(_)) => BlockHeadKind::Alias,
Some(Token::Tag(_)) | Some(Token::Anchor(_)) => {
BlockHeadKind::Value
}
Some(Token::Plain(_))
| Some(Token::SingleQuoted(_))
| Some(Token::DoubleQuoted(..)) => {
if peek_ahead_for_mapping_key(source, directives) {
BlockHeadKind::BlockMapping
} else {
BlockHeadKind::Value
}
}
Some(Token::Comment(_)) | Some(Token::Indent(_)) | Some(Token::Newline) => {
BlockHeadKind::CommentOrTrivia
}
Some(Token::Colon) | Some(Token::QuestionMark) => BlockHeadKind::BlockMapping,
Some(Token::Eof) | None => BlockHeadKind::None,
_ => BlockHeadKind::None,
}
} else {
BlockHeadKind::None
};
source.restore_state(state);
kind
}