1use logos::Logos;
4
5#[derive(Logos, Debug, Clone, PartialEq, Eq, Hash)]
7#[logos(skip r"[ \t\r\n]+")]
8#[logos(skip r"//[^\n]*")]
9pub enum Token {
10 #[token("agent")]
14 KwAgent,
15
16 #[token("belief")]
17 KwBelief,
18
19 #[token("on")]
20 KwOn,
21
22 #[token("start")]
23 KwStart,
24
25 #[token("stop")]
26 KwStop,
27
28 #[token("waking")]
30 KwWaking,
31
32 #[token("pause")]
34 KwPause,
35
36 #[token("resume")]
38 KwResume,
39
40 #[token("resting")]
42 KwResting,
43
44 #[token("message")]
45 KwMessage,
46
47 #[token("divine")]
48 KwDivine,
49
50 #[token("infer")]
51 KwInfer,
52
53 #[token("summon")]
54 KwSummon,
55
56 #[token("await")]
57 KwAwait,
58
59 #[token("send")]
60 KwSend,
61
62 #[token("yield")]
63 KwYield,
64
65 #[token("run")]
66 KwRun,
67
68 #[token("fn")]
69 KwFn,
70
71 #[token("let")]
72 KwLet,
73
74 #[token("return")]
75 KwReturn,
76
77 #[token("if")]
78 KwIf,
79
80 #[token("else")]
81 KwElse,
82
83 #[token("for")]
84 KwFor,
85
86 #[token("while")]
87 KwWhile,
88
89 #[token("loop")]
90 KwLoop,
91
92 #[token("break")]
93 KwBreak,
94
95 #[token("in")]
96 KwIn,
97
98 #[token("self")]
99 KwSelf,
100
101 #[token("true")]
102 KwTrue,
103
104 #[token("false")]
105 KwFalse,
106
107 #[token("mod")]
108 KwMod,
109
110 #[token("use")]
111 KwUse,
112
113 #[token("pub")]
114 KwPub,
115
116 #[token("as")]
117 KwAs,
118
119 #[token("super")]
120 KwSuper,
121
122 #[token("record")]
123 KwRecord,
124
125 #[token("enum")]
126 KwEnum,
127
128 #[token("match")]
129 KwMatch,
130
131 #[token("const")]
132 KwConst,
133
134 #[token("receives")]
135 KwReceives,
136
137 #[token("receive")]
138 KwReceive,
139
140 #[token("fail")]
141 KwFail,
142
143 #[token("fails")]
144 KwFails,
145
146 #[token("timeout")]
147 KwTimeout,
148
149 #[token("retry")]
150 KwRetry,
151
152 #[token("delay")]
153 KwDelay,
154
155 #[token("try")]
156 KwTry,
157
158 #[token("catch")]
159 KwCatch,
160
161 #[token("error")]
162 KwError,
163
164 #[token("tool")]
165 KwTool,
166
167 #[token("test")]
169 KwTest,
170
171 #[token("mock")]
173 KwMock,
174
175 #[token("trace")]
177 KwTrace,
178
179 #[token("span")]
181 KwSpan,
182
183 #[token("checkpoint")]
185 KwCheckpoint,
186
187 #[token("supervisor")]
192 KwSupervisor,
193
194 #[token("children")]
196 KwChildren,
197
198 #[token("strategy")]
200 KwStrategy,
201
202 #[token("restart")]
204 KwRestart,
205
206 #[token("protocol")]
211 KwProtocol,
212
213 #[token("follows")]
215 KwFollows,
216
217 #[token("reply")]
219 KwReply,
220
221 #[token("handler")]
226 KwHandler,
227
228 #[token("handles")]
230 KwHandles,
231
232 #[token("extern")]
237 KwExtern,
238
239 #[token("Int")]
243 TyInt,
244
245 #[token("Float")]
246 TyFloat,
247
248 #[token("Bool")]
249 TyBool,
250
251 #[token("String")]
252 TyString,
253
254 #[token("Unit")]
255 TyUnit,
256
257 #[token("List")]
258 TyList,
259
260 #[token("Option")]
261 TyOption,
262
263 #[token("Oracle")]
264 TyOracle,
265
266 #[token("Agent")]
267 TyAgent,
268
269 #[token("Error")]
270 TyError,
271
272 #[token("ErrorKind")]
273 TyErrorKind,
274
275 #[token("Fn")]
277 TyFn,
278
279 #[token("Map")]
281 TyMap,
282
283 #[token("Result")]
285 TyResult,
286
287 #[regex(r"-?[0-9]+", priority = 2)]
292 IntLit,
293
294 #[regex(r"-?[0-9]+\.[0-9]+")]
296 FloatLit,
297
298 #[regex(r#""([^"\\]|\\.)*""#)]
303 #[regex(r#"'([^'\\]|\\.)*'"#)]
304 StringLit,
305
306 #[regex(r"[a-zA-Z_][a-zA-Z0-9_]*")]
311 Ident,
312
313 #[token("{")]
317 LBrace,
318
319 #[token("}")]
320 RBrace,
321
322 #[token("(")]
323 LParen,
324
325 #[token(")")]
326 RParen,
327
328 #[token("[")]
329 LBracket,
330
331 #[token("]")]
332 RBracket,
333
334 #[token(",")]
335 Comma,
336
337 #[token("::")]
338 ColonColon,
339
340 #[token(":")]
341 Colon,
342
343 #[token(".")]
344 Dot,
345
346 #[token("->")]
347 Arrow,
348
349 #[token("=>")]
350 FatArrow,
351
352 #[token("@")]
354 At,
355
356 #[token("=")]
360 Eq,
361
362 #[token("==")]
363 EqEq,
364
365 #[token("!=")]
366 Ne,
367
368 #[token("<")]
369 Lt,
370
371 #[token(">")]
372 Gt,
373
374 #[token("<=")]
375 Le,
376
377 #[token(">=")]
378 Ge,
379
380 #[token("+")]
381 Plus,
382
383 #[token("-")]
384 Minus,
385
386 #[token("*")]
387 Star,
388
389 #[token("/")]
390 Slash,
391
392 #[token("!")]
393 Bang,
394
395 #[token("&&")]
396 And,
397
398 #[token("||")]
399 Or,
400
401 #[token("|")]
403 Pipe,
404
405 #[token("++")]
407 PlusPlus,
408
409 #[token("%")]
411 Percent,
412
413 #[token(";")]
415 Semicolon,
416}
417
418impl Token {
419 #[must_use]
421 pub fn is_keyword(&self) -> bool {
422 matches!(
423 self,
424 Token::KwAgent
425 | Token::KwBelief
426 | Token::KwOn
427 | Token::KwStart
428 | Token::KwStop
429 | Token::KwWaking
430 | Token::KwPause
431 | Token::KwResume
432 | Token::KwResting
433 | Token::KwMessage
434 | Token::KwDivine
435 | Token::KwInfer
436 | Token::KwSummon
437 | Token::KwAwait
438 | Token::KwSend
439 | Token::KwYield
440 | Token::KwRun
441 | Token::KwFn
442 | Token::KwLet
443 | Token::KwReturn
444 | Token::KwIf
445 | Token::KwElse
446 | Token::KwFor
447 | Token::KwWhile
448 | Token::KwLoop
449 | Token::KwBreak
450 | Token::KwIn
451 | Token::KwSelf
452 | Token::KwTrue
453 | Token::KwFalse
454 | Token::KwMod
455 | Token::KwUse
456 | Token::KwPub
457 | Token::KwAs
458 | Token::KwSuper
459 | Token::KwRecord
460 | Token::KwEnum
461 | Token::KwMatch
462 | Token::KwConst
463 | Token::KwReceives
464 | Token::KwReceive
465 | Token::KwFail
466 | Token::KwFails
467 | Token::KwTimeout
468 | Token::KwRetry
469 | Token::KwDelay
470 | Token::KwTry
471 | Token::KwCatch
472 | Token::KwError
473 | Token::KwTool
474 | Token::KwTrace
475 | Token::KwSpan
476 | Token::KwCheckpoint
477 | Token::KwSupervisor
478 | Token::KwChildren
479 | Token::KwStrategy
480 | Token::KwRestart
481 | Token::KwProtocol
482 | Token::KwFollows
483 | Token::KwReply
484 | Token::KwHandler
485 | Token::KwHandles
486 | Token::KwExtern
487 )
488 }
489
490 #[must_use]
492 pub fn is_type_keyword(&self) -> bool {
493 matches!(
494 self,
495 Token::TyInt
496 | Token::TyFloat
497 | Token::TyBool
498 | Token::TyString
499 | Token::TyUnit
500 | Token::TyList
501 | Token::TyOption
502 | Token::TyOracle
503 | Token::TyAgent
504 | Token::TyError
505 | Token::TyErrorKind
506 | Token::TyFn
507 | Token::TyMap
508 | Token::TyResult
509 )
510 }
511
512 #[must_use]
514 pub fn is_literal(&self) -> bool {
515 matches!(
516 self,
517 Token::IntLit | Token::FloatLit | Token::StringLit | Token::KwTrue | Token::KwFalse
518 )
519 }
520
521 #[must_use]
523 pub fn is_operator(&self) -> bool {
524 matches!(
525 self,
526 Token::Eq
527 | Token::EqEq
528 | Token::Ne
529 | Token::Lt
530 | Token::Gt
531 | Token::Le
532 | Token::Ge
533 | Token::Plus
534 | Token::Minus
535 | Token::Star
536 | Token::Slash
537 | Token::Percent
538 | Token::Bang
539 | Token::And
540 | Token::Or
541 | Token::PlusPlus
542 )
543 }
544}
545
546impl std::fmt::Display for Token {
547 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
548 match self {
549 Token::KwAgent => write!(f, "agent"),
551 Token::KwBelief => write!(f, "belief"),
552 Token::KwOn => write!(f, "on"),
553 Token::KwStart => write!(f, "start"),
554 Token::KwStop => write!(f, "stop"),
555 Token::KwWaking => write!(f, "waking"),
556 Token::KwPause => write!(f, "pause"),
557 Token::KwResume => write!(f, "resume"),
558 Token::KwResting => write!(f, "resting"),
559 Token::KwMessage => write!(f, "message"),
560 Token::KwDivine => write!(f, "divine"),
561 Token::KwInfer => write!(f, "infer"),
562 Token::KwSummon => write!(f, "summon"),
563 Token::KwAwait => write!(f, "await"),
564 Token::KwSend => write!(f, "send"),
565 Token::KwYield => write!(f, "yield"),
566 Token::KwRun => write!(f, "run"),
567 Token::KwFn => write!(f, "fn"),
568 Token::KwLet => write!(f, "let"),
569 Token::KwReturn => write!(f, "return"),
570 Token::KwIf => write!(f, "if"),
571 Token::KwElse => write!(f, "else"),
572 Token::KwFor => write!(f, "for"),
573 Token::KwWhile => write!(f, "while"),
574 Token::KwLoop => write!(f, "loop"),
575 Token::KwBreak => write!(f, "break"),
576 Token::KwIn => write!(f, "in"),
577 Token::KwSelf => write!(f, "self"),
578 Token::KwTrue => write!(f, "true"),
579 Token::KwFalse => write!(f, "false"),
580 Token::KwMod => write!(f, "mod"),
581 Token::KwUse => write!(f, "use"),
582 Token::KwPub => write!(f, "pub"),
583 Token::KwAs => write!(f, "as"),
584 Token::KwSuper => write!(f, "super"),
585 Token::KwRecord => write!(f, "record"),
586 Token::KwEnum => write!(f, "enum"),
587 Token::KwMatch => write!(f, "match"),
588 Token::KwConst => write!(f, "const"),
589 Token::KwReceives => write!(f, "receives"),
590 Token::KwReceive => write!(f, "receive"),
591 Token::KwFail => write!(f, "fail"),
592 Token::KwFails => write!(f, "fails"),
593 Token::KwTimeout => write!(f, "timeout"),
594 Token::KwRetry => write!(f, "retry"),
595 Token::KwDelay => write!(f, "delay"),
596 Token::KwTry => write!(f, "try"),
597 Token::KwCatch => write!(f, "catch"),
598 Token::KwError => write!(f, "error"),
599 Token::KwTool => write!(f, "tool"),
600 Token::KwTest => write!(f, "test"),
601 Token::KwMock => write!(f, "mock"),
602 Token::KwTrace => write!(f, "trace"),
603 Token::KwSpan => write!(f, "span"),
604 Token::KwCheckpoint => write!(f, "checkpoint"),
605 Token::KwSupervisor => write!(f, "supervisor"),
606 Token::KwChildren => write!(f, "children"),
607 Token::KwStrategy => write!(f, "strategy"),
608 Token::KwRestart => write!(f, "restart"),
609 Token::KwProtocol => write!(f, "protocol"),
610 Token::KwFollows => write!(f, "follows"),
611 Token::KwReply => write!(f, "reply"),
612 Token::KwHandler => write!(f, "handler"),
613 Token::KwHandles => write!(f, "handles"),
614 Token::KwExtern => write!(f, "extern"),
615
616 Token::TyInt => write!(f, "Int"),
618 Token::TyFloat => write!(f, "Float"),
619 Token::TyBool => write!(f, "Bool"),
620 Token::TyString => write!(f, "String"),
621 Token::TyUnit => write!(f, "Unit"),
622 Token::TyList => write!(f, "List"),
623 Token::TyOption => write!(f, "Option"),
624 Token::TyOracle => write!(f, "Oracle"),
625 Token::TyAgent => write!(f, "Agent"),
626 Token::TyError => write!(f, "Error"),
627 Token::TyErrorKind => write!(f, "ErrorKind"),
628 Token::TyFn => write!(f, "Fn"),
629 Token::TyMap => write!(f, "Map"),
630 Token::TyResult => write!(f, "Result"),
631
632 Token::IntLit => write!(f, "<int>"),
634 Token::FloatLit => write!(f, "<float>"),
635 Token::StringLit => write!(f, "<string>"),
636
637 Token::Ident => write!(f, "<ident>"),
639
640 Token::LBrace => write!(f, "{{"),
642 Token::RBrace => write!(f, "}}"),
643 Token::LParen => write!(f, "("),
644 Token::RParen => write!(f, ")"),
645 Token::LBracket => write!(f, "["),
646 Token::RBracket => write!(f, "]"),
647 Token::Comma => write!(f, ","),
648 Token::ColonColon => write!(f, "::"),
649 Token::Colon => write!(f, ":"),
650 Token::Dot => write!(f, "."),
651 Token::Arrow => write!(f, "->"),
652 Token::FatArrow => write!(f, "=>"),
653 Token::At => write!(f, "@"),
654
655 Token::Eq => write!(f, "="),
657 Token::EqEq => write!(f, "=="),
658 Token::Ne => write!(f, "!="),
659 Token::Lt => write!(f, "<"),
660 Token::Gt => write!(f, ">"),
661 Token::Le => write!(f, "<="),
662 Token::Ge => write!(f, ">="),
663 Token::Plus => write!(f, "+"),
664 Token::Minus => write!(f, "-"),
665 Token::Star => write!(f, "*"),
666 Token::Slash => write!(f, "/"),
667 Token::Bang => write!(f, "!"),
668 Token::And => write!(f, "&&"),
669 Token::Or => write!(f, "||"),
670 Token::Pipe => write!(f, "|"),
671 Token::PlusPlus => write!(f, "++"),
672 Token::Percent => write!(f, "%"),
673 Token::Semicolon => write!(f, ";"),
674 }
675 }
676}
677
678#[cfg(test)]
679mod tests {
680 use super::*;
681
682 #[test]
683 fn lex_keywords() {
684 let mut lexer = Token::lexer("agent belief on start stop message");
685 assert_eq!(lexer.next(), Some(Ok(Token::KwAgent)));
686 assert_eq!(lexer.next(), Some(Ok(Token::KwBelief)));
687 assert_eq!(lexer.next(), Some(Ok(Token::KwOn)));
688 assert_eq!(lexer.next(), Some(Ok(Token::KwStart)));
689 assert_eq!(lexer.next(), Some(Ok(Token::KwStop)));
690 assert_eq!(lexer.next(), Some(Ok(Token::KwMessage)));
691 assert_eq!(lexer.next(), None);
692 }
693
694 #[test]
695 fn lex_more_keywords() {
696 let mut lexer = Token::lexer(
697 "divine summon await send yield run fn let return if else for in self true false",
698 );
699 assert_eq!(lexer.next(), Some(Ok(Token::KwDivine)));
700 assert_eq!(lexer.next(), Some(Ok(Token::KwSummon)));
701 assert_eq!(lexer.next(), Some(Ok(Token::KwAwait)));
702 assert_eq!(lexer.next(), Some(Ok(Token::KwSend)));
703 assert_eq!(lexer.next(), Some(Ok(Token::KwYield)));
704 assert_eq!(lexer.next(), Some(Ok(Token::KwRun)));
705 assert_eq!(lexer.next(), Some(Ok(Token::KwFn)));
706 assert_eq!(lexer.next(), Some(Ok(Token::KwLet)));
707 assert_eq!(lexer.next(), Some(Ok(Token::KwReturn)));
708 assert_eq!(lexer.next(), Some(Ok(Token::KwIf)));
709 assert_eq!(lexer.next(), Some(Ok(Token::KwElse)));
710 assert_eq!(lexer.next(), Some(Ok(Token::KwFor)));
711 assert_eq!(lexer.next(), Some(Ok(Token::KwIn)));
712 assert_eq!(lexer.next(), Some(Ok(Token::KwSelf)));
713 assert_eq!(lexer.next(), Some(Ok(Token::KwTrue)));
714 assert_eq!(lexer.next(), Some(Ok(Token::KwFalse)));
715 assert_eq!(lexer.next(), None);
716 }
717
718 #[test]
719 fn lex_type_keywords() {
720 let mut lexer = Token::lexer("Int Float Bool String Unit List Option Oracle Agent");
721 assert_eq!(lexer.next(), Some(Ok(Token::TyInt)));
722 assert_eq!(lexer.next(), Some(Ok(Token::TyFloat)));
723 assert_eq!(lexer.next(), Some(Ok(Token::TyBool)));
724 assert_eq!(lexer.next(), Some(Ok(Token::TyString)));
725 assert_eq!(lexer.next(), Some(Ok(Token::TyUnit)));
726 assert_eq!(lexer.next(), Some(Ok(Token::TyList)));
727 assert_eq!(lexer.next(), Some(Ok(Token::TyOption)));
728 assert_eq!(lexer.next(), Some(Ok(Token::TyOracle)));
729 assert_eq!(lexer.next(), Some(Ok(Token::TyAgent)));
730 assert_eq!(lexer.next(), None);
731 }
732
733 #[test]
734 fn lex_integer_literals() {
735 let mut lexer = Token::lexer("42 -7 0 123456");
736 assert_eq!(lexer.next(), Some(Ok(Token::IntLit)));
737 assert_eq!(lexer.slice(), "42");
738 assert_eq!(lexer.next(), Some(Ok(Token::IntLit)));
739 assert_eq!(lexer.slice(), "-7");
740 assert_eq!(lexer.next(), Some(Ok(Token::IntLit)));
741 assert_eq!(lexer.slice(), "0");
742 assert_eq!(lexer.next(), Some(Ok(Token::IntLit)));
743 assert_eq!(lexer.slice(), "123456");
744 assert_eq!(lexer.next(), None);
745 }
746
747 #[test]
748 fn lex_float_literals() {
749 let mut lexer = Token::lexer("3.14 -0.5 0.0 123.456");
750 assert_eq!(lexer.next(), Some(Ok(Token::FloatLit)));
751 assert_eq!(lexer.slice(), "3.14");
752 assert_eq!(lexer.next(), Some(Ok(Token::FloatLit)));
753 assert_eq!(lexer.slice(), "-0.5");
754 assert_eq!(lexer.next(), Some(Ok(Token::FloatLit)));
755 assert_eq!(lexer.slice(), "0.0");
756 assert_eq!(lexer.next(), Some(Ok(Token::FloatLit)));
757 assert_eq!(lexer.slice(), "123.456");
758 assert_eq!(lexer.next(), None);
759 }
760
761 #[test]
762 fn lex_string_literals() {
763 let mut lexer = Token::lexer(r#""hello" "world" "with spaces""#);
764 assert_eq!(lexer.next(), Some(Ok(Token::StringLit)));
765 assert_eq!(lexer.slice(), r#""hello""#);
766 assert_eq!(lexer.next(), Some(Ok(Token::StringLit)));
767 assert_eq!(lexer.slice(), r#""world""#);
768 assert_eq!(lexer.next(), Some(Ok(Token::StringLit)));
769 assert_eq!(lexer.slice(), r#""with spaces""#);
770 assert_eq!(lexer.next(), None);
771 }
772
773 #[test]
774 fn lex_string_with_escapes() {
775 let mut lexer = Token::lexer(r#""hello\nworld" "tab\there" "quote\"here""#);
776 assert_eq!(lexer.next(), Some(Ok(Token::StringLit)));
777 assert_eq!(lexer.slice(), r#""hello\nworld""#);
778 assert_eq!(lexer.next(), Some(Ok(Token::StringLit)));
779 assert_eq!(lexer.slice(), r#""tab\there""#);
780 assert_eq!(lexer.next(), Some(Ok(Token::StringLit)));
781 assert_eq!(lexer.slice(), r#""quote\"here""#);
782 assert_eq!(lexer.next(), None);
783 }
784
785 #[test]
786 fn lex_identifiers() {
787 let mut lexer = Token::lexer("foo bar _private myAgent agent2");
788 assert_eq!(lexer.next(), Some(Ok(Token::Ident)));
789 assert_eq!(lexer.slice(), "foo");
790 assert_eq!(lexer.next(), Some(Ok(Token::Ident)));
791 assert_eq!(lexer.slice(), "bar");
792 assert_eq!(lexer.next(), Some(Ok(Token::Ident)));
793 assert_eq!(lexer.slice(), "_private");
794 assert_eq!(lexer.next(), Some(Ok(Token::Ident)));
795 assert_eq!(lexer.slice(), "myAgent");
796 assert_eq!(lexer.next(), Some(Ok(Token::Ident)));
797 assert_eq!(lexer.slice(), "agent2");
798 assert_eq!(lexer.next(), None);
799 }
800
801 #[test]
802 fn keyword_vs_identifier() {
803 let mut lexer = Token::lexer("agent agent_name agents");
805 assert_eq!(lexer.next(), Some(Ok(Token::KwAgent)));
806 assert_eq!(lexer.next(), Some(Ok(Token::Ident)));
807 assert_eq!(lexer.slice(), "agent_name");
808 assert_eq!(lexer.next(), Some(Ok(Token::Ident)));
809 assert_eq!(lexer.slice(), "agents");
810 assert_eq!(lexer.next(), None);
811 }
812
813 #[test]
814 fn lex_punctuation() {
815 let mut lexer = Token::lexer("{ } ( ) [ ] , : . ->");
816 assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
817 assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
818 assert_eq!(lexer.next(), Some(Ok(Token::LParen)));
819 assert_eq!(lexer.next(), Some(Ok(Token::RParen)));
820 assert_eq!(lexer.next(), Some(Ok(Token::LBracket)));
821 assert_eq!(lexer.next(), Some(Ok(Token::RBracket)));
822 assert_eq!(lexer.next(), Some(Ok(Token::Comma)));
823 assert_eq!(lexer.next(), Some(Ok(Token::Colon)));
824 assert_eq!(lexer.next(), Some(Ok(Token::Dot)));
825 assert_eq!(lexer.next(), Some(Ok(Token::Arrow)));
826 assert_eq!(lexer.next(), None);
827 }
828
829 #[test]
830 fn lex_operators() {
831 let mut lexer = Token::lexer("= == != < > <= >= + - * / % ! && || ++");
832 assert_eq!(lexer.next(), Some(Ok(Token::Eq)));
833 assert_eq!(lexer.next(), Some(Ok(Token::EqEq)));
834 assert_eq!(lexer.next(), Some(Ok(Token::Ne)));
835 assert_eq!(lexer.next(), Some(Ok(Token::Lt)));
836 assert_eq!(lexer.next(), Some(Ok(Token::Gt)));
837 assert_eq!(lexer.next(), Some(Ok(Token::Le)));
838 assert_eq!(lexer.next(), Some(Ok(Token::Ge)));
839 assert_eq!(lexer.next(), Some(Ok(Token::Plus)));
840 assert_eq!(lexer.next(), Some(Ok(Token::Minus)));
841 assert_eq!(lexer.next(), Some(Ok(Token::Star)));
842 assert_eq!(lexer.next(), Some(Ok(Token::Slash)));
843 assert_eq!(lexer.next(), Some(Ok(Token::Percent)));
844 assert_eq!(lexer.next(), Some(Ok(Token::Bang)));
845 assert_eq!(lexer.next(), Some(Ok(Token::And)));
846 assert_eq!(lexer.next(), Some(Ok(Token::Or)));
847 assert_eq!(lexer.next(), Some(Ok(Token::PlusPlus)));
848 assert_eq!(lexer.next(), None);
849 }
850
851 #[test]
852 fn skip_whitespace() {
853 let mut lexer = Token::lexer(" agent belief\n\ttrue ");
854 assert_eq!(lexer.next(), Some(Ok(Token::KwAgent)));
855 assert_eq!(lexer.next(), Some(Ok(Token::KwBelief)));
856 assert_eq!(lexer.next(), Some(Ok(Token::KwTrue)));
857 assert_eq!(lexer.next(), None);
858 }
859
860 #[test]
861 fn skip_comments() {
862 let mut lexer = Token::lexer("agent // this is a comment\nbelief");
863 assert_eq!(lexer.next(), Some(Ok(Token::KwAgent)));
864 assert_eq!(lexer.next(), Some(Ok(Token::KwBelief)));
865 assert_eq!(lexer.next(), None);
866 }
867
868 #[test]
869 fn comment_at_end() {
870 let mut lexer = Token::lexer("agent // comment at end");
871 assert_eq!(lexer.next(), Some(Ok(Token::KwAgent)));
872 assert_eq!(lexer.next(), None);
873 }
874
875 #[test]
876 fn lex_agent_declaration() {
877 let source = r#"
878 agent Researcher {
879 belief topic: String
880
881 on start {
882 let result: Oracle<String> = divine("test")
883 yield(result)
884 }
885 }
886 "#;
887 let tokens: Vec<_> = Token::lexer(source)
888 .map(|r| r.expect("valid token"))
889 .collect();
890
891 assert_eq!(tokens[0], Token::KwAgent);
892 assert_eq!(tokens[1], Token::Ident); assert_eq!(tokens[2], Token::LBrace);
894 assert_eq!(tokens[3], Token::KwBelief);
895 assert_eq!(tokens[4], Token::Ident); assert_eq!(tokens[5], Token::Colon);
897 assert_eq!(tokens[6], Token::TyString);
898 assert_eq!(tokens[7], Token::KwOn);
899 assert_eq!(tokens[8], Token::KwStart);
900 assert_eq!(tokens[9], Token::LBrace);
901 assert_eq!(tokens[10], Token::KwLet);
902 }
903
904 #[test]
905 fn is_keyword_helper() {
906 assert!(Token::KwAgent.is_keyword());
907 assert!(Token::KwLet.is_keyword());
908 assert!(!Token::TyInt.is_keyword());
909 assert!(!Token::Ident.is_keyword());
910 }
911
912 #[test]
913 fn is_type_keyword_helper() {
914 assert!(Token::TyInt.is_type_keyword());
915 assert!(Token::TyAgent.is_type_keyword());
916 assert!(!Token::KwAgent.is_type_keyword());
917 assert!(!Token::Ident.is_type_keyword());
918 }
919
920 #[test]
921 fn is_literal_helper() {
922 assert!(Token::IntLit.is_literal());
923 assert!(Token::FloatLit.is_literal());
924 assert!(Token::StringLit.is_literal());
925 assert!(Token::KwTrue.is_literal());
926 assert!(Token::KwFalse.is_literal());
927 assert!(!Token::Ident.is_literal());
928 }
929
930 #[test]
931 fn is_operator_helper() {
932 assert!(Token::Plus.is_operator());
933 assert!(Token::EqEq.is_operator());
934 assert!(Token::PlusPlus.is_operator());
935 assert!(!Token::LBrace.is_operator());
936 assert!(!Token::Ident.is_operator());
937 }
938
939 #[test]
940 fn lex_module_keywords() {
941 let mut lexer = Token::lexer("mod use pub as super");
942 assert_eq!(lexer.next(), Some(Ok(Token::KwMod)));
943 assert_eq!(lexer.next(), Some(Ok(Token::KwUse)));
944 assert_eq!(lexer.next(), Some(Ok(Token::KwPub)));
945 assert_eq!(lexer.next(), Some(Ok(Token::KwAs)));
946 assert_eq!(lexer.next(), Some(Ok(Token::KwSuper)));
947 assert_eq!(lexer.next(), None);
948 }
949
950 #[test]
951 fn lex_path_separator() {
952 let mut lexer = Token::lexer("agents::Researcher");
953 assert_eq!(lexer.next(), Some(Ok(Token::Ident)));
954 assert_eq!(lexer.slice(), "agents");
955 assert_eq!(lexer.next(), Some(Ok(Token::ColonColon)));
956 assert_eq!(lexer.next(), Some(Ok(Token::Ident)));
957 assert_eq!(lexer.slice(), "Researcher");
958 assert_eq!(lexer.next(), None);
959 }
960
961 #[test]
962 fn lex_use_statement() {
963 let mut lexer = Token::lexer("use agents::{Researcher, Coordinator as Coord}");
964 assert_eq!(lexer.next(), Some(Ok(Token::KwUse)));
965 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::ColonColon)));
967 assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
968 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Comma)));
970 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::KwAs)));
972 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
974 assert_eq!(lexer.next(), None);
975 }
976
977 #[test]
978 fn lex_pub_agent() {
979 let mut lexer = Token::lexer("pub agent Researcher");
980 assert_eq!(lexer.next(), Some(Ok(Token::KwPub)));
981 assert_eq!(lexer.next(), Some(Ok(Token::KwAgent)));
982 assert_eq!(lexer.next(), Some(Ok(Token::Ident)));
983 assert_eq!(lexer.next(), None);
984 }
985
986 #[test]
987 fn token_display() {
988 assert_eq!(format!("{}", Token::KwAgent), "agent");
989 assert_eq!(format!("{}", Token::TyInt), "Int");
990 assert_eq!(format!("{}", Token::IntLit), "<int>");
991 assert_eq!(format!("{}", Token::Ident), "<ident>");
992 assert_eq!(format!("{}", Token::LBrace), "{");
993 assert_eq!(format!("{}", Token::PlusPlus), "++");
994 }
995
996 #[test]
997 fn lex_type_keywords_record_enum_match_const() {
998 let mut lexer = Token::lexer("record enum match const");
999 assert_eq!(lexer.next(), Some(Ok(Token::KwRecord)));
1000 assert_eq!(lexer.next(), Some(Ok(Token::KwEnum)));
1001 assert_eq!(lexer.next(), Some(Ok(Token::KwMatch)));
1002 assert_eq!(lexer.next(), Some(Ok(Token::KwConst)));
1003 assert_eq!(lexer.next(), None);
1004 }
1005
1006 #[test]
1007 fn lex_fat_arrow() {
1008 let mut lexer = Token::lexer("=> -> =");
1009 assert_eq!(lexer.next(), Some(Ok(Token::FatArrow)));
1010 assert_eq!(lexer.next(), Some(Ok(Token::Arrow)));
1011 assert_eq!(lexer.next(), Some(Ok(Token::Eq)));
1012 assert_eq!(lexer.next(), None);
1013 }
1014
1015 #[test]
1016 fn lex_match_expression() {
1017 let mut lexer = Token::lexer("match status { Active => 1, Inactive => 0 }");
1018 assert_eq!(lexer.next(), Some(Ok(Token::KwMatch)));
1019 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1021 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::FatArrow)));
1023 assert_eq!(lexer.next(), Some(Ok(Token::IntLit))); assert_eq!(lexer.next(), Some(Ok(Token::Comma)));
1025 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::FatArrow)));
1027 assert_eq!(lexer.next(), Some(Ok(Token::IntLit))); assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1029 assert_eq!(lexer.next(), None);
1030 }
1031
1032 #[test]
1033 fn lex_record_declaration() {
1034 let mut lexer = Token::lexer("record Point { x: Int, y: Int }");
1035 assert_eq!(lexer.next(), Some(Ok(Token::KwRecord)));
1036 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1038 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Colon)));
1040 assert_eq!(lexer.next(), Some(Ok(Token::TyInt)));
1041 assert_eq!(lexer.next(), Some(Ok(Token::Comma)));
1042 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Colon)));
1044 assert_eq!(lexer.next(), Some(Ok(Token::TyInt)));
1045 assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1046 assert_eq!(lexer.next(), None);
1047 }
1048
1049 #[test]
1050 fn lex_enum_declaration() {
1051 let mut lexer = Token::lexer("enum Status { Active, Pending, Done }");
1052 assert_eq!(lexer.next(), Some(Ok(Token::KwEnum)));
1053 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1055 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Comma)));
1057 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Comma)));
1059 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1061 assert_eq!(lexer.next(), None);
1062 }
1063
1064 #[test]
1065 fn lex_const_declaration() {
1066 let mut lexer = Token::lexer("const MAX_RETRIES: Int = 3");
1067 assert_eq!(lexer.next(), Some(Ok(Token::KwConst)));
1068 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Colon)));
1070 assert_eq!(lexer.next(), Some(Ok(Token::TyInt)));
1071 assert_eq!(lexer.next(), Some(Ok(Token::Eq)));
1072 assert_eq!(lexer.next(), Some(Ok(Token::IntLit))); assert_eq!(lexer.next(), None);
1074 }
1075
1076 #[test]
1077 fn new_keywords_are_keywords() {
1078 assert!(Token::KwRecord.is_keyword());
1079 assert!(Token::KwEnum.is_keyword());
1080 assert!(Token::KwMatch.is_keyword());
1081 assert!(Token::KwConst.is_keyword());
1082 }
1083
1084 #[test]
1085 fn lex_loop_break() {
1086 let mut lexer = Token::lexer("loop { break }");
1087 assert_eq!(lexer.next(), Some(Ok(Token::KwLoop)));
1088 assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1089 assert_eq!(lexer.next(), Some(Ok(Token::KwBreak)));
1090 assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1091 assert_eq!(lexer.next(), None);
1092 }
1093
1094 #[test]
1095 fn lex_receives_receive() {
1096 let mut lexer = Token::lexer("agent Worker receives WorkerMsg { receive }");
1097 assert_eq!(lexer.next(), Some(Ok(Token::KwAgent)));
1098 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::KwReceives)));
1100 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1102 assert_eq!(lexer.next(), Some(Ok(Token::KwReceive)));
1103 assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1104 assert_eq!(lexer.next(), None);
1105 }
1106
1107 #[test]
1108 fn rfc6_keywords_are_keywords() {
1109 assert!(Token::KwLoop.is_keyword());
1110 assert!(Token::KwBreak.is_keyword());
1111 assert!(Token::KwReceives.is_keyword());
1112 assert!(Token::KwReceive.is_keyword());
1113 }
1114
1115 #[test]
1116 fn lex_error_handling_keywords() {
1117 let mut lexer = Token::lexer("fails try catch error");
1118 assert_eq!(lexer.next(), Some(Ok(Token::KwFails)));
1119 assert_eq!(lexer.next(), Some(Ok(Token::KwTry)));
1120 assert_eq!(lexer.next(), Some(Ok(Token::KwCatch)));
1121 assert_eq!(lexer.next(), Some(Ok(Token::KwError)));
1122 assert_eq!(lexer.next(), None);
1123 }
1124
1125 #[test]
1126 fn lex_try_catch_expression() {
1127 let mut lexer = Token::lexer("let x = try divine(prompt) catch { fallback }");
1128 assert_eq!(lexer.next(), Some(Ok(Token::KwLet)));
1129 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Eq)));
1131 assert_eq!(lexer.next(), Some(Ok(Token::KwTry)));
1132 assert_eq!(lexer.next(), Some(Ok(Token::KwDivine)));
1133 assert_eq!(lexer.next(), Some(Ok(Token::LParen)));
1134 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::RParen)));
1136 assert_eq!(lexer.next(), Some(Ok(Token::KwCatch)));
1137 assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1138 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1140 assert_eq!(lexer.next(), None);
1141 }
1142
1143 #[test]
1144 fn lex_fails_function() {
1145 let mut lexer = Token::lexer("fn fetch(url: String) -> String fails { }");
1146 assert_eq!(lexer.next(), Some(Ok(Token::KwFn)));
1147 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::LParen)));
1149 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Colon)));
1151 assert_eq!(lexer.next(), Some(Ok(Token::TyString)));
1152 assert_eq!(lexer.next(), Some(Ok(Token::RParen)));
1153 assert_eq!(lexer.next(), Some(Ok(Token::Arrow)));
1154 assert_eq!(lexer.next(), Some(Ok(Token::TyString)));
1155 assert_eq!(lexer.next(), Some(Ok(Token::KwFails)));
1156 assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1157 assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1158 assert_eq!(lexer.next(), None);
1159 }
1160
1161 #[test]
1162 fn lex_on_error_handler() {
1163 let mut lexer = Token::lexer("on error(e) { yield(fallback) }");
1164 assert_eq!(lexer.next(), Some(Ok(Token::KwOn)));
1165 assert_eq!(lexer.next(), Some(Ok(Token::KwError)));
1166 assert_eq!(lexer.next(), Some(Ok(Token::LParen)));
1167 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::RParen)));
1169 assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1170 assert_eq!(lexer.next(), Some(Ok(Token::KwYield)));
1171 assert_eq!(lexer.next(), Some(Ok(Token::LParen)));
1172 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::RParen)));
1174 assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1175 assert_eq!(lexer.next(), None);
1176 }
1177
1178 #[test]
1179 fn rfc7_keywords_are_keywords() {
1180 assert!(Token::KwFail.is_keyword());
1181 assert!(Token::KwFails.is_keyword());
1182 assert!(Token::KwTry.is_keyword());
1183 assert!(Token::KwCatch.is_keyword());
1184 assert!(Token::KwError.is_keyword());
1185 }
1186
1187 #[test]
1188 fn lex_fail_expression() {
1189 let mut lexer = Token::lexer("fail \"error message\"");
1190 assert_eq!(lexer.next(), Some(Ok(Token::KwFail)));
1191 assert_eq!(lexer.next(), Some(Ok(Token::StringLit)));
1192 assert_eq!(lexer.next(), None);
1193 }
1194
1195 #[test]
1200 fn lex_closure_syntax() {
1201 let mut lexer = Token::lexer("|x: Int| x + 1");
1203 assert_eq!(lexer.next(), Some(Ok(Token::Pipe)));
1204 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Colon)));
1206 assert_eq!(lexer.next(), Some(Ok(Token::TyInt)));
1207 assert_eq!(lexer.next(), Some(Ok(Token::Pipe)));
1208 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Plus)));
1210 assert_eq!(lexer.next(), Some(Ok(Token::IntLit)));
1211 assert_eq!(lexer.next(), None);
1212 }
1213
1214 #[test]
1215 fn lex_empty_closure() {
1216 let mut lexer = Token::lexer("|| 42");
1218 assert_eq!(lexer.next(), Some(Ok(Token::Or))); assert_eq!(lexer.next(), Some(Ok(Token::IntLit)));
1220 assert_eq!(lexer.next(), None);
1221 }
1222
1223 #[test]
1224 fn lex_fn_type() {
1225 let mut lexer = Token::lexer("Fn(Int, String) -> Bool");
1227 assert_eq!(lexer.next(), Some(Ok(Token::TyFn)));
1228 assert_eq!(lexer.next(), Some(Ok(Token::LParen)));
1229 assert_eq!(lexer.next(), Some(Ok(Token::TyInt)));
1230 assert_eq!(lexer.next(), Some(Ok(Token::Comma)));
1231 assert_eq!(lexer.next(), Some(Ok(Token::TyString)));
1232 assert_eq!(lexer.next(), Some(Ok(Token::RParen)));
1233 assert_eq!(lexer.next(), Some(Ok(Token::Arrow)));
1234 assert_eq!(lexer.next(), Some(Ok(Token::TyBool)));
1235 assert_eq!(lexer.next(), None);
1236 }
1237
1238 #[test]
1239 fn fn_is_type_keyword() {
1240 assert!(Token::TyFn.is_type_keyword());
1241 }
1242
1243 #[test]
1244 fn pipe_display() {
1245 assert_eq!(format!("{}", Token::Pipe), "|");
1246 assert_eq!(format!("{}", Token::TyFn), "Fn");
1247 }
1248
1249 #[test]
1254 fn lex_tool_keyword() {
1255 let mut lexer = Token::lexer("tool Http { fn get(url: String) -> String }");
1256 assert_eq!(lexer.next(), Some(Ok(Token::KwTool)));
1257 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1259 assert_eq!(lexer.next(), Some(Ok(Token::KwFn)));
1260 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::LParen)));
1262 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Colon)));
1264 assert_eq!(lexer.next(), Some(Ok(Token::TyString)));
1265 assert_eq!(lexer.next(), Some(Ok(Token::RParen)));
1266 assert_eq!(lexer.next(), Some(Ok(Token::Arrow)));
1267 assert_eq!(lexer.next(), Some(Ok(Token::TyString)));
1268 assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1269 assert_eq!(lexer.next(), None);
1270 }
1271
1272 #[test]
1273 fn tool_is_keyword() {
1274 assert!(Token::KwTool.is_keyword());
1275 }
1276
1277 #[test]
1278 fn lex_agent_use_tool() {
1279 let mut lexer = Token::lexer("agent Fetcher { use Http }");
1280 assert_eq!(lexer.next(), Some(Ok(Token::KwAgent)));
1281 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1283 assert_eq!(lexer.next(), Some(Ok(Token::KwUse)));
1284 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1286 assert_eq!(lexer.next(), None);
1287 }
1288
1289 #[test]
1294 fn lex_trace_span_keywords() {
1295 let mut lexer = Token::lexer("trace span");
1296 assert_eq!(lexer.next(), Some(Ok(Token::KwTrace)));
1297 assert_eq!(lexer.next(), Some(Ok(Token::KwSpan)));
1298 assert_eq!(lexer.next(), None);
1299 }
1300
1301 #[test]
1302 fn trace_span_are_keywords() {
1303 assert!(Token::KwTrace.is_keyword());
1304 assert!(Token::KwSpan.is_keyword());
1305 }
1306
1307 #[test]
1308 fn lex_span_block() {
1309 let mut lexer = Token::lexer("span \"fetch_data\" { let x = 1 }");
1310 assert_eq!(lexer.next(), Some(Ok(Token::KwSpan)));
1311 assert_eq!(lexer.next(), Some(Ok(Token::StringLit)));
1312 assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1313 assert_eq!(lexer.next(), Some(Ok(Token::KwLet)));
1314 assert_eq!(lexer.next(), Some(Ok(Token::Ident)));
1315 assert_eq!(lexer.next(), Some(Ok(Token::Eq)));
1316 assert_eq!(lexer.next(), Some(Ok(Token::IntLit)));
1317 assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1318 assert_eq!(lexer.next(), None);
1319 }
1320
1321 #[test]
1326 fn lex_protocol_keywords() {
1327 let mut lexer = Token::lexer("protocol follows reply");
1328 assert_eq!(lexer.next(), Some(Ok(Token::KwProtocol)));
1329 assert_eq!(lexer.next(), Some(Ok(Token::KwFollows)));
1330 assert_eq!(lexer.next(), Some(Ok(Token::KwReply)));
1331 assert_eq!(lexer.next(), None);
1332 }
1333
1334 #[test]
1335 fn lex_effect_handler_keywords() {
1336 let mut lexer = Token::lexer("handler handles");
1337 assert_eq!(lexer.next(), Some(Ok(Token::KwHandler)));
1338 assert_eq!(lexer.next(), Some(Ok(Token::KwHandles)));
1339 assert_eq!(lexer.next(), None);
1340 }
1341
1342 #[test]
1343 fn protocol_keywords_are_keywords() {
1344 assert!(Token::KwProtocol.is_keyword());
1345 assert!(Token::KwFollows.is_keyword());
1346 assert!(Token::KwReply.is_keyword());
1347 assert!(Token::KwHandler.is_keyword());
1348 assert!(Token::KwHandles.is_keyword());
1349 }
1350
1351 #[test]
1352 fn lex_protocol_declaration() {
1353 let mut lexer = Token::lexer("protocol SchemaSync { Steward -> API: Changed }");
1354 assert_eq!(lexer.next(), Some(Ok(Token::KwProtocol)));
1355 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1357 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Arrow)));
1359 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Colon)));
1361 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1363 assert_eq!(lexer.next(), None);
1364 }
1365
1366 #[test]
1367 fn lex_agent_follows() {
1368 let mut lexer = Token::lexer("agent API follows SchemaSync as APISteward");
1369 assert_eq!(lexer.next(), Some(Ok(Token::KwAgent)));
1370 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::KwFollows)));
1372 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::KwAs)));
1374 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), None);
1376 }
1377
1378 #[test]
1379 fn lex_handler_declaration() {
1380 let mut lexer = Token::lexer("handler DefaultLLM handles Infer { model: \"gpt-4\" }");
1381 assert_eq!(lexer.next(), Some(Ok(Token::KwHandler)));
1382 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::KwHandles)));
1384 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1386 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::Colon)));
1388 assert_eq!(lexer.next(), Some(Ok(Token::StringLit)));
1389 assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1390 assert_eq!(lexer.next(), None);
1391 }
1392
1393 #[test]
1394 fn lex_reply_expression() {
1395 let mut lexer = Token::lexer("reply(Ack {})");
1396 assert_eq!(lexer.next(), Some(Ok(Token::KwReply)));
1397 assert_eq!(lexer.next(), Some(Ok(Token::LParen)));
1398 assert_eq!(lexer.next(), Some(Ok(Token::Ident))); assert_eq!(lexer.next(), Some(Ok(Token::LBrace)));
1400 assert_eq!(lexer.next(), Some(Ok(Token::RBrace)));
1401 assert_eq!(lexer.next(), Some(Ok(Token::RParen)));
1402 assert_eq!(lexer.next(), None);
1403 }
1404
1405 #[test]
1406 fn token_display_phase3() {
1407 assert_eq!(format!("{}", Token::KwProtocol), "protocol");
1408 assert_eq!(format!("{}", Token::KwFollows), "follows");
1409 assert_eq!(format!("{}", Token::KwReply), "reply");
1410 assert_eq!(format!("{}", Token::KwHandler), "handler");
1411 assert_eq!(format!("{}", Token::KwHandles), "handles");
1412 }
1413}