2024-04-24 11:07:38 +02:00
|
|
|
use drop_bomb::DropBomb;
|
|
|
|
|
|
|
|
use self::{error::SyntaxError, events::Event, input::Input, syntax_kind::SyntaxKind};
|
|
|
|
|
|
|
|
pub mod syntax_kind;
|
2024-04-03 00:30:11 +02:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests;
|
2024-04-24 11:07:38 +02:00
|
|
|
|
|
|
|
pub mod error;
|
|
|
|
pub mod events;
|
|
|
|
pub mod grammar;
|
|
|
|
pub mod input;
|
|
|
|
pub mod output;
|
|
|
|
|
|
|
|
pub struct Parser<'src, 'toks> {
|
|
|
|
input: Input<'src, 'toks>,
|
|
|
|
pos: usize,
|
|
|
|
events: Vec<Event>,
|
|
|
|
errors: Vec<SyntaxError>,
|
2024-04-03 00:08:00 +02:00
|
|
|
}
|
2024-04-24 11:07:38 +02:00
|
|
|
|
|
|
|
impl<'src, 'toks> Parser<'src, 'toks> {
|
|
|
|
pub fn new(input: Input<'src, 'toks>) -> Self {
|
|
|
|
Self {
|
|
|
|
input,
|
|
|
|
pos: 0,
|
|
|
|
events: Vec::new(),
|
|
|
|
errors: Vec::new(),
|
2024-04-03 00:08:00 +02:00
|
|
|
}
|
2024-04-24 11:07:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn finish(self) -> (Vec<Event>, Vec<SyntaxError>) {
|
|
|
|
(self.events, self.errors)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn nth(&self, n: usize) -> SyntaxKind {
|
|
|
|
self.input.kind(self.pos + n)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn eat_succeeding_ws(&mut self) {
|
|
|
|
self.push_ev(Event::Eat {
|
|
|
|
count: self.input.meaningless_tail_len(),
|
2024-04-11 03:23:03 +02:00
|
|
|
});
|
2024-04-24 11:07:38 +02:00
|
|
|
}
|
2024-04-11 03:23:03 +02:00
|
|
|
|
2024-04-24 11:07:38 +02:00
|
|
|
pub(crate) fn current(&self) -> SyntaxKind {
|
|
|
|
self.input.kind(self.pos)
|
|
|
|
}
|
2024-04-11 03:23:03 +02:00
|
|
|
|
2024-04-24 11:07:38 +02:00
|
|
|
pub(crate) fn start(&mut self) -> Marker {
|
|
|
|
let pos = self.events.len();
|
|
|
|
self.push_ev(Event::tombstone());
|
|
|
|
Marker::new(pos)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn at(&self, kind: SyntaxKind) -> bool {
|
|
|
|
self.nth_at(0, kind)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn eat(&mut self, kind: SyntaxKind) -> bool {
|
|
|
|
if !self.at(kind) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.do_bump();
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn nth_at(&self, n: usize, kind: SyntaxKind) -> bool {
|
|
|
|
self.nth(n) == kind
|
|
|
|
}
|
|
|
|
|
|
|
|
fn do_bump(&mut self) {
|
|
|
|
self.push_ev(Event::Eat {
|
|
|
|
count: self.input.preceding_meaningless(self.pos),
|
|
|
|
});
|
|
|
|
self.pos += 1;
|
|
|
|
}
|
2024-04-11 03:23:03 +02:00
|
|
|
|
2024-04-24 11:07:38 +02:00
|
|
|
fn push_ev(&mut self, event: Event) {
|
|
|
|
self.events.push(event)
|
|
|
|
}
|
2024-04-03 00:08:00 +02:00
|
|
|
}
|
2024-04-08 14:04:52 +02:00
|
|
|
|
2024-04-24 11:07:38 +02:00
|
|
|
pub(crate) struct Marker {
|
|
|
|
pos: usize,
|
|
|
|
bomb: DropBomb,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Marker {
|
|
|
|
pub(crate) fn new(pos: usize) -> Self {
|
|
|
|
Self {
|
|
|
|
pos,
|
|
|
|
bomb: DropBomb::new("Marker must be completed or abandoned"),
|
|
|
|
}
|
|
|
|
}
|
2024-04-24 19:37:52 +02:00
|
|
|
|
2024-04-24 11:07:38 +02:00
|
|
|
pub(crate) fn complete(mut self, p: &mut Parser<'_, '_>, kind: SyntaxKind) -> CompletedMarker {
|
|
|
|
self.bomb.defuse();
|
|
|
|
match &mut p.events[self.pos] {
|
|
|
|
Event::Start { kind: slot, .. } => *slot = kind,
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
p.push_ev(Event::Finish);
|
|
|
|
|
|
|
|
CompletedMarker {
|
|
|
|
pos: self.pos,
|
|
|
|
kind,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-24 19:37:52 +02:00
|
|
|
pub(crate) fn complete_err(mut self, p: &mut Parser, kind: SyntaxError) -> CompletedMarker {
|
|
|
|
p.errors.push(kind);
|
|
|
|
self.complete(p, SyntaxKind::PARSE_ERR)
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:07:38 +02:00
|
|
|
pub(crate) fn abandon(mut self, p: &mut Parser<'_, '_>) {
|
|
|
|
self.bomb.defuse();
|
|
|
|
if self.pos == p.events.len() - 1 {
|
|
|
|
match p.events.pop() {
|
|
|
|
Some(Event::Start {
|
|
|
|
kind: SyntaxKind::TOMBSTONE,
|
|
|
|
forward_parent: None,
|
|
|
|
}) => (),
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) struct CompletedMarker {
|
|
|
|
pos: usize,
|
|
|
|
kind: SyntaxKind,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CompletedMarker {
|
|
|
|
pub(crate) fn precede(self, p: &mut Parser<'_, '_>) -> Marker {
|
|
|
|
let new_pos = p.start();
|
|
|
|
|
|
|
|
match &mut p.events[self.pos] {
|
|
|
|
Event::Start { forward_parent, .. } => {
|
|
|
|
*forward_parent = Some(new_pos.pos - self.pos);
|
|
|
|
}
|
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
2024-04-08 14:04:52 +02:00
|
|
|
|
2024-04-24 11:07:38 +02:00
|
|
|
new_pos
|
|
|
|
}
|
2024-04-08 14:04:52 +02:00
|
|
|
}
|