(&mut self)
| 164 | } |
| 165 | |
| 166 | fn parse_fields(&mut self) -> Result<Vec<Field>, String> { |
| 167 | self.consume(TokenType::OpenBrace, "Expected '{' after field block")?; |
| 168 | |
| 169 | let mut fields = Vec::new(); |
| 170 | while !self.check(TokenType::CloseBrace) { |
| 171 | // Parse doc comments |
| 172 | let docs = self.parse_docs(); |
| 173 | |
| 174 | // Parse validators |
| 175 | let validators = DirectiveParser::new(&mut self.scanner).parse_validators(); |
| 176 | |
| 177 | // Parse field name |
| 178 | if !self.check(TokenType::Identifier) { |
| 179 | return Err("Expected field name".to_string()); |
| 180 | } |
| 181 | let name = self.current.lexeme.to_string(); |
| 182 | self.advance(); |
| 183 | |
| 184 | self.consume(TokenType::Colon, "Expected ':' after field name")?; |
| 185 | |
| 186 | // Parse field type |
| 187 | if !self.check(TokenType::Identifier) { |
| 188 | return Err("Expected field type".to_string()); |
| 189 | } |
| 190 | let field_type = match self.current.lexeme { |
| 191 | "str" => FieldType::Str, |
| 192 | "int" | "float" => FieldType::Number, |
| 193 | "bool" => FieldType::Bool, |
| 194 | _ => return Err(format!("Invalid field type: {}", self.current.lexeme)), |
| 195 | }; |
| 196 | self.advance(); |
| 197 | |
| 198 | // Parse default value |
| 199 | let mut default = None; |
| 200 | if self.check(TokenType::Equal) { |
| 201 | self.advance(); |
| 202 | default = Some(self.parse_value()?); |
| 203 | } |
| 204 | |
| 205 | fields.push(Field { |
| 206 | name, |
| 207 | _type: field_type, |
| 208 | required: default.is_none(), |
| 209 | default, |
| 210 | validators: validators.into_boxed_slice(), |
| 211 | docs, |
| 212 | }); |
| 213 | |
| 214 | // If this is not the last field (not followed by a closing brace), |
| 215 | // then a comma is required |
| 216 | if !self.check(TokenType::CloseBrace) { |
| 217 | self.consume(TokenType::Comma, "Expected ',' after field definition")?; |
| 218 | } else { |
| 219 | // We've reached the closing brace, we can optionally have a comma |
| 220 | if self.check(TokenType::Comma) { |
| 221 | self.advance(); // consume the optional trailing comma |
| 222 | } |
| 223 | break; |
no test coverage detected