1
use crate::errors::FatalParseError;
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
631
pub fn parse_abstract(
12
631
    ctx: &mut ParseContext,
13
631
    node: &Node,
14
631
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
15
631
    match node.kind() {
16
631
        "record" => parse_record(ctx, node),
17
631
        "tuple" => parse_tuple(ctx, node),
18
631
        "matrix" => parse_matrix(ctx, node),
19
594
        "set_literal" => parse_set_literal(ctx, node),
20
        _ => Err(FatalParseError::internal_error(
21
            format!("Expected abstract literal, got: {}", node.kind()),
22
            Some(node.range()),
23
        )),
24
    }
25
631
}
26

            
27
fn parse_record(
28
    ctx: &mut ParseContext,
29
    node: &Node,
30
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
31
    let mut values = Vec::new();
32
    for child in node.children_by_field_name("name_value_pair", &mut node.walk()) {
33
        let name_node = field!(child, "name");
34
        let name_str = &ctx.source_code[name_node.start_byte()..name_node.end_byte()];
35
        let name = conjure_cp_core::ast::Name::user(name_str);
36

            
37
        let Some(value) = parse_expression(ctx, field!(child, "value"))? else {
38
            return Ok(None);
39
        };
40
        values.push(conjure_cp_core::ast::records::RecordValue { name, value });
41
    }
42
    Ok(Some(AbstractLiteral::Record(values)))
43
}
44

            
45
fn parse_tuple(
46
    ctx: &mut ParseContext,
47
    node: &Node,
48
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
49
    let mut elements = Vec::new();
50
    for child in named_children(node) {
51
        let Some(expr) = parse_expression(ctx, child)? else {
52
            return Ok(None);
53
        };
54
        elements.push(expr);
55
    }
56
    Ok(Some(AbstractLiteral::Tuple(elements)))
57
}
58

            
59
37
fn parse_matrix(
60
37
    ctx: &mut ParseContext,
61
37
    node: &Node,
62
37
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
63
37
    let mut elements = vec![];
64
37
    let mut domain: Option<DomainPtr> = None;
65
82
    for child in named_children(node) {
66
82
        if child.kind() == "arithmetic_expr"
67
82
            || child.kind() == "bool_expr"
68
82
            || child.kind() == "comparison_expr"
69
82
            || child.kind() == "atom"
70
        {
71
78
            let Some(expr) = parse_expression(ctx, child)? else {
72
22
                return Ok(None);
73
            };
74
56
            elements.push(expr);
75
        } else {
76
4
            let Some(parsed_domain) = parse_domain(ctx, child)? else {
77
                return Ok(None);
78
            };
79
4
            domain = Some(parsed_domain);
80
        }
81
    }
82
15
    if domain.is_none() {
83
11
        let count = elements.len() as i32;
84
11
        domain = Some(domain_int!(1..count));
85
15
    }
86

            
87
15
    Ok(Some(AbstractLiteral::Matrix(elements, domain.unwrap())))
88
37
}
89

            
90
594
fn parse_set_literal(
91
594
    ctx: &mut ParseContext,
92
594
    node: &Node,
93
594
) -> Result<Option<AbstractLiteral<Expression>>, FatalParseError> {
94
594
    let mut elements = Vec::new();
95
1540
    for child in named_children(node) {
96
1540
        ctx.typechecking_context = TypecheckingContext::Unknown;
97
1540
        let Some(expr) = parse_expression(ctx, child)? else {
98
            return Ok(None);
99
        };
100
1540
        elements.push(expr);
101
    }
102
594
    Ok(Some(AbstractLiteral::Set(elements)))
103
594
}