datex_core/ast/
binding.rs1use crate::ast::assignment_operation::{
2 AssignmentOperator, assignment_operation,
3};
4use crate::ast::error::error::ParseError;
5use crate::ast::error::pattern::Pattern;
6use crate::ast::lexer::Token;
7use crate::ast::r#type::{r#type, type_declaration};
8use crate::ast::utils::whitespace;
9use crate::ast::{
10 DatexExpression, DatexParserTrait, ParserRecoverExt, TypeExpression,
11 VariableKind,
12};
13use chumsky::prelude::*;
14pub type VariableId = usize;
15
16fn create_variable_declaration(
17 name: String,
18 value: DatexExpression,
19 type_annotation: Option<TypeExpression>,
20 kind: VariableKind,
21) -> DatexExpression {
22 DatexExpression::VariableDeclaration {
23 id: None,
24 kind,
25 name,
26 type_annotation,
27 init_expression: Box::new(value),
28 }
29}
30
31pub fn variable_assignment<'a>(
33 expression: impl DatexParserTrait<'a>,
34) -> impl DatexParserTrait<'a> {
35 let assignment_op = assignment_operation();
36
37 select! { Token::Identifier(name) => name }
38 .then(assignment_op)
39 .then(expression)
40 .map(|((var_name, op), expr)| {
41 DatexExpression::VariableAssignment(
42 op,
43 None,
44 var_name.to_string(),
45 Box::new(expr),
46 )
47 })
48 .labelled(Pattern::Declaration)
49 .as_context()
50}
51pub fn deref_assignment<'a>(
52 expression: impl DatexParserTrait<'a>,
53 unary: impl DatexParserTrait<'a>,
54) -> impl DatexParserTrait<'a> {
55 let assignment_op = assignment_operation();
56
57 just(Token::Star)
58 .repeated()
59 .at_least(1)
60 .count()
61 .then(unary)
62 .then(assignment_op)
63 .then(expression)
64 .map(
65 |(
66 ((deref_count, deref_expression), operator),
67 assigned_expression,
68 )| {
69 DatexExpression::DerefAssignment {
70 operator,
71 deref_count,
72 deref_expression: Box::new(deref_expression),
73 assigned_expression: Box::new(assigned_expression),
74 }
75 },
76 )
77 .labelled(Pattern::Declaration)
79 .as_context()
80}
81
82pub fn variable_declaration<'a>(
84 union: impl DatexParserTrait<'a>,
85) -> impl DatexParserTrait<'a> {
86 let type_annotation = just(Token::Colon)
87 .padded_by(whitespace())
88 .ignore_then(r#type())
89 .or_not();
90
91 let assignment_op = assignment_operation();
92 let keyword = select! {
93 Token::Variable => VariableKind::Var,
94 Token::Const => VariableKind::Const,
95 };
96
97 keyword
98 .padded_by(whitespace())
99 .then(select! { Token::Identifier(s) => s })
100 .then(type_annotation)
101 .then(assignment_op)
102 .then(union.clone())
103 .map(|((((kind, var_name), annotation), op), expr)| {
104 if op != AssignmentOperator::Assign {
105 return Err(ParseError::new_custom(format!(
106 "Cannot use '{}' operator in variable declaration",
107 op
108 )));
109 }
110
111 Ok(create_variable_declaration(
112 var_name.to_string(),
113 expr,
114 annotation,
115 kind,
116 ))
117 })
118 .recover_invalid()
119 .labelled(Pattern::Declaration)
120 .as_context()
121}
122
123pub fn declaration_or_assignment<'a>(
125 expression: impl DatexParserTrait<'a>,
126 unary: impl DatexParserTrait<'a>,
127) -> impl DatexParserTrait<'a> {
128 choice((
129 type_declaration(),
130 variable_declaration(expression.clone()),
131 deref_assignment(expression.clone(), unary),
132 variable_assignment(expression),
133 ))
134}