conjure_cp_essence_parser/parser/
keyword_checks.rs1use crate::errors::RecoverableParseError;
2use crate::parser::syntax_errors::is_malformed_line_error;
3
4const KEYWORDS: [&str; 24] = [
5 "forall",
6 "exists",
7 "such",
8 "that",
9 "letting",
10 "find",
11 "minimise",
12 "maximise",
13 "subject",
14 "to",
15 "where",
16 "and",
17 "or",
18 "not",
19 "if",
20 "then",
21 "else",
22 "in",
23 "sum",
24 "product",
25 "bool",
26 "pareto",
27 "minimising",
28 "maximising",
29];
30
31pub fn keyword_as_identifier(
32 root: tree_sitter::Node,
33 source: &str,
34 errors: &mut Vec<RecoverableParseError>,
35) {
36 let mut stack = vec![root];
37 while let Some(node) = stack.pop() {
38 if node.is_error() && is_malformed_line_error(&node, source) {
39 return;
40 }
41 if (node.kind() == "variable" || node.kind() == "identifier" || node.kind() == "parameter")
42 && let Ok(text) = node.utf8_text(source.as_bytes())
43 {
44 let ident = text.trim();
45 if KEYWORDS.contains(&ident) {
46 let start_point = node.start_position();
47 let end_point = node.end_position();
48 errors.push(RecoverableParseError::new(
49 format!("Keyword '{ident}' used as identifier"),
50 Some(tree_sitter::Range {
51 start_byte: node.start_byte(),
52 end_byte: node.end_byte(),
53 start_point,
54 end_point,
55 }),
56 ));
57 }
58 }
59
60 for i in 0..node.child_count() {
61 if let Some(child) = u32::try_from(i).ok().and_then(|i| node.child(i)) {
62 stack.push(child);
63 }
64 }
65 }
66}