1use serde::Deserialize;
2use serde::Serialize;
3use strum::Display;
4
5use mago_interner::StringIdentifier;
6use mago_span::Span;
7
8#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
9#[serde(tag = "type", content = "value")]
10#[repr(C)]
11pub enum DocumentKind {
12 Heredoc,
13 Nowdoc,
14}
15
16#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
17#[serde(tag = "type", content = "value")]
18#[repr(C)]
19pub enum Associativity {
20 NonAssociative,
21 Left,
22 Right,
23}
24
25#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
26#[serde(tag = "type", content = "value")]
27#[repr(C)]
28pub enum Precedence {
29 Lowest,
30 LowLogicalOr,
31 LowLogicalXor,
32 LowLogicalAnd,
33 Print,
34 Yield,
35 YieldFrom,
36 IncDec,
37 KeyOr,
38 KeyXor,
39 KeyAnd,
40 Assignment,
41 ElvisOrConditional,
42 NullCoalesce,
43 Or,
44 And,
45 BitwiseOr,
46 BitwiseXor,
47 BitwiseAnd,
48 Equality,
49 Comparison,
50 Concat,
51 BitShift,
52 AddSub,
53 MulDivMod,
54 Bang,
55 Instanceof,
56 Prefix,
57 Pow,
58 Clone,
59 CallDim,
60 New,
61 ArrayDim,
62 ObjectAccess,
63}
64
65pub trait GetPrecedence {
66 fn precedence(&self) -> Precedence;
67}
68
69#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
70#[serde(tag = "type", content = "value")]
71#[repr(C)]
72pub enum TokenKind {
73 Whitespace, Eval, Die, Self_, Parent, Backtick, DocumentStart(DocumentKind), DocumentEnd, From, Print, Dollar, HaltCompiler, Readonly, Global, Abstract, Ampersand, AmpersandEqual, AmpersandAmpersand, AmpersandAmpersandEqual, Array, ArrayCast, MinusGreaterThan, QuestionMinusGreaterThan, At, As, Asterisk, HashLeftBracket, Bang, BangEqual, LessThanGreaterThan, BangEqualEqual, LessThanEqualGreaterThan, BoolCast, BooleanCast, And, Or, Break, Callable, Caret, CaretEqual, Case, Catch, Class, ClassConstant, TraitConstant, FunctionConstant, MethodConstant, LineConstant, FileConstant, Clone, MinusEqual, CloseTag, QuestionQuestion, QuestionQuestionEqual, AsteriskEqual, Colon, Comma, SingleLineComment, HashComment, MultiLineComment, DocBlockComment, Const, PartialLiteralString, LiteralString, Continue, Declare, MinusMinus, Default, DirConstant, SlashEqual, Do, DollarLeftBrace, Dot, DotEqual, EqualGreaterThan, DoubleCast, RealCast, FloatCast, ColonColon, EqualEqual, DoubleQuote, Else, Echo, DotDotDot, ElseIf, Empty, EndDeclare, EndFor, EndForeach, EndIf, EndSwitch, EndWhile, Enum, Equal, Extends, False, Final, Finally, LiteralFloat, Fn, For, Foreach, FullyQualifiedIdentifier, Function, Goto, GreaterThan, GreaterThanEqual, Identifier, If, Implements, Include, IncludeOnce, PlusPlus, InlineText, InlineShebang, Instanceof, Insteadof, Exit, Unset, Isset, List, LiteralInteger, IntCast, IntegerCast, Interface, LeftBrace, LeftBracket, LeftParenthesis, LeftShift, LeftShiftEqual, RightShift, RightShiftEqual, LessThan, LessThanEqual, Match, Minus, Namespace, NamespaceSeparator, NamespaceConstant, New, Null, ObjectCast, UnsetCast, OpenTag, EchoTag, ShortOpenTag, Percent, PercentEqual, Pipe, PipeEqual, Plus, PlusEqual, AsteriskAsterisk, AsteriskAsteriskEqual, Private, PrivateSet, Protected, ProtectedSet, Public, PublicSet, QualifiedIdentifier, Question, QuestionColon, Require, RequireOnce, Return, RightBrace, RightBracket, RightParenthesis, Semicolon, Slash, Static, StringCast, BinaryCast, StringPart, Switch, Throw, Trait, EqualEqualEqual, True, Try, Use, Var, Variable, Yield, While, Tilde, PipePipe, Xor, }
263
264#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
265#[repr(C)]
266pub struct Token {
267 pub kind: TokenKind,
268 pub value: StringIdentifier,
269 pub span: Span,
270}
271
272impl Precedence {
273 #[inline(always)]
274 pub fn infix(kind: &TokenKind) -> Precedence {
275 match kind {
276 T!["**"] => Precedence::Pow,
277 T!["instanceof"] => Precedence::Instanceof,
278 T!["*" | "/" | "%"] => Precedence::MulDivMod,
279 T!["+" | "-"] => Precedence::AddSub,
280 T!["<<"] | T![">>"] => Precedence::BitShift,
281 T!["."] => Precedence::Concat,
282 T!["<" | "<=" | ">" | ">="] => Precedence::Comparison,
283 T!["==" | "!=" | "===" | "!==" | "<>" | "<=>"] => Precedence::Equality,
284 T!["&"] => Precedence::BitwiseAnd,
285 T!["^"] => Precedence::BitwiseXor,
286 T!["|"] => Precedence::BitwiseOr,
287 T!["&&"] => Precedence::And,
288 T!["||"] => Precedence::Or,
289 T!["??"] => Precedence::NullCoalesce,
290 T!["?" | "?:"] => Precedence::ElvisOrConditional,
291 T!["="
292 | "+="
293 | "-="
294 | "*="
295 | "**="
296 | "/="
297 | ".="
298 | "&&="
299 | "??="
300 | "%="
301 | "&="
302 | "|="
303 | "^="
304 | "<<="
305 | ">>="] => Precedence::Assignment,
306 T!["yield"] => Precedence::Yield,
307 T!["and"] => Precedence::KeyAnd,
308 T!["or"] => Precedence::KeyOr,
309 T!["xor"] => Precedence::KeyXor,
310 _ => Precedence::Lowest,
311 }
312 }
313
314 #[inline(always)]
315 pub fn postfix(kind: &TokenKind) -> Self {
316 match kind {
317 T!["++" | "--"] => Self::Prefix,
318 T!["("] => Self::CallDim,
319 T!["["] => Self::ArrayDim,
320 T!["->" | "?->" | "::"] => Self::ObjectAccess,
321 _ => Self::Lowest,
322 }
323 }
324
325 #[inline(always)]
326 pub fn associativity(&self) -> Option<Associativity> {
327 Some(match self {
328 Self::Instanceof
329 | Self::MulDivMod
330 | Self::AddSub
331 | Self::BitShift
332 | Self::Concat
333 | Self::BitwiseAnd
334 | Self::BitwiseOr
335 | Self::BitwiseXor
336 | Self::And
337 | Self::Or
338 | Self::KeyAnd
339 | Self::KeyOr
340 | Self::KeyXor => Associativity::Left,
341 Self::Pow | Self::NullCoalesce | Self::Assignment => Associativity::Right,
342 Self::ElvisOrConditional | Self::Equality | Self::Comparison => Associativity::NonAssociative,
343 _ => return None,
344 })
345 }
346}
347
348impl TokenKind {
349 #[inline(always)]
350 pub const fn is_keyword(&self) -> bool {
351 matches!(
352 self,
353 TokenKind::Eval
354 | TokenKind::Die
355 | TokenKind::Empty
356 | TokenKind::Isset
357 | TokenKind::Unset
358 | TokenKind::Exit
359 | TokenKind::EndDeclare
360 | TokenKind::EndSwitch
361 | TokenKind::EndWhile
362 | TokenKind::EndForeach
363 | TokenKind::EndFor
364 | TokenKind::EndIf
365 | TokenKind::From
366 | TokenKind::And
367 | TokenKind::Or
368 | TokenKind::Xor
369 | TokenKind::Print
370 | TokenKind::Readonly
371 | TokenKind::Global
372 | TokenKind::Match
373 | TokenKind::Abstract
374 | TokenKind::Array
375 | TokenKind::As
376 | TokenKind::Break
377 | TokenKind::Case
378 | TokenKind::Catch
379 | TokenKind::Class
380 | TokenKind::Clone
381 | TokenKind::Continue
382 | TokenKind::Const
383 | TokenKind::Declare
384 | TokenKind::Default
385 | TokenKind::Do
386 | TokenKind::Echo
387 | TokenKind::ElseIf
388 | TokenKind::Else
389 | TokenKind::Enum
390 | TokenKind::Extends
391 | TokenKind::False
392 | TokenKind::Finally
393 | TokenKind::Final
394 | TokenKind::Fn
395 | TokenKind::Foreach
396 | TokenKind::For
397 | TokenKind::Function
398 | TokenKind::Goto
399 | TokenKind::If
400 | TokenKind::IncludeOnce
401 | TokenKind::Include
402 | TokenKind::Implements
403 | TokenKind::Interface
404 | TokenKind::Instanceof
405 | TokenKind::Namespace
406 | TokenKind::New
407 | TokenKind::Null
408 | TokenKind::Private
409 | TokenKind::PrivateSet
410 | TokenKind::Protected
411 | TokenKind::Public
412 | TokenKind::RequireOnce
413 | TokenKind::Require
414 | TokenKind::Return
415 | TokenKind::Static
416 | TokenKind::Switch
417 | TokenKind::Throw
418 | TokenKind::Trait
419 | TokenKind::True
420 | TokenKind::Try
421 | TokenKind::Use
422 | TokenKind::Var
423 | TokenKind::Yield
424 | TokenKind::While
425 | TokenKind::Insteadof
426 | TokenKind::List
427 | TokenKind::Self_
428 | TokenKind::Parent
429 | TokenKind::DirConstant
430 | TokenKind::FileConstant
431 | TokenKind::LineConstant
432 | TokenKind::FunctionConstant
433 | TokenKind::ClassConstant
434 | TokenKind::MethodConstant
435 | TokenKind::TraitConstant
436 | TokenKind::NamespaceConstant
437 | TokenKind::HaltCompiler
438 )
439 }
440
441 #[inline(always)]
442 pub const fn is_infix(&self) -> bool {
443 matches!(
444 self,
445 T!["**"
446 | ">>="
447 | "<<="
448 | "^="
449 | "&="
450 | "|="
451 | "%="
452 | "**="
453 | "and"
454 | "or"
455 | "xor"
456 | "<=>"
457 | "<<"
458 | ">>"
459 | "&"
460 | "|"
461 | "^"
462 | "%"
463 | "instanceof"
464 | "*"
465 | "/"
466 | "+"
467 | "-"
468 | "."
469 | "<"
470 | ">"
471 | "<="
472 | ">="
473 | "=="
474 | "==="
475 | "!="
476 | "!=="
477 | "<>"
478 | "?"
479 | "?:"
480 | "&&"
481 | "||"
482 | "="
483 | "+="
484 | "-="
485 | ".="
486 | "??="
487 | "/="
488 | "*="
489 | "??"]
490 )
491 }
492
493 #[inline(always)]
494 pub const fn is_postfix(&self) -> bool {
495 matches!(self, T!["++" | "--" | "(" | "[" | "->" | "?->" | "::"])
496 }
497
498 #[inline(always)]
499 pub const fn is_visibility_modifier(&self) -> bool {
500 matches!(self, T!["public" | "protected" | "private" | "private(set)" | "protected(set)" | "public(set)"])
501 }
502
503 #[inline(always)]
504 pub const fn is_modifier(&self) -> bool {
505 matches!(
506 self,
507 T!["public"
508 | "protected"
509 | "private"
510 | "private(set)"
511 | "protected(set)"
512 | "public(set)"
513 | "static"
514 | "final"
515 | "abstract"
516 | "readonly"]
517 )
518 }
519
520 #[inline(always)]
521 pub const fn is_identifier_maybe_soft_reserved(&self) -> bool {
522 if let TokenKind::Identifier = self { true } else { self.is_soft_reserved_identifier() }
523 }
524
525 #[inline(always)]
526 pub const fn is_identifier_maybe_reserved(&self) -> bool {
527 if let TokenKind::Identifier = self { true } else { self.is_reserved_identifier() }
528 }
529
530 #[inline(always)]
531 pub const fn is_soft_reserved_identifier(&self) -> bool {
532 matches!(
533 self,
534 T!["parent" | "self" | "true" | "false" | "list" | "null" | "enum" | "from" | "readonly" | "match"]
535 )
536 }
537
538 #[inline(always)]
539 pub const fn is_reserved_identifier(&self) -> bool {
540 if self.is_soft_reserved_identifier() {
541 return true;
542 }
543
544 matches!(
545 self,
546 T!["static"
547 | "abstract"
548 | "final"
549 | "for"
550 | "private"
551 | "private(set)"
552 | "protected"
553 | "protected(set)"
554 | "public"
555 | "public(set)"
556 | "include"
557 | "include_once"
558 | "eval"
559 | "require"
560 | "require_once"
561 | "or"
562 | "xor"
563 | "and"
564 | "instanceof"
565 | "new"
566 | "clone"
567 | "exit"
568 | "die"
569 | "if"
570 | "elseif"
571 | "else"
572 | "endif"
573 | "echo"
574 | "do"
575 | "while"
576 | "endwhile"
577 | "endfor"
578 | "foreach"
579 | "endforeach"
580 | "declare"
581 | "enddeclare"
582 | "as"
583 | "try"
584 | "catch"
585 | "finally"
586 | "throw"
587 | "use"
588 | "insteadof"
589 | "global"
590 | "var"
591 | "unset"
592 | "isset"
593 | "empty"
594 | "continue"
595 | "goto"
596 | "function"
597 | "const"
598 | "return"
599 | "print"
600 | "yield"
601 | "list"
602 | "switch"
603 | "endswitch"
604 | "case"
605 | "default"
606 | "break"
607 | "array"
608 | "callable"
609 | "extends"
610 | "implements"
611 | "namespace"
612 | "trait"
613 | "interface"
614 | "class"
615 | "__CLASS__"
616 | "__TRAIT__"
617 | "__FUNCTION__"
618 | "__METHOD__"
619 | "__LINE__"
620 | "__FILE__"
621 | "__DIR__"
622 | "__NAMESPACE__"
623 | "__halt_compiler"
624 | "fn"
625 | "match"]
626 )
627 }
628
629 #[inline(always)]
630 pub const fn is_literal(&self) -> bool {
631 matches!(
632 self,
633 T!["true" | "false" | "null" | LiteralFloat | LiteralInteger | LiteralString | PartialLiteralString]
634 )
635 }
636
637 #[inline(always)]
638 pub const fn is_magic_constant(&self) -> bool {
639 matches!(
640 self,
641 T!["__CLASS__"
642 | "__DIR__"
643 | "__FILE__"
644 | "__FUNCTION__"
645 | "__LINE__"
646 | "__METHOD__"
647 | "__NAMESPACE__"
648 | "__TRAIT__"]
649 )
650 }
651
652 #[inline(always)]
653 pub const fn is_cast(&self) -> bool {
654 matches!(
655 self,
656 T!["(string)"
657 | "(binary)"
658 | "(int)"
659 | "(integer)"
660 | "(float)"
661 | "(double)"
662 | "(real)"
663 | "(bool)"
664 | "(boolean)"
665 | "(array)"
666 | "(object)"
667 | "(unset)"]
668 )
669 }
670
671 #[inline(always)]
672 pub const fn is_unary_prefix(&self) -> bool {
673 if self.is_cast() {
674 return true;
675 }
676
677 matches!(self, T!["@" | "!" | "~" | "-" | "+" | "++" | "--" | "&"])
678 }
679
680 #[inline(always)]
681 pub const fn is_trivia(&self) -> bool {
682 matches!(self, T![SingleLineComment | MultiLineComment | DocBlockComment | HashComment | Whitespace])
683 }
684
685 #[inline(always)]
686 pub const fn is_comment(&self) -> bool {
687 matches!(self, T![SingleLineComment | MultiLineComment | DocBlockComment | HashComment])
688 }
689
690 #[inline(always)]
691 pub const fn is_construct(&self) -> bool {
692 matches!(
693 self,
694 T!["isset"
695 | "empty"
696 | "eval"
697 | "include"
698 | "include_once"
699 | "require"
700 | "require_once"
701 | "print"
702 | "unset"
703 | "exit"
704 | "die"]
705 )
706 }
707}
708
709impl Token {
710 pub fn new(kind: TokenKind, value: StringIdentifier, span: Span) -> Self {
711 Self { kind, value, span }
712 }
713}
714
715impl std::fmt::Display for Token {
716 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
717 write!(f, "{:?} {}", self.kind, self.span)
718 }
719}
720
721#[macro_export]
722macro_rules! T {
723 ("eval") => {
724 $crate::TokenKind::Eval
725 };
726 ("die") => {
727 $crate::TokenKind::Die
728 };
729 ("self") => {
730 $crate::TokenKind::Self_
731 };
732 ("parent") => {
733 $crate::TokenKind::Parent
734 };
735 ("`") => {
736 $crate::TokenKind::Backtick
737 };
738 ("<<<") => {
739 $crate::TokenKind::DocumentStart(_)
740 };
741 (">>>") => {
742 $crate::TokenKind::DocumentEnd
743 };
744 ("from") => {
745 $crate::TokenKind::From
746 };
747 ("print") => {
748 $crate::TokenKind::Print
749 };
750 ("$") => {
751 $crate::TokenKind::Dollar
752 };
753 ("__halt_compiler") => {
754 $crate::TokenKind::HaltCompiler
755 };
756 ("readonly") => {
757 $crate::TokenKind::Readonly
758 };
759 ("global") => {
760 $crate::TokenKind::Global
761 };
762 ("abstract") => {
763 $crate::TokenKind::Abstract
764 };
765 ("&") => {
766 $crate::TokenKind::Ampersand
767 };
768 ("&=") => {
769 $crate::TokenKind::AmpersandEqual
770 };
771 ("&&") => {
772 $crate::TokenKind::AmpersandAmpersand
773 };
774 ("&&=") => {
775 $crate::TokenKind::AmpersandAmpersandEqual
776 };
777 ("array") => {
778 $crate::TokenKind::Array
779 };
780 ("(array)") => {
781 $crate::TokenKind::ArrayCast
782 };
783 ("->") => {
784 $crate::TokenKind::MinusGreaterThan
785 };
786 ("?->") => {
787 $crate::TokenKind::QuestionMinusGreaterThan
788 };
789 ("@") => {
790 $crate::TokenKind::At
791 };
792 ("as") => {
793 $crate::TokenKind::As
794 };
795 ("*") => {
796 $crate::TokenKind::Asterisk
797 };
798 ("#[") => {
799 $crate::TokenKind::HashLeftBracket
800 };
801 ("!") => {
802 $crate::TokenKind::Bang
803 };
804 ("!=") => {
805 $crate::TokenKind::BangEqual
806 };
807 ("<>") => {
808 $crate::TokenKind::LessThanGreaterThan
809 };
810 ("!==") => {
811 $crate::TokenKind::BangEqualEqual
812 };
813 ("<=>") => {
814 $crate::TokenKind::LessThanEqualGreaterThan
815 };
816 ("(bool)") => {
817 $crate::TokenKind::BoolCast
818 };
819 ("(boolean)") => {
820 $crate::TokenKind::BooleanCast
821 };
822 ("and") => {
823 $crate::TokenKind::And
824 };
825 ("or") => {
826 $crate::TokenKind::Or
827 };
828 ("break") => {
829 $crate::TokenKind::Break
830 };
831 ("callable") => {
832 $crate::TokenKind::Callable
833 };
834 ("^") => {
835 $crate::TokenKind::Caret
836 };
837 ("^=") => {
838 $crate::TokenKind::CaretEqual
839 };
840 ("case") => {
841 $crate::TokenKind::Case
842 };
843 ("catch") => {
844 $crate::TokenKind::Catch
845 };
846 ("class") => {
847 $crate::TokenKind::Class
848 };
849 ("__CLASS__") => {
850 $crate::TokenKind::ClassConstant
851 };
852 ("__TRAIT__") => {
853 $crate::TokenKind::TraitConstant
854 };
855 ("__FUNCTION__") => {
856 $crate::TokenKind::FunctionConstant
857 };
858 ("__METHOD__") => {
859 $crate::TokenKind::MethodConstant
860 };
861 ("__LINE__") => {
862 $crate::TokenKind::LineConstant
863 };
864 ("__FILE__") => {
865 $crate::TokenKind::FileConstant
866 };
867 ("clone") => {
868 $crate::TokenKind::Clone
869 };
870 ("-=") => {
871 $crate::TokenKind::MinusEqual
872 };
873 ("?>") => {
874 $crate::TokenKind::CloseTag
875 };
876 ("??") => {
877 $crate::TokenKind::QuestionQuestion
878 };
879 ("??=") => {
880 $crate::TokenKind::QuestionQuestionEqual
881 };
882 ("*=") => {
883 $crate::TokenKind::AsteriskEqual
884 };
885 (":") => {
886 $crate::TokenKind::Colon
887 };
888 (",") => {
889 $crate::TokenKind::Comma
890 };
891 ("// comment") => {
892 $crate::TokenKind::SingleLineComment
893 };
894 ("# comment") => {
895 $crate::TokenKind::HashComment
896 };
897 ("/* comment */") => {
898 $crate::TokenKind::MultiLineComment
899 };
900 ("/** comment */") => {
901 $crate::TokenKind::DocBlockComment
902 };
903 ("const") => {
904 $crate::TokenKind::Const
905 };
906 ("continue") => {
907 $crate::TokenKind::Continue
908 };
909 ("declare") => {
910 $crate::TokenKind::Declare
911 };
912 ("--") => {
913 $crate::TokenKind::MinusMinus
914 };
915 ("default") => {
916 $crate::TokenKind::Default
917 };
918 ("__DIR__") => {
919 $crate::TokenKind::DirConstant
920 };
921 ("/=") => {
922 $crate::TokenKind::SlashEqual
923 };
924 ("do") => {
925 $crate::TokenKind::Do
926 };
927 ("${") => {
928 $crate::TokenKind::DollarLeftBrace
929 };
930 (".") => {
931 $crate::TokenKind::Dot
932 };
933 (".=") => {
934 $crate::TokenKind::DotEqual
935 };
936 ("=>") => {
937 $crate::TokenKind::EqualGreaterThan
938 };
939 ("(double)") => {
940 $crate::TokenKind::DoubleCast
941 };
942 ("(real)") => {
943 $crate::TokenKind::RealCast
944 };
945 ("(float)") => {
946 $crate::TokenKind::FloatCast
947 };
948 ("::") => {
949 $crate::TokenKind::ColonColon
950 };
951 ("==") => {
952 $crate::TokenKind::EqualEqual
953 };
954 ("\"") => {
955 $crate::TokenKind::DoubleQuote
956 };
957 ("else") => {
958 $crate::TokenKind::Else
959 };
960 ("echo") => {
961 $crate::TokenKind::Echo
962 };
963 ("...") => {
964 $crate::TokenKind::DotDotDot
965 };
966 ("elseif") => {
967 $crate::TokenKind::ElseIf
968 };
969 ("empty") => {
970 $crate::TokenKind::Empty
971 };
972 ("enddeclare") => {
973 $crate::TokenKind::EndDeclare
974 };
975 ("endfor") => {
976 $crate::TokenKind::EndFor
977 };
978 ("endforeach") => {
979 $crate::TokenKind::EndForeach
980 };
981 ("endif") => {
982 $crate::TokenKind::EndIf
983 };
984 ("endswitch") => {
985 $crate::TokenKind::EndSwitch
986 };
987 ("endwhile") => {
988 $crate::TokenKind::EndWhile
989 };
990 ("enum") => {
991 $crate::TokenKind::Enum
992 };
993 ("=") => {
994 $crate::TokenKind::Equal
995 };
996 ("extends") => {
997 $crate::TokenKind::Extends
998 };
999 ("false") => {
1000 $crate::TokenKind::False
1001 };
1002 ("final") => {
1003 $crate::TokenKind::Final
1004 };
1005 ("finally") => {
1006 $crate::TokenKind::Finally
1007 };
1008 ("fn") => {
1009 $crate::TokenKind::Fn
1010 };
1011 ("for") => {
1012 $crate::TokenKind::For
1013 };
1014 ("foreach") => {
1015 $crate::TokenKind::Foreach
1016 };
1017 ("\\Fully\\Qualified\\Identifier") => {
1018 $crate::TokenKind::FullyQualifiedIdentifier
1019 };
1020 ("function") => {
1021 $crate::TokenKind::Function
1022 };
1023 ("goto") => {
1024 $crate::TokenKind::Goto
1025 };
1026 (">") => {
1027 $crate::TokenKind::GreaterThan
1028 };
1029 (">=") => {
1030 $crate::TokenKind::GreaterThanEqual
1031 };
1032 ("Identifier") => {
1033 $crate::TokenKind::Identifier
1034 };
1035 ("if") => {
1036 $crate::TokenKind::If
1037 };
1038 ("implements") => {
1039 $crate::TokenKind::Implements
1040 };
1041 ("include") => {
1042 $crate::TokenKind::Include
1043 };
1044 ("include_once") => {
1045 $crate::TokenKind::IncludeOnce
1046 };
1047 ("++") => {
1048 $crate::TokenKind::PlusPlus
1049 };
1050 ("instanceof") => {
1051 $crate::TokenKind::Instanceof
1052 };
1053 ("insteadof") => {
1054 $crate::TokenKind::Insteadof
1055 };
1056 ("exit") => {
1057 $crate::TokenKind::Exit
1058 };
1059 ("unset") => {
1060 $crate::TokenKind::Unset
1061 };
1062 ("isset") => {
1063 $crate::TokenKind::Isset
1064 };
1065 ("list") => {
1066 $crate::TokenKind::List
1067 };
1068 ("(int)") => {
1069 $crate::TokenKind::IntCast
1070 };
1071 ("(integer)") => {
1072 $crate::TokenKind::IntegerCast
1073 };
1074 ("interface") => {
1075 $crate::TokenKind::Interface
1076 };
1077 ("{") => {
1078 $crate::TokenKind::LeftBrace
1079 };
1080 ("[") => {
1081 $crate::TokenKind::LeftBracket
1082 };
1083 ("(") => {
1084 $crate::TokenKind::LeftParenthesis
1085 };
1086 (")") => {
1087 $crate::TokenKind::RightParenthesis
1088 };
1089 ("<<") => {
1090 $crate::TokenKind::LeftShift
1091 };
1092 ("<<=") => {
1093 $crate::TokenKind::LeftShiftEqual
1094 };
1095 (">>") => {
1096 $crate::TokenKind::RightShift
1097 };
1098 (">>=") => {
1099 $crate::TokenKind::RightShiftEqual
1100 };
1101 ("<") => {
1102 $crate::TokenKind::LessThan
1103 };
1104 ("<=") => {
1105 $crate::TokenKind::LessThanEqual
1106 };
1107 ("match") => {
1108 $crate::TokenKind::Match
1109 };
1110 ("-") => {
1111 $crate::TokenKind::Minus
1112 };
1113 ("namespace") => {
1114 $crate::TokenKind::Namespace
1115 };
1116 ("\\") => {
1117 $crate::TokenKind::NamespaceSeparator
1118 };
1119 ("__NAMESPACE__") => {
1120 $crate::TokenKind::NamespaceConstant
1121 };
1122 ("new") => {
1123 $crate::TokenKind::New
1124 };
1125 ("null") => {
1126 $crate::TokenKind::Null
1127 };
1128 ("(object)") => {
1129 $crate::TokenKind::ObjectCast
1130 };
1131 ("(unset)") => {
1132 $crate::TokenKind::UnsetCast
1133 };
1134 ("<?php") => {
1135 $crate::TokenKind::OpenTag
1136 };
1137 ("<?=") => {
1138 $crate::TokenKind::EchoTag
1139 };
1140 ("<?") => {
1141 $crate::TokenKind::ShortOpenTag
1142 };
1143 ("%") => {
1144 $crate::TokenKind::Percent
1145 };
1146 ("%=") => {
1147 $crate::TokenKind::PercentEqual
1148 };
1149 ("|") => {
1150 $crate::TokenKind::Pipe
1151 };
1152 ("|=") => {
1153 $crate::TokenKind::PipeEqual
1154 };
1155 ("+") => {
1156 $crate::TokenKind::Plus
1157 };
1158 ("+=") => {
1159 $crate::TokenKind::PlusEqual
1160 };
1161 ("**") => {
1162 $crate::TokenKind::AsteriskAsterisk
1163 };
1164 ("**=") => {
1165 $crate::TokenKind::AsteriskAsteriskEqual
1166 };
1167 ("private(set)") => {
1168 $crate::TokenKind::PrivateSet
1169 };
1170 ("private") => {
1171 $crate::TokenKind::Private
1172 };
1173 ("protected") => {
1174 $crate::TokenKind::Protected
1175 };
1176 ("protected(set)") => {
1177 $crate::TokenKind::ProtectedSet
1178 };
1179 ("public") => {
1180 $crate::TokenKind::Public
1181 };
1182 ("public(set)") => {
1183 $crate::TokenKind::PublicSet
1184 };
1185 ("Qualified\\Identifier") => {
1186 $crate::TokenKind::QualifiedIdentifier
1187 };
1188 ("?") => {
1189 $crate::TokenKind::Question
1190 };
1191 ("?:") => {
1192 $crate::TokenKind::QuestionColon
1193 };
1194 ("require") => {
1195 $crate::TokenKind::Require
1196 };
1197 ("require_once") => {
1198 $crate::TokenKind::RequireOnce
1199 };
1200 ("return") => {
1201 $crate::TokenKind::Return
1202 };
1203 ("}") => {
1204 $crate::TokenKind::RightBrace
1205 };
1206 ("]") => {
1207 $crate::TokenKind::RightBracket
1208 };
1209 (";") => {
1210 $crate::TokenKind::Semicolon
1211 };
1212 ("/") => {
1213 $crate::TokenKind::Slash
1214 };
1215 ("static") => {
1216 $crate::TokenKind::Static
1217 };
1218 ("(string)") => {
1219 $crate::TokenKind::StringCast
1220 };
1221 ("(binary)") => {
1222 $crate::TokenKind::BinaryCast
1223 };
1224 ("switch") => {
1225 $crate::TokenKind::Switch
1226 };
1227 ("throw") => {
1228 $crate::TokenKind::Throw
1229 };
1230 ("trait") => {
1231 $crate::TokenKind::Trait
1232 };
1233 ("===") => {
1234 $crate::TokenKind::EqualEqualEqual
1235 };
1236 ("true") => {
1237 $crate::TokenKind::True
1238 };
1239 ("try") => {
1240 $crate::TokenKind::Try
1241 };
1242 ("use") => {
1243 $crate::TokenKind::Use
1244 };
1245 ("var") => {
1246 $crate::TokenKind::Var
1247 };
1248 ("$variable") => {
1249 $crate::TokenKind::Variable
1250 };
1251 ("yield") => {
1252 $crate::TokenKind::Yield
1253 };
1254 ("while") => {
1255 $crate::TokenKind::While
1256 };
1257 ("~") => {
1258 $crate::TokenKind::Tilde
1259 };
1260 ("||") => {
1261 $crate::TokenKind::PipePipe
1262 };
1263 ("xor") => {
1264 $crate::TokenKind::Xor
1265 };
1266 ($name:ident) => {
1267 $crate::TokenKind::$name
1268 };
1269 ($first:tt | $($rest:tt)+) => {
1270 $crate::T![$first] | $crate::T![$($rest)+]
1271 };
1272 ($($kind:tt),+ $(,)?) => {
1273 &[$($crate::T![$kind]),+]
1274 };
1275}