Expand description
Generic Abstract Syntax Support Module
Rustlr allows any type that implements the Default trait to be used as the abstract syntax type (grammar directive absyntype). However, this module defines custom smart pointers LBox and LRc that simplify the construction of abstract syntax trees. LBox/LRc keep the line and column numbers of each syntatic construct, as these are often needed during later stages of code analysis post-parsing.
For example, an abstract syntax type can be defined by
enum Expr {
Val(i64),
PlusExpr(LBox<Expr>,LBox<Expr>),
...
} fn check(e:&Expr) {
match e {
PlusExpr(a,b) => {
println!("checking expressions on lines {} and {}",a.line(),b.line());
check(a); check(b); // Deref coercion used here
},
...The ZCParser::lbx function can be called from the semantic actions
of a grammar
to create LBoxed-values that include line/column information. LBox<T>
implements the Default trait if T does, so an LBox type can also serve
as the absyntract syntax type for a grammar.
It is also possible to use LBox<dyn Any> as the abstract syntax type
along with the LBox::upcast and LBox::downcast functions and
convenience macros lbup and lbdown.
Sufficient functionality has also been implemented to allow the use of
LBox<dyn Any> as the abstract syntax type of Grammars.
This effectively allows grammar symbols to carray values of different types
as Any-trait objects. The functions LBox::upcast, LBox::downcast, ZCParser::lba,
and the convenience macros lbup, lbdown and lbget
are intended to support this usage. A simplified, sample grammar using
LBox<dyn Any> as the abstract syntax type returned by the parser is
found here,
which generates this LALR parser.
Equivalent functions are available for LRc.
Structs§
- Bumper
- Structure intended to support bumpalo AST generations,
which allows recursive AST types to be defined using references instead of
smart pointers (LBox). The benefit of bump-allocated ASTs is the ability to
pattern match against nested, recursive structures, e.g.,
Negative(Negative(x)). The lifetime'tof a Bumper should be the same as the lifetime of the parser’s input. This structure is intended to become the ‘external state’ that’s carried by the runtime parser (parser.exstate), and therefore wraps another value (exstate) of the declaredexterntype. - LBox
- Custom smart pointer that encapsulates line and column numbers along with a regular Box. Implements Deref and DerefMut so the encapsulated expression can be accessed as in a standard Box. This is intended to to be used in the formation of abstract syntax trees so that the lexical information is available for each construct after the parsing stage. Also included in each LBox created by the runtime parser (ZCParser) is a 32 bit (u32) unique identifier uid that uniquely identifies each LBox. An expression and a subexpression can both begin at the same line and column numbers and the unique id would be required to distinguish them. This device is useful for hashing information, such as inferred types, based on the location of an expression in the source.
- LC
- Version of LBox that does not use a Box. This tuple struct contains a value of type T in the first position and a tuple consisting of (line, column, uid) numbers in the second position. The uid or unique identifier is a unique number placed in each LC structure created by the parser. It is useful for hashing information (such as inferred types) based on their source location. Multiple AST constructs may begin with the same line/column position, but the unique id will disambiguate them. This feature was added to Rustlr to support bumpalo-allocated ASTs.
- LRc
- Like LBox but encapsulates an Rc. Implements Deref and emulates the Rc::clone function.