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}