Skip to main content

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