use crate::parser::cursor;
use crate::parser::diagnostics;
use crate::parser::diagnostics::ParseDiagnostic;
use crate::parser::lexer::Token;
pub(crate) struct ParserCtx<'a> {
tokens: &'a [Token],
}
impl<'a> ParserCtx<'a> {
pub(crate) fn new(tokens: &'a [Token]) -> Self {
Self { tokens }
}
pub(crate) fn token(&self, i: usize) -> Option<&'a Token> {
self.tokens.get(i)
}
pub(crate) fn tokens(&self) -> &'a [Token] {
self.tokens
}
pub(crate) fn skip_ws(&self, i: usize) -> usize {
cursor::skip_ws(self.tokens, i)
}
pub(crate) fn skip_ws_and_newlines(&self, i: usize) -> usize {
cursor::skip_ws_and_newlines(self.tokens, i)
}
pub(crate) fn skip_ws_newlines_comments(&self, i: usize) -> usize {
cursor::skip_ws_newlines_comments(self.tokens, i)
}
}
#[derive(Default)]
pub(crate) struct StatementTracker {
prev_end: Option<usize>,
prev_recovered: bool,
}
impl StatementTracker {
pub(crate) fn record(
&mut self,
tokens: &[Token],
start: usize,
end: usize,
recovered: bool,
diagnostics_out: &mut Vec<ParseDiagnostic>,
) {
if let Some(prev_end) = self.prev_end
&& !self.prev_recovered
&& !recovered
&& !cursor::has_statement_separator(tokens, prev_end, start)
&& let Some(token) = tokens.get(start)
{
diagnostics::push_token_diagnostic(
diagnostics_out,
diagnostics::MISSING_STATEMENT_SEPARATOR,
token,
);
}
self.prev_end = Some(end);
self.prev_recovered = recovered;
}
pub(crate) fn record_recovery(&mut self, end: usize) {
self.prev_end = Some(end);
self.prev_recovered = true;
}
}
pub(crate) fn push_token_diagnostic_ctx(
diagnostics_out: &mut Vec<ParseDiagnostic>,
message: &str,
token: &Token,
) {
diagnostics::push_token_diagnostic(diagnostics_out, message, token);
}