mod collect;
mod parse;
use super::*;
impl Parser {
pub(super) fn wrap_with_doc(&mut self, node: IrNode) -> ParseResult<IrNode> {
if let Some(doc) = self.pending_doc.take() {
let span = node.span();
Ok(IrNode::Documented {
span,
doc,
inner: Box::new(node),
})
} else {
Ok(node)
}
}
pub(super) fn looks_like_block_stmt(&self) -> bool {
if self.context_stack.len() > 1 {
return false;
}
let mut lookahead_pos = self.pos + 1;
while lookahead_pos < self.tokens.len() {
if self.tokens[lookahead_pos].kind == SyntaxKind::Whitespace {
lookahead_pos += 1;
} else {
break;
}
}
if lookahead_pos >= self.tokens.len() {
return false;
}
let next_kind = self.tokens[lookahead_pos].kind;
matches!(
next_kind,
SyntaxKind::ConstKw
| SyntaxKind::LetKw
| SyntaxKind::VarKw
| SyntaxKind::IfKw
| SyntaxKind::ForKw
| SyntaxKind::WhileKw
| SyntaxKind::ReturnKw
| SyntaxKind::ThrowKw
| SyntaxKind::RBrace )
}
pub(super) fn peek_is_enum(&self) -> bool {
let mut lookahead_pos = self.pos + 1;
while lookahead_pos < self.tokens.len() {
if self.tokens[lookahead_pos].kind == SyntaxKind::Whitespace {
lookahead_pos += 1;
} else {
break;
}
}
if lookahead_pos >= self.tokens.len() {
return false;
}
self.tokens[lookahead_pos].kind == SyntaxKind::EnumKw
}
pub(super) fn placeholder_kind(&self) -> PlaceholderKind {
let ctx_kind = self.current_context_kind();
let kind = match ctx_kind {
ContextKind::TypeAnnotation
| ContextKind::TypeAssertion
| ContextKind::GenericParams => PlaceholderKind::Type,
ContextKind::Identifier | ContextKind::InterfaceMember => PlaceholderKind::Ident,
ContextKind::Statement => PlaceholderKind::Stmt,
ContextKind::Expression(_) | ContextKind::Parameters => PlaceholderKind::Expr,
};
#[cfg(debug_assertions)]
if std::env::var("MF_DEBUG_PARSER").is_ok() {
eprintln!(
"[MF_DEBUG_PARSER] placeholder_kind: ctx={:?}, kind={:?}, stack={:?}",
ctx_kind, kind, self.context_stack
);
}
kind
}
pub(super) fn merge_adjacent_text(nodes: Vec<IrNode>) -> Vec<IrNode> {
let mut result = Vec::with_capacity(nodes.len());
let mut pending_text = String::new();
for node in nodes {
match node {
IrNode::StrLit { value, .. } | IrNode::Ident { value, .. } => {
pending_text.push_str(&value);
}
other => {
if !pending_text.is_empty() {
result.push(IrNode::StrLit {
span: IrSpan::empty(),
value: std::mem::take(&mut pending_text),
});
}
result.push(other);
}
}
}
if !pending_text.is_empty() {
result.push(IrNode::StrLit {
span: IrSpan::empty(),
value: pending_text,
});
}
result
}
}