#![deny(missing_docs)]
pub trait Parser {
type Terminal;
type Nonterminal;
#[inline(always)]
fn peek(&mut self) -> &Self::Terminal;
#[inline(always)]
fn shift(&mut self, state_fn: fn(&mut Self), goto_fn: fn(&mut Self, Self::Nonterminal));
#[inline(always)]
fn goto(
&mut self,
nonterminal: Self::Nonterminal,
state_fn: fn(&mut Self),
goto_fn: fn(&mut Self, Self::Nonterminal),
);
#[inline(always)]
fn reduce<F: Fn(Vec<Symbol<Self::Terminal, Self::Nonterminal>>) -> Self::Nonterminal>(
&mut self,
length: usize,
f: F,
);
fn accept(&mut self);
}
#[allow(missing_docs)]
pub enum Symbol<T, NT> {
Terminal(T),
Nonterminal(NT),
}
impl<T, NT> Symbol<T, NT> {
#[inline(always)]
pub fn unwrap_terminal(self) -> T {
match self {
Symbol::Terminal(x) => x,
_ => panic!("symbol is not a terminal"),
}
}
#[inline(always)]
pub fn unwrap_nonterminal(self) -> NT {
match self {
Symbol::Nonterminal(x) => x,
_ => panic!("symbol is not a nonterminal"),
}
}
}
pub trait StateSpace {
type Terminal;
type Nonterminal;
type Root;
fn root_state_fn<P: Parser<Terminal = Self::Terminal, Nonterminal = Self::Nonterminal>>(
) -> fn(&mut P);
fn root_goto_fn<P: Parser<Terminal = Self::Terminal, Nonterminal = Self::Nonterminal>>(
) -> fn(&mut P, Self::Nonterminal);
}
pub struct ParserMachine<I: ParserInput, S: StateSpace> {
input: I,
result: Option<S::Nonterminal>,
stack: Vec<StackEntry<I, S>>,
}
struct StackEntry<I: ParserInput, S: StateSpace> {
symbol: Symbol<S::Terminal, S::Nonterminal>,
state_fn: fn(&mut ParserMachine<I, S>),
goto_fn: fn(&mut ParserMachine<I, S>, S::Nonterminal),
}
impl<I: ParserInput<Item = S::Terminal>, S: StateSpace> ParserMachine<I, S> {
pub fn new(input: I) -> ParserMachine<I, S> {
ParserMachine {
input: input,
result: None,
stack: Vec::new(),
}
}
fn step(&mut self) {
if self.result.is_some() {
return;
}
let state_fn = self.stack
.last()
.map(|e| e.state_fn)
.unwrap_or(S::root_state_fn());
state_fn(self);
}
pub fn run(mut self) -> S::Nonterminal {
while self.result.is_none() {
self.step()
}
self.result.unwrap()
}
}
impl<I: Iterator, S: StateSpace<Terminal = Option<I::Item>>> ParserMachine<IterInput<I>, S> {
pub fn from_iter(input: I) -> ParserMachine<IterInput<I>, S> {
ParserMachine::new(IterInput::new(input))
}
}
impl<I, S> Parser for ParserMachine<I, S>
where
I: ParserInput<Item = S::Terminal>,
S: StateSpace,
{
type Terminal = S::Terminal;
type Nonterminal = S::Nonterminal;
fn peek(&mut self) -> &S::Terminal {
self.input.peek()
}
fn shift(&mut self, state_fn: fn(&mut Self), goto_fn: fn(&mut Self, S::Nonterminal)) {
let terminal = self.input.next();
self.stack.push(StackEntry {
symbol: Symbol::Terminal(terminal),
state_fn: state_fn,
goto_fn: goto_fn,
});
}
fn goto(
&mut self,
nonterminal: S::Nonterminal,
state_fn: fn(&mut Self),
goto_fn: fn(&mut Self, S::Nonterminal),
) {
self.stack.push(StackEntry {
symbol: Symbol::Nonterminal(nonterminal),
state_fn: state_fn,
goto_fn: goto_fn,
});
}
fn reduce<F: Fn(Vec<Symbol<S::Terminal, S::Nonterminal>>) -> S::Nonterminal>(
&mut self,
length: usize,
f: F,
) {
let at = self.stack.len() - length;
let args = self.stack.drain(at..).map(|e| e.symbol).collect();
let goto_fn = self.stack
.last()
.map(|e| e.goto_fn)
.unwrap_or(S::root_goto_fn());
let nonterminal = f(args);
goto_fn(self, nonterminal);
}
fn accept(&mut self) {
self.result = Some(self.stack.pop().unwrap().symbol.unwrap_nonterminal());
}
}
pub trait ParserInput {
type Item;
#[inline(always)]
fn peek(&mut self) -> &Self::Item;
#[inline(always)]
fn next(&mut self) -> Self::Item;
#[inline(always)]
fn marker() -> Self::Item;
}
pub struct IterInput<I: Iterator> {
iter: I,
peek: Option<I::Item>,
}
impl<I: Iterator> IterInput<I> {
pub fn new(mut iter: I) -> IterInput<I> {
IterInput {
peek: iter.next(),
iter: iter,
}
}
}
impl<I: Iterator> ParserInput for IterInput<I> {
type Item = Option<I::Item>;
fn peek(&mut self) -> &Self::Item {
&self.peek
}
fn next(&mut self) -> Self::Item {
std::mem::replace(&mut self.peek, self.iter.next())
}
fn marker() -> Self::Item {
None
}
}