astmaker/
lib.rs

1//! # Introduction
2//!
3//! `astmaker` is a DSL for programming language designers to build Abstract
4//! Syntax Trees and tree-walking models quickly.
5//!
6//! # Features
7//!
8//! AST definition:
9//!
10//!  - custom location type
11//!  - structural nodes (`struct`) and variant nodes (`enum`)
12//!  - custom node attributes type
13//!
14//! Model definition:
15//!
16//!  - visitor pattern
17//!  - support for generics and lifetimes
18//!
19//! # Architecture
20//!
21//! When creating an AST, this crate will define the following types and traits:
22//!
23//! ```rust
24//! pub trait NodeAttributes {
25//!   type Attributes;
26//! }
27//!
28//! #[derive(Debug, Clone, PartialEq)]
29//! pub struct Node<T: NodeAttributes> {
30//!   pub location: LocationType,
31//!   pub data: Box<T>,
32//!   pub attrs: Option<T::NodeAttributes>,
33//! }
34//! ```
35//!
36//! When creating a model, this crate will define the following types:
37//!
38//! ```rust
39//! pub trait Visitor: Sized {
40//!   fn visit<T: NodeAttributes + Visitable<Self, T>>(
41//!     &mut self,
42//!     node: &mut Node<T>,
43//!   ) -> OutputType;
44//! }
45//!
46//! pub trait Visitable<C: Visitor, T: NodeAttributes> {
47//!   fn visit(context: &mut C, node: &mut Node<T>) -> OutputType;
48//! }
49//! ```
50//!
51//! # Basic usage
52//!
53//! This crates provide 2 macros:
54//!
55//!  - `ast!`: to define the AST
56//!  - `model!`: to implement the tree-walking model
57//!
58//! Each macro provide a custom DSL.
59//!
60//! ## Defining Abstract Syntax Tress
61//!
62//! ```rust
63//! use astmaker::{ast, model};
64//!
65//! ast!{
66//!   location = (usize, usize);
67//!
68//!   pub node VariantNode =
69//!     | A -> Node<StructuralNodeA>
70//!     | B -> Node<StructuralNodeB>
71//!     ;
72//!
73//!   pub node StructuralNodeA = {
74//!     data: u8,
75//!   }
76//!
77//!   pub node StructuralNodeB = {
78//!     data: u16,
79//!   }
80//!
81//!   pub node NodeWithAttributes where attrs: String = {
82//!     data: u32,
83//!   }
84//! }
85//! ```
86//!
87//! When not specified, the default attributes type is the unit type `()`.
88//!
89//! The generated code will contain the `struct`s and `enum`s as well as their
90//! implementation of the `NodeAttributes` trait.
91//!
92//! Every generated type implements the traits `Debug`, `Clone` and `PartialEq`.
93//!
94//! ## Defining tree-walking models
95//!
96//! ```rust
97//! pub struct Model;
98//!
99//! model!{
100//!   impl Model -> Result<(), ()> {
101//!     where VariantNode => {
102//!       match node.data.as_mut() {
103//!         VariantNode::A(child) => context.visit(child)?,
104//!         VariantNode::B(child) => context.visit(child)?,
105//!       }
106//!
107//!       Ok(())
108//!     },
109//!     where StructuralNodeA => {
110//!       Ok(())
111//!     },
112//!     where StructuralNodeB => {
113//!       Ok(())
114//!     },
115//!   }
116//! }
117//! ```
118//!
119//! The `impl for Type` part will implement the `Visitor` trait for the supplied
120//! type. Each `where` clause will implement the `Visitable` trait for the node
121//! type.
122//!
123//! Generics and lifetimes are also supported:
124//!
125//! ```rust
126//! pub struct Model<'a, T> {
127//!   data: &'a T,
128//! }
129//!
130//! model!{
131//!   impl<'a, T> Model -> Result<(), ()> {
132//!     // ...
133//!   }
134//! }
135//! ```
136
137use proc_macro::TokenStream;
138
139mod parser;
140mod codegen;
141
142#[proc_macro]
143pub fn ast(input: TokenStream) -> TokenStream {
144  codegen::ast::generate(input)
145}
146
147#[proc_macro]
148pub fn model(input: TokenStream) -> TokenStream {
149  codegen::model::generate(input)
150}