use crate::grammar::{AstNodeId, HasTokenType, Index, TokenId};
pub struct ReductionList<'a, T, A> {
indices: &'a [Index],
tokens: &'a [T],
nodes: &'a [A],
}
impl<'a, T: HasTokenType, A> ReductionList<'a, T, A> {
#[must_use]
pub const fn new(indices: &'a [Index], tokens: &'a [T], nodes: &'a [A]) -> Self {
Self {
indices,
tokens,
nodes,
}
}
#[must_use]
pub fn token_id(&self, index: usize) -> TokenId {
self.indices[index].as_token_id()
}
#[must_use]
pub fn token(&self, index: usize) -> &'a T {
&self.tokens[self.token_id(index).0]
}
#[must_use]
pub fn node(&self, index: usize) -> AstNodeId {
self.indices[index].as_ast_node_id()
}
#[must_use]
pub fn ast_node(&self, index: usize) -> &'a A {
&self.nodes[self.node(index).0]
}
}
#[macro_export]
macro_rules! rule {
(|$list:ident| Passthrough($index:expr)) => {
|indices, _tokens, _nodes| {
$crate::grammar::ReductionResult::Forward(indices[$index].as_ast_node_id())
}
};
(|$list:ident| $list2:ident.node($index:expr)) => {
|indices, _tokens, _nodes| {
$crate::grammar::ReductionResult::Forward(indices[$index].as_ast_node_id())
}
};
(|$list:ident| $body:expr) => {
|indices, tokens, nodes| {
let $list = $crate::grammar::builder::ReductionList::new(indices, tokens, nodes);
$crate::grammar::ReductionResult::NewNode($body)
}
};
}
#[macro_export]
macro_rules! extract {
($token:expr, $pattern:pat => $result:expr) => {
match $token {
$pattern => $result,
_ => unreachable!("Token pattern mismatch"),
}
};
}