jia_parse/jia_lang/parser/
decl.rs1use super::Parser;
13use crate::error::ParseError;
14use crate::jia_lang::ast::{VarDecl, VarType};
15use crate::jia_lang::lexer::TokenKind;
16
17impl<'a> Parser<'a> {
18 pub fn parse_variables_block(&mut self) -> Result<Vec<VarDecl>, ParseError> {
20 self.expect_ident_matching("variables")?;
21 self.expect_token(TokenKind::LBrace)?;
22
23 let mut decls = Vec::new();
24 while self.peek_kind() != Some(TokenKind::RBrace) {
25 decls.push(self.parse_var_decl()?);
26 }
27 self.expect_token(TokenKind::RBrace)?;
28 Ok(decls)
29 }
30
31 fn parse_var_decl(&mut self) -> Result<VarDecl, ParseError> {
33 let var_type = self.parse_var_type()?;
34 self.expect_token(TokenKind::Colon)?;
35 let names = self.parse_ident_list()?;
36 Ok(VarDecl { names, var_type })
37 }
38
39 fn parse_var_type(&mut self) -> Result<VarType, ParseError> {
41 let name = self.expect_ident()?;
42 match name.as_str() {
43 "Interval" => Ok(VarType::Interval),
44 "Integer" => Ok(VarType::Integer),
45 "Real" => Ok(VarType::Real),
46 "Set" => {
47 self.expect_token(TokenKind::LBracket)?;
48 let inner = self.expect_ident()?;
49 self.expect_token(TokenKind::RBracket)?;
50 match inner.as_str() {
51 "Interval" => Ok(VarType::SetInterval),
52 "Integer" => Ok(VarType::SetInteger),
53 _ => Err(ParseError::new(
54 format!("expected 'Interval' or 'Integer' in Set[...], got '{inner}'"),
55 self.current_span(),
56 )),
57 }
58 }
59 _ => Err(ParseError::new(
60 format!("expected type (Interval, Integer, Real, Set[...]), got '{name}'"),
61 self.current_span(),
62 )),
63 }
64 }
65
66 pub fn parse_ident_list(&mut self) -> Result<Vec<String>, ParseError> {
68 let mut names = vec![self.expect_ident()?];
69 while self.peek_kind() == Some(TokenKind::Comma) {
70 self.advance();
71 names.push(self.expect_ident()?);
72 }
73 Ok(names)
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use crate::jia_lang::ast::{VarDecl, VarType};
80 use crate::jia_lang::lexer::tokenize;
81 use crate::jia_lang::parser::Parser;
82
83 #[test]
84 fn test_variables_block() {
85 let input = "variables { Interval: a, b Integer: makespan Set[Interval]: m1, m2 }";
86 let tokens = tokenize(input).unwrap();
87 let mut parser = Parser::new(&tokens);
88 let decls = parser.parse_variables_block().unwrap();
89 assert_eq!(
90 decls,
91 vec![
92 VarDecl {
93 names: vec!["a".to_string(), "b".to_string()],
94 var_type: VarType::Interval,
95 },
96 VarDecl {
97 names: vec!["makespan".to_string()],
98 var_type: VarType::Integer,
99 },
100 VarDecl {
101 names: vec!["m1".to_string(), "m2".to_string()],
102 var_type: VarType::SetInterval,
103 },
104 ]
105 );
106 }
107
108 #[test]
109 fn test_set_integer_type() {
110 let input = "variables { Set[Integer]: costs }";
111 let tokens = tokenize(input).unwrap();
112 let mut parser = Parser::new(&tokens);
113 let decls = parser.parse_variables_block().unwrap();
114 assert_eq!(decls[0].var_type, VarType::SetInteger);
115 }
116
117 #[test]
118 fn test_invalid_types() {
119 for input in [
120 "variables { Set[String]: bad }",
121 "variables { Boolean: bad }",
122 ] {
123 let tokens = tokenize(input).unwrap();
124 let mut parser = Parser::new(&tokens);
125 assert!(parser.parse_variables_block().is_err(), "{input}");
126 }
127 }
128}