use std::{collections::{HashSet, HashMap}, rc::Rc, usize};
use indexmap::IndexSet;
use petgraph::{Direction::Outgoing, prelude::EdgeIndex};
use regex_automata::dfa::Automaton;
use crate::{label::RegexTerminal, value::Value, AttributeKey, AttributeMap, GLLResult, ReturnMap};
use crate::{GLLImplementationError, ImplementationResult, GLLError};
use crate::{gss::{GSS, GSSNodeIndex, GSSNode}, sppf::{SPPF, SPPFNodeIndex, SPPFNode}, descriptor::Descriptor, GrammarSlot, ParseResult, GLLParseError, Terminal, Ident, ROOT_UUID, GLLBlockLabel};
pub type LabelMap<'a> = HashMap<&'a str, GLLBlockLabel<'a>>;
pub type RuleMap<'a> = HashMap<&'a str, Rc<Vec<Ident>>>;
pub type RegexMap<'a> = HashMap<&'a str, Rc<RegexTerminal<'a>>>;
pub struct GLLState<'a> {
input: &'a [u8],
gss: GSS<'a>,
sppf: SPPF<'a>,
pub input_pointer: usize, pub gss_pointer: GSSNodeIndex, gss_root: GSSNodeIndex, context_pointer: GSSNodeIndex, pub sppf_pointer: SPPFNodeIndex, pub sppf_root: SPPFNodeIndex, todo: IndexSet<Descriptor<'a>>, visited: HashSet<Descriptor<'a>>, pop: HashMap<GSSNodeIndex, Vec<SPPFNodeIndex>>, gss_map: HashMap<Rc<GSSNode<'a>>, GSSNodeIndex>,
sppf_map: HashMap<SPPFNode<'a>, SPPFNodeIndex>,
label_map: LabelMap<'a>,
rule_map: RuleMap<'a>,
regex_map: RegexMap<'a>,
pub errors: Vec<GLLError<'a>>
}
impl<'a> GLLState<'a> {
pub fn init(input: &'a [u8], label_map: LabelMap<'a>, rule_map: RuleMap<'a>, regex_map: RegexMap<'a>) -> ImplementationResult<'a, Self> {
let mut sppf = SPPF::default();
let mut gss = GSS::default();
let mut sppf_map = HashMap::new();
let mut gss_map = HashMap::new();
let root_slot = Rc::new(GrammarSlot::new(label_map.get(ROOT_UUID).ok_or(GLLImplementationError::MissingRoot)?.clone(), rule_map.get(ROOT_UUID).ok_or(GLLImplementationError::MissingRoot)?.clone(), 0, 0, ROOT_UUID));
let gss_root_node = Rc::new(GSSNode::new(root_slot.clone(), 0, Vec::default()));
let sppf_root = sppf.add_node(SPPFNode::Dummy);
let gss_root = gss.add_node(gss_root_node.clone());
sppf_map.insert(SPPFNode::Dummy, sppf_root);
gss_map.insert(gss_root_node, gss_root);
let mut state = GLLState {
input,
gss,
sppf,
input_pointer: 0,
gss_pointer: gss_root,
gss_root,
context_pointer: gss_root,
sppf_pointer: sppf_root,
sppf_root,
todo: IndexSet::default(),
visited: HashSet::default(),
pop: HashMap::default(),
gss_map,
sppf_map,
rule_map,
label_map,
regex_map,
errors: Vec::default(),
};
state.add(root_slot, gss_root, 0, sppf_root, gss_root);
Ok(state)
}
pub fn create(&mut self, slot: &Rc<GrammarSlot<'a>>, args: AttributeMap<'a>) -> ImplementationResult<'a, GSSNodeIndex> {
let candidate = GSSNode::new(slot.clone(), self.input_pointer, args);
let v = self.find_or_create_gss_node(candidate);
if self.gss.find_edge(v, self.gss_pointer).is_none() {
self.gss.add_edge(v, self.gss_pointer, self.sppf_pointer);
let pop = std::mem::take(&mut self.pop); if let Some(nodes) = pop.get(&v) {
for sppf_node in nodes {
let y = self.get_node_p(slot.clone(), self.sppf_pointer, *sppf_node, v, v == self.gss_pointer)?;
self.add(
slot.clone(),
self.gss_pointer,
self.get_sppf_node(*sppf_node)?.right_extend()?,
y,
v
);
}
}
self.pop = pop;
}
Ok(v)
}
fn get_packed_node(&self, parent: SPPFNodeIndex, ref_slot: &Rc<GrammarSlot<'a>>, i: usize, l: Option<SPPFNodeIndex>, r: SPPFNodeIndex) -> Option<SPPFNodeIndex> {
for child in self.sppf.neighbors_directed(parent, Outgoing) {
match self.sppf.node_weight(child) {
Some(SPPFNode::Packed { slot, split, left, right }) if slot == ref_slot && *split == i && *left == l && *right == r => return Some(child),
_ => {}
}
}
None
}
pub fn get_node_p(&mut self, slot: Rc<GrammarSlot<'a>>, left: SPPFNodeIndex, right: SPPFNodeIndex, context_pointer: GSSNodeIndex, gss_cycle: bool) -> ImplementationResult<'a, SPPFNodeIndex> {
if self.is_special_slot(&slot)? {
Ok(right)
} else {
let left_node = self.get_sppf_node(left)?;
let right_node = self.get_sppf_node(right)?;
let j = right_node.right_extend()?;
let (t, weight) = if slot.is_last(self) {
let new_slot = Rc::new(GrammarSlot { label: slot.label.clone(), rule: slot.rule.clone(), dot: slot.rule.len()+1, pos: 0, uuid: slot.uuid});
let weight = self.get_label(&slot.rule[0])._weight(self);
(new_slot, weight)
} else {
(slot.clone(), None)
};
if matches!(left_node, SPPFNode::Dummy) {
let i = right_node.left_extend()?;
let node = self.find_or_create_sppf_intermediate(&t, i, j, context_pointer)?;
if (gss_cycle || right != node) && self.get_packed_node(node, &slot, i, None, right).is_none() {
let packed = SPPFNode::Packed { slot, split: i, left: None, right };
let ix = self.sppf.add_node(packed);
self.sppf.add_edge(ix, right, None);
self.sppf.add_edge(node, ix, weight.transpose()?);
}
Ok(node)
} else {
let (i, k) = (left_node.left_extend()?, left_node.right_extend()?);
let node = self.find_or_create_sppf_intermediate(&t, i, j, context_pointer)?;
if (gss_cycle || (right != node && left != node)) && self.get_packed_node(node, &slot, k, Some(left), right).is_none() {
let packed = SPPFNode::Packed { slot, split: k, left: Some(left), right };
let ix = self.sppf.add_node(packed);
self.sppf.add_edge(ix, left, None);
self.sppf.add_edge(ix, right, None);
self.sppf.add_edge(node, ix, weight.transpose()?);
}
Ok(node)
}
}
}
pub fn get_node_t(&mut self, terminal: &'a [u8], left: usize, right: usize) -> SPPFNodeIndex {
self.find_or_create_sppf_symbol(terminal, left, right)
}
pub fn get_current_gss_node(&self) -> ImplementationResult<'a, &Rc<GSSNode<'a>>> {
self.get_gss_node(self.gss_pointer)
}
pub fn get_current_sppf_node(&self) -> ImplementationResult<'a, &SPPFNode<'a>> {
self.get_sppf_node(self.sppf_pointer)
}
pub(crate) fn get_sppf_node(&self, i: SPPFNodeIndex) -> ImplementationResult<'a, &SPPFNode<'a>> {
self.sppf.node_weight(i).ok_or_else(|| GLLImplementationError::MissingSPPFNode(i))
}
fn get_sppf_node_mut(&mut self, i: SPPFNodeIndex) -> ImplementationResult<'a, &mut SPPFNode<'a>> {
self.sppf.node_weight_mut(i).ok_or_else(|| GLLImplementationError::MissingSPPFNode(i))
}
fn get_gss_node(&self, i: GSSNodeIndex) -> ImplementationResult<'a, &Rc<GSSNode<'a>>> {
self.gss.node_weight(i).ok_or_else(|| GLLImplementationError::MissingGSSNode(i))
}
fn get_gss_edge_endpoints(&self, i: EdgeIndex) -> ImplementationResult<'a, (GSSNodeIndex, GSSNodeIndex)> {
self.gss.edge_endpoints(i).ok_or_else(|| GLLImplementationError::MissingGSSEdge(i))
}
fn get_gss_edge_weight(&self, i: EdgeIndex) -> ImplementationResult<'a, &SPPFNodeIndex> {
self.gss.edge_weight(i).ok_or_else(|| GLLImplementationError::MissingGSSEdge(i))
}
fn find_or_create_sppf_symbol(&mut self, terminal: &'a [u8], left: usize, right: usize) -> SPPFNodeIndex {
let candidate = SPPFNode::Symbol { terminal, left, right };
self.find_or_create_sppf(candidate)
}
fn find_or_create_sppf_intermediate(&mut self, slot: &Rc<GrammarSlot<'a>>, left: usize, right: usize, context_pointer: GSSNodeIndex) -> ImplementationResult<'a, SPPFNodeIndex> {
let context_node = self.get_gss_node(context_pointer)?.clone();
let candidate = SPPFNode::Intermediate {
slot: slot.clone(),
left,
right,
ret: Vec::default(),
context: context_node,
};
Ok(self.find_or_create_sppf(candidate))
}
fn find_or_create_gss_node(&mut self, node: GSSNode<'a>) -> GSSNodeIndex {
if let Some(i) = self.gss_map.get(&node) {
i.to_owned()
} else {
let rc = Rc::new(node);
let i = self.gss.add_node(rc.clone());
self.gss_map.insert(rc, i);
i
}
}
fn find_or_create_sppf(&mut self, candidate: SPPFNode<'a>) -> SPPFNodeIndex {
if let Some(ix) = self.sppf_map.get(&candidate) {
*ix
} else {
let ix = self.sppf.add_node(candidate.clone());
self.sppf_map.insert(candidate, ix);
ix
}
}
pub fn add(&mut self, slot: Rc<GrammarSlot<'a>>, g: GSSNodeIndex, i: usize, s: SPPFNodeIndex, context_pointer: GSSNodeIndex) {
let d = Descriptor::new(slot, g, i, s, context_pointer);
if !self.visited.contains(&d) {
self.visited.insert(d.clone());
self.todo.insert(d);
}
}
pub fn pop(&mut self, ret_vals: &ReturnMap<'a>, attrs: AttributeMap<'a>) -> ImplementationResult<'a, ()> {
let slot = self.get_current_gss_node()?.slot.clone();
let ctx_node = self.find_or_create_gss_node(GSSNode::new(slot.clone(), self.input_pointer, attrs));
let ctx = self.get_gss_node(ctx_node)?.clone();
let curr_sppf = self.get_sppf_node_mut(self.sppf_pointer)?;
if let SPPFNode::Intermediate { context, .. } = curr_sppf {
*context = ctx; }
if self.gss_pointer != self.gss_root {
if let Some(map) = self.pop.get_mut(&self.gss_pointer) {
map.push(self.sppf_pointer);
} else {
let map = vec![self.sppf_pointer];
self.pop.insert(self.gss_pointer, map);
}
let mut detached = self.gss.neighbors_directed(self.gss_pointer, Outgoing).detach();
while let Some(edge) = detached.next_edge(&self.gss) {
let v = self.get_gss_edge_endpoints(edge)?.1;
let y = self.get_node_p(slot.clone(), *self.get_gss_edge_weight(edge)?, self.sppf_pointer, self.gss_pointer, v == self.gss_pointer)?;
self.get_sppf_node_mut(y)?.insert_ret_vals(ret_vals.clone())?;
self.add(slot.clone(), v, self.input_pointer, y, self.gss_pointer);
}
}
Ok(())
}
fn __next(bytes: Terminal<'a>, start_pointer: usize, input: &'a [u8]) -> ParseResult<'a, usize> {
let mut pointer = start_pointer;
let input_len = input.len();
while pointer < input_len && input[pointer].is_ascii_whitespace() { pointer += 1;
}
for expected in bytes {
if pointer >= input_len {
return Err(GLLParseError::TooLong { pointer, offender: bytes })
}
let check = input[pointer];
if check != *expected && !check.is_ascii_whitespace() {
return Err(GLLParseError::UnexpectedByte { pointer, expected: *expected, offender: check })
}
pointer += 1;
}
Ok(pointer)
}
fn _next(&self, bytes: Terminal<'a>) -> ParseResult<'a, usize> {
Self::__next(bytes, self.input_pointer, self.input)
}
pub fn next(&mut self, bytes: Terminal<'a>) -> ParseResult<'a, ()> {
let pointer = self._next(bytes)?;
self.input_pointer = pointer;
Ok(())
}
pub fn has_next(&mut self, bytes: Terminal<'a>) -> bool {
self._next(bytes).is_ok()
}
#[must_use]
fn _next_regex(regex: &RegexTerminal<'a>, start_pointer: usize, input: &[u8]) -> Option<usize> {
let current_byte = &input[start_pointer..=start_pointer];
let Ok(mut curr_state) = regex.automaton.start_state_forward(¤t_byte.into()) else { return None
};
let input_len = input.len();
let mut i = 0;
let mut last_match = None;
while !regex.automaton.is_dead_state(curr_state) && !regex.automaton.is_quit_state(curr_state) { let pointer = start_pointer + i; if pointer >= input_len { break;
}
let byte = input[pointer];
curr_state = regex.automaton.next_state(curr_state, byte); if regex.automaton.is_match_state(curr_state) { last_match = Some(i); }
i += 1;
}
if regex.automaton.is_quit_state(curr_state) || regex.automaton.is_dead_state(curr_state) { last_match } else { let state = regex.automaton.next_eoi_state(curr_state); if regex.automaton.is_match_state(state) { Some(i)
} else {
last_match }
}
}
pub fn next_regex(&mut self, pattern: &'a str) -> GLLResult<'a, Option<Terminal<'a>>> {
let regex = self.get_regex_automaton(pattern)?;
if let Some(j) = Self::_next_regex(®ex, self.input_pointer, self.input) {
let result = &self.input[self.input_pointer..self.input_pointer + j];
self.input_pointer += j + 1;
Ok(Some(result))
} else {
Ok(None)
}
}
pub fn has_regex(&self, pattern: &'a str) -> GLLResult<'a, bool> {
let regex = self.get_regex_automaton(pattern)?;
Ok(Self::_next_regex(®ex, self.input_pointer, self.input).is_some())
}
pub fn regex_bytes(&self, pattern: &'a str) -> GLLResult<'a, Option<Terminal<'a>>> {
let regex = self.get_regex_automaton(pattern)?;
Ok(Self::_next_regex(®ex, self.input_pointer, self.input).map(|j| &self.input[self.input_pointer..self.input_pointer + j]))
}
#[must_use]
pub fn current_byte(&self) -> &[u8] {
&self.input[self.input_pointer..=self.input_pointer]
}
pub fn test_next(&mut self, label: &GLLBlockLabel<'a>) -> GLLResult<'a, bool> {
label.first(self)
}
pub fn get_rule(&self, ident: &'a str) -> ImplementationResult<'a, Rc<Vec<Ident>>> {
Ok(self.rule_map.get(ident).ok_or_else(|| GLLImplementationError::UnknownRule(ident))?.clone())
}
#[must_use]
pub fn get_label(&self, ident: &Ident) -> GLLBlockLabel<'a> {
let raw_string = ident.extract_string();
self.label_map.get(raw_string).map_or_else(|| todo!(), std::clone::Clone::clone)
}
pub fn get_label_by_uuid(&self, label: &'a str) -> ImplementationResult<'a, GLLBlockLabel<'a>> {
Ok(self.label_map.get(label).ok_or_else(|| GLLImplementationError::UnknownLabel(label))?.clone())
}
pub fn get_regex_automaton(&self, regex: &'a str) -> ImplementationResult<'a, Rc<RegexTerminal<'a>>> {
Ok(self.regex_map.get(regex).ok_or_else(|| GLLImplementationError::UnknownLabel(regex))?.clone())
}
pub fn get_attribute(&self, i: AttributeKey) -> ImplementationResult<'a, &Value<'a>> {
let node = self.get_gss_node(self.gss_pointer)?;
node.get_attribute(i).ok_or_else(|| GLLImplementationError::MissingAttribute(i, node.clone()))
}
pub fn restore_attribute(&self, i: AttributeKey) -> ImplementationResult<'a, &Value<'a>> {
let node = self.get_gss_node(self.context_pointer)?;
node.get_attribute(i).ok_or_else(|| GLLImplementationError::MissingContext(i, node.clone()))
}
pub fn get_ret_val(&self, i: AttributeKey) -> ImplementationResult<'a, Option<&Value<'a>>> {
self.get_sppf_node(self.sppf_pointer)?.get_ret_val(i)
}
fn is_special_slot(&self, slot: &GrammarSlot<'a>) -> ImplementationResult<'a, bool> {
Ok(if slot.dot == 1 && slot.pos == 0 && !slot.is_last(self) {
match slot.rule.first() {
Some(r) => {
let a = self.get_label(r);
a.str_parts().len() == 1 && (a.is_terminal() || !(a.is_nullable(self)?))
},
None => false
}
} else {
false
})
}
fn get_current_label_slot(&self, slot: &GrammarSlot<'a>) -> ImplementationResult<'a, GLLBlockLabel<'a>> {
Ok(self.get_label(slot.rule.get(slot.dot).ok_or_else(|| GLLImplementationError::CompletedSlot(slot.to_string(self, false)))?))
}
fn goto(&mut self, slot: &GrammarSlot<'a>) {
match self.get_current_label_slot(slot) {
Ok(label) => {
if let Err(e) = label.code(self) {
self.errors.push(e);
}
},
Err(e) => self.errors.push(e.into())
}
}
pub fn main(&mut self) {
while let Some(Descriptor {slot, gss, pointer, sppf, context_pointer}) = self.todo.pop() {
self.sppf_pointer = sppf;
self.gss_pointer = gss;
self.input_pointer = pointer;
self.context_pointer = context_pointer;
self.goto(&slot);
}
}
pub fn print_sppf_dot(&mut self, crop: bool, math_mode: bool) -> ImplementationResult<'a, String> {
if crop {
self.sppf.crop(self.find_roots_sppf());
}
self.sppf.to_dot(self, math_mode, &self.find_roots_sppf()) }
pub fn print_gss_dot(&self, math_mode: bool) -> ImplementationResult<'a, String> {
self.gss.to_dot(self, math_mode)
}
#[must_use]
pub fn accepts(&self) -> bool {
!self.find_roots_sppf().is_empty()
}
#[must_use]
pub fn final_accepts(&mut self) -> bool {
let success = self.accepts();
if !success && self.errors.is_empty() {
self.errors.push(GLLError::ImplementationError(GLLImplementationError::Fatal("Parser is not accepting, but no errors were encountered.")));
}
success
}
#[allow(clippy::expect_used)]
fn find_roots_sppf(&self) -> Vec<SPPFNodeIndex> {
let s_p = self.label_map.get(ROOT_UUID).expect("S' label not found in state. Should be impossible.");
let start_label = s_p.first_set(self).expect("Unable to get root uuid from S'. Should be impossible.");
let uuid = start_label[0].0[0].uuid();
self.sppf.find_accepting_roots(Some(self.input.len()), uuid)
}
}