do_not_use_antlr_rust/
rule_context.rs

1//! Minimal parser node
2use std::borrow::{Borrow, BorrowMut};
3use std::cell::{Cell, RefCell};
4use std::fmt::{Debug, Formatter};
5use std::iter::from_fn;
6use std::marker::PhantomData;
7use std::rc::{Rc, Weak};
8
9use crate::atn::INVALID_ALT;
10use crate::parser::ParserNodeType;
11use crate::parser_rule_context::ParserRuleContext;
12use crate::token_factory::TokenFactory;
13use crate::tree::{ParseTree, Tree};
14use better_any::{Tid, TidAble};
15use std::any::type_name;
16
17//pub trait RuleContext:RuleNode {
18/// Minimal rule context functionality required for parser to work properly
19pub trait RuleContext<'input>: CustomRuleContext<'input> {
20    /// Internal parser state
21    fn get_invoking_state(&self) -> isize { -1 }
22
23    /// Sets internal parser state
24    fn set_invoking_state(&self, _t: isize) {}
25
26    /// A context is empty if there is no invoking state; meaning nobody called
27    /// current context. Which is usually true for the root of the syntax tree
28    fn is_empty(&self) -> bool { self.get_invoking_state() == -1 }
29
30    /// Get parent context
31    fn get_parent_ctx(&self) -> Option<Rc<<Self::Ctx as ParserNodeType<'input>>::Type>> { None }
32
33    /// Set parent context
34    fn set_parent(&self, _parent: &Option<Rc<<Self::Ctx as ParserNodeType<'input>>::Type>>) {}
35}
36
37pub(crate) fn states_stack<'input, T: ParserRuleContext<'input> + ?Sized + 'input>(
38    mut ctx: Rc<T>,
39) -> impl Iterator<Item = isize>
40where
41    T::Ctx: ParserNodeType<'input, Type = T>,
42{
43    from_fn(move || {
44        if ctx.get_invoking_state() < 0 {
45            None
46        } else {
47            let state = ctx.get_invoking_state();
48            ctx = ctx.get_parent_ctx().unwrap();
49            Some(state)
50        }
51    })
52}
53
54// #[doc(hidden)]
55// pub unsafe trait Tid {
56//     fn self_id(&self) -> TypeId;
57//     fn id() -> TypeId
58//     where
59//         Self: Sized;
60// }
61
62#[derive(Debug)]
63#[doc(hidden)]
64pub struct EmptyCustomRuleContext<'a, TF: TokenFactory<'a> + 'a>(
65    pub(crate) PhantomData<&'a TF::Tok>,
66);
67
68better_any::tid! { impl <'a,TF> TidAble<'a> for EmptyCustomRuleContext<'a,TF> where TF:TokenFactory<'a> + 'a}
69
70impl<'a, TF: TokenFactory<'a> + 'a> CustomRuleContext<'a> for EmptyCustomRuleContext<'a, TF> {
71    type TF = TF;
72    type Ctx = EmptyContextType<'a, TF>;
73
74    fn get_rule_index(&self) -> usize { usize::max_value() }
75}
76
77// unsafe impl<'a, TF: TokenFactory<'a> + 'a> Tid for EmptyCustomRuleContext<'a, TF> {
78//     fn self_id(&self) -> TypeId {
79//         TypeId::of::<EmptyCustomRuleContext<'static, CommonTokenFactory>>()
80//     }
81//
82//     fn id() -> TypeId
83//     where
84//         Self: Sized,
85//     {
86//         TypeId::of::<EmptyCustomRuleContext<'static, CommonTokenFactory>>()
87//     }
88// }
89#[doc(hidden)] // public for implementation reasons
90pub type EmptyContext<'a, TF> =
91    dyn ParserRuleContext<'a, TF = TF, Ctx = EmptyContextType<'a, TF>> + 'a;
92
93#[derive(Debug)]
94#[doc(hidden)] // public for implementation reasons
95pub struct EmptyContextType<'a, TF: TokenFactory<'a>>(pub PhantomData<&'a TF>);
96
97better_any::tid! { impl <'a,TF> TidAble<'a> for EmptyContextType<'a,TF> where TF:TokenFactory<'a> }
98
99impl<'a, TF: TokenFactory<'a>> ParserNodeType<'a> for EmptyContextType<'a, TF> {
100    type TF = TF;
101    type Type = dyn ParserRuleContext<'a, TF = Self::TF, Ctx = Self> + 'a;
102    // type Visitor = dyn ParseTreeVisitor<'a, Self> + 'a;
103}
104
105/// Implemented by generated parser for context extension for particular rule
106#[allow(missing_docs)]
107pub trait CustomRuleContext<'input> {
108    type TF: TokenFactory<'input> + 'input;
109    /// Type that describes type of context nodes, stored in this context
110    type Ctx: ParserNodeType<'input, TF = Self::TF>;
111    //const RULE_INDEX:usize;
112    /// Rule index that corresponds to this context type
113    fn get_rule_index(&self) -> usize;
114
115    fn get_alt_number(&self) -> isize { INVALID_ALT }
116    fn set_alt_number(&self, _alt_number: isize) {}
117
118    /// Returns text representation of current node type,
119    /// rule name for context nodes and token text for terminal nodes
120    fn get_node_text(&self, rule_names: &[&str]) -> String {
121        let rule_index = self.get_rule_index();
122        let rule_name = rule_names[rule_index];
123        let alt_number = self.get_alt_number();
124        if alt_number != INVALID_ALT {
125            return format!("{}:{}", rule_name, alt_number);
126        }
127        return rule_name.to_owned();
128    }
129    // fn enter(_ctx: &dyn Tree<'input, Node=Self>, _listener: &mut dyn Any) where Self: Sized {}
130    // fn exit(_ctx: &dyn Tree<'input, Node=Self>, _listener: &mut dyn Any) where Self: Sized {}
131}
132
133/// Minimal parse tree node implementation, that stores only data required for correct parsing
134pub struct BaseRuleContext<'input, ExtCtx: CustomRuleContext<'input>> {
135    pub(crate) parent_ctx: RefCell<Option<Weak<<ExtCtx::Ctx as ParserNodeType<'input>>::Type>>>,
136    invoking_state: Cell<isize>,
137    pub(crate) ext: ExtCtx,
138}
139
140better_any::tid! { impl <'input,Ctx> TidAble<'input> for BaseRuleContext<'input,Ctx> where Ctx:CustomRuleContext<'input>}
141
142#[allow(missing_docs)]
143impl<'input, ExtCtx: CustomRuleContext<'input>> BaseRuleContext<'input, ExtCtx> {
144    pub fn new_parser_ctx(
145        parent_ctx: Option<Rc<<ExtCtx::Ctx as ParserNodeType<'input>>::Type>>,
146        invoking_state: isize,
147        ext: ExtCtx,
148    ) -> Self {
149        Self {
150            parent_ctx: RefCell::new(parent_ctx.as_ref().map(Rc::downgrade)),
151            invoking_state: Cell::new(invoking_state),
152            ext,
153        }
154    }
155
156    pub fn copy_from<T: ParserRuleContext<'input, TF = ExtCtx::TF, Ctx = ExtCtx::Ctx> + ?Sized>(
157        ctx: &T,
158        ext: ExtCtx,
159    ) -> Self {
160        Self::new_parser_ctx(ctx.get_parent_ctx(), ctx.get_invoking_state(), ext)
161    }
162}
163
164impl<'input, Ctx: CustomRuleContext<'input>> Borrow<Ctx> for BaseRuleContext<'input, Ctx> {
165    fn borrow(&self) -> &Ctx { &self.ext }
166}
167
168impl<'input, Ctx: CustomRuleContext<'input>> BorrowMut<Ctx> for BaseRuleContext<'input, Ctx> {
169    fn borrow_mut(&mut self) -> &mut Ctx { &mut self.ext }
170}
171
172impl<'input, ExtCtx: CustomRuleContext<'input>> CustomRuleContext<'input>
173    for BaseRuleContext<'input, ExtCtx>
174{
175    type TF = ExtCtx::TF;
176    type Ctx = ExtCtx::Ctx;
177
178    fn get_rule_index(&self) -> usize { self.ext.get_rule_index() }
179}
180
181// unsafe impl<'input, Ctx: CustomRuleContext<'input>> Tid for BaseRuleContext<'input, Ctx> {
182//     fn self_id(&self) -> TypeId { self.ext.self_id() }
183//
184//     fn id() -> TypeId
185//     where
186//         Self: Sized,
187//     {
188//         Ctx::id()
189//     }
190// }
191
192impl<'input, ExtCtx: CustomRuleContext<'input>> RuleContext<'input>
193    for BaseRuleContext<'input, ExtCtx>
194{
195    fn get_invoking_state(&self) -> isize { self.invoking_state.get() }
196
197    fn set_invoking_state(&self, t: isize) { self.invoking_state.set(t) }
198
199    fn get_parent_ctx(&self) -> Option<Rc<<ExtCtx::Ctx as ParserNodeType<'input>>::Type>> {
200        self.parent_ctx
201            .borrow()
202            .as_ref()
203            .map(Weak::upgrade)
204            .flatten()
205    }
206
207    //    fn get_parent_ctx(&self) -> Option<ParserRuleContextType> {
208    //        self.parent_ctx.borrow().as_ref().map(Weak::upgrade).map(Option::unwrap)
209    //    }
210
211    fn set_parent(&self, parent: &Option<Rc<<ExtCtx::Ctx as ParserNodeType<'input>>::Type>>) {
212        *self.parent_ctx.borrow_mut() = parent.as_ref().map(Rc::downgrade);
213    }
214}
215
216impl<'input, ExtCtx: CustomRuleContext<'input>> Debug for BaseRuleContext<'input, ExtCtx> {
217    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
218        f.debug_struct(type_name::<Self>())
219            .field("invoking_state", &self.invoking_state)
220            .field("..", &"..")
221            .finish()
222    }
223}
224
225impl<'input, ExtCtx: CustomRuleContext<'input>> Tree<'input> for BaseRuleContext<'input, ExtCtx> {}
226
227impl<'input, ExtCtx: CustomRuleContext<'input>> ParseTree<'input>
228    for BaseRuleContext<'input, ExtCtx>
229{
230}
231
232impl<'input, ExtCtx: CustomRuleContext<'input> + TidAble<'input>> ParserRuleContext<'input>
233    for BaseRuleContext<'input, ExtCtx>
234{
235}