use rowan::Checkpoint;
use crate::diagnostics::DiagnosticKind;
use crate::parser::Parser;
use crate::parser::cst::SyntaxKind;
use crate::parser::cst::token_sets::{EXPR_FIRST_TOKENS, QUANTIFIERS};
use crate::parser::lexer::token_text;
impl Parser<'_, '_> {
pub(crate) fn parse_type_annotation(&mut self) {
self.start_node(SyntaxKind::Type);
self.expect(SyntaxKind::DoubleColon, "'::' for type annotation");
if self.currently_is(SyntaxKind::Id) {
let span = self.current_span();
let text = token_text(self.source, &self.tokens[self.pos]);
self.bump();
self.validate_type_name(text, span);
} else {
self.error(DiagnosticKind::ExpectedTypeName);
}
self.finish_node();
}
pub(crate) fn parse_type_annotation_single_colon(&mut self) {
if !self.next_is(SyntaxKind::Id) {
return;
}
self.start_node(SyntaxKind::Type);
let span = self.current_span();
self.error_with_fix(
DiagnosticKind::InvalidTypeAnnotationSyntax,
span,
"single `:` looks like a field",
"use `::`",
"::",
);
self.bump();
if self.currently_is(SyntaxKind::Id) {
self.bump();
}
self.finish_node();
}
pub(crate) fn parse_negated_field(&mut self) {
self.start_node(SyntaxKind::NegatedField);
if self.currently_is(SyntaxKind::Negation) {
let span = self.current_span();
self.diagnostics
.report(
self.source_id,
DiagnosticKind::NegationSyntaxDeprecated,
span,
)
.emit();
self.bump();
} else {
self.expect(SyntaxKind::Minus, "'-' for negated field");
}
if !self.currently_is(SyntaxKind::Id) {
self.error(DiagnosticKind::ExpectedFieldName);
self.finish_node();
return;
}
let span = self.current_span();
let text = token_text(self.source, &self.tokens[self.pos]);
self.bump();
self.validate_field_name(text, span);
self.finish_node();
}
pub(crate) fn parse_tree_or_field(&mut self) {
if self.next_is(SyntaxKind::Colon) {
self.parse_field();
return;
}
if self.next_is(SyntaxKind::Equals) {
self.parse_field_equals_typo();
return;
}
let span = self.current_span();
let text = token_text(self.source, &self.tokens[self.pos]);
self.diagnostics
.report(self.source_id, DiagnosticKind::BareIdentifier, span)
.fix("wrap in parentheses", format!("({})", text))
.emit();
self.bump_as_error();
}
pub(crate) fn parse_field(&mut self) {
self.start_node(SyntaxKind::Field);
self.assert_current(SyntaxKind::Id);
let span = self.current_span();
let text = token_text(self.source, &self.tokens[self.pos]);
self.bump();
self.validate_field_name(text, span);
self.expect(
SyntaxKind::Colon,
"':' to separate field name from its value",
);
if self.currently_is_one_of(EXPR_FIRST_TOKENS) {
self.parse_expr_no_suffix();
} else {
self.error(DiagnosticKind::ExpectedExpression);
}
self.finish_node();
}
pub(crate) fn parse_field_equals_typo(&mut self) {
self.start_node(SyntaxKind::Field);
self.bump();
let span = self.current_span();
self.error_with_fix(
DiagnosticKind::InvalidFieldEquals,
span,
"this isn't a definition",
"use `:`",
":",
);
self.bump();
if self.currently_is_one_of(EXPR_FIRST_TOKENS) {
self.parse_expr();
} else {
self.error(DiagnosticKind::ExpectedExpression);
}
self.finish_node();
}
pub(crate) fn try_parse_quantifier(&mut self, checkpoint: Checkpoint) {
if self.currently_is_one_of(QUANTIFIERS) {
self.start_node_at(checkpoint, SyntaxKind::Quantifier);
self.bump();
self.finish_node();
}
}
pub(crate) fn try_parse_capture(&mut self, checkpoint: Checkpoint) {
let is_capture = self.currently_is(SyntaxKind::CaptureToken);
let is_suppressive = self.currently_is(SyntaxKind::SuppressiveCapture);
if !is_capture && !is_suppressive {
return;
}
self.start_node_at(checkpoint, SyntaxKind::Capture);
self.drain_trivia();
let span = self.current_span();
let text = token_text(self.source, &self.tokens[self.pos]);
let name = &text[1..]; self.validate_capture_name(name, span);
self.bump();
if is_capture {
if self.currently_is(SyntaxKind::DoubleColon) {
self.parse_type_annotation();
} else if self.currently_is(SyntaxKind::Colon) {
self.parse_type_annotation_single_colon();
}
}
self.finish_node();
}
}