use std::collections::{BTreeSet, HashMap, HashSet};
use std::ops::{Deref, DerefMut};
use crate::grammar::{AstNodeType, Grammar, GrammarItem, GrammarRuleId, HasTokenType, TokenType};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum InternalToken {
User(TokenType),
Eof,
Special,
}
impl From<TokenType> for InternalToken {
fn from(token: TokenType) -> Self {
Self::User(token)
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Lr0Item {
pub rule: GrammarRuleId,
pub index: usize,
}
impl Lr0Item {
#[must_use]
pub const fn new(rule: GrammarRuleId, index: usize) -> Self {
Self { rule, index }
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct Lr0Kernel(pub BTreeSet<Lr0Item>);
impl Deref for Lr0Kernel {
type Target = BTreeSet<Lr0Item>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Lr0Kernel {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'a> IntoIterator for &'a Lr0Kernel {
type Item = &'a Lr0Item;
type IntoIter = std::collections::btree_set::Iter<'a, Lr0Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl IntoIterator for Lr0Kernel {
type Item = Lr0Item;
type IntoIter = std::collections::btree_set::IntoIter<Lr0Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct Lr0Closure(pub BTreeSet<Lr0Item>);
impl Lr0Closure {
#[must_use]
pub fn goto<T: HasTokenType, A>(
&self,
grammar: &Grammar<T, A>,
next_entry: &GrammarItem,
) -> Lr0Kernel {
let mut new_kernel = Lr0Kernel::default();
for &Lr0Item { rule, index } in &self.0 {
let components = &grammar.get_rule(rule).components;
if index < components.len() && components[index] == *next_entry {
new_kernel.insert(Lr0Item {
rule,
index: index + 1,
});
}
}
new_kernel
}
}
impl Deref for Lr0Closure {
type Target = BTreeSet<Lr0Item>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Lr0Closure {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'a> IntoIterator for &'a Lr0Closure {
type Item = &'a Lr0Item;
type IntoIter = std::collections::btree_set::Iter<'a, Lr0Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl IntoIterator for Lr0Closure {
type Item = Lr0Item;
type IntoIter = std::collections::btree_set::IntoIter<Lr0Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Lr1Item {
pub rule: GrammarRuleId,
pub index: usize,
pub lookahead: InternalToken,
}
impl Lr1Item {
#[must_use]
pub const fn new(rule: GrammarRuleId, index: usize, lookahead: InternalToken) -> Self {
Self {
rule,
index,
lookahead,
}
}
#[must_use]
pub fn closure<T: HasTokenType, A>(
&self,
grammar: &Grammar<T, A>,
generators: &HashMap<AstNodeType, Vec<GrammarRuleId>>,
first_sets: &HashMap<AstNodeType, HashSet<TokenType>>,
) -> Lr1Closure {
let mut closure = Lr1Closure(BTreeSet::from([self.clone()]));
let mut queue = vec![self.clone()];
while let Some(Self {
rule,
index,
lookahead,
}) = queue.pop()
{
let components = &grammar.get_rule(rule).components;
if let Some(GrammarItem::AstNode(node_type)) = components.get(index)
&& let Some(generators) = generators.get(node_type)
{
let lookaheads: Vec<InternalToken> = match components.get(index + 1) {
Some(GrammarItem::Token(token_type)) => vec![InternalToken::User(*token_type)],
Some(GrammarItem::AstNode(node_type)) => first_sets
.get(node_type)
.cloned()
.map(|set| set.into_iter().map(InternalToken::User).collect())
.unwrap_or_default(),
None => vec![lookahead],
};
for &rule in generators {
for &lookahead in &lookaheads {
let new_item = Self::new(rule, 0, lookahead);
if closure.insert(new_item.clone()) {
queue.push(new_item);
}
}
}
}
}
closure
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct Lr1Kernel(pub BTreeSet<Lr1Item>);
impl Deref for Lr1Kernel {
type Target = BTreeSet<Lr1Item>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Lr1Kernel {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'a> IntoIterator for &'a Lr1Kernel {
type Item = &'a Lr1Item;
type IntoIter = std::collections::btree_set::Iter<'a, Lr1Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl IntoIterator for Lr1Kernel {
type Item = Lr1Item;
type IntoIter = std::collections::btree_set::IntoIter<Lr1Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct Lr1Closure(pub BTreeSet<Lr1Item>);
impl Deref for Lr1Closure {
type Target = BTreeSet<Lr1Item>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Lr1Closure {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'a> IntoIterator for &'a Lr1Closure {
type Item = &'a Lr1Item;
type IntoIter = std::collections::btree_set::Iter<'a, Lr1Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl IntoIterator for Lr1Closure {
type Item = Lr1Item;
type IntoIter = std::collections::btree_set::IntoIter<Lr1Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct LalrItem {
pub rule: GrammarRuleId,
pub index: usize,
pub lookaheads: BTreeSet<InternalToken>,
}
impl LalrItem {
#[must_use]
pub const fn new(
rule: GrammarRuleId,
index: usize,
lookaheads: BTreeSet<InternalToken>,
) -> Self {
Self {
rule,
index,
lookaheads,
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct LalrKernel(pub BTreeSet<LalrItem>);
impl Deref for LalrKernel {
type Target = BTreeSet<LalrItem>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for LalrKernel {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'a> IntoIterator for &'a LalrKernel {
type Item = &'a LalrItem;
type IntoIter = std::collections::btree_set::Iter<'a, LalrItem>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl IntoIterator for LalrKernel {
type Item = LalrItem;
type IntoIter = std::collections::btree_set::IntoIter<LalrItem>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct LalrClosure(pub BTreeSet<LalrItem>);
impl Deref for LalrClosure {
type Target = BTreeSet<LalrItem>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for LalrClosure {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'a> IntoIterator for &'a LalrClosure {
type Item = &'a LalrItem;
type IntoIter = std::collections::btree_set::Iter<'a, LalrItem>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl IntoIterator for LalrClosure {
type Item = LalrItem;
type IntoIter = std::collections::btree_set::IntoIter<LalrItem>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}