tree_builder_macro/
lib.rs

1mod regex_builder;
2mod ast_builder;
3mod parser;
4extern crate proc_macro;
5
6use proc_macro::TokenStream;
7use parser::parser_ast::RuleKind;
8use quote::quote;
9use regex::Regex;
10
11use crate::parser::parser_ast::Specification;
12
13trait Parser {
14    fn parse(input: &str) -> Self;
15}
16
17#[proc_macro]
18pub fn build_tree(input: TokenStream) -> TokenStream {
19    let input = input.to_string();
20    let input: Vec<&str> = input.split_whitespace().collect();
21    let input = input.join("");
22    let Specification(mut ast) = match parser::specification(&input){
23        Ok((_, out)) => out,
24        Err(nom::Err::Error(e) | nom::Err::Failure(e)) => panic!("{}", nom::error::convert_error(input.as_str(), e)),
25        _ => panic!("Unknown error. Please report this error on GitHub issues, together with the grammar you used")
26    };
27    let tokens: Vec<proc_macro2::TokenStream> = ast.iter_mut().map(rule_kind_to_stream).collect();
28    quote!{
29        #(#tokens)
30            *
31    }.into()
32}
33
34#[proc_macro]
35pub fn ast_parser_maker(input: TokenStream) -> TokenStream {
36    let comment = Regex::new(r"//.*$").unwrap();
37    let input = input.to_string();
38    let input: Vec<String> = input.split_whitespace().map(|x| comment.replace_all(x, "").to_string()).collect();
39    let input = input.join("");
40    let mut ast = match parser::struct_rule(&input){
41        Ok((_, out)) => out,
42        Err(nom::Err::Error(e) | nom::Err::Failure(e)) => panic!("{}", nom::error::convert_error(input.as_str(), e)),
43        _ => panic!("Unknown error. Please report this error on GitHub issues, together with the grammar you used")
44    };
45    ast_builder::parser_builder::gen_parser(&mut ast, None).into()
46}
47
48
49#[proc_macro]
50pub fn rule(input: TokenStream) -> TokenStream {
51    let input = input.to_string();
52    let input: Vec<&str> = input.split_whitespace().collect();
53    let input = input.join("");
54    let mut ast = match parser::rule(&input){
55        Ok((_, out)) => out,
56        Err(nom::Err::Error(e)) => panic!("{}", nom::error::convert_error(input.as_str(), e)),
57        _ => panic!("Unknown error, please open a github issue which includes your source code")
58    };
59    rule_kind_to_stream(&mut ast).into()
60}
61
62fn rule_kind_to_stream(ast: &mut RuleKind) -> proc_macro2::TokenStream {
63    match ast {
64        RuleKind::StructRule(ref mut ast) => {
65            let tuple_type = ast_builder::ast_from_rule(ast);
66            let parser = ast_builder::parser_builder::gen_parser(ast, None);
67            quote!{
68                #tuple_type
69
70                #parser
71            }.into()
72        },
73        RuleKind::RegexRule(ref mut ast) => {
74            regex_builder::rule(ast).into()
75        }
76    }
77}