use std::collections::BTreeSet;
use super::token::TokenMapped;
use proc_macro2::Ident;
use proc_macro2::Span;
use proc_macro2::TokenStream;
#[derive(Clone)]
pub struct CustomReduceAction {
pub body: TokenStream,
idents_used: BTreeSet<Ident>,
}
impl CustomReduceAction {
fn fetch_idents(set: &mut BTreeSet<Ident>, 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);
}
_ => {}
}
}
}
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, ident: &Ident) -> bool {
self.idents_used.contains(ident)
}
}
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_span: Span,
pub lookaheads: Option<BTreeSet<usize>>,
pub prec: Option<(rusty_lr_core::rule::Precedence, Span)>,
pub dprec: Option<(usize, Span)>,
pub(crate) is_used: bool,
}
impl Rule {
pub fn span_pair(&self) -> (Span, Span) {
let begin = self.separator_span;
let end = if let Some(token) = self.tokens.last() {
token.end_span
} else {
begin
};
(begin, end)
}
pub fn reduce_action_contains_ident(&self, ident: &Ident) -> bool {
match self.reduce_action.as_ref() {
Some(ReduceAction::Custom(custom)) => custom.contains_ident(ident),
Some(ReduceAction::Identity(identity_idx)) => {
self.tokens[*identity_idx].mapto.as_ref() == Some(ident)
}
None => false,
}
}
}
pub struct NonTerminalInfo {
pub name: Ident,
pub pretty_name: String,
pub ruletype: Option<TokenStream>,
pub rules: Vec<Rule>,
pub(crate) regex_span: Option<(Span, Span)>,
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.regex_span.is_some()
}
pub fn origin_span(&self) -> Option<(Span, Span)> {
self.regex_span
}
pub(crate) fn is_protected(&self) -> bool {
self.protected
}
}