1use crate::ast::*;
22use crate::error::{Result, SchemaError};
23use crate::span::Span;
24use crate::token::{Token, TokenKind};
25
26pub struct Parser<'a> {
28 tokens: &'a [Token],
30 pos: usize,
32 recovered_errors: Vec<crate::error::SchemaError>,
34}
35
36impl<'a> Parser<'a> {
37 pub fn new(tokens: &'a [Token], source: &'a str) -> Self {
39 let _ = source; Self {
41 tokens,
42 pos: 0,
43 recovered_errors: Vec::new(),
44 }
45 }
46
47 pub fn take_errors(&mut self) -> Vec<crate::error::SchemaError> {
53 std::mem::take(&mut self.recovered_errors)
54 }
55
56 pub fn parse_schema(&mut self) -> Result<Schema> {
58 let start = self.current_span();
59 self.skip_newlines();
60
61 let mut declarations = Vec::new();
62
63 while !self.is_at_end() {
64 match self.parse_declaration() {
65 Ok(decl) => declarations.push(decl),
66 Err(e) => {
67 self.recovered_errors.push(e);
69 self.recover_to_next_declaration();
70 }
71 }
72 self.skip_newlines();
73 }
74
75 let end = self.previous_span();
76 Ok(Schema::new(declarations, start.merge(end)))
77 }
78
79 fn parse_declaration(&mut self) -> Result<Declaration> {
81 self.skip_newlines();
82
83 match self.peek_kind() {
84 Some(TokenKind::Datasource) => Ok(Declaration::Datasource(self.parse_datasource()?)),
85 Some(TokenKind::Generator) => Ok(Declaration::Generator(self.parse_generator()?)),
86 Some(TokenKind::Model) => Ok(Declaration::Model(self.parse_model()?)),
87 Some(TokenKind::Enum) => Ok(Declaration::Enum(self.parse_enum()?)),
88 Some(TokenKind::Type) => Ok(Declaration::Type(self.parse_type_decl()?)),
89 Some(kind) => Err(SchemaError::Parse(
90 format!("Expected declaration, found {:?}", kind),
91 self.current_span(),
92 )),
93 None => Err(SchemaError::Parse(
94 "Unexpected end of file".to_string(),
95 self.current_span(),
96 )),
97 }
98 }
99
100 fn parse_datasource(&mut self) -> Result<DatasourceDecl> {
102 let start = self.expect(TokenKind::Datasource)?.span;
103 let name = self.parse_ident()?;
104 self.expect(TokenKind::LBrace)?;
105 self.skip_newlines();
106
107 let mut fields = Vec::new();
108 while !self.check(TokenKind::RBrace) && !self.is_at_end() {
109 fields.push(self.parse_config_field()?);
110 self.skip_newlines();
111 }
112
113 let end = self.expect(TokenKind::RBrace)?.span;
114 Ok(DatasourceDecl {
115 name,
116 fields,
117 span: start.merge(end),
118 })
119 }
120
121 fn parse_generator(&mut self) -> Result<GeneratorDecl> {
123 let start = self.expect(TokenKind::Generator)?.span;
124 let name = self.parse_ident()?;
125 self.expect(TokenKind::LBrace)?;
126 self.skip_newlines();
127
128 let mut fields = Vec::new();
129 while !self.check(TokenKind::RBrace) && !self.is_at_end() {
130 fields.push(self.parse_config_field()?);
131 self.skip_newlines();
132 }
133
134 let end = self.expect(TokenKind::RBrace)?.span;
135 Ok(GeneratorDecl {
136 name,
137 fields,
138 span: start.merge(end),
139 })
140 }
141
142 fn parse_config_field(&mut self) -> Result<ConfigField> {
144 let name = self.parse_ident()?;
145 self.expect(TokenKind::Equal)?;
146 let value = self.parse_expr()?;
147 let span = name.span.merge(value.span());
148 Ok(ConfigField { name, value, span })
149 }
150
151 fn parse_model(&mut self) -> Result<ModelDecl> {
153 let start = self.expect(TokenKind::Model)?.span;
154 let name = self.parse_ident()?;
155 self.expect(TokenKind::LBrace)?;
156 self.skip_newlines();
157
158 let mut fields = Vec::new();
159 let mut attributes = Vec::new();
160
161 while !self.check(TokenKind::RBrace) && !self.is_at_end() {
162 if self.check(TokenKind::AtAt) {
163 attributes.push(self.parse_model_attribute()?);
164 } else {
165 fields.push(self.parse_field_decl()?);
166 }
167 self.skip_newlines();
168 }
169
170 let end = self.expect(TokenKind::RBrace)?.span;
171 Ok(ModelDecl {
172 name,
173 fields,
174 attributes,
175 span: start.merge(end),
176 })
177 }
178
179 fn parse_type_decl(&mut self) -> Result<TypeDecl> {
181 let start = self.expect(TokenKind::Type)?.span;
182 let name = self.parse_ident()?;
183 self.expect(TokenKind::LBrace)?;
184 self.skip_newlines();
185
186 let mut fields = Vec::new();
187
188 while !self.check(TokenKind::RBrace) && !self.is_at_end() {
189 fields.push(self.parse_field_decl()?);
191 self.skip_newlines();
192 }
193
194 let end = self.expect(TokenKind::RBrace)?.span;
195 Ok(TypeDecl {
196 name,
197 fields,
198 span: start.merge(end),
199 })
200 }
201
202 fn parse_field_decl(&mut self) -> Result<FieldDecl> {
204 let name = self.parse_ident()?;
205 let field_type = self.parse_field_type()?;
206 let modifier = self.parse_field_modifier()?;
207 let base_span = name.span.merge(self.previous_span());
209
210 let mut attributes = Vec::new();
211 while self.check(TokenKind::At) && !self.check(TokenKind::AtAt) {
212 attributes.push(self.parse_field_attribute()?);
213 }
214
215 let span = if let Some(last_attr) = attributes.last() {
216 match last_attr {
217 FieldAttribute::Id => base_span,
218 FieldAttribute::Unique => base_span,
219 FieldAttribute::UpdatedAt { span } => base_span.merge(*span),
220 FieldAttribute::Default(_, span) => base_span.merge(*span),
221 FieldAttribute::Map(_) => base_span,
222 FieldAttribute::Store { .. } => base_span,
223 FieldAttribute::Relation { span, .. } => base_span.merge(*span),
224 FieldAttribute::Computed { span, .. } => base_span.merge(*span),
225 FieldAttribute::Check { span, .. } => base_span.merge(*span),
226 }
227 } else {
228 base_span
229 };
230
231 Ok(FieldDecl {
232 name,
233 field_type,
234 modifier,
235 attributes,
236 span,
237 })
238 }
239
240 fn parse_field_type(&mut self) -> Result<FieldType> {
242 let ident = self.parse_ident()?;
243
244 let field_type = match ident.value.as_str() {
245 "String" => FieldType::String,
246 "Boolean" => FieldType::Boolean,
247 "Int" => FieldType::Int,
248 "BigInt" => FieldType::BigInt,
249 "Float" => FieldType::Float,
250 "DateTime" => FieldType::DateTime,
251 "Bytes" => FieldType::Bytes,
252 "Json" => FieldType::Json,
253 "Uuid" => FieldType::Uuid,
254 "Jsonb" => FieldType::Jsonb,
255 "Xml" => FieldType::Xml,
256 "Char" => {
257 self.expect(TokenKind::LParen)?;
258 let length = self.parse_number()?.parse::<u32>().map_err(|_| {
259 SchemaError::Parse("Invalid length value".to_string(), self.current_span())
260 })?;
261 self.expect(TokenKind::RParen)?;
262 FieldType::Char { length }
263 }
264 "VarChar" => {
265 self.expect(TokenKind::LParen)?;
266 let length = self.parse_number()?.parse::<u32>().map_err(|_| {
267 SchemaError::Parse("Invalid length value".to_string(), self.current_span())
268 })?;
269 self.expect(TokenKind::RParen)?;
270 FieldType::VarChar { length }
271 }
272 "Decimal" => {
273 if self.check(TokenKind::LParen) {
275 self.advance();
276 let precision = self.parse_number()?.parse::<u32>().map_err(|_| {
277 SchemaError::Parse(
278 "Invalid precision value".to_string(),
279 self.current_span(),
280 )
281 })?;
282 self.expect(TokenKind::Comma)?;
283 let scale = self.parse_number()?.parse::<u32>().map_err(|_| {
284 SchemaError::Parse("Invalid scale value".to_string(), self.current_span())
285 })?;
286 self.expect(TokenKind::RParen)?;
287 FieldType::Decimal { precision, scale }
288 } else {
289 return Err(SchemaError::Parse(
290 "Decimal type requires precision and scale: Decimal(p, s)".to_string(),
291 ident.span,
292 ));
293 }
294 }
295 _ => FieldType::UserType(ident.value),
296 };
297
298 Ok(field_type)
299 }
300
301 fn parse_field_modifier(&mut self) -> Result<FieldModifier> {
303 if self.check(TokenKind::Question) {
304 self.advance();
305 Ok(FieldModifier::Optional)
306 } else if self.check(TokenKind::Bang) {
307 self.advance();
308 Ok(FieldModifier::NotNull)
309 } else if self.check(TokenKind::LBracket) {
310 self.advance();
311 self.expect(TokenKind::RBracket)?;
312 Ok(FieldModifier::Array)
313 } else {
314 Ok(FieldModifier::None)
315 }
316 }
317
318 fn parse_field_attribute(&mut self) -> Result<FieldAttribute> {
320 let at_token = self.expect(TokenKind::At)?;
321 let at_span = at_token.span;
322 let name = self.parse_ident()?;
323
324 match name.value.as_str() {
325 "id" => Ok(FieldAttribute::Id),
326 "unique" => Ok(FieldAttribute::Unique),
327 "updatedAt" => Ok(FieldAttribute::UpdatedAt {
328 span: at_span.merge(name.span),
329 }),
330 "default" => {
331 self.expect(TokenKind::LParen)?;
332 let expr = self.parse_expr()?;
333 let rparen = self.expect(TokenKind::RParen)?;
334 let full_span = at_span.merge(rparen.span);
335 Ok(FieldAttribute::Default(expr, full_span))
336 }
337 "map" => {
338 self.expect(TokenKind::LParen)?;
339 let map_name = self.parse_string()?;
340 self.expect(TokenKind::RParen)?;
341 Ok(FieldAttribute::Map(map_name))
342 }
343 "store" => {
344 let start = name.span;
345 self.expect(TokenKind::LParen)?;
346 let strategy_ident = self.parse_ident()?;
347 let strategy = match strategy_ident.value.as_str() {
348 "json" => StorageStrategy::Json,
349 "native" => StorageStrategy::Native,
350 _ => {
351 return Err(SchemaError::Parse(
352 format!(
353 "Unknown storage strategy: '{}'. Valid options: 'json', 'native'",
354 strategy_ident.value
355 ),
356 strategy_ident.span,
357 ))
358 }
359 };
360 let end = self.expect(TokenKind::RParen)?.span;
361 Ok(FieldAttribute::Store {
362 strategy,
363 span: start.merge(end),
364 })
365 }
366 "relation" => {
367 let start = name.span;
368 self.expect(TokenKind::LParen)?;
369
370 let mut rel_name = None;
371 let mut fields = None;
372 let mut references = None;
373 let mut on_delete = None;
374 let mut on_update = None;
375
376 while !self.check(TokenKind::RParen) && !self.is_at_end() {
378 let arg_name = self.parse_ident()?;
379 self.expect(TokenKind::Colon)?;
380
381 match arg_name.value.as_str() {
382 "name" => rel_name = Some(self.parse_string()?),
383 "fields" => fields = Some(self.parse_ident_array()?),
384 "references" => references = Some(self.parse_ident_array()?),
385 "onDelete" => on_delete = Some(self.parse_referential_action()?),
386 "onUpdate" => on_update = Some(self.parse_referential_action()?),
387 _ => {
388 return Err(SchemaError::Parse(
389 format!("Unknown relation argument: {}", arg_name.value),
390 arg_name.span,
391 ))
392 }
393 }
394
395 if self.check(TokenKind::Comma) {
396 self.advance();
397 }
398 }
399
400 let end = self.expect(TokenKind::RParen)?.span;
401 Ok(FieldAttribute::Relation {
402 name: rel_name,
403 fields,
404 references,
405 on_delete,
406 on_update,
407 span: start.merge(end),
408 })
409 }
410 "computed" => {
411 let start = at_span;
412 self.expect(TokenKind::LParen)?;
413 let expr = self.parse_sql_expr()?;
414 self.expect(TokenKind::Comma)?;
415 let kind_ident = self.parse_ident()?;
416 let kind = match kind_ident.value.as_str() {
417 "Stored" => ComputedKind::Stored,
418 "Virtual" => ComputedKind::Virtual,
419 other => {
420 return Err(SchemaError::Parse(
421 format!(
422 "Unknown computed kind '{}'. Valid options: Stored, Virtual",
423 other
424 ),
425 kind_ident.span,
426 ))
427 }
428 };
429 let end = self.expect(TokenKind::RParen)?.span;
430 Ok(FieldAttribute::Computed {
431 expr,
432 kind,
433 span: start.merge(end),
434 })
435 }
436 "check" => {
437 let start = at_span;
438 self.expect(TokenKind::LParen)?;
439 let expr = self.parse_bool_expr()?;
440 let end = self.expect(TokenKind::RParen)?.span;
441 Ok(FieldAttribute::Check {
442 expr,
443 span: start.merge(end),
444 })
445 }
446 _ => Err(SchemaError::Parse(
447 format!("Unknown field attribute: @{}", name.value),
448 name.span,
449 )),
450 }
451 }
452
453 fn parse_sql_expr(&mut self) -> Result<crate::sql_expr::SqlExpr> {
456 if self.pos >= self.tokens.len() {
457 return Err(SchemaError::Parse(
458 "Unexpected end of file in @computed expression".to_string(),
459 self.current_span(),
460 ));
461 }
462 let fallback_span = self.current_span();
463 let expr_start = self.pos;
464 let mut depth: i32 = 0;
465
466 loop {
467 match self.peek_kind() {
468 Some(TokenKind::LParen) => {
469 depth += 1;
470 self.advance();
471 }
472 Some(TokenKind::RParen) if depth == 0 => break,
473 Some(TokenKind::RParen) => {
474 depth -= 1;
475 self.advance();
476 }
477 Some(TokenKind::Comma) if depth == 0 => break,
478 None | Some(TokenKind::Eof) => {
479 return Err(SchemaError::Parse(
480 "Unexpected end of file in @computed expression".to_string(),
481 self.current_span(),
482 ));
483 }
484 _ => {
485 self.advance();
486 }
487 }
488 }
489
490 let expr_tokens: Vec<_> = self.tokens[expr_start..self.pos]
491 .iter()
492 .filter(|t| !matches!(t.kind, TokenKind::Newline))
493 .cloned()
494 .collect();
495
496 crate::sql_expr::parse_sql_expr(&expr_tokens, fallback_span)
497 }
498
499 fn parse_bool_expr(&mut self) -> Result<crate::bool_expr::BoolExpr> {
502 if self.pos >= self.tokens.len() {
503 return Err(SchemaError::Parse(
504 "Unexpected end of file in @check expression".to_string(),
505 self.current_span(),
506 ));
507 }
508 let fallback_span = self.current_span();
509 let expr_start = self.pos;
510 let mut depth: i32 = 0;
511
512 loop {
513 match self.peek_kind() {
514 Some(TokenKind::LParen) => {
515 depth += 1;
516 self.advance();
517 }
518 Some(TokenKind::RParen) if depth == 0 => break,
519 Some(TokenKind::RParen) => {
520 depth -= 1;
521 self.advance();
522 }
523 None | Some(TokenKind::Eof) => {
524 return Err(SchemaError::Parse(
525 "Unexpected end of file in @check expression".to_string(),
526 self.current_span(),
527 ));
528 }
529 _ => {
530 self.advance();
531 }
532 }
533 }
534
535 let expr_tokens: Vec<_> = self.tokens[expr_start..self.pos]
536 .iter()
537 .filter(|t| !matches!(t.kind, TokenKind::Newline))
538 .cloned()
539 .collect();
540
541 crate::bool_expr::parse_bool_expr(&expr_tokens, fallback_span)
542 }
543
544 fn parse_model_attribute(&mut self) -> Result<ModelAttribute> {
546 self.expect(TokenKind::AtAt)?;
547 let name = self.parse_ident()?;
548
549 match name.value.as_str() {
550 "map" => {
551 self.expect(TokenKind::LParen)?;
552 let map_name = self.parse_string()?;
553 self.expect(TokenKind::RParen)?;
554 Ok(ModelAttribute::Map(map_name))
555 }
556 "id" => {
557 self.expect(TokenKind::LParen)?;
558 let fields = self.parse_ident_array()?;
559 self.expect(TokenKind::RParen)?;
560 Ok(ModelAttribute::Id(fields))
561 }
562 "unique" => {
563 self.expect(TokenKind::LParen)?;
564 let fields = self.parse_ident_array()?;
565 self.expect(TokenKind::RParen)?;
566 Ok(ModelAttribute::Unique(fields))
567 }
568 "index" => {
569 self.expect(TokenKind::LParen)?;
570 let fields = self.parse_ident_array()?;
571 let mut index_type: Option<Ident> = None;
572 let mut index_name: Option<String> = None;
573 let mut index_map: Option<String> = None;
574 while self.check(TokenKind::Comma) {
576 self.advance(); if self.check(TokenKind::RParen) {
578 break; }
580 let key = self.parse_ident()?;
581 self.expect(TokenKind::Colon)?;
582 match key.value.as_str() {
583 "type" => {
584 index_type = Some(self.parse_ident()?);
585 }
586 "name" => {
587 index_name = Some(self.parse_string()?);
588 }
589 "map" => {
590 index_map = Some(self.parse_string()?);
591 }
592 _ => {
593 return Err(SchemaError::Parse(
594 format!("Unknown @@index argument: '{}'", key.value),
595 key.span,
596 ));
597 }
598 }
599 }
600 self.expect(TokenKind::RParen)?;
601 Ok(ModelAttribute::Index {
602 fields,
603 index_type,
604 name: index_name,
605 map: index_map,
606 })
607 }
608 "check" => {
609 self.expect(TokenKind::LParen)?;
610 let expr = self.parse_bool_expr()?;
611 let end = self.expect(TokenKind::RParen)?.span;
612 Ok(ModelAttribute::Check {
613 expr,
614 span: name.span.merge(end),
615 })
616 }
617 _ => Err(SchemaError::Parse(
618 format!("Unknown model attribute: @@{}", name.value),
619 name.span,
620 )),
621 }
622 }
623
624 fn parse_ident_array(&mut self) -> Result<Vec<Ident>> {
626 self.expect(TokenKind::LBracket)?;
627 let mut idents = Vec::new();
628
629 while !self.check(TokenKind::RBracket) && !self.is_at_end() {
630 idents.push(self.parse_ident()?);
631 if self.check(TokenKind::Comma) {
632 self.advance();
633 }
634 }
635
636 self.expect(TokenKind::RBracket)?;
637 Ok(idents)
638 }
639
640 fn parse_referential_action(&mut self) -> Result<ReferentialAction> {
642 let ident = self.parse_ident()?;
643 match ident.value.as_str() {
644 "Cascade" => Ok(ReferentialAction::Cascade),
645 "Restrict" => Ok(ReferentialAction::Restrict),
646 "NoAction" => Ok(ReferentialAction::NoAction),
647 "SetNull" => Ok(ReferentialAction::SetNull),
648 "SetDefault" => Ok(ReferentialAction::SetDefault),
649 _ => Err(SchemaError::Parse(
650 format!("Unknown referential action: {}", ident.value),
651 ident.span,
652 )),
653 }
654 }
655
656 fn parse_enum(&mut self) -> Result<EnumDecl> {
658 let start = self.expect(TokenKind::Enum)?.span;
659 let name = self.parse_ident()?;
660 self.expect(TokenKind::LBrace)?;
661 self.skip_newlines();
662
663 let mut variants = Vec::new();
664 while !self.check(TokenKind::RBrace) && !self.is_at_end() {
665 let variant_name = self.parse_ident()?;
666 let variant_span = variant_name.span;
667 variants.push(EnumVariant {
668 name: variant_name,
669 span: variant_span,
670 });
671 self.skip_newlines();
672 }
673
674 let end = self.expect(TokenKind::RBrace)?.span;
675 Ok(EnumDecl {
676 name,
677 variants,
678 span: start.merge(end),
679 })
680 }
681
682 fn parse_expr(&mut self) -> Result<Expr> {
684 match self.peek_kind() {
685 Some(TokenKind::String(_)) => {
686 let s = self.parse_string()?;
687 let span = self.previous_span();
688 Ok(Expr::Literal(Literal::String(s, span)))
689 }
690 Some(TokenKind::Number(_)) => {
691 let n = self.parse_number()?;
692 let span = self.previous_span();
693 Ok(Expr::Literal(Literal::Number(n, span)))
694 }
695 Some(TokenKind::True) => {
696 let span = self.advance().span;
697 Ok(Expr::Literal(Literal::Boolean(true, span)))
698 }
699 Some(TokenKind::False) => {
700 let span = self.advance().span;
701 Ok(Expr::Literal(Literal::Boolean(false, span)))
702 }
703 Some(TokenKind::LBracket) => self.parse_array_expr(),
704 Some(TokenKind::Ident(_)) => {
705 let ident = self.parse_ident()?;
706
707 if self.check(TokenKind::LParen) {
709 let start = ident.span;
710 self.advance();
711
712 let mut args = Vec::new();
713 while !self.check(TokenKind::RParen) && !self.is_at_end() {
714 args.push(self.parse_expr()?);
715 if self.check(TokenKind::Comma) {
716 self.advance();
717 }
718 }
719
720 let end = self.expect(TokenKind::RParen)?.span;
721 Ok(Expr::FunctionCall {
722 name: ident,
723 args,
724 span: start.merge(end),
725 })
726 } else {
727 Ok(Expr::Ident(ident))
729 }
730 }
731 Some(kind) => Err(SchemaError::Parse(
732 format!("Expected expression, found {:?}", kind),
733 self.current_span(),
734 )),
735 None => Err(SchemaError::Parse(
736 "Unexpected end of file in expression".to_string(),
737 self.current_span(),
738 )),
739 }
740 }
741
742 fn parse_array_expr(&mut self) -> Result<Expr> {
744 let start = self.expect(TokenKind::LBracket)?.span;
745 let mut elements = Vec::new();
746
747 while !self.check(TokenKind::RBracket) && !self.is_at_end() {
748 elements.push(self.parse_expr()?);
749 if self.check(TokenKind::Comma) {
750 self.advance();
751 }
752 }
753
754 let end = self.expect(TokenKind::RBracket)?.span;
755 Ok(Expr::Array {
756 elements,
757 span: start.merge(end),
758 })
759 }
760
761 fn parse_ident(&mut self) -> Result<Ident> {
763 match self.peek_kind() {
764 Some(TokenKind::Ident(ref name)) => {
765 let name = name.clone();
766 let span = self.advance().span;
767 Ok(Ident::new(name, span))
768 }
769 Some(TokenKind::Type) => {
772 let span = self.advance().span;
773 Ok(Ident::new("type".to_string(), span))
774 }
775 Some(kind) => Err(SchemaError::Parse(
776 format!("Expected identifier, found {:?}", kind),
777 self.current_span(),
778 )),
779 None => Err(SchemaError::Parse(
780 "Expected identifier, found EOF".to_string(),
781 self.current_span(),
782 )),
783 }
784 }
785
786 fn parse_string(&mut self) -> Result<String> {
788 match self.peek_kind() {
789 Some(TokenKind::String(ref s)) => {
790 let s = s.clone();
791 self.advance();
792 Ok(s)
793 }
794 Some(kind) => Err(SchemaError::Parse(
795 format!("Expected string, found {:?}", kind),
796 self.current_span(),
797 )),
798 None => Err(SchemaError::Parse(
799 "Expected string, found EOF".to_string(),
800 self.current_span(),
801 )),
802 }
803 }
804
805 fn parse_number(&mut self) -> Result<String> {
807 match self.peek_kind() {
808 Some(TokenKind::Number(ref n)) => {
809 let n = n.clone();
810 self.advance();
811 Ok(n)
812 }
813 Some(kind) => Err(SchemaError::Parse(
814 format!("Expected number, found {:?}", kind),
815 self.current_span(),
816 )),
817 None => Err(SchemaError::Parse(
818 "Expected number, found EOF".to_string(),
819 self.current_span(),
820 )),
821 }
822 }
823
824 fn check(&self, kind: TokenKind) -> bool {
828 self.peek_kind()
829 .map(|k| std::mem::discriminant(&k) == std::mem::discriminant(&kind))
830 .unwrap_or(false)
831 }
832
833 fn expect(&mut self, kind: TokenKind) -> Result<&'a Token> {
835 if self.check(kind.clone()) {
836 Ok(self.advance())
837 } else {
838 Err(SchemaError::Parse(
839 format!("Expected {:?}, found {:?}", kind, self.peek_kind()),
840 self.current_span(),
841 ))
842 }
843 }
844
845 fn peek_kind(&self) -> Option<TokenKind> {
847 self.tokens.get(self.pos).map(|t| t.kind.clone())
848 }
849
850 fn advance(&mut self) -> &'a Token {
852 let token = &self.tokens[self.pos];
853 if self.pos < self.tokens.len() {
854 self.pos += 1;
855 }
856 token
857 }
858
859 fn current_span(&self) -> Span {
861 self.tokens
862 .get(self.pos)
863 .map(|t| t.span)
864 .unwrap_or_else(|| self.previous_span())
865 }
866
867 fn previous_span(&self) -> Span {
869 if self.pos > 0 {
870 self.tokens[self.pos - 1].span
871 } else {
872 Span::new(0, 0)
873 }
874 }
875
876 fn is_at_end(&self) -> bool {
878 self.pos >= self.tokens.len() || matches!(self.peek_kind(), Some(TokenKind::Eof))
879 }
880
881 fn skip_newlines(&mut self) {
883 while matches!(self.peek_kind(), Some(TokenKind::Newline)) {
884 self.advance();
885 }
886 }
887
888 fn recover_to_next_declaration(&mut self) {
890 while !self.is_at_end() {
891 match self.peek_kind() {
892 Some(TokenKind::Datasource)
893 | Some(TokenKind::Generator)
894 | Some(TokenKind::Model)
895 | Some(TokenKind::Enum)
896 | Some(TokenKind::Type) => break,
897 _ => {
898 self.advance();
899 }
900 }
901 }
902 }
903}
904
905#[cfg(test)]
906mod tests {
907 use super::*;
908 use crate::lexer::Lexer;
909
910 fn tokenize(input: &str) -> Vec<Token> {
911 let mut lexer = Lexer::new(input);
912 let mut tokens = Vec::new();
913 loop {
914 match lexer.next_token() {
915 Ok(token) => {
916 if matches!(token.kind, TokenKind::Eof) {
917 tokens.push(token);
918 break;
919 }
920 tokens.push(token);
921 }
922 Err(e) => panic!("Tokenization failed: {}", e),
923 }
924 }
925 tokens
926 }
927
928 #[test]
929 fn test_parse_empty_schema() {
930 let input = "";
931 let tokens = tokenize(input);
932 let schema = Parser::new(&tokens, input).parse_schema().unwrap();
933 assert_eq!(schema.declarations.len(), 0);
934 }
935
936 #[test]
937 fn test_parse_simple_model() {
938 let input = r#"
939 model User {
940 id Int @id
941 }
942 "#;
943 let tokens = tokenize(input);
944 let schema = Parser::new(&tokens, input).parse_schema().unwrap();
945 assert_eq!(schema.declarations.len(), 1);
946
947 match &schema.declarations[0] {
948 Declaration::Model(model) => {
949 assert_eq!(model.name.value, "User");
950 assert_eq!(model.fields.len(), 1);
951 assert_eq!(model.fields[0].name.value, "id");
952 }
953 _ => panic!("Expected model declaration"),
954 }
955 }
956
957 #[test]
958 fn test_parse_field_types() {
959 let input = r#"
960 model Test {
961 str String
962 num Int
963 big BigInt
964 opt String?
965 arr Int[]
966 dec Decimal(10, 2)
967 }
968 "#;
969 let tokens = tokenize(input);
970 let schema = Parser::new(&tokens, input).parse_schema().unwrap();
971
972 match &schema.declarations[0] {
973 Declaration::Model(model) => {
974 assert_eq!(model.fields.len(), 6);
975 assert!(matches!(model.fields[0].field_type, FieldType::String));
976 assert!(matches!(model.fields[1].field_type, FieldType::Int));
977 assert!(matches!(model.fields[2].field_type, FieldType::BigInt));
978 assert!(model.fields[3].is_optional());
979 assert!(model.fields[4].is_array());
980 assert!(matches!(
981 model.fields[5].field_type,
982 FieldType::Decimal {
983 precision: 10,
984 scale: 2
985 }
986 ));
987 }
988 _ => panic!("Expected model"),
989 }
990 }
991
992 #[test]
993 fn test_parse_field_attributes() {
994 let input = r#"
995 model User {
996 id Int @id @default(autoincrement())
997 email String @unique @map("user_email")
998 }
999 "#;
1000 let tokens = tokenize(input);
1001 let schema = Parser::new(&tokens, input).parse_schema().unwrap();
1002
1003 match &schema.declarations[0] {
1004 Declaration::Model(model) => {
1005 assert_eq!(model.fields[0].attributes.len(), 2);
1006 assert!(matches!(model.fields[0].attributes[0], FieldAttribute::Id));
1007 assert!(matches!(
1008 model.fields[0].attributes[1],
1009 FieldAttribute::Default(..)
1010 ));
1011
1012 assert_eq!(model.fields[1].attributes.len(), 2);
1013 assert!(matches!(
1014 model.fields[1].attributes[0],
1015 FieldAttribute::Unique
1016 ));
1017 assert!(matches!(
1018 model.fields[1].attributes[1],
1019 FieldAttribute::Map(_)
1020 ));
1021 }
1022 _ => panic!("Expected model"),
1023 }
1024 }
1025
1026 #[test]
1027 fn test_parse_model_attributes() {
1028 let input = r#"
1029 model User {
1030 id Int
1031 @@map("users")
1032 @@id([id])
1033 }
1034 "#;
1035 let tokens = tokenize(input);
1036 let schema = Parser::new(&tokens, input).parse_schema().unwrap();
1037
1038 match &schema.declarations[0] {
1039 Declaration::Model(model) => {
1040 assert_eq!(model.attributes.len(), 2);
1041 assert!(matches!(model.attributes[0], ModelAttribute::Map(_)));
1042 assert!(matches!(model.attributes[1], ModelAttribute::Id(_)));
1043 }
1044 _ => panic!("Expected model"),
1045 }
1046 }
1047
1048 #[test]
1049 fn test_parse_enum() {
1050 let input = r#"
1051 enum Role {
1052 USER
1053 ADMIN
1054 }
1055 "#;
1056 let tokens = tokenize(input);
1057 let schema = Parser::new(&tokens, input).parse_schema().unwrap();
1058
1059 match &schema.declarations[0] {
1060 Declaration::Enum(enum_decl) => {
1061 assert_eq!(enum_decl.name.value, "Role");
1062 assert_eq!(enum_decl.variants.len(), 2);
1063 assert_eq!(enum_decl.variants[0].name.value, "USER");
1064 assert_eq!(enum_decl.variants[1].name.value, "ADMIN");
1065 }
1066 _ => panic!("Expected enum"),
1067 }
1068 }
1069
1070 #[test]
1071 fn test_parse_datasource() {
1072 let input = r#"
1073 datasource db {
1074 provider = "postgresql"
1075 url = env("DATABASE_URL")
1076 }
1077 "#;
1078 let tokens = tokenize(input);
1079 let schema = Parser::new(&tokens, input).parse_schema().unwrap();
1080
1081 match &schema.declarations[0] {
1082 Declaration::Datasource(ds) => {
1083 assert_eq!(ds.name.value, "db");
1084 assert_eq!(ds.fields.len(), 2);
1085 assert_eq!(ds.provider(), Some("postgresql"));
1086 }
1087 _ => panic!("Expected datasource"),
1088 }
1089 }
1090
1091 #[test]
1092 fn test_parse_generator() {
1093 let input = r#"
1094 generator client {
1095 provider = "nautilus-client-rs"
1096 output = "../generated"
1097 }
1098 "#;
1099 let tokens = tokenize(input);
1100 let schema = Parser::new(&tokens, input).parse_schema().unwrap();
1101
1102 match &schema.declarations[0] {
1103 Declaration::Generator(gen) => {
1104 assert_eq!(gen.name.value, "client");
1105 assert_eq!(gen.fields.len(), 2);
1106 }
1107 _ => panic!("Expected generator"),
1108 }
1109 }
1110
1111 #[test]
1112 fn test_parse_relation() {
1113 let input = r#"
1114 model Post {
1115 userId Int
1116 user User @relation(fields: [userId], references: [id], onDelete: Cascade)
1117 }
1118 "#;
1119 let tokens = tokenize(input);
1120 let schema = Parser::new(&tokens, input).parse_schema().unwrap();
1121
1122 match &schema.declarations[0] {
1123 Declaration::Model(model) => match &model.fields[1].attributes[0] {
1124 FieldAttribute::Relation {
1125 fields,
1126 references,
1127 on_delete,
1128 ..
1129 } => {
1130 assert!(fields.is_some());
1131 assert!(references.is_some());
1132 assert_eq!(*on_delete, Some(ReferentialAction::Cascade));
1133 }
1134 _ => panic!("Expected relation attribute"),
1135 },
1136 _ => panic!("Expected model"),
1137 }
1138 }
1139}