iowo/crates/lang/src/lst_parser.rs

150 lines
3.5 KiB
Rust
Raw Normal View History

2024-04-24 09:07:38 +00:00
use drop_bomb::DropBomb;
use self::{error::SyntaxError, events::Event, input::Input, syntax_kind::SyntaxKind};
pub mod syntax_kind;
2024-04-02 22:30:11 +00:00
#[cfg(test)]
mod tests;
2024-04-24 09:07:38 +00: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-02 22:08:00 +00:00
}
2024-04-24 09:07:38 +00: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-02 22:08:00 +00:00
}
2024-04-24 09:07:38 +00: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-24 09:07:38 +00:00
}
2024-04-24 09:07:38 +00:00
pub(crate) fn current(&self) -> SyntaxKind {
self.input.kind(self.pos)
}
2024-04-24 17:55:16 +00:00
pub(crate) fn start(&mut self, name: &str) -> Marker {
2024-04-24 09:07:38 +00:00
let pos = self.events.len();
self.push_ev(Event::tombstone());
2024-04-24 17:55:16 +00:00
Marker::new(pos, name)
2024-04-24 09:07:38 +00:00
}
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-24 09:07:38 +00:00
fn push_ev(&mut self, event: Event) {
self.events.push(event)
}
2024-04-02 22:08:00 +00:00
}
2024-04-08 12:04:52 +00:00
2024-04-24 09:07:38 +00:00
pub(crate) struct Marker {
pos: usize,
bomb: DropBomb,
}
impl Marker {
2024-04-24 17:55:16 +00:00
pub(crate) fn new(pos: usize, name: &str) -> Self {
2024-04-24 09:07:38 +00:00
Self {
pos,
2024-04-24 17:55:16 +00:00
bomb: DropBomb::new(format!("Marker {name} must be completed or abandoned")),
2024-04-24 09:07:38 +00:00
}
}
2024-04-24 17:37:52 +00:00
2024-04-24 09:07:38 +00: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 17:37:52 +00: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 09:07:38 +00: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<'_, '_>, name: &str) -> Marker {
let new_pos = p.start(name);
2024-04-24 09:07:38 +00:00
match &mut p.events[self.pos] {
Event::Start { forward_parent, .. } => {
*forward_parent = Some(new_pos.pos - self.pos);
}
_ => unreachable!(),
}
2024-04-08 12:04:52 +00:00
2024-04-24 09:07:38 +00:00
new_pos
}
2024-04-08 12:04:52 +00:00
}