1#[macro_export]
2macro_rules! peek_token {
3 ([ $($(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? => $out:expr),+ $(,)? ], $state:expr, [ $($message:literal),+ $(,)? ]) => {{
4 match &$state.stream.current().kind {
5 $(
6 $( $pattern )|+ $( if $guard )? => $out,
7 )+
8 _ => {
9 return $crate::expected_token_err!([ $($message,)+ ], $state);
10 }
11 }
12 }};
13 ([ $($(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?),+ $(,)? ], $state:expr, [ $($message:literal),+ $(,)? ]) => {{
14 if !matches!($state.stream.current().kind, $( $pattern )|+ $( if $guard )?) {
15 return $crate::expected_token_err!([ $($message,)+ ], $state);
16 }
17 }};
18 ([ $($(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? => $out:expr),+ $(,)? ], $state:expr, $message:literal) => {
19 $crate::peek_token!([ $($( $pattern )|+ $( if $guard )? => $out,)+ ], $state, [$message])
20 };
21 ([ $($(|)? $( $pattern:pat_param )|+ $( if $guard: expr )?),+ $(,)? ], $state:expr, $message:literal) => {
22 $crate::peek_token!([ $($( $pattern )|+ $( if $guard )?,)+ ], $state, [$message])
23 };
24}
25
26#[macro_export]
27macro_rules! expect_token {
28 ([ $($(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? => $out:expr),+ $(,)? ], $state:expr, [ $($message:literal),+ $(,)? ]) => {{
29 let token = $state.stream.current();
30 $state.stream.next();
31 match token.kind {
32 $(
33 $( $pattern )|+ $( if $guard )? => {
34 $out
35 },
36 )+
37 _ => {
38 return Err($crate::parser::error::unexpected_token(
39 vec![$($message.into(),)+],
40 token,
41 ))
42 }
43 }
44 }};
45 ([ $($(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? => $out:expr),+ $(,)? ], $state:expr, $message:literal) => {
46 $crate::expect_token!([ $($( $pattern )|+ $( if $guard )? => $out,)+ ], $state, [$message])
47 };
48}
49
50#[macro_export]
51macro_rules! expect_literal {
52 ($state:expr) => {{
53 let current = $state.stream.current();
54
55 match ¤t.kind {
56 TokenKind::LiteralInteger => {
57 $state.stream.next();
58
59 $crate::parser::ast::literals::Literal::Integer(
60 $crate::parser::ast::literals::LiteralInteger {
61 span: current.span,
62 value: current.value.clone(),
63 },
64 )
65 }
66 TokenKind::LiteralFloat => {
67 $state.stream.next();
68
69 $crate::parser::ast::literals::Literal::Float(
70 $crate::parser::ast::literals::LiteralFloat {
71 span: current.span,
72 value: current.value.clone(),
73 },
74 )
75 }
76 TokenKind::LiteralSingleQuotedString | TokenKind::LiteralDoubleQuotedString => {
77 $state.stream.next();
78
79 $crate::parser::ast::literals::Literal::String(
80 $crate::parser::ast::literals::LiteralString {
81 span: current.span,
82 value: current.value.clone(),
83 kind: if matches!(current.kind, TokenKind::LiteralSingleQuotedString) {
84 $crate::parser::ast::literals::LiteralStringKind::SingleQuoted
85 } else {
86 $crate::parser::ast::literals::LiteralStringKind::DoubleQuoted
87 },
88 },
89 )
90 }
91 _ => {
92 return $crate::expected_token_err!(["a literal"], $state);
93 }
94 }
95 }};
96}
97
98#[macro_export]
99macro_rules! expected_token_err {
100 ([ $($expected:literal),+ $(,)? ], $state:expr $(,)?) => {{
101 Err($crate::expected_token!([$($expected),+], $state))
102 }};
103
104 ($expected:literal, $state:expr $(,)?) => {
105 $crate::expected_token_err!([$expected], $state)
106 };
107}
108
109#[macro_export]
110macro_rules! expected_token {
111 ([ $($expected:literal),+ $(,)? ], $state:expr $(,)?) => {{
112 $crate::parser::error::unexpected_token(
113 vec![$($expected.into()),+],
114 $state.stream.current(),
115 )
116 }};
117
118 ($expected:literal, $state:expr $(,)?) => {
119 $crate::expected_token!([$expected], $state)
120 };
121}
122
123#[macro_export]
124macro_rules! expected_scope {
125 ([ $($(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? => $out:expr),+ $(,)? ], $state:expr) => {{
126 match $state.scope().cloned()? {
127 $(
128 $( $pattern )|+ $( if $guard )? => $out,
129 )+
130 _ => {
131 return Err($crate::parser::error::reached_unpredictable_state($state.stream.current().span));
132 }
133 }
134 }};
135}
136
137#[macro_export]
138macro_rules! scoped {
139 ($state:expr, $scope:expr, $block:block) => {{
140 $state.enter($scope);
141
142 let result = $block;
143
144 $state.exit();
145
146 result
147 }};
148}