pub mod builder;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct TokenType(pub u32);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct AstNodeType(pub u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum GrammarItem {
Token(TokenType),
AstNode(AstNodeType),
}
impl From<TokenType> for GrammarItem {
fn from(token: TokenType) -> Self {
Self::Token(token)
}
}
impl From<AstNodeType> for GrammarItem {
fn from(node: AstNodeType) -> Self {
Self::AstNode(node)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct TokenId(pub usize);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct AstNodeId(pub usize);
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Index {
Token(TokenId),
AstNode(AstNodeId),
}
impl Index {
#[must_use]
pub fn as_token_id(&self) -> TokenId {
let &Self::Token(id) = self else {
panic!("Expected `Token`, found `AstNode`")
};
id
}
#[must_use]
pub fn as_ast_node_id(&self) -> AstNodeId {
let &Self::AstNode(id) = self else {
panic!("Expected `AstNode`, found `Token`")
};
id
}
}
#[derive(Debug, Clone)]
pub enum ReductionResult<A> {
NewNode(A),
Forward(AstNodeId),
}
pub trait HasTokenType {
fn token_type(&self) -> TokenType;
}
pub type ReductionFn<T, A> = fn(&[Index], &[T], &[A]) -> ReductionResult<A>;
#[derive(Debug, Clone)]
pub struct GrammarRule<T, A> {
pub result: AstNodeType,
pub components: Vec<GrammarItem>,
pub reduction: ReductionFn<T, A>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GrammarRuleId(pub usize);
#[derive(Clone)]
pub struct Grammar<T, A> {
pub root_ast_node: AstNodeType,
pub rules: Vec<GrammarRule<T, A>>,
}
impl<T, A> Grammar<T, A> {
#[must_use]
pub fn new(root_ast_node: AstNodeType) -> Self {
Self {
rules: vec![GrammarRule {
result: root_ast_node,
components: vec![root_ast_node.into()],
reduction: |indices, _, _| ReductionResult::Forward(indices[0].as_ast_node_id()),
}],
root_ast_node,
}
}
pub fn add_rule(
&mut self,
result: AstNodeType,
components: &[GrammarItem],
reduction: ReductionFn<T, A>,
) {
self.rules.push(GrammarRule {
result,
components: components.to_vec(),
reduction,
});
}
#[must_use]
pub fn get_rule(&self, id: GrammarRuleId) -> &GrammarRule<T, A> {
&self.rules[id.0]
}
}