lopal_core 0.1.0

Lossless Parser Library. Parses to rowan LSTs.
Documentation
use drop_bomb::DropBomb;

use super::{
    error::SyntaxError,
    event::{Event, NodeKind},
    Parser, SyntaxElement,
};

pub struct Marker {
    pos: usize,
    bomb: DropBomb,
}

impl Marker {
    pub(super) fn new(pos: usize, name: &str) -> Self {
        Self {
            pos,
            bomb: DropBomb::new(format!("Marker {name} must be completed or abandoned.")),
        }
    }

    fn close_node<SyntaxKind: SyntaxElement, SyntaxErr: SyntaxError>(
        mut self,
        p: &mut Parser<SyntaxKind, SyntaxErr>,
        kind: NodeKind<SyntaxKind, SyntaxErr>,
    ) -> CompletedMarker<SyntaxKind, SyntaxErr> {
        self.bomb.defuse();

        match &mut p.events[self.pos] {
            Event::Start { kind: slot, .. } => *slot = kind.clone(),
            _ => unreachable!(),
        }

        p.push_ev(Event::Finish);
        CompletedMarker {
            pos: self.pos,
            kind,
        }
    }

    pub fn complete<SyntaxKind: SyntaxElement, SyntaxErr: SyntaxError>(
        self,
        p: &mut Parser<SyntaxKind, SyntaxErr>,
        kind: SyntaxKind,
    ) -> CompletedMarker<SyntaxKind, SyntaxErr> {
        self.close_node(p, NodeKind::Syntax(kind))
    }

    pub fn error<SyntaxKind: SyntaxElement, SyntaxErr: SyntaxError>(
        self,
        p: &mut Parser<SyntaxKind, SyntaxErr>,
        kind: SyntaxErr,
    ) -> CompletedMarker<SyntaxKind, SyntaxErr> {
        self.close_node(p, NodeKind::Error(kind))
    }

    pub fn abandon<SyntaxKind: SyntaxElement, SyntaxErr: SyntaxError>(
        mut self,
        p: &mut Parser<SyntaxKind, SyntaxErr>,
    ) {
        self.bomb.defuse();

        // clean up empty tombstone event from marker
        if self.pos == p.events.len() - 1 {
            match p.events.pop() {
                Some(Event::Start {
                    kind: NodeKind::Tombstone,
                    forward_parent: None,
                }) => (),
                _ => unreachable!(),
            }
        }
    }
}

pub struct CompletedMarker<SyntaxKind: SyntaxElement, SyntaxErr: SyntaxError> {
    pos: usize,
    kind: NodeKind<SyntaxKind, SyntaxErr>,
}

impl<SyntaxKind: SyntaxElement, SyntaxErr: SyntaxError> CompletedMarker<SyntaxKind, SyntaxErr> {
    pub fn precede(self, p: &mut Parser<SyntaxKind, SyntaxErr>, name: &str) -> Marker {
        let new_pos = p.start(name);

        match &mut p.events[self.pos] {
            Event::Start { forward_parent, .. } => {
                // point forward parent of the node this marker completed to the new node
                // will later be used to make the new node a parent of the current node.
                *forward_parent = Some(new_pos.pos - self.pos);
            }
            _ => unreachable!(),
        }

        new_pos
    }
}