lang: improve and simplify error handling and storage
fixes wrong error ordering with errors using `forward_parents`.
This commit is contained in:
parent
ed151c2e3c
commit
f6da90a354
8 changed files with 110 additions and 42 deletions
|
@ -1,6 +1,12 @@
|
|||
use drop_bomb::DropBomb;
|
||||
|
||||
use self::{error::SyntaxError, events::Event, input::Input, syntax_kind::SyntaxKind};
|
||||
use self::{
|
||||
error::SyntaxError,
|
||||
events::{Event, NodeKind},
|
||||
input::Input,
|
||||
syntax_kind::SyntaxKind,
|
||||
};
|
||||
use std::cell::Cell;
|
||||
|
||||
pub mod syntax_kind;
|
||||
#[cfg(test)]
|
||||
|
@ -12,11 +18,13 @@ pub mod grammar;
|
|||
pub mod input;
|
||||
pub mod output;
|
||||
|
||||
const PARSER_STEP_LIMIT: u32 = 4096;
|
||||
|
||||
pub struct Parser<'src, 'toks> {
|
||||
input: Input<'src, 'toks>,
|
||||
pos: usize,
|
||||
events: Vec<Event>,
|
||||
errors: Vec<SyntaxError>,
|
||||
steps: Cell<u32>,
|
||||
}
|
||||
|
||||
impl<'src, 'toks> Parser<'src, 'toks> {
|
||||
|
@ -25,15 +33,16 @@ impl<'src, 'toks> Parser<'src, 'toks> {
|
|||
input,
|
||||
pos: 0,
|
||||
events: Vec::new(),
|
||||
errors: Vec::new(),
|
||||
steps: Cell::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish(self) -> (Vec<Event>, Vec<SyntaxError>) {
|
||||
(self.events, self.errors)
|
||||
pub fn finish(self) -> Vec<Event> {
|
||||
self.events
|
||||
}
|
||||
|
||||
pub(crate) fn nth(&self, n: usize) -> SyntaxKind {
|
||||
self.step();
|
||||
self.input.kind(self.pos + n)
|
||||
}
|
||||
|
||||
|
@ -44,6 +53,7 @@ impl<'src, 'toks> Parser<'src, 'toks> {
|
|||
}
|
||||
|
||||
pub(crate) fn current(&self) -> SyntaxKind {
|
||||
self.step();
|
||||
self.input.kind(self.pos)
|
||||
}
|
||||
|
||||
|
@ -80,6 +90,12 @@ impl<'src, 'toks> Parser<'src, 'toks> {
|
|||
fn push_ev(&mut self, event: Event) {
|
||||
self.events.push(event)
|
||||
}
|
||||
|
||||
fn step(&self) {
|
||||
let steps = self.steps.get();
|
||||
assert!(steps <= PARSER_STEP_LIMIT, "the parser seems stuck...");
|
||||
self.steps.set(steps + 1);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Marker {
|
||||
|
@ -95,12 +111,13 @@ impl Marker {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn complete(mut self, p: &mut Parser<'_, '_>, kind: SyntaxKind) -> CompletedMarker {
|
||||
fn complete_node(mut self, p: &mut Parser, kind: NodeKind) -> CompletedMarker {
|
||||
self.bomb.defuse();
|
||||
match &mut p.events[self.pos] {
|
||||
Event::Start { kind: slot, .. } => *slot = kind,
|
||||
Event::Start { kind: slot, .. } => *slot = kind.clone(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
p.push_ev(Event::Finish);
|
||||
|
||||
CompletedMarker {
|
||||
|
@ -109,9 +126,12 @@ impl Marker {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn complete_err(mut self, p: &mut Parser, kind: SyntaxError) -> CompletedMarker {
|
||||
p.errors.push(kind);
|
||||
self.complete(p, SyntaxKind::PARSE_ERR)
|
||||
pub(crate) fn complete(self, p: &mut Parser<'_, '_>, kind: SyntaxKind) -> CompletedMarker {
|
||||
self.complete_node(p, NodeKind::Syntax(kind))
|
||||
}
|
||||
|
||||
pub(crate) fn error(self, p: &mut Parser, kind: SyntaxError) -> CompletedMarker {
|
||||
self.complete_node(p, NodeKind::Error(kind))
|
||||
}
|
||||
|
||||
pub(crate) fn abandon(mut self, p: &mut Parser<'_, '_>) {
|
||||
|
@ -119,7 +139,7 @@ impl Marker {
|
|||
if self.pos == p.events.len() - 1 {
|
||||
match p.events.pop() {
|
||||
Some(Event::Start {
|
||||
kind: SyntaxKind::TOMBSTONE,
|
||||
kind: NodeKind::Syntax(SyntaxKind::TOMBSTONE),
|
||||
forward_parent: None,
|
||||
}) => (),
|
||||
_ => unreachable!(),
|
||||
|
@ -130,7 +150,7 @@ impl Marker {
|
|||
|
||||
pub(crate) struct CompletedMarker {
|
||||
pos: usize,
|
||||
kind: SyntaxKind,
|
||||
kind: NodeKind,
|
||||
}
|
||||
|
||||
impl CompletedMarker {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue