erl_parse 0.0.8

Erlang source code parser
Documentation
use erl_tokenize::LexicalToken;

use crate::traits::{Expect, Parse, ParseTail, TokenRead};
use crate::{Error, ErrorKind, Result};

#[derive(Debug)]
pub struct Parser<T> {
    reader: T,
    // TODO: optimize
    // (単一のバッファとトランザクション開始位置配列、に分離)
    transactions: Vec<Vec<LexicalToken>>,
    last_read_error: Option<Error>,
}
impl<T> Parser<T>
where
    T: TokenRead,
{
    pub fn new(reader: T) -> Self {
        Parser {
            reader,
            transactions: Vec::new(),
            last_read_error: None,
        }
    }
    pub fn parse<P: Parse>(&mut self) -> Result<P> {
        track!(P::parse(self))
    }
    pub fn parse_tail<P: ParseTail>(&mut self, head: P::Head) -> Result<P> {
        track!(P::parse_tail(self, head))
    }
    pub fn expect<P: Parse + Expect>(&mut self, expected: &P::Value) -> Result<P> {
        self.transaction(|parser| {
            let actual = track!(parser.parse::<P>(), "expected={:?}", expected)?;
            track!(actual.expect(expected))?;
            Ok(actual)
        })
    }
    pub fn expect_any<P: Parse + Expect>(&mut self, expected: &[&P::Value]) -> Result<P> {
        let actual = track!(self.parse::<P>())?;
        let mut last_error = None;
        for e in expected.iter() {
            if let Err(e) = track!(actual.expect(e)) {
                last_error = Some(e);
            } else {
                last_error = None;
                break;
            }
        }
        if let Some(e) = last_error {
            Err(e)
        } else {
            Ok(actual)
        }
    }
    pub fn peek<F, P>(&mut self, f: F) -> Result<P>
    where
        F: FnOnce(&mut Self) -> Result<P>,
    {
        self.start_transaction();
        let result = track!(f(self));
        self.abort_transaction();
        result
    }
    pub fn transaction<F, P>(&mut self, f: F) -> Result<P>
    where
        F: FnOnce(&mut Self) -> Result<P>,
    {
        self.start_transaction();
        let result = track!(f(self));
        if result.is_ok() {
            self.commit_transaction();
        } else {
            self.abort_transaction();
        }
        result
    }
    pub fn eos(&mut self) -> Result<bool> {
        if let Some(t) = track!(self.reader.try_read_token())? {
            self.reader.unread_token(t);
            Ok(false)
        } else {
            Ok(true)
        }
    }

    fn next_token(&mut self) -> Result<LexicalToken> {
        if let Some(ref e) = self.last_read_error {
            return Err(e.clone());
        }
        match self.reader.read_token() {
            Err(e) => {
                if let ErrorKind::UnexpectedEos = *e.kind() {
                } else {
                    self.last_read_error = Some(e.clone());
                }
                Err(e)
            }
            Ok(t) => {
                if let Some(tail) = self.transactions.last_mut() {
                    tail.push(t.clone());
                }
                Ok(t)
            }
        }
    }
    fn start_transaction(&mut self) {
        self.transactions.push(Vec::new());
    }
    fn commit_transaction(&mut self) {
        let last = self.transactions.pop().unwrap();
        if let Some(tail) = self.transactions.last_mut() {
            tail.extend(last);
        }
    }
    fn abort_transaction(&mut self) {
        let last = self.transactions.pop().unwrap();
        for t in last.into_iter().rev() {
            self.reader.unread_token(t);
        }
    }
}
impl<T> Parser<T> {
    pub fn reader(&self) -> &T {
        &self.reader
    }
    pub fn reader_mut(&mut self) -> &mut T {
        &mut self.reader
    }
    pub fn into_reader(self) -> T {
        self.reader
    }
}
impl Parse for LexicalToken {
    fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
    where
        T: TokenRead,
    {
        track!(parser.next_token())
    }
}