1
use conjure_cp_essence_parser::parser::ParseContext;
2
use conjure_cp_essence_parser::util::node_is_expression;
3
use conjure_cp_essence_parser::{
4
    diagnostics::source_map::SourceMap,
5
    expression::parse_expression,
6
    util::{get_expr_tree, query_toplevel},
7
};
8
use polyquine::Quine;
9
use proc_macro2::{TokenStream, TokenTree};
10
use quote::{ToTokens, quote};
11
use std::collections::BTreeMap;
12
use syn::{Error, LitStr, Result};
13
use tree_sitter::Node;
14

            
15
224
pub fn expand_expr(essence: &TokenTree) -> Result<TokenStream> {
16
224
    let src = to_src(essence);
17
224
    let (tree, source_code) =
18
224
        get_expr_tree(&src).ok_or(Error::new(essence.span(), "Could not parse Essence AST"))?;
19
224
    let root = tree.root_node();
20

            
21
    // Get top level expressions
22
224
    let mut query = query_toplevel(&root, &node_is_expression);
23
224
    let expr_node = query
24
224
        .next()
25
224
        .ok_or(Error::new(essence.span(), "Expected an Essence expression"))?;
26

            
27
    // We only expect one expression, error if that's not the case
28
224
    if let Some(expr) = query.next() {
29
        let tokens = &source_code[expr.start_byte()..expr.end_byte()];
30
        return Err(Error::new(
31
            essence.span(),
32
            format!(
33
                "Unexpected tokens: `{tokens}`. Expected a single Essence expression. Perhaps you meant `essence_vec!`?"
34
            ),
35
        ));
36
224
    }
37

            
38
    // Parse expression and build the token stream
39
224
    let expr = mk_expr(expr_node, &source_code, &root, essence)?;
40
224
    Ok(expr)
41
224
}
42

            
43
1
pub fn expand_expr_vec(tt: &TokenTree) -> Result<TokenStream> {
44
1
    let mut ans: Vec<TokenStream> = Vec::new();
45
1
    let src = to_src(tt);
46
1
    let (tree, source_code) =
47
1
        get_expr_tree(&src).ok_or(Error::new(tt.span(), "Could not parse Essence AST"))?;
48
1
    let root = tree.root_node();
49

            
50
1
    let query = query_toplevel(&root, &node_is_expression);
51
2
    for expr_node in query {
52
2
        let expr = mk_expr(expr_node, &source_code, &root, tt)?;
53
2
        ans.push(expr);
54
    }
55
1
    Ok(quote! { vec![#(#ans),*] })
56
1
}
57

            
58
/// Parse a single expression or make a compile time error
59
226
fn mk_expr(node: Node, src: &str, root: &Node, tt: &TokenTree) -> Result<TokenStream> {
60
226
    let mut errors = Vec::new();
61
226
    let mut source_map = SourceMap::default();
62
226
    let mut decl_spans = BTreeMap::new();
63
226
    let mut ctx = ParseContext::new(
64
226
        src,
65
226
        root,
66
226
        None,
67
226
        &mut errors,
68
226
        &mut source_map,
69
226
        &mut decl_spans,
70
    );
71
226
    match parse_expression(&mut ctx, node) {
72
226
        Ok(Some(expr)) => Ok(expr.ctor_tokens()),
73
        Ok(None) => {
74
            // Recoverable error occurred - get the error message from the errors vector
75
            let error_message = if let Some(err) = ctx.errors.first() {
76
                format!("Recoverable parse error: {}", err)
77
            } else {
78
                "Parse error: Unknown error occurred".to_string()
79
            };
80
            Err(Error::new(tt.span(), error_message))
81
        }
82
        Err(err) => Err(Error::new(tt.span(), err.to_string())),
83
    }
84
226
}
85

            
86
/// Parse string literals (gets rid of ""), otherwise use tokens as is
87
225
fn to_src(tt: &TokenTree) -> String {
88
225
    match syn::parse::<LitStr>(tt.to_token_stream().into()) {
89
65
        Ok(src) => src.value(),
90
160
        Err(_) => tt.to_string(),
91
    }
92
225
}