1
use crate::errors::{FatalParseError, RecoverableParseError};
2
use crate::expression::parse_expression;
3
use crate::field;
4
use crate::parser::ParseContext;
5
use crate::parser::domain::parse_domain;
6
use crate::util::{TypecheckingContext, named_children};
7
use conjure_cp_core::ast::{AbstractLiteral, DomainPtr, Expression};
8
use conjure_cp_core::{domain_int, range};
9
use tree_sitter::Node;
10

            
11
4979
pub fn parse_abstract(
12
4979
    ctx: &mut ParseContext,
13
4979
    node: &Node,
14
4979
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
15
    // If we're in a set context, we can only parse set literals, so add an error if we see any other kind of abstract literal
16
4979
    if ctx.typechecking_context == TypecheckingContext::Set && node.kind() != "set_literal" {
17
        ctx.record_error(RecoverableParseError::new(
18
            format!(
19
                "Type error: {}\n\tExpected: set\n\tGot: {}",
20
                ctx.source_code[node.start_byte()..node.end_byte()].trim(),
21
                node.kind()
22
            ),
23
            Some(node.range()),
24
        ));
25
        return Ok(None);
26
4979
    }
27

            
28
4979
    match node.kind() {
29
4979
        "record" => parse_record(ctx, node),
30
4953
        "tuple" => parse_tuple(ctx, node),
31
4836
        "matrix" => parse_matrix(ctx, node),
32
1482
        "set_literal" => parse_set_literal(ctx, node),
33
        _ => {
34
            ctx.record_error(RecoverableParseError::new(
35
                format!("Expected abstract literal, got: {}", node.kind()),
36
                Some(node.range()),
37
            ));
38
            Ok(None)
39
        }
40
    }
41
4979
}
42

            
43
26
fn parse_record(
44
26
    ctx: &mut ParseContext,
45
26
    node: &Node,
46
26
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
47
26
    let mut values = Vec::new();
48
52
    for child in node.children_by_field_name("name_value_pair", &mut node.walk()) {
49
52
        let Some(name_node) = field!(recover, ctx, child, "name") else {
50
            return Ok(None);
51
        };
52
52
        let name_str = &ctx.source_code[name_node.start_byte()..name_node.end_byte()];
53
52
        let name = conjure_cp_core::ast::Name::user(name_str);
54

            
55
52
        let Some(value_node) = field!(recover, ctx, child, "value") else {
56
            return Ok(None);
57
        };
58
52
        let Some(value) = parse_expression(ctx, value_node)? else {
59
            return Ok(None);
60
        };
61
52
        values.push(conjure_cp_core::ast::records::RecordValue { name, value });
62
    }
63
26
    Ok(Some(AbstractLiteral::Record(values)))
64
26
}
65

            
66
117
fn parse_tuple(
67
117
    ctx: &mut ParseContext,
68
117
    node: &Node,
69
117
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
70
117
    let mut elements = Vec::new();
71
286
    for child in named_children(node) {
72
286
        let Some(expr) = parse_expression(ctx, child)? else {
73
13
            return Ok(None);
74
        };
75
273
        elements.push(expr);
76
    }
77
104
    Ok(Some(AbstractLiteral::Tuple(elements)))
78
117
}
79

            
80
3354
fn parse_matrix(
81
3354
    ctx: &mut ParseContext,
82
3354
    node: &Node,
83
3354
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
84
3354
    let mut elements = vec![];
85
3354
    let mut domain: Option<DomainPtr> = None;
86
8915
    for child in named_children(node) {
87
8915
        if child.kind() == "arithmetic_expr"
88
8603
            || child.kind() == "bool_expr"
89
8593
            || child.kind() == "comparison_expr"
90
8277
            || child.kind() == "atom"
91
        {
92
8564
            let Some(expr) = parse_expression(ctx, child)? else {
93
26
                return Ok(None);
94
            };
95
8538
            elements.push(expr);
96
        } else {
97
351
            let Some(parsed_domain) = parse_domain(ctx, child)? else {
98
13
                return Ok(None);
99
            };
100
338
            domain = Some(parsed_domain);
101
        }
102
    }
103
3315
    if domain.is_none() {
104
2977
        let count = elements.len() as i32;
105
2977
        domain = Some(domain_int!(1..count));
106
3159
    }
107

            
108
3315
    Ok(Some(AbstractLiteral::Matrix(elements, domain.unwrap())))
109
3354
}
110

            
111
1482
fn parse_set_literal(
112
1482
    ctx: &mut ParseContext,
113
1482
    node: &Node,
114
1482
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
115
1482
    let mut elements = Vec::new();
116
3835
    for child in named_children(node) {
117
3835
        ctx.typechecking_context = TypecheckingContext::Unknown;
118
3835
        let Some(expr) = parse_expression(ctx, child)? else {
119
26
            return Ok(None);
120
        };
121
3809
        elements.push(expr);
122
    }
123
1456
    Ok(Some(AbstractLiteral::Set(elements)))
124
1482
}