rustlr/
generic_absyn.rs

1//! Generic Abstract Syntax Support Module
2//!
3//! Rustlr allows any type that implements the Default trait to be used as
4//! the abstract syntax type (grammar directive absyntype).  However, this
5//! module defines custom smart pointers [LBox] and [LRc] that simplify the
6//! construction of abstract syntax trees. LBox/LRc keep the line and column
7//! numbers of each syntatic construct, as these are often
8//! needed during later stages of code analysis post-parsing.
9//!
10//! For example, an abstract syntax type can be defined by
11//!```text
12//! enum Expr {
13//!   Val(i64),
14//!   PlusExpr(LBox<Expr>,LBox<Expr>),
15//!   ...
16//! }
17//!```
18//!```text
19//! fn check(e:&Expr) {
20//!   match e {
21//!     PlusExpr(a,b) => {
22//!       println!("checking expressions on lines {} and {}",a.line(),b.line());
23//!       check(a); check(b); // Deref coercion used here
24//!     },
25//!   ...
26//!```
27//! The [ZCParser::lbx] function can be called from the semantic actions
28//! of a grammar
29//! to create LBoxed-values that include line/column information.  `LBox<T>`
30//! implements the Default trait if T does, so an LBox type can also serve
31//! as the absyntract syntax type for a grammar.
32//! It is also possible to use `LBox<dyn Any>` as the abstract syntax type
33//! along with the [LBox::upcast] and [LBox::downcast] functions and
34//! convenience macros [lbup] and [lbdown].
35//!
36//! Sufficient functionality has also been implemented to allow the use of
37//! `LBox<dyn Any>` as the abstract syntax type of Grammars.
38//! This effectively allows grammar symbols to carray values of different types
39//! as Any-trait objects.  The functions [LBox::upcast], [LBox::downcast], [ZCParser::lba],
40//! and the convenience macros [lbup], [lbdown] and [lbget]
41//! are intended to support this usage.  A simplified, sample grammar using
42//! `LBox<dyn Any>` as the abstract syntax type returned by the parser is
43//! found [here](https://cs.hofstra.edu/~cscccl/rustlr_project/simple.grammar),
44//! which generates this LALR [parser](https://cs.hofstra.edu/~cscccl/rustlr_project/simpleparser.rs).
45//!
46//! Equivalent functions are available for [LRc]. 
47
48#![allow(dead_code)]
49#![allow(unused_variables)]
50#![allow(unused_parens)]
51#![allow(unused_imports)]
52#![allow(unused_mut)]
53#![allow(unused_macros)]
54#![allow(non_snake_case)]
55#![allow(non_camel_case_types)]
56#![allow(non_upper_case_globals)]
57
58use std::rc::Rc;
59use std::ops::{Deref,DerefMut};
60use std::collections::{HashMap,HashSet};
61use std::any::Any;
62use crate::zc_parser;
63use crate::zc_parser::ZCParser;
64use crate::{lbup,lbdown,lbget};
65use bumpalo::Bump;
66
67/// Custom smart pointer that encapsulates line and column numbers along with
68/// a regular [Box].  Implements [Deref] and [DerefMut] so the encapsulated
69/// expression can be accessed as in a standard Box.  This is intended to
70/// to be used in the formation of abstract syntax trees so that the lexical
71/// information is available for each construct after the parsing stage.
72/// Also included in each LBox created by the runtime parser ([ZCParser])
73/// is a 32 bit (u32) *unique identifier* **uid** that uniquely identifies
74/// each LBox.  An expression and a subexpression can both begin at the same
75/// line and column numbers and the unique id would be required to
76/// distinguish them.  This device is useful for hashing information, such
77/// as inferred types, based on the location of an expression in the source.
78pub struct LBox<T:?Sized>
79{
80  pub exp:Box<T>,
81  pub line:u32,
82  pub column:u32,
83  pub uid:u32, // unique id
84  // must refer to information kept externally  
85  //pub src_id:usize,   
86}
87impl<T> LBox<T>
88{
89  /// creates a new LBox with line ln, column col and uid set to zero;
90  /// this function is deprecated by [LBox::make].
91  pub fn new(e:T,ln:usize,col:usize /*,src:usize*/) -> LBox<T>
92  { LBox { exp:Box::new(e), line:ln as u32, column:col as u32,uid:0, } }
93  /// creates a new LBox enclosing e, with line ln, column col and uid u
94  pub fn make(e:T,ln:usize,col:usize, u:u32) -> LBox<T>
95  { LBox { exp:Box::new(e), line:ln as u32, column:col as u32,uid:u, } }  
96  ///should be used to create a new LBoxed expression that inherits
97  /// lexical information from existing LBox
98  pub fn transfer<U>(&self,e:U) -> LBox<U>
99  {
100     LBox::make(e,self.line(),self.column(),self.uid)
101  }
102  /// Since version 0.2.4, Rustlr now stores the line and column
103  /// information internally as u32 values instead of usize, and
104  /// the [LBox::line] and [LBox::column] functions are provided for
105  /// interface
106  pub fn line(&self)-> usize {self.line as usize}
107  pub fn column(&self)->usize {self.column as usize}
108  pub fn uid(&self) -> u32 {self.uid}
109}//impl LBox
110impl<T> Deref for LBox<T>
111{
112    type Target = T;
113    fn deref(&self) -> &Self::Target {
114        &self.exp
115    }
116}
117impl<T> DerefMut for LBox<T>
118{
119    fn deref_mut(&mut self) -> &mut Self::Target {
120        &mut self.exp
121    }
122}
123impl<T:Default> Default for LBox<T>
124{
125  fn default() -> Self {LBox::new(T::default(),0,0/*,0*/)}
126}
127impl<T:Clone> Clone for LBox<T>
128{
129   fn clone(&self) -> Self
130   {
131      LBox {
132        exp : self.exp.clone(),
133        line: self.line,
134        column: self.column,
135        uid:self.uid,
136        //src_id: self.src_id,
137      }
138   }//clone
139}
140impl<T:?Sized> AsRef<T> for LBox<T>
141{
142  fn as_ref(&self) -> &T  { &*self.exp }
143}
144impl<T:?Sized> AsMut<T> for LBox<T>
145{
146  fn as_mut(&mut self) -> &mut T  { &mut *self.exp }
147}
148impl<T:Default+?Sized> LBox<T>
149{
150   /// replaces the boxed value with T::default() and returns the value
151   pub fn take(&mut self) -> T
152   {   let mut res = T::default();
153       std::mem::swap(&mut res, self.as_mut());
154       res
155   }
156   /// convert information from [LC] to LBox, consumes LC
157   pub fn from_lc(c:LC<T>) -> Self
158   {
159       LBox{exp:Box::new(c.0), line:c.1.0, column:c.1.1, uid:c.1.2}
160   }
161}
162impl<'t> LBox<dyn Any+'t>
163{
164  /// emulates [Box::downcast] function, when `LBox<dyn Any>` is used as
165  /// the abstract syntax type.  Note that unlike Box::downcast, an Option
166  /// is returned here instead of a result.
167  pub fn downcast<U:'t>(self) -> Option<LBox<U>>
168  {
169     let boxdown = self.exp.downcast::<U>();
170     if let Err(_) = boxdown {return None;}
171     Some(LBox {
172       exp : boxdown.unwrap(),
173       line: self.line,
174       column: self.column,
175       uid:self.uid,
176       //src_id: self.src_id,
177     })
178  }
179  /// do not try to create a `LBox<dyn Any>` structure with something like
180  ///```
181  /// let lb:LBox<dyn Any> = LBox::new(String::from("abc"),0,0);
182  ///```  
183  /// This does not work as LBox is simply borrowing the underlying mechanics of
184  /// [Box] instead of re-creating them.  Do instead:
185  ///```
186  /// let lb:LBox<dyn Any> = LBox::upcast(LBox::new(String::from("abc"),0,0));
187  ///```
188  /// upcast always returns a `LBox<dyn Any>`.
189  pub fn upcast<T:'t>(lb:LBox<T>) -> Self
190  {
191     let bx:Box<dyn Any+'t> = lb.exp; // this requires Any+'static ??
192     LBox { exp:bx, line:lb.line, column:lb.column, uid:lb.uid, }
193  }
194}// downcast/upcast for LBox
195
196///this is provided so `LBox<dyn Any>` can be used for the abstract syntax type.
197/// the default is a Lbox containing a static string.
198impl Default for LBox<dyn Any>
199{
200  fn default() -> Self {LBox::upcast(LBox::new("LBox<dyn Any> defaults to this string",0,0/*,0*/))}
201}
202
203impl<T:std::fmt::Debug> std::fmt::Debug for LBox<T> {
204    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
205        std::fmt::Debug::fmt(&**self, f)    
206//        f.debug_struct("LBox")
207//         .field("exp", &self.exp)
208//         .field("y", &self.y)
209//         .finish()
210    }
211}
212
213
214
215///Like LBox but encapsulates an Rc. Implements [Deref] and emulates the
216///[Rc::clone] function.
217pub struct LRc<T:?Sized>
218{
219  pub exp:Rc<T>,
220  pub line:u32,
221  pub column:u32,
222  //pub src_id:usize,
223}
224impl<T> LRc<T>
225{
226  pub fn new(e:T,ln:usize,col:usize /*,src:usize*/) -> LRc<T>
227  { LRc { exp:Rc::new(e), line:ln as u32, column:col as u32, /*src_id:src*/ } }
228  //pub fn set_src_id(&mut self, id:usize) {self.src_id=id;}
229  ///should be used to create a new LRc-expression that inherits
230  /// lexical information from existing LRc
231  pub fn transfer<U>(&self,e:U) -> LRc<U>
232  {
233     LRc::new(e,self.line(),self.column() /*,self.src_id*/)
234  }
235  ///uses [Rc::clone] to increase reference count of encapsulated Rc,
236  ///copies line, column and source_id information.
237  pub fn clone(lrc:&LRc<T>) -> LRc<T>
238  {
239     LRc {
240        exp: Rc::clone(&lrc.exp),
241        line: lrc.line,
242        column: lrc.column,
243        //src_id: lrc.src_id,
244     }
245  }//clone
246  pub fn line(&self) -> usize {self.line as usize}
247  //self.line.try_into().unwrap()}
248  pub fn column(&self) -> usize {self.column as usize}
249}
250
251impl<T:Clone> Clone for LRc<T>
252{
253   fn clone(&self) -> Self
254   {
255     LRc::clone(self)
256   }//clone
257}
258
259impl<T> Deref for LRc<T>
260{
261    type Target = T;
262    fn deref(&self) -> &Self::Target {
263        &self.exp
264    }
265}
266/*  DerefMut is not implemented for Rc<T>
267impl<T> DerefMut for LRc<T>
268{
269    fn deref_mut(&mut self) -> &mut Self::Target {
270        &mut self.exp
271    }
272}
273*/
274impl<T:Default> Default for LRc<T>
275{
276  fn default() -> Self {LRc::new(T::default(),0,0/*,0*/)}
277}
278
279impl LRc<dyn Any+'static>
280{
281  /// emulates [LRc::downcast] function. Note that unlike Box::downcast,
282  ///an Option is returned here instead of a result.
283  pub fn downcast<U:'static>(self) -> Option<LRc<U>>
284  {
285     let rcdown = self.exp.downcast::<U>();
286     if let Err(_) = rcdown {return None;}
287     Some(LRc {
288       exp : rcdown.unwrap(),
289       line: self.line,
290       column: self.column,
291       //src_id: self.src_id,
292     })
293  }
294  /// upcasts `LRc<T>` to `LRc<dyn Any>`
295  pub fn upcast<T:'static>(lb:LRc<T>) -> Self
296  {
297     let bx:Rc<dyn Any> = lb.exp;
298     LRc { exp:bx, line:lb.line, column:lb.column, /*src_id:lb.src_id,*/ }
299  }
300}// downcast/upcast for LRc
301
302///this is required if `LRc<dyn Any>` is used for the abstract syntax type
303impl Default for LRc<dyn Any+'static>
304{
305  fn default() -> Self {LRc::upcast(LRc::new("LRc<dyn Any> defaults to this string",0,0 /*,0*/))}
306}
307
308impl<T:std::fmt::Debug> std::fmt::Debug for LRc<T> {
309    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
310        std::fmt::Debug::fmt(&**self, f)    
311    }
312}
313
314/// Version of LBox that does not use a Box. This tuple struct contains
315/// a value of type T in the first position and a tuple consisting of
316/// (line, column, uid) numbers in the second position.  The uid or
317/// *unique identifier* is a unique number placed in each LC structure
318/// created by the parser.  It is useful for hashing information (such as
319/// inferred types) based on their source location.  Multiple AST constructs
320/// may begin with the same line/column position, but the unique id will
321/// disambiguate them.
322/// This feature was added to Rustlr to support bumpalo-allocated ASTs.
323pub struct LC<T>(pub T,pub (u32,u32,u32));
324
325impl<T:Default> Default for LC<T> {
326  fn default() -> Self {LC(T::default(),(0,0,0))}
327}
328
329impl<T> Deref for LC<T>
330{
331    type Target = T;
332    fn deref(&self) -> &Self::Target {
333        &self.0
334    }
335}
336impl<T> DerefMut for LC<T>
337{
338    fn deref_mut(&mut self) -> &mut Self::Target {
339        &mut self.0
340    }
341}
342impl<T> AsRef<T> for LC<T>
343{
344  fn as_ref(&self) -> &T  { &self.0 }
345}
346impl<T> AsMut<T> for LC<T>
347{
348  fn as_mut(&mut self) -> &mut T  { &mut self.0 }
349}
350impl<T:std::fmt::Debug> std::fmt::Debug for LC<T> {
351    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
352        std::fmt::Debug::fmt(&self.0, f)    
353    }
354}
355impl<T> LC<T>
356{
357  /// creates a new LC tuple struct in the form (value, (line,column,unique_id))
358  pub fn make(x:T,ln:usize,cl:usize,uid:u32) -> Self {
359    LC(x,(ln as u32,cl as u32,uid))
360  }
361  /// creates a new LC tuple struct in the form (value, (line,column))
362  /// with the unique_id field set to zero (for backwards compatibility)
363  pub fn new(x:T,ln:usize,cl:usize) -> Self {
364    LC(x,(ln as u32,cl as u32,0))
365  }
366  /// returns encapsulated line
367  pub fn line(&self) -> usize { (self.1.0) as usize }
368  /// returns encapsulated column
369  pub fn column(&self) -> usize { (self.1.1) as usize }
370  /// returns (line,column) as a pair of 32 values
371  pub fn lncl(&self) -> (u32,u32) { (self.1.0,self.1.1) }
372  /// returns unique id
373  pub fn uid(&self) -> u32 { self.1.2 }
374  /// returns value reference
375  pub fn value(&self) -> &T { &self.0 }
376  /// transfers line/column information to another LC
377  pub fn transfer<U>(&self,x:U) -> LC<U> {
378   LC::make(x,self.line(),self.column(),self.1.2) 
379  }
380  /// consumes the LC enclosure and returns the enclosed value
381  pub fn consume(self) -> T { self.0 }
382}//impl LC
383
384impl<T:Default+?Sized> LC<T>
385{
386  ///transfers information from an [LBox] into an LC, consumes LBox
387  pub fn from_lbox(mut lb:LBox<T>) -> Self {
388    LC::make(lb.take(),lb.line(),lb.column(),lb.uid())
389  }
390}  
391
392impl<T:Default+?Sized> LC<T>
393{
394   /// replaces the enclosed value with T::default() and returns the value
395   pub fn take(&mut self) -> T
396   {   let mut res = T::default();
397       std::mem::swap(&mut res, self.as_mut());
398       res
399   }
400}
401
402/// Structure intended to support [bumpalo](https://docs.rs/bumpalo/latest/bumpalo/index.html) AST generations,
403///which allows recursive AST types to be defined using references instead of
404///smart pointers (LBox).  The benefit of bump-allocated ASTs is the ability to
405///pattern match against nested, recursive structures, e.g.,
406///`Negative(Negative(x))`.  The lifetime `'t` of a Bumper should be the same
407///as the lifetime of the parser's input.
408/// This structure is intended to become the
409///'external state' that's carried by the runtime parser (parser.exstate),
410///and therefore wraps another value (exstate) of the declared `externtype`.
411pub struct Bumper<'t,ET:Default>
412{
413  bump:Option<&'t Bump>,
414  exstate: ET,
415}//bumper struct
416impl<T:Default> Default for Bumper<'_,T>  {
417  fn default() -> Self { Bumper{exstate:T::default(), bump:None} }
418}
419impl<'t,T:Default> Bumper<'t,T>
420{
421  /// sets the encapsulated [Bump](https://docs.rs/bumpalo/latest/bumpalo/struct.Bump.html) allocator
422  pub fn set(&mut self, b:&'t Bump) { self.bump = Some(b); }
423
424  /// tests if the allocator has been set
425  pub fn is_set(&self) -> bool { self.bump.is_some() }
426  
427  /// returns pointer to the bump allocator.  Warning: this function calls
428  /// unwrap and should only be called after [Bumper::set] has been called
429  pub fn get(&self)->&'t Bump { self.bump.expect("bump arena not set") }
430
431  /// bump-allocates x and returns a reference, which will live as long
432  /// as the bump allocator.  Warning: this function calls unwrap and
433  /// will panic if the Bumper is not set.
434  pub fn make<S>(&self,x:S) -> &'t S {
435     self.get().alloc(x)
436  }
437
438  /// version of make that returns Option, but will not panic
439  pub fn make_safe<S>(&self,x:S) -> Option<&'t S> {
440     if self.bump.is_some() {Some(self.get().alloc(x))}
441     else {None}
442  }
443
444  /// version of make_safe that returns a mutable reference to the allocated
445  /// value
446  pub fn alloc<S>(&self,x:S) -> Option<&'t mut S> {
447     self.bump.map(|b|b.alloc(x))
448  }
449
450  /// returns a mut reference to the encapsulated "state" of type ET
451  pub fn state(&mut self) -> &mut T { &mut self.exstate }
452}//impl Bumper
453
454
455
456
457
458// [LBox] specific to [GenAbsyn] type, implements [Debug] and [Clone],
459// unlike a generic LBox
460type ABox = LBox<GenAbsyn>;
461
462
463/// Generic Abstract Syntax type: Rustlr offers the user the option
464/// of using a ready-made abstract syntax type that should be suitable for
465/// ordinary situations.  Incorporates the usage of LBox so that abstract
466/// syntax trees always carry line/column information for error reporting and
467/// warnings.  Rustlr will implement an option to produce a parser that
468/// uses GenAbsyn in conjunction with [ABox], and a custom parse_generic function
469/// that should simplify the process of parsing into abstract syntax.
470#[derive(Clone,Debug)]
471enum GenAbsyn
472{
473  Integer(i64),
474  BigInteger(String),
475  Float(f64),
476  Symbol(&'static str),
477  Keyword(&'static str),
478  Alphanum(String),
479  Stringlit(String),
480  Verbatim(String),
481  Uniop(usize,ABox),
482  Binop(usize,ABox,ABox),
483  Ternop(usize,ABox,ABox,ABox),
484  Sequence(usize,Vec<ABox>),
485  Partial(ABox,String), // error result, line/column/msg
486  NewLine,
487  Whitespaces(usize),
488  Nothing,
489}
490impl GenAbsyn
491{
492   fn is_complete(&self) -> bool
493   {
494      match self
495      {
496        GenAbsyn::Partial(_,_) => false,
497        GenAbsyn::Uniop(_,s) => {
498            println!("s.line {}{}",s.line,s.column);
499            s.is_complete()
500        },
501        GenAbsyn::Binop(_,a,b) => a.is_complete() && b.is_complete(),
502        GenAbsyn::Ternop(_,a,b,c) => a.is_complete() && b.is_complete() && c.is_complete(),
503        GenAbsyn::Sequence(_,v) => {
504          for x in v { if !x.is_complete() {return false; } }
505          true
506        }
507        _ => true,
508      }
509   }//is_complete
510}//impl GenAbsyn
511
512impl Default for GenAbsyn
513{
514  fn default() -> Self { GenAbsyn::Nothing }
515}//impl Default
516
517
518//const KEYWORDS:[&'static str;4] = ["if","while","let","lambda"];
519//const SYMBOLS:[&'static str;4] = ["==","(",")",":"];
520
521// don't know what to do with this yet
522
523/// Structure for configuring specific use of [GenAbsyn] type, which
524/// provides generic representations of binary, unary, ternary and
525/// vectorized operators.  GenAbsyn also distinguishes keywords from
526/// other alphanumeric and non-alphanumeric symbols. Since these are
527/// provided from source code, &'static str is used instead of owned
528/// strings.  The index of the corresponding &'static str in 
529/// the static array OPERATORS will determine
530/// the usize index that identifies each Binop, Uniop, etc.
531struct Absyn_Statics<const N:usize,const M:usize,const P:usize>
532{
533   pub KEYWORDS: [&'static str; N],
534   pub SYMBOLS: [&'static str; M],
535   /// indices determine usize identifier of Binop, Uniop, Ternop, etc.
536   pub OPERATORS: [&'static str; P],
537   /// maps each string to corresponding index in KEYWORDS
538   pub Keyhash:HashMap<&'static str,usize>,
539   pub Symhash:HashMap<&'static str,usize>,
540   pub Ophash: HashMap<&'static str,usize>,
541}
542impl<const N:usize,const M:usize,const P:usize> Absyn_Statics<N,M,P>
543{
544  fn new(k:[&'static str; N],s:[&'static str;M],p:[&'static str;P])
545      -> Absyn_Statics<N,M,P>
546  {
547    let mut newas = Absyn_Statics {
548       KEYWORDS: k,
549       SYMBOLS: s,
550       OPERATORS:p,
551       Keyhash: HashMap::with_capacity(N),
552       Symhash: HashMap::with_capacity(M),
553       Ophash: HashMap::with_capacity(P),       
554    };
555    for i in 0..N { newas.Keyhash.insert(k[i],i); }
556    for i in 0..M { newas.Symhash.insert(s[i],i); }
557    for i in 0..P { newas.Ophash.insert(p[i],i); }
558    return newas;
559  }//new
560
561  pub fn is_keyword(&self,k:&str) -> bool
562  { self.Keyhash.contains_key(k) }
563  pub fn is_symbol(&self,k:&str) -> bool
564  { self.Symhash.contains_key(k) }
565  pub fn is_operator(&self,k:&str) -> bool
566  { self.Ophash.contains_key(k) }    
567}//impl Absyn_Statics
568
569
570/* //testing  - did compile
571fn check(e:&GenAbsyn) -> bool {
572  match e {
573    Binop(3,x,_) => {
574         println!("Binop 3 not allowed on line {}, column {}",x.line,x.column);
575         false
576    },
577    Binop(i,a,b) => { check(a) && check(b) },
578    _ => true
579  }
580}
581*/
582
583/*
584///macro for creating [LBox] structures, for use in grammar semantic actions: each semantic action associated
585/// with a grammar rule is a Rust lambda expression of the form
586/// __|parser|{...}__
587/// of type __fn(&mut RuntimeParser) -> AT__ where AT is the type of the abstract
588/// syntax value defined for the grammar. __lbox!(e)__ expands to **parser.lb(e)**, calling the [RuntimeParser::lb] function.
589// The macro can also form an [ABox], which is an alias for LBox<GenAbsyn>
590#[macro_export]
591macro_rules! lbox {
592  ( $parser:expr,$x:expr ) => {
593    $parser.lb($x)
594  };
595}
596*/
597
598///macro for creating `LBox<dyn Any>` structures that can encapsulate any type
599///as abstract syntax.  **Must** be called from within the semantic actions of
600///a grammar production rule.
601#[macro_export]
602macro_rules! lbup {
603  ( $x:expr ) => {
604    LBox::upcast($x)
605  };
606}
607
608/// macro for downcasting `LBox<dyn Any>` to `LBox<A>` for some 
609/// concrete type A. Must be called
610/// from within the semantic actions of grammar productions.  **Warning:**
611/// **unwrap** is called within the macro
612#[macro_export]
613macro_rules! lbdown {
614  ( $x:expr,$t:ty ) => {
615    $x.downcast::<$t>().unwrap()
616  };
617}
618
619/// similar to [lbdown], but also extracts the boxed expression
620#[macro_export]
621macro_rules! lbget {
622  ( $x:expr,$t:ty ) => {
623    *$x.downcast::<$t>().unwrap().exp
624  };
625}
626/// just extract value from LBox
627#[macro_export]
628macro_rules! unbox {
629  ( $x:expr ) => {
630    *$x.exp
631  };
632}
633
634/// macro for creating an [LBox] from a [crate::StackedItem] ($si) popped from
635/// the parse stack; should be called from within the semantics actions of
636/// a grammar to accurately encode lexical information. 
637#[macro_export]
638macro_rules! makelbox {
639  ($si:expr, $e:expr) => {
640    LBox::new($e,$si.line,$si.column)
641  };
642}
643
644/// similar to [makelbox] but creates an [LRc] from lexical information
645/// inside stack item $si
646#[macro_export]
647macro_rules! makelrc {
648  ($si:expr, $e:expr) => {
649    LRc::new($e,$si.line,$si.column)
650  };
651}
652
653/*
654// just to see if it compiles
655struct BB(usize);
656fn testing() 
657{
658  let bb1:&dyn Any = &BB(1);
659  let bb2:Box<dyn Any> = Box::new(BB(2));
660  let bx:Box<dyn Any> = Box::new(String::from("abc"));
661  //let b1:LBox<dyn Any> = LBox::new(BB(1),0,0,0); // doesn't work
662  //let b3:LBox<dyn Any> = LBox::frombox(bb2,0,0,0); // works!
663  let b5:LBox<BB> = LBox::new(BB(100),0,0,0);
664  let b6:LBox<dyn Any> = LBox::upcast(b5);
665  let b4:LBox<BB> = b6.downcast::<BB>().unwrap();
666  let lb:LBox<dyn Any> = LBox::upcast(LBox::new(String::from("abc"),0,0,0));
667  //let lbd:LBox<dyn Default> = LBox::upcast(LBox::new(String::from("ab"),0,0,0));  
668}
669*/