use crate::{
builder::Builder, context::Context, input::Input, lexer::Token, parser::State,
position::SourceSpan,
};
use core::fmt::Debug;
pub trait LRBuilder<'i, I, C, S, P, TK>: Builder
where
I: Input + ?Sized,
C: Context<'i, I, S, TK>,
S: State,
{
fn shift_action(&mut self, context: &C, token: Token<'i, I, TK>);
fn reduce_action(&mut self, context: &C, prod: P, prod_len: usize);
}
pub struct TreeBuilder<'i, I, P, TK>
where
I: Input + ?Sized,
{
res_stack: Vec<TreeNode<'i, I, P, TK>>,
}
impl<I, P, TK> TreeBuilder<'_, I, P, TK>
where
I: Input + ?Sized,
{
pub fn new() -> Self {
Self { res_stack: vec![] }
}
}
impl<I, P, TK> Default for TreeBuilder<'_, I, P, TK>
where
I: Input + ?Sized,
{
fn default() -> Self {
Self::new()
}
}
impl<'i, I, P, TK> Builder for TreeBuilder<'i, I, P, TK>
where
I: Input + ?Sized,
{
type Output = TreeNode<'i, I, P, TK>;
fn get_result(&mut self) -> Self::Output {
self.res_stack.pop().unwrap()
}
}
impl<'i, I, C, S, P, TK> LRBuilder<'i, I, C, S, P, TK> for TreeBuilder<'i, I, P, TK>
where
I: Input + ?Sized,
C: Context<'i, I, S, TK>,
S: State,
{
fn shift_action(&mut self, context: &C, token: Token<'i, I, TK>) {
self.res_stack.push(TreeNode::TermNode {
token,
layout: context.layout_ahead(),
})
}
fn reduce_action(&mut self, context: &C, prod: P, prod_len: usize) {
let children;
let layout;
if prod_len > 0 {
children = self.res_stack.split_off(self.res_stack.len() - prod_len);
layout = match children[0] {
TreeNode::TermNode { layout, .. } => layout,
TreeNode::NonTermNode { layout, .. } => layout,
};
} else {
children = vec![];
layout = None;
}
self.res_stack.push(TreeNode::NonTermNode {
children,
prod,
span: context.span(),
layout,
});
}
}
#[derive(Debug)]
pub enum TreeNode<'i, I, P, TK>
where
I: Input + ?Sized,
{
TermNode {
token: Token<'i, I, TK>,
layout: Option<&'i I>,
},
NonTermNode {
prod: P,
span: SourceSpan,
children: Vec<TreeNode<'i, I, P, TK>>,
layout: Option<&'i I>,
},
}
pub struct SliceBuilder<'i, I: ?Sized> {
input: &'i I,
slice: Option<&'i I>,
}
impl<'i, I> SliceBuilder<'i, I>
where
I: Input + ?Sized,
{
pub fn new(input: &'i I) -> Self {
Self { input, slice: None }
}
}
impl<'i, I> Builder for SliceBuilder<'i, I>
where
I: Input + ?Sized,
{
type Output = Option<&'i I>;
fn get_result(&mut self) -> Self::Output {
self.slice
}
}
impl<'i, I, C, S, P, TK> LRBuilder<'i, I, C, S, P, TK> for SliceBuilder<'i, I>
where
I: Input + ?Sized,
C: Context<'i, I, S, TK>,
S: State,
{
fn shift_action(&mut self, _context: &C, _token: Token<'i, I, TK>) {
}
fn reduce_action(&mut self, context: &C, _prod: P, _prod_len: usize) {
self.slice = Some(&self.input[context.span().into()]);
}
}