use std::collections::BTreeSet;
use super::token::TokenMapped;
use crate::parser::location::Located;
use crate::parser::location::Location;
use proc_macro2::TokenStream;
#[derive(Clone)]
pub struct CustomReduceAction {
pub body: TokenStream,
idents_used: BTreeSet<String>,
}
impl CustomReduceAction {
fn fetch_idents(set: &mut BTreeSet<String>, ts: TokenStream) {
for token in ts {
match token {
proc_macro2::TokenTree::Group(g) => {
Self::fetch_idents(set, g.stream());
}
proc_macro2::TokenTree::Ident(i) => {
set.insert(i.to_string());
}
_ => {}
}
}
}
pub fn new(body: TokenStream) -> Self {
let mut idents_used = BTreeSet::new();
Self::fetch_idents(&mut idents_used, body.clone());
Self { body, idents_used }
}
fn contains_ident(&self, name: &str) -> bool {
self.idents_used.contains(name)
}
}
pub enum ReduceAction {
Custom(CustomReduceAction),
Identity(usize), }
impl ReduceAction {
pub fn new_custom(body: TokenStream) -> Self {
ReduceAction::Custom(CustomReduceAction::new(body))
}
pub fn is_identity(&self) -> bool {
matches!(self, ReduceAction::Identity(_))
}
pub fn is_custom(&self) -> bool {
matches!(self, ReduceAction::Custom(_))
}
}
pub struct Rule {
pub tokens: Vec<TokenMapped>,
pub reduce_action: Option<ReduceAction>,
pub separator_location: Location,
pub lookaheads: Option<BTreeSet<usize>>,
pub prec: Option<Located<rusty_lr_core::rule::Precedence>>,
pub dprec: Option<Located<usize>>,
pub(crate) is_used: bool,
}
impl Rule {
pub fn location(&self) -> Location {
let begin = self.separator_location.clone();
if let Some(token) = self.tokens.last() {
let end = &token.location;
begin.merge(&end)
} else {
begin
}
}
pub fn reduce_action_contains_ident(&self, name: &str) -> bool {
match self.reduce_action.as_ref() {
Some(ReduceAction::Custom(custom)) => custom.contains_ident(name),
Some(ReduceAction::Identity(identity_idx)) => {
self.tokens[*identity_idx]
.mapto
.as_ref()
.map(|m| m.value().as_str())
== Some(name)
}
None => false,
}
}
}
pub struct NonTerminalInfo {
pub name: Located<String>,
pub pretty_name: String,
pub ruletype: Option<TokenStream>,
pub rules: Vec<Rule>,
pub(crate) root_location: Option<Location>,
pub(crate) trace: bool,
pub(crate) protected: bool,
pub(crate) nonterm_type: Option<rusty_lr_core::parser::nonterminal::NonTerminalType>,
}
impl NonTerminalInfo {
pub fn is_auto_generated(&self) -> bool {
self.root_location.is_some()
}
pub fn root_location(&self) -> Option<Location> {
self.root_location
}
pub(crate) fn is_protected(&self) -> bool {
self.protected
}
}