use std::cell::{Cell, OnceCell, RefCell};
use std::cmp::Ordering;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::fmt;
use std::ops::Deref;
use std::rc::Rc;
use super::forking::{GrammarFacts, Lead};
pub(super) use super::keyword_lexing::KeywordLexing;
use super::operations::{OperationValue, State};
use super::ordering::settled_order;
pub(super) use super::ordering::{complete_order, preferred_tokens};
use super::program::{Name, PrecedenceTag, Settling, TokenRank, TokenRanks, Trivia};
use super::separators::separator_text;
pub(super) use super::walk::same_children;
use super::walk::same_output;
use crate::grammar::PrecedenceEntry;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(super) enum TreeType {
Node,
Token,
Error,
Missing,
Embed,
}
pub(super) type Children = Rc<ChildList>;
#[derive(Default)]
pub(super) struct ChildList {
pub(super) count: usize,
pub(super) flat: OnceCell<Vec<Rc<Tree>>>,
pub(super) link: RefCell<Option<(Children, Children)>>,
}
impl ChildList {
fn flatten(&self) -> Vec<Rc<Tree>> {
let Some((left, right)) = self.link.borrow_mut().take() else {
return Vec::new();
};
let mut flat = Vec::with_capacity(self.count);
let mut pending = vec![right, left];
while let Some(part) = pending.pop() {
if let Some(items) = part.flat.get() {
flat.extend_from_slice(items);
} else if let Some((before, after)) = part.link.borrow().clone() {
pending.push(after);
pending.push(before);
}
}
flat
}
}
impl Deref for ChildList {
type Target = [Rc<Tree>];
fn deref(&self) -> &[Rc<Tree>] {
self.flat.get_or_init(|| self.flatten())
}
}
impl fmt::Debug for ChildList {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.debug_list().entries(self.iter()).finish()
}
}
impl Drop for ChildList {
fn drop(&mut self) {
let mut next = self.link.get_mut().take();
while let Some((left, _)) = next {
next = Rc::try_unwrap(left)
.ok()
.and_then(|mut list| list.link.get_mut().take());
}
}
}
pub(super) fn children_of(items: Vec<Rc<Tree>>) -> Children {
Rc::new(ChildList {
count: items.len(),
flat: OnceCell::from(items),
link: RefCell::new(None),
})
}
pub(super) fn join_children(left: &Children, right: &Children) -> Children {
if right.count == 0 {
return left.clone();
}
if left.count == 0 {
return right.clone();
}
Rc::new(ChildList {
count: left.count + right.count,
flat: OnceCell::new(),
link: RefCell::new(Some((left.clone(), right.clone()))),
})
}
#[derive(Clone, Debug)]
#[allow(clippy::struct_excessive_bools)] pub(super) struct Tree {
pub(super) ty: TreeType,
pub(super) kind: Option<Name>,
pub(super) rule: Option<Name>,
pub(super) field: Option<Name>,
pub(super) trivia: bool,
pub(super) start: usize,
pub(super) end: usize,
pub(super) children: Children,
pub(super) attributes: Option<BTreeMap<String, OperationValue>>,
pub(super) precedence: Option<PrecedenceTag>,
pub(super) tail: Option<PrecedenceTag>,
pub(super) priority: Option<i64>,
pub(super) reduced: Option<PrecedenceTag>,
pub(super) closes: Option<PrecedenceTag>,
pub(super) reduced_to: Vec<Name>,
pub(super) forked_to: Vec<Name>,
pub(super) alone: bool,
pub(super) before: Option<Lead>,
pub(super) dynamic: i64,
pub(super) ambiguous: bool,
pub(super) literal: bool,
pub(super) scanned: bool,
pub(super) lexed: Option<Name>,
pub(super) plain: bool,
pub(super) rank: Option<TokenRank>,
pub(super) language: Option<Name>,
pub(super) root: Option<Rc<Self>>,
pub(super) program: usize,
}
impl Tree {
pub(super) fn new(ty: TreeType, kind: Option<Name>, start: usize, end: usize) -> Self {
Self {
ty,
kind,
rule: None,
field: None,
trivia: false,
start,
end,
children: no_children(),
attributes: None,
precedence: None,
tail: None,
priority: None,
reduced: None,
closes: None,
reduced_to: Vec::new(),
forked_to: Vec::new(),
alone: false,
before: None,
dynamic: 0,
ambiguous: false,
literal: false,
scanned: false,
lexed: None,
plain: false,
rank: None,
language: None,
root: None,
program: 0,
}
}
pub(super) fn node(kind: &Name, start: usize, end: usize, children: Children) -> Self {
let mut node = Self::new(TreeType::Node, Some(kind.clone()), start, end);
node.rule = Some(kind.clone());
node.children = children;
node
}
pub(super) fn trivia_leaf(kind: Option<Name>, start: usize, end: usize) -> Self {
let mut leaf = Self::new(TreeType::Token, kind, start, end);
leaf.trivia = true;
leaf
}
}
pub(super) fn no_children() -> Children {
children_of(Vec::new())
}
pub(super) fn concat(left: &[Rc<Tree>], right: &[Rc<Tree>]) -> Children {
let mut joined = Vec::with_capacity(left.len() + right.len());
joined.extend_from_slice(left);
joined.extend_from_slice(right);
children_of(joined)
}
pub(super) fn is_separator(tree: &Tree) -> bool {
tree.ty == TreeType::Token && tree.trivia && tree.kind.is_none()
}
pub(super) fn with_leaf(leaves: &[Rc<Tree>], leaf: Tree) -> Children {
concat(leaves, &[Rc::new(leaf)])
}
#[derive(Clone, Debug)]
pub(super) struct Res {
pub(super) end: usize,
pub(super) state: State,
pub(super) children: Children,
pub(super) dynamic: i64,
pub(super) precedence: Option<PrecedenceTag>,
pub(super) tail: Option<PrecedenceTag>,
pub(super) ambiguous: bool,
pub(super) cost: usize,
pub(super) before: Option<Lead>,
pub(super) open: bool,
}
impl Res {
pub(super) const fn new(end: usize, state: State, children: Children, dynamic: i64) -> Self {
Self {
end,
state,
children,
dynamic,
precedence: None,
tail: None,
ambiguous: false,
cost: 0,
before: None,
open: false,
}
}
pub(super) fn join(left: &Self, right: Self, in_token: bool) -> Self {
Self {
end: right.end,
state: right.state,
children: if in_token {
no_children()
} else {
join_children(&left.children, &right.children)
},
dynamic: left.dynamic + right.dynamic,
precedence: None,
tail: if in_token {
None
} else if right.children.count == 0 {
left.tail.clone()
} else {
right.tail
},
ambiguous: left.ambiguous || right.ambiguous,
cost: left.cost + right.cost,
before: None,
open: right.open || left.open && right.end == left.end,
}
}
pub(super) const fn closed(mut self) -> Self {
self.open = false;
self
}
pub(super) fn key(&self) -> (usize, State) {
(self.end, self.state.clone())
}
}
#[derive(Clone, Copy, Debug)]
pub(super) struct TokenOrder<'c> {
pub(super) ranks: &'c TokenRanks,
pub(super) bytes: &'c [u8],
pub(super) orders: &'c [Vec<PrecedenceEntry>],
pub(super) grammar: &'c GrammarFacts,
pub(super) trivia: &'c [Trivia],
}
impl TokenOrder<'_> {
pub(super) fn separator_text(&self, start: usize, end: usize) -> bool {
separator_text(self.trivia, self.bytes, start, end)
}
}
#[derive(Clone, Debug, Default)]
pub(super) struct ResultSet<'c> {
pub(super) items: Vec<Res>,
index: HashMap<(usize, State), usize>,
tokens: Option<TokenOrder<'c>>,
settling: Settling,
owner: Option<PrecedenceTag>,
}
impl<'c> ResultSet<'c> {
pub(super) fn new(tokens: Option<TokenOrder<'c>>, settling: Settling) -> Self {
Self {
tokens,
settling,
..Self::default()
}
}
pub(super) fn owned(mut self, owner: Option<&PrecedenceTag>) -> Self {
self.owner = owner.cloned();
self
}
pub(super) fn add(&mut self, result: Res) -> bool {
match self.index.get(&result.key()) {
None => self.push(result),
Some(&position) => {
let existing = &mut self.items[position];
if result.cost > existing.cost {
return false;
}
if result.cost == existing.cost {
let order = settled_order(
(&result.children, result.dynamic),
(&existing.children, existing.dynamic),
self.settling,
self.tokens,
self.owner.as_ref(),
);
if order != Ordering::Greater {
if order == Ordering::Equal
&& self.settling.ambiguity()
&& existing.cost == 0
&& !same_output(&result.children, &existing.children)
{
existing.ambiguous = true;
}
return false;
}
}
*existing = result;
}
}
true
}
pub(super) fn get(&self, result: &Res) -> Option<&Res> {
self.index
.get(&result.key())
.map(|&position| &self.items[position])
}
pub(super) fn get_key(&self, key: &(usize, State)) -> Option<&Res> {
self.index.get(key).map(|&position| &self.items[position])
}
pub(super) fn remove(&mut self, result: &Res) {
let key = result.key();
if let Some(&position) = self.index.get(&key)
&& Rc::ptr_eq(&self.items[position].children, &result.children)
{
self.index.remove(&key);
self.items.remove(position);
for slot in self.index.values_mut() {
if *slot > position {
*slot -= 1;
}
}
}
}
pub(super) fn set(&mut self, result: Res) {
match self.index.get(&result.key()) {
Some(&position) => self.items[position] = result,
None => self.push(result),
}
}
fn push(&mut self, result: Res) {
self.index.insert(result.key(), self.items.len());
self.items.push(result);
}
pub(super) const fn len(&self) -> usize {
self.items.len()
}
}
pub(super) fn reduced_alone(result: Res, name: &Name, ranked: bool, forked: bool) -> Res {
let mut children = result.children.to_vec();
let mut meaningful = children
.iter()
.enumerate()
.filter(|(_, child)| !child.trivia);
let (Some((at, only)), None) = (meaningful.next(), meaningful.next()) else {
return result;
};
let alone = only.ty == TreeType::Token && !only.alone;
let reduced = ranked && !only.reduced_to.contains(name);
let fork = forked && !only.forked_to.contains(name);
if !alone && !reduced && !fork {
return result;
}
let mut tagged = (**only).clone();
tagged.alone |= alone;
if reduced {
tagged.reduced_to.push(name.clone());
}
if fork {
tagged.forked_to.push(name.clone());
}
children[at] = Rc::new(tagged);
Res {
children: children_of(children),
..result
}
}
pub(super) fn longest_result(results: Vec<Res>) -> Option<Res> {
let mut best: Option<Res> = None;
for result in results {
if best.as_ref().is_none_or(|best| result.end > best.end) {
best = Some(result);
}
}
best
}
pub(super) fn content_start(children: &[Rc<Tree>], fallback: usize) -> usize {
children
.iter()
.find(|child| !child.trivia)
.map_or(fallback, |child| child.start)
}
#[derive(Debug)]
pub(super) struct Shared {
pub(super) steps: Cell<usize>,
pub(super) limit: usize,
pub(super) frames: Cell<usize>,
pub(super) memo_limit: usize,
pub(super) cells: Rc<Cell<usize>>,
pub(super) memory_limit: usize,
pub(super) expectations: RefCell<Expectations>,
}
pub(super) type Expectation = (usize, usize);
#[derive(Debug, Default)]
pub(super) struct Expectations {
requested: HashMap<usize, HashSet<Expectation>>,
consulted: HashMap<usize, HashSet<Expectation>>,
pub(super) stale: bool,
}
impl Expectations {
pub(super) fn restart(&mut self) {
self.consulted.clear();
self.stale = false;
}
pub(super) fn request(&mut self, position: usize, item: Expectation) {
if !self.requested.entry(position).or_default().insert(item) {
return;
}
if self
.consulted
.get(&position)
.is_some_and(|items| items.contains(&item))
{
self.stale = true;
}
}
pub(super) fn holds(&mut self, position: usize, item: Expectation) -> bool {
if self
.requested
.get(&position)
.is_some_and(|items| items.contains(&item))
{
return true;
}
self.consulted.entry(position).or_default().insert(item);
false
}
}
#[derive(Debug)]
pub(super) enum Outcome {
Parsed(Rc<Tree>),
Failed {
farthest: usize,
expected: Vec<String>,
element_farthest: Option<usize>,
partial: Option<Rc<Tree>>,
},
}
#[derive(Debug, Default)]
pub(super) struct Entry {
pub(super) evaluating: bool,
pub(super) left_recursive: bool,
pub(super) involved: bool,
pub(super) seed: Vec<Res>,
pub(super) results: Vec<Res>,
pub(super) call: Option<usize>,
pub(super) position: usize,
pub(super) builds: Option<Name>,
pub(super) outranks: HashMap<usize, i64>,
}
#[derive(Debug)]
pub(super) struct Skipped {
pub(super) end: usize,
pub(super) leaves: Children,
}
#[derive(Debug)]
pub(super) struct Scanned {
pub(super) token_start: usize,
pub(super) end: usize,
pub(super) skipped: Vec<Rc<Tree>>,
pub(super) state: State,
}
pub(super) type MemoKey = (usize, usize, State, bool, Repair);
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(super) enum Repair {
Open,
Quiet,
Chained,
}