php_parser_rs/parser/
macros.rs

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 &current.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}